mcp-workflow-server-enhanced
Version:
Enhanced MCP Workflow Server with smart problem routing, comprehensive validation, guide compliance, and robust error handling. Intelligently routes to appropriate AI functions based on problem type.
527 lines (467 loc) • 15.2 kB
text/typescript
import {
TaskGenerationInputSchema,
FunctionOutput,
WorkflowContext,
} from '../shared/types.js';
import { logWorkflowProgress } from '../shared/utils.js';
/**
* Task Generation Function
*
* This function converts the detailed implementation plan into specific,
* actionable tasks with clear instructions, acceptance criteria, and
* implementation details for the execution phase.
*/
export function createTaskGenerationFunction() {
return async (input: any, context: WorkflowContext): Promise<FunctionOutput> => {
try {
// Validate input
const validatedInput = TaskGenerationInputSchema.parse(input);
const { plan, granularity } = validatedInput;
logWorkflowProgress(context, 'task-generation', 'Starting task generation from plan');
// Generate detailed tasks from the plan
const tasks = await generateDetailedTasks(plan, granularity);
// Create task execution order
const executionOrder = determineExecutionOrder(tasks);
// Generate task templates
const taskTemplates = createTaskTemplates(tasks);
// Create validation criteria
const validationCriteria = createValidationCriteria(tasks);
// Generate implementation guidelines
const implementationGuidelines = generateImplementationGuidelines(plan, tasks);
const result = {
tasks,
executionOrder,
taskTemplates,
validationCriteria,
implementationGuidelines,
taskSummary: generateTaskSummary(tasks),
estimatedEffort: calculateTotalEffort(tasks),
dependencies: mapTaskDependencies(tasks),
qualityChecks: defineQualityChecks(tasks),
};
logWorkflowProgress(context, 'task-generation', 'Task generation completed successfully');
return {
success: true,
result,
nextStep: 'implementation',
context,
metadata: {
totalTasks: tasks.length,
granularity,
estimatedDuration: result.estimatedEffort,
processingTime: Date.now(),
},
};
} catch (error) {
return {
success: false,
result: {
error: error.message,
step: 'task-generation',
},
context,
};
}
};
}
/**
* Generate detailed tasks from the implementation plan
*/
async function generateDetailedTasks(
plan: any,
granularity: 'high' | 'medium' | 'fine'
): Promise<Array<{
id: string;
name: string;
description: string;
phase: string;
priority: 'high' | 'medium' | 'low';
effort: string;
dependencies: string[];
acceptanceCriteria: string[];
implementationSteps: string[];
deliverables: string[];
testingRequirements: string[];
qualityGates: string[];
}>> {
const tasks = [];
let taskId = 1;
if (!plan?.implementationPlan?.phases) {
throw new Error('Invalid plan structure: missing phases');
}
for (const phase of plan.implementationPlan.phases) {
for (const planTask of phase.tasks) {
// Break down tasks based on granularity
const detailedTasks = breakDownTask(planTask, phase.name, granularity);
for (const task of detailedTasks) {
tasks.push({
id: `TASK-${taskId.toString().padStart(3, '0')}`,
name: task.name,
description: task.description,
phase: phase.name,
priority: task.priority,
effort: task.effort,
dependencies: task.dependencies,
acceptanceCriteria: generateAcceptanceCriteria(task),
implementationSteps: generateImplementationSteps(task),
deliverables: task.deliverables,
testingRequirements: generateTestingRequirements(task),
qualityGates: generateQualityGates(task),
});
taskId++;
}
}
}
return tasks;
}
/**
* Break down a plan task into detailed implementation tasks
*/
function breakDownTask(
planTask: any,
phaseName: string,
granularity: 'high' | 'medium' | 'fine'
): Array<any> {
const tasks = [];
if (granularity === 'high') {
// Keep tasks at high level
tasks.push(planTask);
} else if (granularity === 'medium') {
// Break into 2-3 subtasks
tasks.push(...breakIntoMediumTasks(planTask));
} else {
// Break into fine-grained tasks
tasks.push(...breakIntoFineTasks(planTask));
}
return tasks;
}
/**
* Break task into medium granularity
*/
function breakIntoMediumTasks(planTask: any): Array<any> {
const tasks = [];
const baseName = planTask.name;
if (baseName.includes('Setup') || baseName.includes('Initialization')) {
tasks.push({
...planTask,
name: `${baseName} - Configuration`,
description: `Configure ${baseName.toLowerCase()} components and settings`,
});
tasks.push({
...planTask,
name: `${baseName} - Validation`,
description: `Validate ${baseName.toLowerCase()} setup and configuration`,
});
} else if (baseName.includes('Development') || baseName.includes('Implementation')) {
tasks.push({
...planTask,
name: `${baseName} - Core Logic`,
description: `Implement core logic for ${baseName.toLowerCase()}`,
});
tasks.push({
...planTask,
name: `${baseName} - Integration`,
description: `Integrate ${baseName.toLowerCase()} with existing components`,
});
} else if (baseName.includes('Testing')) {
tasks.push({
...planTask,
name: `${baseName} - Test Implementation`,
description: `Implement tests for ${baseName.toLowerCase()}`,
});
tasks.push({
...planTask,
name: `${baseName} - Test Execution`,
description: `Execute and validate ${baseName.toLowerCase()}`,
});
} else {
// Default breakdown
tasks.push({
...planTask,
name: `${baseName} - Implementation`,
description: `Implement ${baseName.toLowerCase()}`,
});
tasks.push({
...planTask,
name: `${baseName} - Validation`,
description: `Validate ${baseName.toLowerCase()}`,
});
}
return tasks;
}
/**
* Break task into fine granularity
*/
function breakIntoFineTasks(planTask: any): Array<any> {
const mediumTasks = breakIntoMediumTasks(planTask);
const fineTasks = [];
for (const mediumTask of mediumTasks) {
fineTasks.push({
...mediumTask,
name: `${mediumTask.name} - Planning`,
description: `Plan and design ${mediumTask.name.toLowerCase()}`,
effort: '1-2 hours',
});
fineTasks.push({
...mediumTask,
name: `${mediumTask.name} - Implementation`,
description: `Implement ${mediumTask.name.toLowerCase()}`,
effort: '2-4 hours',
});
fineTasks.push({
...mediumTask,
name: `${mediumTask.name} - Testing`,
description: `Test ${mediumTask.name.toLowerCase()}`,
effort: '1-2 hours',
});
}
return fineTasks;
}
/**
* Generate acceptance criteria for a task
*/
function generateAcceptanceCriteria(task: any): string[] {
const criteria = [];
criteria.push('Task implementation matches requirements');
criteria.push('Code follows established patterns and standards');
criteria.push('All deliverables are completed');
if (task.name.includes('Test')) {
criteria.push('All tests pass successfully');
criteria.push('Test coverage meets minimum requirements');
}
if (task.name.includes('Documentation')) {
criteria.push('Documentation is comprehensive and accurate');
criteria.push('Examples and usage instructions are provided');
}
if (task.name.includes('Integration')) {
criteria.push('Integration points work correctly');
criteria.push('No breaking changes to existing functionality');
}
return criteria;
}
/**
* Generate implementation steps for a task
*/
function generateImplementationSteps(task: any): string[] {
const steps = [];
steps.push('Review task requirements and acceptance criteria');
steps.push('Plan implementation approach');
if (task.name.includes('Setup') || task.name.includes('Configuration')) {
steps.push('Create configuration files');
steps.push('Install required dependencies');
steps.push('Validate configuration');
} else if (task.name.includes('Development') || task.name.includes('Implementation')) {
steps.push('Implement core functionality');
steps.push('Add error handling and validation');
steps.push('Integrate with existing components');
} else if (task.name.includes('Testing')) {
steps.push('Write test cases');
steps.push('Implement test code');
steps.push('Execute tests and validate results');
} else if (task.name.includes('Documentation')) {
steps.push('Create documentation structure');
steps.push('Write comprehensive documentation');
steps.push('Add examples and usage instructions');
}
steps.push('Review implementation against acceptance criteria');
steps.push('Perform quality checks');
steps.push('Mark task as complete');
return steps;
}
/**
* Generate testing requirements for a task
*/
function generateTestingRequirements(task: any): string[] {
const requirements = [];
if (task.name.includes('Test')) {
requirements.push('Implement comprehensive test suite');
requirements.push('Achieve minimum test coverage');
requirements.push('Include edge case testing');
} else {
requirements.push('Unit tests for new functionality');
requirements.push('Integration tests where applicable');
requirements.push('Manual testing of deliverables');
}
return requirements;
}
/**
* Generate quality gates for a task
*/
function generateQualityGates(task: any): string[] {
return [
'Code review completed',
'All tests passing',
'Quality standards met',
'Documentation updated',
'Acceptance criteria satisfied',
];
}
/**
* Determine execution order for tasks
*/
function determineExecutionOrder(tasks: any[]): Array<{ taskId: string; order: number; parallelGroup?: number }> {
const executionOrder = [];
let currentOrder = 1;
let parallelGroup = 1;
// Group tasks by phase
const tasksByPhase = tasks.reduce((groups, task) => {
if (!groups[task.phase]) groups[task.phase] = [];
groups[task.phase].push(task);
return groups;
}, {});
// Order tasks within each phase
for (const [phase, phaseTasks] of Object.entries(tasksByPhase)) {
const sortedTasks = (phaseTasks as any[]).sort((a, b) => {
// High priority first
if (a.priority === 'high' && b.priority !== 'high') return -1;
if (b.priority === 'high' && a.priority !== 'high') return 1;
// Then by dependencies
if (a.dependencies.length === 0 && b.dependencies.length > 0) return -1;
if (b.dependencies.length === 0 && a.dependencies.length > 0) return 1;
return 0;
});
for (const task of sortedTasks) {
executionOrder.push({
taskId: task.id,
order: currentOrder++,
parallelGroup: task.dependencies.length === 0 ? parallelGroup : undefined,
});
}
parallelGroup++;
}
return executionOrder;
}
/**
* Create task templates for common patterns
*/
function createTaskTemplates(tasks: any[]): { [key: string]: any } {
return {
setup: {
steps: ['Plan', 'Configure', 'Validate'],
checklist: ['Dependencies installed', 'Configuration verified', 'Setup tested'],
},
development: {
steps: ['Design', 'Implement', 'Test', 'Review'],
checklist: ['Code implemented', 'Tests written', 'Code reviewed', 'Quality gates passed'],
},
testing: {
steps: ['Plan tests', 'Write tests', 'Execute tests', 'Validate results'],
checklist: ['Test cases defined', 'Tests implemented', 'All tests pass', 'Coverage adequate'],
},
documentation: {
steps: ['Plan structure', 'Write content', 'Add examples', 'Review'],
checklist: ['Structure defined', 'Content complete', 'Examples added', 'Review completed'],
},
};
}
/**
* Create validation criteria for task completion
*/
function createValidationCriteria(tasks: any[]): { [key: string]: string[] } {
const criteria = {};
for (const task of tasks) {
criteria[task.id] = [
'All acceptance criteria met',
'Implementation follows standards',
'Quality gates passed',
'Deliverables completed',
'Testing requirements satisfied',
];
}
return criteria;
}
/**
* Generate implementation guidelines
*/
function generateImplementationGuidelines(plan: any, tasks: any[]): {
general: string[];
codeStandards: string[];
testingGuidelines: string[];
qualityRequirements: string[];
} {
return {
general: [
'Follow the established project structure',
'Implement tasks in the specified order',
'Validate each task before proceeding',
'Document any deviations or issues',
],
codeStandards: [
'Use TypeScript for type safety',
'Follow ESLint and Prettier configurations',
'Write clear, self-documenting code',
'Include appropriate error handling',
],
testingGuidelines: [
'Write tests before or alongside implementation',
'Aim for high test coverage',
'Include both positive and negative test cases',
'Test edge cases and error conditions',
],
qualityRequirements: [
'All code must pass linting checks',
'No TypeScript errors allowed',
'All tests must pass',
'Code review required for all changes',
],
};
}
/**
* Generate task summary
*/
function generateTaskSummary(tasks: any[]): {
totalTasks: number;
tasksByPhase: { [key: string]: number };
tasksByPriority: { [key: string]: number };
estimatedDuration: string;
} {
const tasksByPhase = tasks.reduce((counts, task) => {
counts[task.phase] = (counts[task.phase] || 0) + 1;
return counts;
}, {});
const tasksByPriority = tasks.reduce((counts, task) => {
counts[task.priority] = (counts[task.priority] || 0) + 1;
return counts;
}, {});
return {
totalTasks: tasks.length,
tasksByPhase,
tasksByPriority,
estimatedDuration: `${Math.ceil(tasks.length * 0.5)} to ${Math.ceil(tasks.length * 0.8)} days`,
};
}
/**
* Calculate total effort for all tasks
*/
function calculateTotalEffort(tasks: any[]): string {
const totalHours = tasks.length * 4; // Average 4 hours per task
const days = Math.ceil(totalHours / 8);
return `${totalHours} hours (approximately ${days} days)`;
}
/**
* Map task dependencies
*/
function mapTaskDependencies(tasks: any[]): Array<{ taskId: string; dependsOn: string[] }> {
return tasks
.filter(task => task.dependencies.length > 0)
.map(task => ({
taskId: task.id,
dependsOn: task.dependencies,
}));
}
/**
* Define quality checks for tasks
*/
function defineQualityChecks(tasks: any[]): { [key: string]: string[] } {
const checks = {};
for (const task of tasks) {
checks[task.id] = [
'Code compiles without errors',
'All tests pass',
'Linting checks pass',
'Code review approved',
'Documentation updated',
];
}
return checks;
}