UNPKG

claudemaster

Version:

Task management MCP server optimized for Claude Code - no API keys required

166 lines (149 loc) 5.67 kB
/** * claude-guided-prd-parsing.js * Guide Claude Code through intelligent PRD parsing */ import { z } from 'zod'; import { readFileSync, existsSync } from 'fs'; import { join } from 'path'; import TaskEngine from '../core/task-engine.js'; import { generateClaudePrompt } from '../core/claude-templates.js'; export function registerClaudeGuidedPRDParsingTool(server) { server.addTool({ name: 'claude_guided_prd_parsing', description: 'Guide Claude Code through intelligent PRD parsing and task creation. This tool provides structured prompts to help Claude Code analyze PRD documents and create well-organized development tasks.', parameters: z.object({ projectRoot: z.string().describe('Absolute path to project root directory'), prdPath: z.string().optional().describe('Path to PRD file (relative to project root or absolute)'), numTasks: z.number().optional().default(10).describe('Target number of main tasks to create'), projectType: z.enum(['react_app', 'node_api', 'full_stack', 'general']).optional().default('general').describe('Type of project for contextual guidance'), customInstructions: z.string().optional().describe('Additional instructions for task creation') }), execute: async (args) => { try { const { projectRoot, prdPath, numTasks, projectType, customInstructions } = args; const taskEngine = new TaskEngine(projectRoot); // Find PRD file let prdFilePath; if (prdPath) { prdFilePath = prdPath.startsWith('/') ? prdPath : join(projectRoot, prdPath); } else { // Look for common PRD file locations const commonPaths = [ join(projectRoot, '.taskmaster', 'docs', 'prd.txt'), join(projectRoot, '.taskmaster', 'docs', 'prd.md'), join(projectRoot, 'prd.txt'), join(projectRoot, 'PRD.md'), join(projectRoot, 'requirements.txt'), join(projectRoot, 'docs', 'requirements.md') ]; prdFilePath = commonPaths.find(path => existsSync(path)); } if (!prdFilePath || !existsSync(prdFilePath)) { return { success: false, error: 'PRD file not found. Please create a PRD file or specify the correct path.', suggestions: [ 'Create a PRD file at .taskmaster/docs/prd.txt', 'Use the initialize_project tool first to set up the project structure', 'Specify the exact path to your PRD file' ] }; } // Read PRD content const prdContent = readFileSync(prdFilePath, 'utf8'); // Generate Claude-optimized prompt const prompt = generateClaudePrompt('PRD_PARSING', prdContent, numTasks); // Prepare context for Claude Code const analysisContext = { projectType, prdLength: prdContent.length, estimatedComplexity: prdContent.length > 2000 ? 'high' : prdContent.length > 1000 ? 'medium' : 'low', targetTasks: numTasks }; return { success: true, claudeInstructions: { systemPrompt: prompt.system, userPrompt: prompt.user + (customInstructions ? `\n\nAdditional Instructions: ${customInstructions}` : ''), context: analysisContext, nextSteps: [ 'Analyze the PRD content provided', 'Create structured tasks following the guidelines', 'Use the save_parsed_tasks tool to save the results', 'Consider running project_health_check after task creation' ] }, prdSummary: { path: prdFilePath, size: prdContent.length, preview: prdContent.substring(0, 200) + (prdContent.length > 200 ? '...' : '') }, projectContext: analysisContext }; } catch (error) { return { success: false, error: error.message, suggestions: [ 'Check that the project root path is correct', 'Ensure the PRD file exists and is readable', 'Try using the initialize_project tool first' ] }; } } }); } export function registerSaveParsedTasksTool(server) { server.addTool({ name: 'save_parsed_tasks', description: 'Save tasks parsed from PRD analysis. Use this after Claude Code has analyzed the PRD and created structured tasks.', parameters: z.object({ projectRoot: z.string().describe('Absolute path to project root directory'), tasks: z.array(z.object({ id: z.number().optional(), title: z.string(), description: z.string(), priority: z.enum(['high', 'medium', 'low']).default('medium'), dependencies: z.array(z.number()).default([]), details: z.string().default(''), testStrategy: z.string().default('') })).describe('Array of parsed tasks'), replaceExisting: z.boolean().default(false).describe('Whether to replace existing tasks or append') }), execute: async (args) => { try { const { projectRoot, tasks, replaceExisting } = args; const taskEngine = new TaskEngine(projectRoot); let savedTasks = []; if (replaceExisting) { // Clear existing tasks and save new ones taskEngine.saveTasks([]); } // Add each task for (const taskData of tasks) { const savedTask = taskEngine.addTask(taskData); savedTasks.push(savedTask); } // Get project statistics const stats = taskEngine.getProjectStats(); return { success: true, message: `Successfully saved ${savedTasks.length} tasks`, tasks: savedTasks, projectStats: stats, nextSteps: [ 'Run get_next_task to see what to work on first', 'Use analyze_project_complexity to identify tasks that need breakdown', 'Consider running generate_implementation_plans for complex tasks' ] }; } catch (error) { return { success: false, error: error.message }; } } }); }