@spaik/mcp-server-roi
Version:
MCP server for AI ROI prediction and tracking with Monte Carlo simulations
443 lines • 19.8 kB
JavaScript
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