UNPKG

@spaik/mcp-server-roi

Version:

MCP server for AI ROI prediction and tracking with Monte Carlo simulations

339 lines 15.4 kB
import { z } from 'zod'; import { createLogger } from '../utils/logger.js'; /** * Response Transformer Service * * Transforms raw tool outputs into semantic-rich, multi-layered responses * optimized for AI agent consumption. */ // Schema for transformed responses export const TransformedResponseSchema = z.object({ executive_summary: z.object({ headline: z.string(), confidence: z.enum(['low', 'medium', 'high']), key_insight: z.string(), primary_metric: z.string().optional() }), insights: z.object({ primary: z.array(z.string()).describe('Top 3-5 key insights'), risks: z.array(z.string()).describe('Key risk factors'), opportunities: z.array(z.string()).describe('Growth opportunities'), patterns: z.array(z.string()).optional().describe('Detected patterns across data') }), recommendations: z.object({ next_action: z.string(), timeline: z.string(), success_criteria: z.string(), prerequisites: z.array(z.string()).optional(), alternatives: z.array(z.object({ action: z.string(), tradeoff: z.string() })).optional() }), narrative: z.object({ context: z.string().describe('Business context and background'), analysis: z.string().describe('Detailed analysis narrative'), conclusion: z.string().describe('Summary and next steps') }).optional(), detailed_analysis: z.any().describe('Original detailed data'), metadata: z.object({ confidence_score: z.number().min(0).max(1), data_quality: z.enum(['low', 'medium', 'high']), assumptions_impact: z.enum(['low', 'medium', 'high']), generated_at: z.string().datetime(), response_version: z.string().default('2.0'), tool_name: z.string(), processing_time_ms: z.number().optional() }) }); export class ResponseTransformer { logger = createLogger({ component: 'ResponseTransformer' }); /** * Transform predict_roi tool response */ async transformPredictROI(response) { const startTime = Date.now(); try { const { summary, financial_metrics, use_cases, metadata } = response; // Generate executive summary const executiveSummary = this.generateExecutiveSummary(summary); // Extract insights const insights = this.extractROIInsights(summary, financial_metrics, use_cases); // Generate recommendations const recommendations = this.generateROIRecommendations(summary, use_cases, insights.primary); // Create narrative (optional for now) const narrative = this.generateROINarrative(summary, insights); // Calculate metadata const responseMetadata = this.calculateMetadata('predict_roi', metadata, startTime); return { executive_summary: executiveSummary, insights, recommendations, narrative, detailed_analysis: response, metadata: responseMetadata }; } catch (error) { this.logger.error('Failed to transform predict_roi response', error); throw error; } } /** * Transform compare_projects tool response */ async transformCompareProjects(response) { const startTime = Date.now(); try { const { projects, rankings, insights, recommendations } = response; // Generate executive summary const executiveSummary = this.generateComparativeExecutiveSummary(projects, rankings, insights); // Enhance existing insights const enhancedInsights = this.enhanceComparativeInsights(insights, projects); // Structure recommendations const structuredRecommendations = this.structureComparativeRecommendations(recommendations, insights); // Generate narrative const narrative = this.generateComparativeNarrative(projects, rankings); // Calculate metadata const responseMetadata = this.calculateMetadata('compare_projects', response.metadata, startTime); return { executive_summary: executiveSummary, insights: enhancedInsights, recommendations: structuredRecommendations, narrative, detailed_analysis: response, metadata: responseMetadata }; } catch (error) { this.logger.error('Failed to transform compare_projects response', error); throw error; } } // Private helper methods generateExecutiveSummary(summary) { const roi = summary.expected_roi; const payback = summary.payback_period_months; let confidence = 'medium'; let headline = ''; if (roi > 200 && payback < 12) { confidence = 'high'; headline = `Exceptional ROI opportunity with ${roi.toFixed(0)}% return in ${payback} months`; } else if (roi > 100 && payback < 18) { confidence = 'high'; headline = `Strong ROI potential of ${roi.toFixed(0)}% with ${payback}-month payback`; } else if (roi > 50) { confidence = 'medium'; headline = `Solid investment case with ${roi.toFixed(0)}% ROI over 5 years`; } else { confidence = 'low'; headline = `Moderate returns expected with ${roi.toFixed(0)}% ROI`; } const key_insight = this.generateKeyInsight(summary, payback); const primary_metric = `$${(summary.net_present_value / 1000).toFixed(0)}K NPV`; return { headline, confidence, key_insight, primary_metric }; } generateKeyInsight(summary, payback) { if (payback <= 6) { return 'Rapid payback enables quick reinvestment in additional AI initiatives'; } else if (payback <= 12) { return 'Sub-year payback provides strong business case for immediate implementation'; } else if (payback <= 24) { return 'Investment timeline aligns well with typical enterprise planning cycles'; } else { return 'Long-term value creation requires sustained commitment and phased approach'; } } extractROIInsights(summary, financial_metrics, use_cases) { const insights = { primary: [], risks: [], opportunities: [], patterns: [] }; // Analyze use case distribution const categories = use_cases.reduce((acc, uc) => { acc[uc.category] = (acc[uc.category] || 0) + uc.monthly_benefit; return acc; }, {}); const topCategory = Object.entries(categories) .sort(([, a], [, b]) => b - a)[0]; if (topCategory) { insights.primary.push(`${topCategory[0]} use cases drive ${((topCategory[1] / summary.total_investment) * 100).toFixed(0)}% of total value`); } // ROI insights if (summary.expected_roi > 150) { insights.primary.push('ROI exceeds typical enterprise hurdle rates by 3-5x'); } // Payback insights if (summary.payback_period_months < 12) { insights.primary.push('Quick payback reduces financial risk and enables rapid scaling'); } // Risk factors if (summary.payback_period_months > 24) { insights.risks.push('Extended payback period increases execution risk'); } if (use_cases.length > 5) { insights.risks.push('Multiple concurrent use cases may strain implementation resources'); } // Opportunities insights.opportunities.push('Consider phased rollout to capture quick wins first'); if (summary.expected_roi > 100) { insights.opportunities.push('High ROI justifies accelerated timeline with additional resources'); } return insights; } generateROIRecommendations(summary, use_cases, primaryInsights) { // Sort use cases by benefit const sortedUseCases = [...use_cases].sort((a, b) => b.monthly_benefit - a.monthly_benefit); const topUseCase = sortedUseCases[0]; let next_action = ''; let timeline = ''; let success_criteria = ''; if (summary.payback_period_months <= 12) { next_action = `Launch pilot program for ${topUseCase.name}`; timeline = 'Begin within 30 days'; success_criteria = `Achieve ${(topUseCase.monthly_benefit * 0.7).toFixed(0)} monthly benefit within 90 days`; } else { next_action = 'Conduct detailed feasibility study for top 3 use cases'; timeline = 'Complete within 60 days'; success_criteria = 'Validate assumptions and refine implementation plan'; } return { next_action, timeline, success_criteria, prerequisites: [ 'Secure executive sponsorship', 'Allocate dedicated project team', 'Establish success metrics baseline' ] }; } generateROINarrative(summary, insights) { const context = `This AI investment analysis evaluates a total investment of $${(summary.total_investment / 1000).toFixed(0)}K ` + `with projected returns of ${summary.expected_roi.toFixed(0)}% over 5 years.`; const analysis = `The financial analysis reveals a ${summary.payback_period_months}-month payback period ` + `with a net present value of $${(summary.net_present_value / 1000).toFixed(0)}K. ` + insights.primary.join('. ') + '.'; const conclusion = `Based on the analysis, this investment presents a ${summary.expected_roi > 100 ? 'compelling' : 'solid'} opportunity with ${summary.payback_period_months <= 18 ? 'rapid' : 'reasonable'} time to value. ` + `Key success factors include focused execution and phased implementation.`; return { context, analysis, conclusion }; } generateComparativeExecutiveSummary(projects, rankings, insights) { const topProject = projects.find(p => p.id === rankings.by_roi[0].project_id); const confidence = this.assessComparativeConfidence(projects); const headline = insights.best_overall ? `${insights.best_overall} emerges as the optimal choice across multiple dimensions` : `Portfolio analysis reveals diverse strengths across ${projects.length} projects`; const key_insight = this.extractTopComparativeInsight(projects, rankings); return { headline, confidence, key_insight, primary_metric: topProject ? `Top ROI: ${topProject.financial_summary.expected_roi.toFixed(0)}%` : undefined }; } enhanceComparativeInsights(existingInsights, projects) { const insights = { primary: [], risks: [], opportunities: [], patterns: [] }; // Add existing insights if (existingInsights.best_overall) { insights.primary.push(`${existingInsights.best_overall} offers the best overall value`); } if (existingInsights.quickest_payback) { insights.primary.push(`${existingInsights.quickest_payback} provides fastest time to value`); } // Analyze patterns const avgROI = projects.reduce((sum, p) => sum + p.financial_summary.expected_roi, 0) / projects.length; insights.patterns.push(`Portfolio average ROI: ${avgROI.toFixed(0)}%`); // Risk analysis if (existingInsights.highest_risk) { insights.risks.push(`${existingInsights.highest_risk} requires careful risk management`); } // Opportunities from synergies if (existingInsights.synergies && existingInsights.synergies.length > 0) { insights.opportunities.push('Synergy opportunities identified between projects'); } return insights; } structureComparativeRecommendations(recommendations, insights) { const next_action = recommendations[0] || 'Prioritize projects based on strategic alignment'; return { next_action, timeline: 'Review within 2 weeks', success_criteria: 'Select 1-2 projects for immediate implementation', alternatives: recommendations.slice(1, 3).map(rec => ({ action: rec, tradeoff: 'May require different resource allocation' })) }; } generateComparativeNarrative(projects, rankings) { const context = `This analysis compares ${projects.length} AI investment opportunities ` + `to identify optimal resource allocation strategies.`; const analysis = `Projects range from ${Math.min(...projects.map(p => p.financial_summary.total_investment)) / 1000}K to ${Math.max(...projects.map(p => p.financial_summary.total_investment)) / 1000}K in investment with ROIs between ${Math.min(...projects.map(p => p.financial_summary.expected_roi))}% and ${Math.max(...projects.map(p => p.financial_summary.expected_roi))}%.`; const conclusion = 'Portfolio approach enables risk diversification while maximizing overall returns.'; return { context, analysis, conclusion }; } calculateMetadata(toolName, originalMetadata, startTime) { return { confidence_score: originalMetadata?.confidence_level || 0.85, data_quality: this.assessDataQuality(originalMetadata), assumptions_impact: 'medium', // Could be calculated based on variance generated_at: new Date().toISOString(), response_version: '2.0', tool_name: toolName, processing_time_ms: Date.now() - startTime }; } assessDataQuality(metadata) { if (!metadata) return 'medium'; if (metadata.calculated_with_benchmarks && metadata.confidence_level > 0.9) { return 'high'; } if (metadata.confidence_level < 0.7) { return 'low'; } return 'medium'; } assessComparativeConfidence(projects) { if (projects.length >= 3 && projects.every(p => p.ml_insights)) { return 'high'; } if (projects.length >= 2) { return 'medium'; } return 'low'; } extractTopComparativeInsight(projects, rankings) { const roiSpread = Math.max(...projects.map(p => p.financial_summary.expected_roi)) - Math.min(...projects.map(p => p.financial_summary.expected_roi)); if (roiSpread > 100) { return 'Significant ROI variance suggests careful project selection critical'; } else if (roiSpread < 30) { return 'Similar ROI profiles indicate selection should focus on strategic fit'; } else { return 'Balanced portfolio approach recommended for risk mitigation'; } } } // Export singleton instance export const responseTransformer = new ResponseTransformer(); //# sourceMappingURL=response-transformer.js.map