@boundless-oss/atlas
Version:
Atlas - MCP Server for comprehensive startup project management
387 lines • 11.9 kB
JavaScript
import { Router } 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, res) => {
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.message
});
}
});
// Get epic timeline
router.get('/epics/:epicId/timeline', async (req, res) => {
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.message
});
}
});
// Get epic stories
router.get('/epics/:epicId/stories', async (req, res) => {
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 = { epicId };
if (status)
params.status = status;
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.message
});
}
});
// Validate epic requirements
router.get('/epics/:epicId/validate', async (req, res) => {
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.message
});
}
});
// Generate epic report
router.get('/epics/:epicId/report', async (req, res) => {
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.message
});
}
});
// Generate epic burndown
router.get('/epics/:epicId/burndown', async (req, res) => {
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.message
});
}
});
// Close epic
router.post('/epics/:epicId/close', async (req, res) => {
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.message
});
}
});
// Generate sprint report
router.get('/sprints/:sprintId/report', async (req, res) => {
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.message
});
}
});
// Get team velocity trend
router.get('/analytics/velocity-trend', async (req, res) => {
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.message
});
}
});
// Get cycle time metrics
router.get('/analytics/cycle-time', async (req, res) => {
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 = {};
if (start && end) {
params.dateRange = {
start: start,
end: end
};
}
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.message
});
}
});
// Generate retrospective template
router.post('/sprints/:sprintId/retrospective', async (req, res) => {
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.message
});
}
});
// Get cross-sprint analytics
router.get('/analytics/cross-sprint', async (req, res) => {
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.message
});
}
});
// Get dependency report
router.get('/analytics/dependencies', async (req, res) => {
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.message
});
}
});
export default router;
//# sourceMappingURL=agile-analytics.js.map