UNPKG

@boundless-oss/atlas

Version:

Atlas - MCP Server for comprehensive startup project management

429 lines (372 loc) 10.9 kB
import { Router, Request, Response } from 'express'; import { getMCPClient } from '../utils/mcp-client.js'; const router = Router(); /** * Advanced Agile Analytics API endpoints * Provides access to Phase 2 MCP tools for epic management and reporting */ // Get epic progress router.get('/epics/:epicId/progress', async (req: Request, res: Response) => { try { const { epicId } = req.params; const mcpClient = getMCPClient(); if (!mcpClient) { return res.status(503).json({ success: false, error: 'MCP client not available' }); } const result = await mcpClient.callTool('get_epic_progress', { epicId }); res.json({ success: true, data: result, timestamp: new Date().toISOString() }); } catch (error) { console.error('Error fetching epic progress:', error); res.status(500).json({ success: false, error: 'Failed to fetch epic progress', message: (error as Error).message }); } }); // Get epic timeline router.get('/epics/:epicId/timeline', async (req: Request, res: Response) => { try { const { epicId } = req.params; const mcpClient = getMCPClient(); if (!mcpClient) { return res.status(503).json({ success: false, error: 'MCP client not available' }); } const result = await mcpClient.callTool('get_epic_timeline', { epicId }); res.json({ success: true, data: result, timestamp: new Date().toISOString() }); } catch (error) { console.error('Error fetching epic timeline:', error); res.status(500).json({ success: false, error: 'Failed to fetch epic timeline', message: (error as Error).message }); } }); // Get epic stories router.get('/epics/:epicId/stories', async (req: Request, res: Response) => { try { const { epicId } = req.params; const { status } = req.query; const mcpClient = getMCPClient(); if (!mcpClient) { return res.status(503).json({ success: false, error: 'MCP client not available' }); } const params: any = { epicId }; if (status) params.status = status as string; const result = await mcpClient.callTool('get_epic_stories', params); res.json({ success: true, data: result, timestamp: new Date().toISOString() }); } catch (error) { console.error('Error fetching epic stories:', error); res.status(500).json({ success: false, error: 'Failed to fetch epic stories', message: (error as Error).message }); } }); // Validate epic requirements router.get('/epics/:epicId/validate', async (req: Request, res: Response) => { try { const { epicId } = req.params; const mcpClient = getMCPClient(); if (!mcpClient) { return res.status(503).json({ success: false, error: 'MCP client not available' }); } const result = await mcpClient.callTool('validate_epic_requirements', { epicId }); res.json({ success: true, data: result, timestamp: new Date().toISOString() }); } catch (error) { console.error('Error validating epic requirements:', error); res.status(500).json({ success: false, error: 'Failed to validate epic requirements', message: (error as Error).message }); } }); // Generate epic report router.get('/epics/:epicId/report', async (req: Request, res: Response) => { try { const { epicId } = req.params; const mcpClient = getMCPClient(); if (!mcpClient) { return res.status(503).json({ success: false, error: 'MCP client not available' }); } const result = await mcpClient.callTool('generate_epic_report', { epicId }); res.json({ success: true, data: result, timestamp: new Date().toISOString() }); } catch (error) { console.error('Error generating epic report:', error); res.status(500).json({ success: false, error: 'Failed to generate epic report', message: (error as Error).message }); } }); // Generate epic burndown router.get('/epics/:epicId/burndown', async (req: Request, res: Response) => { try { const { epicId } = req.params; const mcpClient = getMCPClient(); if (!mcpClient) { return res.status(503).json({ success: false, error: 'MCP client not available' }); } const result = await mcpClient.callTool('generate_epic_burndown', { epicId }); res.json({ success: true, data: result, timestamp: new Date().toISOString() }); } catch (error) { console.error('Error generating epic burndown:', error); res.status(500).json({ success: false, error: 'Failed to generate epic burndown', message: (error as Error).message }); } }); // Close epic router.post('/epics/:epicId/close', async (req: Request, res: Response) => { try { const { epicId } = req.params; const { completionNotes, businessValueRealized, closedBy } = req.body; const mcpClient = getMCPClient(); if (!mcpClient) { return res.status(503).json({ success: false, error: 'MCP client not available' }); } const result = await mcpClient.callTool('close_epic', { epicId, completionNotes, businessValueRealized, closedBy }); res.json({ success: true, data: result, timestamp: new Date().toISOString() }); } catch (error) { console.error('Error closing epic:', error); res.status(500).json({ success: false, error: 'Failed to close epic', message: (error as Error).message }); } }); // Generate sprint report router.get('/sprints/:sprintId/report', async (req: Request, res: Response) => { try { const { sprintId } = req.params; const mcpClient = getMCPClient(); if (!mcpClient) { return res.status(503).json({ success: false, error: 'MCP client not available' }); } const result = await mcpClient.callTool('generate_sprint_report', { sprintId }); res.json({ success: true, data: result, timestamp: new Date().toISOString() }); } catch (error) { console.error('Error generating sprint report:', error); res.status(500).json({ success: false, error: 'Failed to generate sprint report', message: (error as Error).message }); } }); // Get team velocity trend router.get('/analytics/velocity-trend', async (req: Request, res: Response) => { try { const { numberOfSprints = 5 } = req.query; const mcpClient = getMCPClient(); if (!mcpClient) { return res.status(503).json({ success: false, error: 'MCP client not available' }); } const result = await mcpClient.callTool('get_team_velocity_trend', { numberOfSprints: Number(numberOfSprints) }); res.json({ success: true, data: result, timestamp: new Date().toISOString() }); } catch (error) { console.error('Error fetching velocity trend:', error); res.status(500).json({ success: false, error: 'Failed to fetch velocity trend', message: (error as Error).message }); } }); // Get cycle time metrics router.get('/analytics/cycle-time', async (req: Request, res: Response) => { try { const { start, end } = req.query; const mcpClient = getMCPClient(); if (!mcpClient) { return res.status(503).json({ success: false, error: 'MCP client not available' }); } const params: any = {}; if (start && end) { params.dateRange = { start: start as string, end: end as string }; } const result = await mcpClient.callTool('get_cycle_time_metrics', params); res.json({ success: true, data: result, timestamp: new Date().toISOString() }); } catch (error) { console.error('Error fetching cycle time metrics:', error); res.status(500).json({ success: false, error: 'Failed to fetch cycle time metrics', message: (error as Error).message }); } }); // Generate retrospective template router.post('/sprints/:sprintId/retrospective', async (req: Request, res: Response) => { try { const { sprintId } = req.params; const { templateType = 'starfish' } = req.body; const mcpClient = getMCPClient(); if (!mcpClient) { return res.status(503).json({ success: false, error: 'MCP client not available' }); } const result = await mcpClient.callTool('generate_retrospective_template', { sprintId, templateType }); res.json({ success: true, data: result, timestamp: new Date().toISOString() }); } catch (error) { console.error('Error generating retrospective template:', error); res.status(500).json({ success: false, error: 'Failed to generate retrospective template', message: (error as Error).message }); } }); // Get cross-sprint analytics router.get('/analytics/cross-sprint', async (req: Request, res: Response) => { try { const { numberOfSprints = 5 } = req.query; const mcpClient = getMCPClient(); if (!mcpClient) { return res.status(503).json({ success: false, error: 'MCP client not available' }); } const result = await mcpClient.callTool('get_cross_sprint_analytics', { numberOfSprints: Number(numberOfSprints) }); res.json({ success: true, data: result, timestamp: new Date().toISOString() }); } catch (error) { console.error('Error fetching cross-sprint analytics:', error); res.status(500).json({ success: false, error: 'Failed to fetch cross-sprint analytics', message: (error as Error).message }); } }); // Get dependency report router.get('/analytics/dependencies', async (req: Request, res: Response) => { try { const { includeResolved = false } = req.query; const mcpClient = getMCPClient(); if (!mcpClient) { return res.status(503).json({ success: false, error: 'MCP client not available' }); } const result = await mcpClient.callTool('get_dependency_report', { includeResolved: includeResolved === 'true' }); res.json({ success: true, data: result, timestamp: new Date().toISOString() }); } catch (error) { console.error('Error fetching dependency report:', error); res.status(500).json({ success: false, error: 'Failed to fetch dependency report', message: (error as Error).message }); } }); export default router;