UNPKG

strategic-intelligence-mcp

Version:

Strategic Intelligence MCP Server - connecting technical progress to business outcomes with systematic strategic planning

645 lines 28.3 kB
import { StrategicReporting } from '../reporting/strategicReporting.js'; import { TechnicalMilestoneTracker } from '../intelligence/technicalMilestoneTracker.js'; export class ReportingTools { storage; reporting; milestoneTracker; constructor(storage) { this.storage = storage; this.reporting = new StrategicReporting(); this.milestoneTracker = new TechnicalMilestoneTracker(storage); } async generateStrategicReport(params) { try { // Gather data from storage const data = await this.storage.load(); // Load milestones from milestone tracker await this.milestoneTracker.loadMilestones(); const milestones = this.milestoneTracker.getAllMilestones(); // Convert Record structures to arrays for report processing const reportData = { milestones: milestones, goals: data.goals ? Object.values(data.goals) : [], conversations: data.conversations ? Object.values(data.conversations) : [], forecasts: data.forecasts || [], competitiveIntel: data.competitiveIntel, strategyGaps: data.strategyGaps || [], reviews: data.reviews || [], collaborations: data.collaborationSessions || [] }; const report = await this.reporting.generateReport({ type: params.type, templateId: params.templateId, period: { start: params.periodStart, end: params.periodEnd }, data: reportData, options: params.options }); return { success: true, data: { report, sections: report.sections.length, visualizations: report.sections.reduce((sum, s) => sum + (s.visualizations?.length || 0), 0), tables: report.sections.reduce((sum, s) => sum + (s.tables?.length || 0), 0), exportPath: report.exportPath } }; } catch (error) { return { success: false, error: `Failed to generate report: ${error instanceof Error ? error.message : 'Unknown error'}` }; } } async getStrategicReport(params) { try { const report = this.reporting.getReport(params.reportId); if (!report) { throw new Error('Report not found'); } return { success: true, data: { report, metadata: { sectionCount: report.sections.length, visualizationCount: report.sections.reduce((sum, s) => sum + (s.visualizations?.length || 0), 0), tableCount: report.sections.reduce((sum, s) => sum + (s.tables?.length || 0), 0) } } }; } catch (error) { return { success: false, error: `Failed to get report: ${error instanceof Error ? error.message : 'Unknown error'}` }; } } async listStrategicReports(params) { try { const reports = this.reporting.getReports(params); const reportSummaries = reports.map(report => ({ id: report.id, title: report.title, type: report.type, generated: report.generated, period: report.period, format: report.format, confidentiality: report.metadata.confidentiality, sections: report.sections.length })); return { success: true, data: { reports: reportSummaries, summary: { total: reports.length, byType: this.groupReportsByType(reports), byConfidentiality: this.groupReportsByConfidentiality(reports) } } }; } catch (error) { return { success: false, error: `Failed to list reports: ${error instanceof Error ? error.message : 'Unknown error'}` }; } } async getReportTemplates() { try { const templates = this.reporting.getTemplates(); return { success: true, data: { templates, summary: { total: templates.length, byType: this.groupTemplatesByType(templates) } } }; } catch (error) { return { success: false, error: `Failed to get templates: ${error instanceof Error ? error.message : 'Unknown error'}` }; } } async generateQuickInsights(params) { try { const data = await this.storage.load(); // Load milestones from milestone tracker await this.milestoneTracker.loadMilestones(); const milestones = this.milestoneTracker.getAllMilestones(); const endDate = new Date(); const startDate = new Date(); switch (params.timeframe) { case '7-days': startDate.setDate(startDate.getDate() - 7); break; case '30-days': startDate.setDate(startDate.getDate() - 30); break; case '90-days': startDate.setDate(startDate.getDate() - 90); break; } const insights = { timeframe: params.timeframe, period: { start: startDate.toISOString(), end: endDate.toISOString() }, milestoneProgress: this.calculateMilestoneProgress(milestones, startDate, endDate), goalHealth: this.calculateGoalHealth(data.goals ? Object.values(data.goals) : []), strategicHighlights: this.extractStrategicHighlights(data, startDate, endDate), criticalIssues: this.identifyCriticalIssues(data), upcomingMilestones: this.getUpcomingMilestones(milestones), recommendations: this.generateQuickRecommendations(data) }; return { success: true, data: insights }; } catch (error) { return { success: false, error: `Failed to generate quick insights: ${error instanceof Error ? error.message : 'Unknown error'}` }; } } async exportReportData(params) { try { if (params.reportId) { const report = this.reporting.getReport(params.reportId); if (!report) { throw new Error('Report not found'); } const exportData = this.prepareExportData(report, params.format, params.includeRawData); return { success: true, data: { format: params.format, content: exportData, report: report } }; } else { // Export all current data const data = await this.storage.load(); // Load milestones from milestone tracker await this.milestoneTracker.loadMilestones(); const milestones = this.milestoneTracker.getAllMilestones(); // Create data object with milestones for export const dataWithMilestones = { ...data, milestones: milestones }; const exportData = this.prepareAllDataExport(dataWithMilestones, params.format); return { success: true, data: { format: params.format, content: exportData, summary: { conversations: data.conversations?.length || 0, goals: data.goals?.length || 0, milestones: milestones?.length || 0, insights: data.insights?.length || 0 } } }; } } catch (error) { return { success: false, error: `Failed to export data: ${error instanceof Error ? error.message : 'Unknown error'}` }; } } async generateDashboardMetrics(params) { try { const data = await this.storage.load(); const goals = data.goals ? Object.values(data.goals) : []; const milestones = data.milestones ? Object.values(data.milestones) : []; const conversations = data.conversations ? Object.values(data.conversations) : []; const metrics = { overview: { activeGoals: goals.filter((g) => g.status === 'active').length, completedMilestones: milestones.filter((m) => m.status === 'completed').length, strategicDecisions: conversations.reduce((sum, c) => sum + (c.decisions?.length || 0), 0), actionItems: conversations.reduce((sum, c) => sum + (c.actionItems?.length || 0), 0) }, trends: { goalCompletionRate: this.calculateCompletionRate(goals), milestoneVelocity: this.calculateMilestoneVelocity(milestones), decisionFrequency: this.calculateDecisionFrequency(conversations), confidenceTrend: this.calculateConfidenceTrend(goals) }, health: { overallHealth: this.calculateOverallHealth(data), riskLevel: this.assessRiskLevel(data), opportunityScore: this.calculateOpportunityScore(data), alignmentScore: this.calculateAlignmentScore(data) }, projections: { revenueProjection: this.projectRevenue(data), goalCompletionProjection: this.projectGoalCompletion(goals), milestoneCompletionProjection: this.projectMilestoneCompletion(milestones) } }; return { success: true, data: metrics }; } catch (error) { return { success: false, error: `Failed to generate dashboard metrics: ${error instanceof Error ? error.message : 'Unknown error'}` }; } } // Helper methods groupReportsByType(reports) { return reports.reduce((acc, report) => { acc[report.type] = (acc[report.type] || 0) + 1; return acc; }, {}); } groupReportsByConfidentiality(reports) { return reports.reduce((acc, report) => { acc[report.metadata.confidentiality] = (acc[report.metadata.confidentiality] || 0) + 1; return acc; }, {}); } groupTemplatesByType(templates) { return templates.reduce((acc, template) => { acc[template.type] = (acc[template.type] || 0) + 1; return acc; }, {}); } calculateMilestoneProgress(milestones, startDate, endDate) { const relevantMilestones = milestones.filter((m) => { const date = new Date(m.created || m.plannedDate); return date >= startDate && date <= endDate; }); return { total: relevantMilestones.length, completed: relevantMilestones.filter((m) => m.status === 'completed').length, inProgress: relevantMilestones.filter((m) => m.status === 'in-progress').length, delayed: relevantMilestones.filter((m) => m.status === 'delayed').length, completionRate: relevantMilestones.length > 0 ? (relevantMilestones.filter((m) => m.status === 'completed').length / relevantMilestones.length) * 100 : 0 }; } calculateGoalHealth(goals) { const activeGoals = goals.filter((g) => g.status === 'active'); const avgConfidence = activeGoals.length > 0 ? activeGoals.reduce((sum, g) => sum + (g.confidence || 50), 0) / activeGoals.length : 0; return { totalGoals: goals.length, activeGoals: activeGoals.length, averageConfidence: Math.round(avgConfidence), healthyGoals: goals.filter((g) => g.confidence >= 70).length, atRiskGoals: goals.filter((g) => g.confidence < 50).length }; } extractStrategicHighlights(data, startDate, endDate) { const highlights = []; // Check milestone completions const completedMilestones = (data.milestones || []).filter((m) => m.status === 'completed' && new Date(m.completionDate) >= startDate && new Date(m.completionDate) <= endDate); if (completedMilestones.length > 0) { highlights.push(`Completed ${completedMilestones.length} technical milestones`); } // Check high-impact decisions const recentDecisions = (data.conversations || []).reduce((decisions, c) => { const conversationDecisions = (c.decisions || []).filter((d) => new Date(d.timestamp) >= startDate && new Date(d.timestamp) <= endDate); return decisions.concat(conversationDecisions); }, []); if (recentDecisions.length > 0) { highlights.push(`Made ${recentDecisions.length} strategic decisions`); } return highlights; } identifyCriticalIssues(data) { const issues = []; // Check for delayed milestones const delayedMilestones = (data.milestones || []).filter((m) => m.status === 'delayed'); if (delayedMilestones.length > 0) { issues.push(`${delayedMilestones.length} milestones are delayed`); } // Check for low confidence goals const lowConfidenceGoals = (data.goals || []).filter((g) => g.confidence < 40 && g.status === 'active'); if (lowConfidenceGoals.length > 0) { issues.push(`${lowConfidenceGoals.length} goals have critically low confidence`); } // Check for critical strategy gaps const criticalGaps = (data.strategyGaps || []).filter((g) => g.severity === 'critical'); if (criticalGaps.length > 0) { issues.push(`${criticalGaps.length} critical strategy gaps identified`); } return issues; } getUpcomingMilestones(milestones) { const upcoming = milestones .filter((m) => m.status !== 'completed' && m.plannedDate) .sort((a, b) => new Date(a.plannedDate).getTime() - new Date(b.plannedDate).getTime()) .slice(0, 5); return upcoming.map((m) => ({ name: m.name, category: m.category, plannedDate: m.plannedDate, daysUntilDue: Math.ceil((new Date(m.plannedDate).getTime() - new Date().getTime()) / (1000 * 60 * 60 * 24)) })); } generateQuickRecommendations(data) { const recommendations = []; // Check milestone velocity const inProgressMilestones = (data.milestones || []).filter((m) => m.status === 'in-progress'); if (inProgressMilestones.length > 5) { recommendations.push('Consider focusing on completing in-progress milestones before starting new ones'); } // Check goal confidence const lowConfidenceGoals = (data.goals || []).filter((g) => g.confidence < 50 && g.status === 'active'); if (lowConfidenceGoals.length > 0) { recommendations.push('Address low-confidence goals to improve overall strategic health'); } // Check for overdue action items const overdueActions = (data.conversations || []).reduce((overdue, c) => { const overdueItems = (c.actionItems || []).filter((a) => a.status !== 'completed' && new Date(a.dueDate) < new Date()); return overdue + overdueItems.length; }, 0); if (overdueActions > 0) { recommendations.push(`Review and update ${overdueActions} overdue action items`); } return recommendations; } prepareExportData(report, format, includeRawData) { switch (format) { case 'json': return includeRawData ? report : { title: report.title, type: report.type, generated: report.generated, period: report.period, sections: report.sections.map(s => ({ title: s.title, type: s.type, content: s.content })) }; case 'csv': // Convert report data to CSV format const csvData = []; csvData.push('Section,Type,Content'); report.sections.forEach(section => { csvData.push(`"${section.title}","${section.type}","${JSON.stringify(section.content).replace(/"/g, '""')}"`); }); return csvData.join('\n'); case 'markdown': // Already implemented in the reporting class return report; default: return report; } } prepareAllDataExport(data, format) { switch (format) { case 'json': return data; case 'csv': // Create multiple CSV sections const csvSections = []; // Goals if (data.goals?.length > 0) { csvSections.push('BUSINESS GOALS'); csvSections.push('Title,Category,Status,Confidence,Owner'); data.goals.forEach((g) => { csvSections.push(`"${g.title}","${g.category}","${g.status}",${g.confidence},"${g.owner}"`); }); csvSections.push(''); } // Milestones if (data.milestones?.length > 0) { csvSections.push('TECHNICAL MILESTONES'); csvSections.push('Name,Category,Status,Complexity,Planned Date'); data.milestones.forEach((m) => { csvSections.push(`"${m.name}","${m.category}","${m.status}","${m.complexity}","${m.plannedDate}"`); }); } return csvSections.join('\n'); case 'markdown': let markdown = '# Strategic Data Export\n\n'; markdown += `*Generated: ${new Date().toISOString()}*\n\n`; if (data.goals?.length > 0) { markdown += '## Business Goals\n\n'; data.goals.forEach((g) => { markdown += `### ${g.title}\n`; markdown += `- **Category**: ${g.category}\n`; markdown += `- **Status**: ${g.status}\n`; markdown += `- **Confidence**: ${g.confidence}%\n\n`; }); } if (data.milestones?.length > 0) { markdown += '## Technical Milestones\n\n'; data.milestones.forEach((m) => { markdown += `### ${m.name}\n`; markdown += `- **Category**: ${m.category}\n`; markdown += `- **Status**: ${m.status}\n`; markdown += `- **Complexity**: ${m.complexity}\n\n`; }); } return markdown; default: return data; } } calculateCompletionRate(goals) { if (goals.length === 0) return 0; const completed = goals.filter((g) => g.status === 'completed').length; return Math.round((completed / goals.length) * 100); } calculateMilestoneVelocity(milestones) { const completed = milestones.filter((m) => m.status === 'completed' && m.completionDate); if (completed.length < 2) return 0; const dates = completed.map((m) => new Date(m.completionDate).getTime()).sort(); const timeSpan = (dates[dates.length - 1] - dates[0]) / (1000 * 60 * 60 * 24 * 30); // months return Math.round(completed.length / Math.max(timeSpan, 1)); } calculateDecisionFrequency(conversations) { const totalDecisions = conversations.reduce((sum, c) => sum + (c.decisions?.length || 0), 0); if (conversations.length === 0) return 0; return Math.round(totalDecisions / conversations.length); } calculateConfidenceTrend(goals) { if (goals.length === 0) return 'stable'; const recentGoals = goals .filter((g) => g.progressHistory?.length > 0) .slice(-5); if (recentGoals.length < 2) return 'stable'; let increasingCount = 0; let decreasingCount = 0; recentGoals.forEach((g) => { const history = g.progressHistory; if (history.length >= 2) { const recent = history[history.length - 1].confidence; const previous = history[history.length - 2].confidence; if (recent > previous) increasingCount++; if (recent < previous) decreasingCount++; } }); if (increasingCount > decreasingCount) return 'improving'; if (decreasingCount > increasingCount) return 'declining'; return 'stable'; } calculateOverallHealth(data) { let healthScore = 50; // Start at neutral // Goal confidence contributes 30% const avgGoalConfidence = this.calculateGoalHealth(data.goals || []).averageConfidence; healthScore += (avgGoalConfidence - 50) * 0.3; // Milestone completion contributes 30% const milestoneCompletion = this.calculateCompletionRate(data.milestones || []); healthScore += (milestoneCompletion - 50) * 0.3; // Active conversations contribute 20% const activeConversations = (data.conversations || []).filter((c) => c.status === 'active').length; if (activeConversations > 0) healthScore += 10; // Decision making contributes 20% const recentDecisions = (data.conversations || []).reduce((sum, c) => { const recent = (c.decisions || []).filter((d) => { const daysSince = (Date.now() - new Date(d.timestamp).getTime()) / (1000 * 60 * 60 * 24); return daysSince <= 30; }); return sum + recent.length; }, 0); if (recentDecisions > 5) healthScore += 10; return Math.max(0, Math.min(100, Math.round(healthScore))); } assessRiskLevel(data) { let riskScore = 0; // Delayed milestones increase risk const delayedMilestones = (data.milestones || []).filter((m) => m.status === 'delayed').length; riskScore += delayedMilestones * 10; // Low confidence goals increase risk const lowConfidenceGoals = (data.goals || []).filter((g) => g.confidence < 40 && g.status === 'active').length; riskScore += lowConfidenceGoals * 15; // Critical strategy gaps increase risk const criticalGaps = (data.strategyGaps || []).filter((g) => g.severity === 'critical').length; riskScore += criticalGaps * 20; if (riskScore >= 60) return 'high'; if (riskScore >= 30) return 'medium'; return 'low'; } calculateOpportunityScore(data) { let score = 50; // Start neutral // Competitive opportunities if (data.competitiveIntel?.opportunityMapping?.length > 0) { score += Math.min(20, data.competitiveIntel.opportunityMapping.length * 5); } // High confidence goals const highConfidenceGoals = (data.goals || []).filter((g) => g.confidence >= 80).length; score += highConfidenceGoals * 5; // Completed milestones create opportunities const recentCompletions = (data.milestones || []).filter((m) => { if (m.status !== 'completed' || !m.completionDate) return false; const daysSince = (Date.now() - new Date(m.completionDate).getTime()) / (1000 * 60 * 60 * 24); return daysSince <= 30; }).length; score += recentCompletions * 10; return Math.min(100, score); } calculateAlignmentScore(data) { let alignmentScore = 0; let totalChecks = 0; // Check milestone-goal alignment const milestones = data.milestones || []; const goals = data.goals || []; milestones.forEach((m) => { if (m.linkedGoals?.length > 0) { alignmentScore += 1; } totalChecks += 1; }); // Check conversation-goal alignment const conversations = data.conversations || []; conversations.forEach((c) => { if (c.context?.businessGoals?.length > 0) { alignmentScore += 1; } totalChecks += 1; }); if (totalChecks === 0) return 50; return Math.round((alignmentScore / totalChecks) * 100); } projectRevenue(data) { // Simple projection based on current trajectory let baseRevenue = 0; // Use forecasts if available if (data.forecasts?.length > 0) { const latestForecast = data.forecasts[data.forecasts.length - 1]; baseRevenue = latestForecast.businessMetrics?.projectedRevenue?.realistic || 0; } // Adjust based on goal confidence const avgConfidence = this.calculateGoalHealth(data.goals || []).averageConfidence; const confidenceMultiplier = avgConfidence / 100; return Math.round(baseRevenue * confidenceMultiplier); } projectGoalCompletion(goals) { const activeGoals = goals.filter((g) => g.status === 'active'); const avgConfidence = activeGoals.length > 0 ? activeGoals.reduce((sum, g) => sum + (g.confidence || 50), 0) / activeGoals.length : 0; const projectedCompletions = Math.round(activeGoals.length * (avgConfidence / 100)); return { activeGoals: activeGoals.length, projectedCompletions, completionRate: activeGoals.length > 0 ? Math.round((projectedCompletions / activeGoals.length) * 100) : 0 }; } projectMilestoneCompletion(milestones) { const inProgress = milestones.filter((m) => m.status === 'in-progress'); const planned = milestones.filter((m) => m.status === 'planned'); // Calculate average completion rate const completed = milestones.filter((m) => m.status === 'completed').length; const total = milestones.length; const historicalRate = total > 0 ? completed / total : 0.5; const projectedCompletions = Math.round((inProgress.length + planned.length) * historicalRate); return { inProgress: inProgress.length, planned: planned.length, projectedCompletions, projectedTotal: completed + projectedCompletions }; } } //# sourceMappingURL=reportingTools.js.map