UNPKG

@boundless-oss/atlas

Version:

Atlas - MCP Server for comprehensive startup project management

220 lines (175 loc) 7.41 kB
import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js'; import { setupProductRoadmapTools } from './tools.js'; import { SQLiteManager } from '../../storage/sqlite-manager.js'; import { RequestContext } from '../../core/types.js'; /** * Adapter to convert 12-factor tools to MCP SDK format */ export async function setupProductRoadmapMCP(server: Server, dbManager: SQLiteManager, projectId: string = 'default') { const toolRegistration = await setupProductRoadmapTools(); // Register the composite handler for all tools server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; if (!args) { throw new Error('No arguments provided'); } // Find the matching tool const tool = toolRegistration.tools.find(t => t.name === name); if (!tool) { throw new Error(`Unknown tool: ${name}`); } // Create request context const context: RequestContext = { toolName: name, requestId: `req-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`, timestamp: Date.now(), projectId, db: dbManager }; // Execute the tool const result = await tool.execute(args as any, context); // Convert result to MCP format if (result.success) { return { content: [{ type: 'text', text: formatResultText(name, result.data) }] }; } else { // Return error in MCP format return { isError: true, content: [{ type: 'text', text: `Error: ${result.error?.message || 'Unknown error'}\n\nDetails: ${JSON.stringify(result.error?.details || {}, null, 2)}` }] }; } }); return toolRegistration; } /** * Format result data as text for MCP response */ function formatResultText(toolName: string, data: any): string { switch (toolName) { case 'create_roadmap': return `✅ Product roadmap "${data.roadmap.name}" created successfully! **Vision**: ${data.roadmap.vision} **Time Horizon**: ${data.roadmap.timeHorizon} **Owner**: ${data.roadmap.owner} **Status**: ${data.roadmap.status} **Roadmap ID**: ${data.roadmap.id} ${data.nextSteps ? `Next steps:\n${data.nextSteps.map((s: string, i: number) => `${i + 1}. ${s}`).join('\n')}` : ''}`; case 'add_roadmap_theme': return `✅ Theme "${data.theme.name}" added to roadmap! **Description**: ${data.theme.description} **Priority**: ${data.theme.priority} **Timeframe**: ${data.theme.timeframe.startQuarter} - ${data.theme.timeframe.endQuarter} **Objectives**: ${data.theme.objectives.map((obj: string, i: number) => `${i + 1}. ${obj}`).join('\n')} **Theme ID**: ${data.theme.id} ${data.nextSteps ? `Next: ${data.nextSteps.join(', ')}` : ''}`; case 'create_initiative': return `✅ Initiative "${data.initiative.title}" created! **Description**: ${data.initiative.description} **Estimated Value**: - User Impact: ${data.initiative.value.userImpact} - Revenue Impact: $${data.initiative.value.revenueImpact.toLocaleString()} - Cost Savings: $${data.initiative.value.costSavings.toLocaleString()} - Strategic Value: ${data.initiative.value.strategicValue}/10 - Customer Satisfaction: ${data.initiative.value.customerSatisfaction > 0 ? '+' : ''}${data.initiative.value.customerSatisfaction} NPS **Estimated Effort**: ${data.initiative.totalEffortWeeks} weeks total - Development: ${data.initiative.effort.developmentWeeks} weeks - Design: ${data.initiative.effort.designWeeks} weeks - QA: ${data.initiative.effort.qaWeeks} weeks - Confidence: ${data.initiative.effort.confidence} **Risks**: ${data.initiative.risks.length} identified **Initiative ID**: ${data.initiative.id}`; case 'add_feature': return `✅ Feature "${data.feature.name}" added! **Description**: ${data.feature.description} **Business Value**: ${data.feature.businessValue.score}/100 **Technical Complexity**: ${data.feature.technicalComplexity} **Status**: ${data.feature.status} ${data.feature.targetRelease ? `**Target Release**: ${data.feature.targetRelease}` : ''} **Value Rationale**: ${data.feature.businessValue.rationale} **Success Metrics**: ${data.feature.businessValue.metrics.map((metric: string, i: number) => `${i + 1}. ${metric}`).join('\n')} **Feature ID**: ${data.feature.id}`; case 'list_roadmaps': if (data.roadmaps.length === 0) { return 'No product roadmaps found. Create one using create_roadmap.'; } return `📋 Product Roadmaps (${data.roadmaps.length}): ${data.roadmaps.map((r: any) => ` **${r.name}** (${r.id}) - Vision: ${r.vision} - Time Horizon: ${r.timeHorizon} - Status: ${r.status} - Owner: ${r.owner} - Themes: ${r.themes} - Updated: ${r.updatedAt}` ).join('\n')}`; case 'get_roadmap': const roadmap = data.roadmap; return `# ${roadmap.name} **Vision**: ${roadmap.vision} **Time Horizon**: ${roadmap.timeHorizon} **Status**: ${roadmap.status} **Owner**: ${roadmap.owner} ## Overview - Themes: ${roadmap.statistics.themes || 0} - Initiatives: ${roadmap.statistics.initiatives || 0} - Features: ${roadmap.statistics.features || 0} - Milestones: ${roadmap.statistics.milestones || 0} - Releases: ${roadmap.statistics.releases || 0} ## Themes ${roadmap.themes.map((theme: any) => ` ### ${theme.name} - Priority: ${theme.priority} - Timeframe: ${theme.timeframe} - Status: ${theme.status} - Initiatives: ${theme.initiatives} - Features: ${theme.features}` ).join('\n')} ## Upcoming Milestones ${roadmap.upcomingMilestones.length > 0 ? roadmap.upcomingMilestones.map((m: any) => `- ${m.name} (${m.date})`).join('\n') : 'No upcoming milestones'}`; case 'prioritize_features': return `📊 Feature Prioritization Results (${data.method.toUpperCase()}) **Scope**: ${data.scope} **Features Analyzed**: ${data.totalFeatures} **Top Features**: ${data.topFeatures.map((f: any) => `${f.rank}. **${f.name}**\n Score: ${f.score.toFixed(2)}\n ${f.rationale}\n Status: ${f.currentStatus}\n Complexity: ${f.complexity}` ).join('\n\n')} ${data.insights ? `\n**Insights**:\n${data.insights.map((i: string) => `- ${i}`).join('\n')}` : ''}`; case 'get_roadmap_health': const healthEmoji: Record<string, string> = { 'excellent': '🟢', 'good': '🟡', 'at-risk': '🟠', 'critical': '🔴' }; return `${healthEmoji[data.health] || '⚪'} Roadmap Health: **${data.health.toUpperCase()}** **Metrics**: - Features Planned: ${data.metrics.featuresPlanned} - Features Completed: ${data.metrics.featuresCompleted} (${ data.metrics.featuresPlanned > 0 ? Math.round((data.metrics.featuresCompleted / data.metrics.featuresPlanned) * 100) : 0 }%) - Active Initiatives: ${data.metrics.initiativesActive} - Velocity Trend: ${data.metrics.velocityTrend} - On-Time Delivery: ${data.metrics.onTimeDelivery}% - Value Delivered: ${data.metrics.valueDelivered}% ${data.risks.length > 0 ? `**Risks**:\n${data.risks.map((r: string) => `- ⚠️ ${r}`).join('\n')}` : ''} ${data.recommendations.length > 0 ? `\n**Recommendations**:\n${data.recommendations.map((r: string) => `- 💡 ${r}`).join('\n')}` : ''}`; default: // Generic formatting for other tools return data.message || JSON.stringify(data, null, 2); } }