UNPKG

@spaik/mcp-server-roi

Version:

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

191 lines 7.12 kB
#!/usr/bin/env node import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; // Import utilities import { logger } from './utils/logger.js'; import { ConfigurationError } from './utils/errors.js'; import { ValidationError } from './utils/error-handler.js'; import { validateServerSetup, getSetupInstructions } from './utils/config-validator.js'; // Import tools import { predictROI, PredictROISchema } from './tools/predict-roi.js'; import { compareProjects, CompareProjectsSchema } from './tools/compare-projects.js'; // Import response transformer for AI agent optimization import { responseTransformer } from './services/response-transformer.js'; // Create MCP server instance with capabilities const server = new McpServer({ name: '@spaik/mcp-server-roi', version: '1.3.0', }, { capabilities: { tools: {}, // Resources can be added later if needed // resources: {} } }); // Register the predict_roi tool server.tool('predict_roi', 'Generate comprehensive ROI predictions for AI implementation projects with mandatory Dutch market validation', {}, async (args) => { try { logger.info('Executing predict_roi tool', { args }); // Parse and validate the input args with the schema const parsedInput = PredictROISchema.parse(args); const result = await predictROI(parsedInput); // Transform response for AI agents const transformedResult = await responseTransformer.transformPredictROI(result); return { content: [{ type: 'text', text: JSON.stringify(transformedResult, null, 2) }] }; } catch (error) { logger.error('Tool execution failed', error); // Handle different error types appropriately if (error instanceof ValidationError) { return { content: [{ type: 'text', text: `Validation Error: ${error.message}\n\nFields with issues:\n${error.fields.map(f => `- ${f.field}: ${f.message}`).join('\n')}` }], isError: true }; } else if (error instanceof ConfigurationError) { return { content: [{ type: 'text', text: `Configuration Error: ${error.message}\n\n${getSetupInstructions()}` }], isError: true }; } else { return { content: [{ type: 'text', text: `Error: ${error instanceof Error ? error.message : 'Unknown error occurred'}` }], isError: true }; } } }); // Register the compare_projects tool server.tool('compare_projects', 'Compare multiple AI projects side-by-side for ROI and other metrics with Dutch market validation', {}, async (args) => { try { logger.info('Executing compare_projects tool', { args }); // Parse and validate the input args with the schema const parsedInput = CompareProjectsSchema.parse(args); const result = await compareProjects(parsedInput); // Transform response for AI agents const transformedResult = await responseTransformer.transformCompareProjects(result); return { content: [{ type: 'text', text: JSON.stringify(transformedResult, null, 2) }] }; } catch (error) { logger.error('Tool execution failed', error); // Handle different error types appropriately if (error instanceof ValidationError) { return { content: [{ type: 'text', text: `Validation Error: ${error.message}\n\nFields with issues:\n${error.fields.map(f => `- ${f.field}: ${f.message}`).join('\n')}` }], isError: true }; } else if (error instanceof ConfigurationError) { return { content: [{ type: 'text', text: `Configuration Error: ${error.message}\n\n${getSetupInstructions()}` }], isError: true }; } else { return { content: [{ type: 'text', text: `Error: ${error instanceof Error ? error.message : 'Unknown error occurred'}` }], isError: true }; } } }); // Main server initialization async function main() { logger.info('Starting MCP Server ROI', { version: '1.3.0', environment: process.env.NODE_ENV || 'production' }); // Validate server setup try { await validateServerSetup(); logger.info('Server setup validation completed successfully'); } catch (error) { logger.error('Server setup validation failed', error); console.error('\n❌ Server Setup Error\n'); console.error(error.message); console.error('\n' + getSetupInstructions()); process.exit(1); } // Create transport const transport = new StdioServerTransport(); // Handle transport errors transport.onerror = (error) => { logger.error('Transport error', error); process.exit(1); }; // Handle transport close transport.onclose = () => { logger.info('Transport closed, shutting down server'); process.exit(0); }; try { await server.connect(transport); logger.info('MCP server started successfully', { tools: ['predict_roi', 'compare_projects'], perplexityEnabled: !!process.env.PERPLEXITY_API_KEY, supabaseConfigured: !!process.env.SUPABASE_URL && !!process.env.SUPABASE_SERVICE_KEY }); } catch (error) { logger.error('Failed to start server', error); console.error('Failed to start server:', error); process.exit(1); } } // Handle process termination process.on('SIGINT', () => { logger.info('Received SIGINT, shutting down gracefully'); process.exit(0); }); process.on('SIGTERM', () => { logger.info('Received SIGTERM, shutting down gracefully'); process.exit(0); }); // Handle uncaught errors process.on('uncaughtException', (error) => { logger.error('Uncaught exception', error); console.error('Uncaught exception:', error); process.exit(1); }); process.on('unhandledRejection', (reason, promise) => { logger.error('Unhandled rejection', reason, { promise }); console.error('Unhandled rejection:', reason); process.exit(1); }); // Start the server main().catch((error) => { logger.error('Fatal error during startup', error); console.error('Fatal error during startup:', error); process.exit(1); }); //# sourceMappingURL=index.js.map