claudemaster
Version:
Task management MCP server optimized for Claude Code - no API keys required
166 lines (149 loc) • 5.67 kB
JavaScript
/**
* 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
};
}
}
});
}