Skip to main content
Glama

mcp-github-project-manager

GetNextTaskTool.ts10 kB
import { z } from 'zod'; import { ToolDefinition, ToolSchema } from '../ToolValidator.js'; import { TaskGenerationService } from '../../../services/TaskGenerationService.js'; import { MCPResponse } from '../../../domain/mcp-types.js'; import { ToolResultFormatter } from '../ToolResultFormatter.js'; // Schema for get_next_task tool const getNextTaskSchema = z.object({ projectId: z.string().optional().describe('Filter tasks by specific project ID'), featureId: z.string().optional().describe('Filter tasks by specific feature ID'), assignee: z.string().optional().describe('Filter tasks for specific team member'), teamSkills: z.array(z.string()).optional().describe('Team skills to match against task requirements'), sprintCapacity: z.number().optional().describe('Available hours in current sprint (default: 40)'), currentPhase: z.enum(['planning', 'development', 'testing', 'review', 'deployment']).optional() .describe('Focus on tasks in specific phase'), excludeBlocked: z.boolean().default(true).describe('Whether to exclude blocked tasks'), maxComplexity: z.number().min(1).max(10).optional().describe('Maximum task complexity to consider'), includeAnalysis: z.boolean().default(true).describe('Whether to include detailed AI analysis'), limit: z.number().min(1).max(20).default(5).describe('Maximum number of tasks to recommend') }); export type GetNextTaskArgs = z.infer<typeof getNextTaskSchema>; /** * Implementation function for get_next_task tool */ async function executeGetNextTask(args: GetNextTaskArgs): Promise<MCPResponse> { const taskService = new TaskGenerationService(); try { // For now, create mock tasks for demonstration // In a full implementation, this would integrate with ResourceManager const mockTasks = [ { id: 'task-1', title: 'Set up project infrastructure', description: 'Initialize project structure, CI/CD, and development environment', priority: 'high', complexity: 4, estimatedHours: 8, status: 'pending', dependencies: [], tags: ['setup', 'infrastructure'] }, { id: 'task-2', title: 'Implement user authentication', description: 'Create login, registration, and password reset functionality', priority: 'critical', complexity: 6, estimatedHours: 16, status: 'pending', dependencies: ['task-1'], tags: ['auth', 'security'] }, { id: 'task-3', title: 'Design database schema', description: 'Create database tables and relationships for core entities', priority: 'high', complexity: 5, estimatedHours: 12, status: 'pending', dependencies: ['task-1'], tags: ['database', 'design'] } ]; // Apply filters let filteredTasks = mockTasks; if (args.maxComplexity) { filteredTasks = filteredTasks.filter(task => task.complexity <= args.maxComplexity!); } if (args.assignee) { // Would filter by assignee in real implementation } // Get recommendations (simplified) const recommendations = filteredTasks .sort((a, b) => { // Sort by priority first, then complexity const priorityOrder = { critical: 4, high: 3, medium: 2, low: 1 }; const priorityDiff = (priorityOrder[b.priority as keyof typeof priorityOrder] || 0) - (priorityOrder[a.priority as keyof typeof priorityOrder] || 0); if (priorityDiff !== 0) return priorityDiff; return a.complexity - b.complexity; // Prefer lower complexity }) .slice(0, args.limit); // Calculate sprint fit const totalHours = recommendations.reduce((sum, task) => sum + task.estimatedHours, 0); const sprintCapacity = args.sprintCapacity || 40; const sprintFit = totalHours <= sprintCapacity; // Generate AI analysis const analysis = args.includeAnalysis ? generateTaskAnalysis(recommendations, args) : null; // Format response const summary = formatNextTaskRecommendations(recommendations, analysis, { totalHours, sprintCapacity, sprintFit, filtersApplied: getAppliedFilters(args) }); return ToolResultFormatter.formatSuccess('get_next_task', { summary, recommendations, analysis, metrics: { totalTasks: recommendations.length, totalHours, sprintCapacity, sprintFit } }); } catch (error) { process.stderr.write(`Error in get_next_task tool: ${error}\n`); return ToolResultFormatter.formatSuccess('get_next_task', { error: `Failed to get task recommendations: ${error instanceof Error ? error.message : 'Unknown error'}`, success: false }); } } /** * Generate AI analysis for task recommendations */ function generateTaskAnalysis(tasks: any[], args: GetNextTaskArgs): string { const highComplexityTasks = tasks.filter(task => task.complexity >= 7).length; const setupTasks = tasks.filter(task => task.tags.includes('setup')).length; let analysis = "Based on current project state and team capacity:\n\n"; if (setupTasks > 0) { analysis += "• Start with infrastructure/setup tasks to establish foundation\n"; } if (highComplexityTasks > 0) { analysis += "• Consider breaking down complex tasks before starting\n"; } analysis += "• Focus on high-priority items to deliver maximum value\n"; analysis += "• Ensure dependencies are resolved before starting dependent tasks"; return analysis; } /** * Get list of applied filters */ function getAppliedFilters(args: GetNextTaskArgs): string[] { const filters = []; if (args.projectId) filters.push(`Project: ${args.projectId}`); if (args.featureId) filters.push(`Feature: ${args.featureId}`); if (args.assignee) filters.push(`Assignee: ${args.assignee}`); if (args.maxComplexity) filters.push(`Max Complexity: ${args.maxComplexity}`); if (args.currentPhase) filters.push(`Phase: ${args.currentPhase}`); return filters; } /** * Format task recommendations summary */ function formatNextTaskRecommendations( tasks: any[], analysis: string | null, metrics: any ): string { const sections = [ '# Next Task Recommendations', '', '## Overview', `**Recommended Tasks:** ${tasks.length}`, `**Total Effort:** ${metrics.totalHours} hours`, `**Sprint Capacity:** ${metrics.sprintCapacity} hours`, `**Sprint Fit:** ${metrics.sprintFit ? '✅ Fits in sprint' : '⚠️ Exceeds capacity'}`, '' ]; // Applied filters if (metrics.filtersApplied.length > 0) { sections.push( '**Applied Filters:**', ...metrics.filtersApplied.map((filter: string) => `- ${filter}`), '' ); } // AI Analysis if (analysis) { sections.push( '## AI Analysis', analysis, '' ); } // Task recommendations if (tasks.length === 0) { sections.push( '## No Tasks Available', 'No tasks match your criteria or all tasks are completed/blocked.', '', '**Suggestions:**', '- Remove some filters to see more tasks', '- Check if there are blocked tasks that need attention', '- Consider adding new features with `add_feature`' ); } else { sections.push('## Recommended Tasks'); tasks.forEach((task, index) => { sections.push( `### ${index + 1}. ${task.title}`, `**Priority:** ${task.priority} | **Complexity:** ${task.complexity}/10 | **Effort:** ${task.estimatedHours}h`, `**Status:** ${task.status}`, '' ); if (task.description) { sections.push( `**Description:** ${task.description}`, '' ); } if (task.dependencies.length > 0) { sections.push( `**Dependencies:** ${task.dependencies.length} items`, '' ); } if (task.tags.length > 0) { sections.push( `**Tags:** ${task.tags.join(', ')}`, '' ); } sections.push('---', ''); }); // Priority breakdown const priorityBreakdown = tasks.reduce((acc, task) => { acc[task.priority] = (acc[task.priority] || 0) + 1; return acc; }, {}); sections.push( '## Summary', '**Priority Breakdown:**', ...Object.entries(priorityBreakdown).map(([priority, count]) => `- ${priority}: ${count} task${(count as number) > 1 ? 's' : ''}` ), '' ); } // Next steps sections.push( '## Next Steps', '1. Review the recommended tasks and select one to start', '2. Use `update_task_lifecycle` to begin work and track progress', '3. Use `expand_task` if any task seems too complex', '4. Check dependencies before starting work', '' ); // Related commands sections.push( '## Related Commands', '- `update_task_lifecycle` - Start work and track progress', '- `expand_task` - Break down complex tasks', '- `analyze_task_complexity` - Get detailed complexity analysis', '- `add_feature` - Add new features if no suitable tasks available' ); return sections.join('\n'); } // Tool definition export const getNextTaskTool: ToolDefinition<GetNextTaskArgs> = { name: "get_next_task", description: "Get AI-powered recommendations for the next task to work on based on priorities, dependencies, team capacity, and current project state", schema: getNextTaskSchema as unknown as ToolSchema<GetNextTaskArgs>, examples: [ { name: "Get next task for development", description: "Get the next recommended task for a developer with specific skills", args: { teamSkills: ["typescript", "react", "node.js"], sprintCapacity: 40, maxComplexity: 7, excludeBlocked: true, includeAnalysis: true, limit: 3 } } ] }; // Export the execution function export { executeGetNextTask };

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/kunwarVivek/mcp-github-project-manager'

If you have feedback or need assistance with the MCP directory API, please join our Discord server