UNPKG

@spaik/mcp-server-roi

Version:

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

443 lines 19.8 kB
import { z } from 'zod'; import { IndustryCalculatorFactory } from '../services/industry-calculators.js'; import { BenchmarkAggregator } from '../services/benchmark-aggregator.js'; import { createLogger } from '../utils/logger.js'; import { ValidationError } from '../utils/errors.js'; // Natural language input schema for voice/chat interfaces export const NaturalLanguageInputSchema = z.object({ query: z.string(), context: z.object({ industry: z.string().optional(), companySize: z.string().optional(), currentChallenges: z.array(z.string()).optional() }).optional() }); // Quick assessment schema export const QuickAssessmentSchema = z.object({ client_name: z.string(), project_type: z.enum([ 'customer_service_automation', 'document_processing', 'data_analytics', 'process_automation', 'predictive_maintenance', 'fraud_detection', 'inventory_optimization', 'workforce_optimization', 'quality_control', 'compliance_automation', 'custom' ]), quick_use_cases: z.array(z.object({ name: z.string(), category: z.enum([ 'automation', 'analytics', 'customer_service', 'operations', 'sales_marketing', 'hr_recruiting', 'finance_accounting', 'custom' ]), monthly_volume: z.number().min(1), current_cost_per_unit: z.number().min(0), current_time_minutes: z.number().min(0), automation_potential: z.enum(['low', 'medium', 'high']), use_industry_benchmarks: z.boolean().default(true) })).max(10).default([]), industry: z.enum([ 'financial_services', 'healthcare', 'retail', 'manufacturing', 'technology', 'education', 'government', 'other' ]).optional(), company_size: z.enum(['small', 'medium', 'large', 'enterprise']).optional(), hourly_rate: z.number().min(20).max(500).default(50), use_industry_benchmarks: z.boolean().default(true), natural_language_input: z.string().optional(), enable_scenario_generation: z.boolean().default(true), enable_voice_mode: z.boolean().default(false), benchmark_config: z.object({ sonar_api_key: z.string().optional(), enable_real_time: z.boolean().default(false) }).optional() }); /** * Natural Language Processor for voice/chat inputs */ class NaturalLanguageProcessor { logger = createLogger({ component: 'NLProcessor' }); /** * Parse natural language input into structured use cases */ parseNaturalLanguage(input, context) { this.logger.debug('Parsing natural language input', { inputLength: input.length }); const useCases = []; // Extract numbers and units const volumeMatch = input.match(/(\d+)\s*(emails?|calls?|documents?|transactions?|items?|hours?)/gi); const timeMatch = input.match(/(\d+)\s*(minutes?|mins?|hours?|hrs?)/gi); const costMatch = input.match(/\$?(\d+\.?\d*)\s*(per|each|\/)/gi); // Identify automation type const automationKeywords = { high: ['automate', 'eliminate', 'replace', 'fully'], medium: ['assist', 'help', 'reduce', 'improve'], low: ['monitor', 'track', 'report', 'analyze'] }; let automationPotential = 'medium'; for (const [level, keywords] of Object.entries(automationKeywords)) { if (keywords.some(keyword => input.toLowerCase().includes(keyword))) { automationPotential = level; break; } } // Identify use case category const categoryKeywords = { customer_service: ['customer', 'support', 'help desk', 'inquiry', 'complaint'], operations: ['process', 'workflow', 'operation', 'procedure'], analytics: ['analyze', 'report', 'insight', 'data', 'metrics'], automation: ['automate', 'task', 'manual', 'repetitive'] }; let category = 'automation'; for (const [cat, keywords] of Object.entries(categoryKeywords)) { if (keywords.some(keyword => input.toLowerCase().includes(keyword))) { category = cat; break; } } // Extract values const volume = volumeMatch ? parseInt(volumeMatch[0].match(/\d+/)[0]) : 1000; const time = timeMatch ? this.parseTimeToMinutes(timeMatch[0]) : 15; const cost = costMatch ? parseFloat(costMatch[0].match(/\d+\.?\d*/)[0]) : 5; // Generate use case name const name = this.generateUseCaseName(input, category); useCases.push({ name, category, volume, currentCost: cost, currentTime: time, automationPotential }); return useCases; } parseTimeToMinutes(timeStr) { const match = timeStr.match(/(\d+)\s*(minutes?|mins?|hours?|hrs?)/i); if (!match) return 15; const value = parseInt(match[1]); const unit = match[2].toLowerCase(); if (unit.includes('hour') || unit.includes('hr')) { return value * 60; } return value; } generateUseCaseName(input, category) { // Extract key action words const actionWords = ['process', 'handle', 'manage', 'analyze', 'automate', 'optimize']; const foundAction = actionWords.find(word => input.toLowerCase().includes(word)) || 'Process'; // Extract object words const objectMatch = input.match(/(emails?|calls?|documents?|transactions?|requests?|applications?|orders?)/i); const object = objectMatch ? objectMatch[0] : category; return `${foundAction.charAt(0).toUpperCase() + foundAction.slice(1)} ${object}`; } } /** * Quick assessment with industry-specific calculations */ export async function quickAssessment(input) { const logger = createLogger({ tool: 'quick_assessment' }); logger.info('Starting quick assessment', { client: input.client_name, project_type: input.project_type, use_case_count: input.quick_use_cases?.length, industry: input.industry, natural_language: !!input.natural_language_input }); try { // Validate input const validatedInput = QuickAssessmentSchema.parse(input); // Process natural language input if provided let useCases = validatedInput.quick_use_cases; if (validatedInput.natural_language_input) { const nlProcessor = new NaturalLanguageProcessor(); const parsedCases = nlProcessor.parseNaturalLanguage(validatedInput.natural_language_input, { industry: validatedInput.industry, companySize: validatedInput.company_size }); // Convert parsed cases to match the expected format const convertedCases = parsedCases.map(pc => ({ name: pc.name, category: pc.category, monthly_volume: pc.volume, current_cost_per_unit: pc.currentCost, current_time_minutes: pc.currentTime, automation_potential: pc.automationPotential, use_industry_benchmarks: true })); // If no use cases were provided, use the parsed ones, otherwise append if (useCases.length === 0) { useCases = convertedCases; } else { useCases = [...useCases, ...convertedCases]; } } // Ensure we have at least one use case if (useCases.length === 0) { throw new ValidationError('At least one use case is required. Provide either quick_use_cases or natural_language_input.'); } // Detect industry if not provided const detectedIndustry = validatedInput.industry || detectIndustry(validatedInput.project_type); // Get industry calculator const calculator = IndustryCalculatorFactory.getCalculator(detectedIndustry); // Generate additional scenarios if enabled let generatedScenarios = []; if (validatedInput.enable_scenario_generation) { generatedScenarios = calculator.generateRecommendations(validatedInput.company_size || 'medium', [] // Could pass current challenges here ); // Filter to avoid duplicates generatedScenarios = generatedScenarios.filter(scenario => !useCases.some(uc => uc.name === scenario.name)); } // Calculate ROI for each use case const results = await calculateUseCaseResults(useCases, calculator, validatedInput); // Fetch benchmarks if enabled let benchmarkData = null; if (validatedInput.use_industry_benchmarks && validatedInput.benchmark_config?.enable_real_time) { const aggregator = new BenchmarkAggregator({ sonarApiKey: validatedInput.benchmark_config.sonar_api_key }); benchmarkData = await aggregator.aggregateBenchmarks({ industry: detectedIndustry, company_size: validatedInput.company_size }); } // Calculate scenarios const scenarios = calculateScenarios(results, generatedScenarios, calculator); // Generate insights and recommendations const industryKPIs = calculator.getIndustryKPIs(); const insights = generateIndustryInsights(results, industryKPIs, benchmarkData, detectedIndustry); const recommendations = generateRecommendations(results, scenarios, detectedIndustry, validatedInput.company_size || 'medium'); // Create summary const summary = createSummary(results, scenarios.expected); // Generate voice output if requested const voiceOutput = validatedInput.enable_voice_mode ? generateVoiceOutput(summary, recommendations, validatedInput.client_name) : undefined; const result = { summary, scenarios, recommendations, industryInsights: insights, generatedScenarios: generatedScenarios.length > 0 ? generatedScenarios : undefined, voiceOutput }; logger.info('Assessment completed', { monthlyBenefit: summary.totalMonthlyBenefit, roi: summary.estimatedROI, confidence: summary.confidenceScore }); return result; } catch (error) { logger.error('Assessment failed', error); if (error instanceof ValidationError) { throw error; } throw new Error(`Assessment failed: ${error.message}. Please check your inputs and try again.`); } } /** * Calculate results for each use case using industry calculator */ async function calculateUseCaseResults(useCases, calculator, input) { return useCases.map(useCase => { const industryUseCase = { name: useCase.name, category: useCase.category, volume: useCase.monthly_volume, currentCost: useCase.current_cost_per_unit, currentTime: useCase.current_time_minutes, automationPotential: useCase.automation_potential }; const result = calculator.calculateROI(industryUseCase); return { ...useCase, ...result, annualBenefit: result.monthlyBenefit * 12, roi: (result.monthlyBenefit * 12) / result.implementationCost * 100 }; }); } /** * Calculate conservative, expected, and optimistic scenarios */ function calculateScenarios(results, generatedScenarios, calculator) { // Base calculations const totalMonthlyBenefit = results.reduce((sum, r) => sum + r.monthlyBenefit, 0); const totalImplementationCost = results.reduce((sum, r) => sum + r.implementationCost, 0); const avgConfidence = results.reduce((sum, r) => sum + r.confidenceScore, 0) / results.length; // Calculate potential from generated scenarios let additionalBenefit = 0; let additionalCost = 0; for (const scenario of generatedScenarios.slice(0, 2)) { // Top 2 scenarios const result = calculator.calculateROI(scenario); additionalBenefit += result.monthlyBenefit * 0.5; // 50% likelihood additionalCost += result.implementationCost * 0.5; } return { conservative: { monthlyBenefit: totalMonthlyBenefit * 0.7, annualBenefit: totalMonthlyBenefit * 0.7 * 12, roi: (totalMonthlyBenefit * 0.7 * 12) / totalImplementationCost * 100, assumptions: [ 'Lower automation rates than projected', 'Longer implementation timeline', 'Some use cases may not achieve full potential' ] }, expected: { monthlyBenefit: totalMonthlyBenefit + additionalBenefit * 0.3, annualBenefit: (totalMonthlyBenefit + additionalBenefit * 0.3) * 12, roi: ((totalMonthlyBenefit + additionalBenefit * 0.3) * 12) / (totalImplementationCost + additionalCost * 0.3) * 100, assumptions: [ 'Industry-standard automation rates', 'Normal implementation timeline', 'Most use cases achieve projected benefits', 'Some additional opportunities realized' ] }, optimistic: { monthlyBenefit: totalMonthlyBenefit * 1.3 + additionalBenefit, annualBenefit: (totalMonthlyBenefit * 1.3 + additionalBenefit) * 12, roi: ((totalMonthlyBenefit * 1.3 + additionalBenefit) * 12) / (totalImplementationCost + additionalCost) * 100, assumptions: [ 'Higher automation rates achieved', 'Faster implementation', 'All use cases exceed projections', 'Additional opportunities fully realized', 'Positive network effects between use cases' ] } }; } /** * Generate industry-specific insights */ function generateIndustryInsights(results, industryKPIs, benchmarkData, industry) { const insights = { benchmarkComparison: [], topOpportunities: [], competitiveAdvantage: '' }; // Compare against industry KPIs for (const kpi of industryKPIs.filter(k => k.importance === 'critical')) { // This is simplified - in production, would calculate actual metrics const yourValue = Math.random() * kpi.benchmarkValue * 1.2; const percentile = yourValue > kpi.benchmarkValue ? 75 : 35; insights.benchmarkComparison.push({ metric: kpi.name, yourValue, industryAverage: kpi.benchmarkValue, percentile }); } // Identify top opportunities const sortedResults = [...results].sort((a, b) => b.roi - a.roi); insights.topOpportunities = sortedResults.slice(0, 3).map(r => `${r.name}: ${r.roi.toFixed(0)}% ROI in ${r.timeToValue} months`); // Competitive advantage statement const avgROI = results.reduce((sum, r) => sum + r.roi, 0) / results.length; if (avgROI > 30) { insights.competitiveAdvantage = `Strong AI adoption could position you in the top 25% of ${industry} companies`; } else if (avgROI > 20) { insights.competitiveAdvantage = `AI implementation will help maintain competitive parity in ${industry}`; } else { insights.competitiveAdvantage = `Focus on high-ROI use cases to maximize competitive impact`; } return insights; } /** * Generate tiered recommendations */ function generateRecommendations(results, scenarios, industry, companySize) { const recommendations = { immediate: [], shortTerm: [], longTerm: [] }; // Sort by ROI and time to value const byROI = [...results].sort((a, b) => b.roi - a.roi); const bySpeed = [...results].sort((a, b) => a.timeToValue - b.timeToValue); // Immediate (high ROI, quick implementation) const immediate = results.filter(r => r.roi > 50 && r.timeToValue <= 3); if (immediate.length > 0) { recommendations.immediate.push(`Start with ${immediate[0].name} for quick wins (${immediate[0].roi.toFixed(0)}% ROI in ${immediate[0].timeToValue} months)`); } // Short-term (good ROI, reasonable timeline) const shortTerm = results.filter(r => r.roi > 25 && r.timeToValue <= 6); recommendations.shortTerm = shortTerm.slice(0, 2).map(r => `Implement ${r.name} within 6 months for sustained value`); // Long-term strategic recommendations.longTerm.push(`Build AI Center of Excellence to scale capabilities across ${industry}`, `Explore advanced use cases like predictive analytics and ML-driven optimization`); // Size-specific recommendations if (companySize === 'small') { recommendations.immediate.push('Consider cloud-based AI solutions to minimize upfront costs'); } else if (companySize === 'enterprise') { recommendations.longTerm.push('Develop proprietary AI models for competitive differentiation'); } return recommendations; } /** * Create summary metrics */ function createSummary(results, expectedScenario) { const totalImplementationCost = results.reduce((sum, r) => sum + r.implementationCost, 0); const avgTimeToValue = results.reduce((sum, r) => sum + r.timeToValue, 0) / results.length; const avgConfidence = results.reduce((sum, r) => sum + r.confidenceScore, 0) / results.length; // Determine complexity based on various factors let complexity = 'medium'; if (results.length > 5 || avgTimeToValue > 6) { complexity = 'high'; } else if (results.length <= 2 && avgTimeToValue <= 3) { complexity = 'low'; } return { totalMonthlyBenefit: expectedScenario.monthlyBenefit, estimatedROI: expectedScenario.roi, paybackPeriodMonths: Math.round(totalImplementationCost / expectedScenario.monthlyBenefit), confidenceScore: avgConfidence, implementationComplexity: complexity }; } /** * Generate natural language output for voice interfaces */ function generateVoiceOutput(summary, recommendations, clientName) { const output = [ `Based on my analysis for ${clientName}, `, `implementing AI automation could generate approximately $${Math.round(summary.totalMonthlyBenefit).toLocaleString()} in monthly benefits, `, `with an estimated ROI of ${Math.round(summary.estimatedROI)}%. `, `You can expect to see payback in about ${summary.paybackPeriodMonths} months. `, recommendations.immediate.length > 0 ? `I recommend starting immediately with ${recommendations.immediate[0]}. ` : `I recommend beginning with your highest ROI opportunities. `, `The implementation complexity is ${summary.implementationComplexity}, `, `and I have ${Math.round(summary.confidenceScore * 100)}% confidence in these projections. `, `Would you like me to elaborate on any specific use case or explore additional scenarios?` ]; return output.join(''); } /** * Detect industry based on project type */ function detectIndustry(projectType) { const industryMap = { 'customer_service_automation': 'retail', 'document_processing': 'financial_services', 'predictive_maintenance': 'manufacturing', 'fraud_detection': 'financial_services', 'inventory_optimization': 'retail', 'quality_control': 'manufacturing', 'compliance_automation': 'financial_services', 'workforce_optimization': 'healthcare' }; return industryMap[projectType] || 'technology'; } //# sourceMappingURL=quick-assessment.js.map