UNPKG

@spaik/mcp-server-roi

Version:

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

180 lines 9.3 kB
import { FinancialCalculator } from './financial.js'; import { FINANCIAL_CONSTANTS } from './financial-utils.js'; import { createLogger } from '../../utils/logger.js'; export class ROIEngine { calculator; config; constructor(config) { this.calculator = new FinancialCalculator(); this.config = { defaultDiscountRate: FINANCIAL_CONSTANTS.DEFAULT_DISCOUNT_RATE, implementationMonths: FINANCIAL_CONSTANTS.DEFAULT_IMPLEMENTATION_MONTHS, rampUpMonths: FINANCIAL_CONSTANTS.DEFAULT_RAMP_UP_MONTHS, confidenceMultipliers: { conservative: 0.7, expected: 1.0, optimistic: 1.3 }, ...config }; } /** * Calculate ROI projection from use cases * * Note on development hours: * - If implementationCosts.development_hours > 0: Assumes this is the total for the entire project * - If implementationCosts.development_hours = 0: Sums up individual use case development hours * - This prevents double-counting when project-level hours already include use case work */ calculateProjection(projectId, useCases, implementationCosts, timelineMonths, scenarioName = 'Base Case') { // Aggregate benefits from all use cases const aggregatedMetrics = this.aggregateUseCaseMetrics(useCases); // Calculate financial metrics for each confidence level const financialMetrics = { conservative: this.calculateFinancialMetrics(aggregatedMetrics, this.config.confidenceMultipliers.conservative), expected: this.calculateFinancialMetrics(aggregatedMetrics, this.config.confidenceMultipliers.expected), optimistic: this.calculateFinancialMetrics(aggregatedMetrics, this.config.confidenceMultipliers.optimistic) }; // Use expected case for main calculations const totalInvestment = this.calculateTotalInvestment(implementationCosts, useCases); const monthlyBenefit = financialMetrics.expected.total_monthly_benefit; // Generate cash flows const cashFlows = this.calculator.generateCashFlows(totalInvestment, monthlyBenefit, timelineMonths, this.config.implementationMonths, this.config.rampUpMonths, implementationCosts.ongoing_monthly); // Calculate ROI metrics const calculations = { total_investment: totalInvestment, net_present_value: this.calculator.calculateNPV(cashFlows, this.config.defaultDiscountRate), internal_rate_of_return: this.calculator.calculateIRR(cashFlows), payback_period_months: this.calculator.calculatePaybackPeriod(cashFlows), five_year_roi: this.calculator.calculate5YearROI(totalInvestment, monthlyBenefit, implementationCosts.ongoing_monthly), break_even_date: this.calculator.calculateBreakEvenDate(new Date(), this.calculator.calculatePaybackPeriod(cashFlows)).toISOString() }; // Generate assumptions const assumptions = this.generateAssumptions(useCases, implementationCosts); return { project_id: projectId, scenario_name: scenarioName, metadata: { confidence_level: 0.95, assumptions }, implementation_costs: implementationCosts, timeline_months: timelineMonths, financial_metrics: financialMetrics, calculations }; } aggregateUseCaseMetrics(useCases) { const metrics = { monthly_cost_savings: 0, monthly_time_savings_hours: 0, quality_improvement_value: 0, revenue_uplift: 0, total_monthly_benefit: 0 }; for (const useCase of useCases) { const { current_state, future_state } = useCase; // Time savings const timeSavingsHours = current_state.process_time_hours * current_state.volume_per_month * future_state.time_reduction_percentage; metrics.monthly_time_savings_hours += timeSavingsHours; // Cost savings (including labor cost from time savings) const laborCostSavings = timeSavingsHours * FINANCIAL_CONSTANTS.DEFAULT_HOURLY_RATE; const processCostSavings = current_state.cost_per_transaction * current_state.volume_per_month * future_state.automation_percentage; metrics.monthly_cost_savings += laborCostSavings + processCostSavings; // Quality improvements (reduction in error costs) // Note: ERROR_COST_MULTIPLIER is applied to the error rate, not the entire volume const errorVolume = current_state.volume_per_month * current_state.error_rate; const errorCostReduction = current_state.cost_per_transaction * errorVolume * future_state.error_reduction_percentage * FINANCIAL_CONSTANTS.ERROR_COST_MULTIPLIER; metrics.quality_improvement_value += errorCostReduction; // Revenue uplift from scalability const scalabilityBenefit = current_state.cost_per_transaction * current_state.volume_per_month * (future_state.scalability_factor - 1) * FINANCIAL_CONSTANTS.SCALABILITY_PROFIT_MARGIN; metrics.revenue_uplift += scalabilityBenefit; } metrics.total_monthly_benefit = metrics.monthly_cost_savings + metrics.quality_improvement_value + metrics.revenue_uplift; // Log aggregated metrics for debugging createLogger({ component: 'ROIEngine' }).debug('Aggregated use case metrics', { use_case_count: useCases.length, monthly_cost_savings: metrics.monthly_cost_savings, quality_improvement_value: metrics.quality_improvement_value, revenue_uplift: metrics.revenue_uplift, total_monthly_benefit: metrics.total_monthly_benefit }); return metrics; } calculateFinancialMetrics(baseMetrics, confidenceMultiplier) { return { monthly_cost_savings: baseMetrics.monthly_cost_savings * confidenceMultiplier, monthly_time_savings_hours: baseMetrics.monthly_time_savings_hours * confidenceMultiplier, quality_improvement_value: baseMetrics.quality_improvement_value * confidenceMultiplier, revenue_uplift: baseMetrics.revenue_uplift * confidenceMultiplier, total_monthly_benefit: baseMetrics.total_monthly_benefit * confidenceMultiplier }; } calculateTotalInvestment(implementationCosts, useCases) { // Check if development_hours is project-level or already includes use case hours // If development_hours is 0 or undefined, assume use case hours are separate const projectLevelDevelopmentCost = implementationCosts.development_hours * FINANCIAL_CONSTANTS.DEFAULT_DEVELOPER_HOURLY_RATE; // Only add use case development hours if they're not already included in project development_hours let useCaseDevelopmentCost = 0; if (implementationCosts.development_hours === 0) { // If no project-level hours specified, sum up use case hours useCaseDevelopmentCost = useCases.reduce((total, uc) => total + uc.implementation.development_hours * FINANCIAL_CONSTANTS.DEFAULT_DEVELOPER_HOURLY_RATE, 0); } // Note: If development_hours > 0, we assume it includes all development work return (implementationCosts.software_licenses + projectLevelDevelopmentCost + implementationCosts.training_costs + implementationCosts.infrastructure + useCaseDevelopmentCost); } generateAssumptions(useCases, costs) { const assumptions = [ { category: 'Implementation', description: `${this.config.implementationMonths} months for initial deployment`, impact: 'high' }, { category: 'Adoption', description: `${this.config.rampUpMonths} months to reach full utilization`, impact: 'medium' }, { category: 'Labor Cost', description: `Assumed $${FINANCIAL_CONSTANTS.DEFAULT_HOURLY_RATE}/hour for time savings calculations`, impact: 'medium' } ]; if (costs.ongoing_monthly > 0) { assumptions.push({ category: 'Operating Costs', description: `$${costs.ongoing_monthly.toLocaleString()} monthly ongoing costs`, impact: 'medium' }); } // Add use case specific assumptions const avgComplexity = useCases.reduce((sum, uc) => sum + uc.implementation.complexity_score, 0) / useCases.length; if (avgComplexity > 7) { assumptions.push({ category: 'Complexity', description: 'High implementation complexity may extend timeline', impact: 'high' }); } return assumptions; } } //# sourceMappingURL=roi-engine.js.map