UNPKG

falcon-mcp-server

Version:

MCP server for Honeycomb Falcon Insurance API integration

377 lines (376 loc) 14.2 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const express_1 = __importDefault(require("express")); const cors_1 = __importDefault(require("cors")); const helmet_1 = __importDefault(require("helmet")); const zod_1 = require("zod"); const policyService_1 = require("./policyService"); const dotenv_1 = __importDefault(require("dotenv")); // Load environment variables dotenv_1.default.config(); const app = (0, express_1.default)(); const PORT = process.env.PORT || 3010; // Middleware app.use((0, helmet_1.default)()); app.use((0, cors_1.default)()); app.use(express_1.default.json()); // Request validation schemas const GetPolicySchema = zod_1.z.object({ policyID: zod_1.z.string(), authToken: zod_1.z.string() }); const GetSubmissionSchema = zod_1.z.object({ submissionID: zod_1.z.string(), authToken: zod_1.z.string() }); // Health check endpoint app.get('/health', (req, res) => { res.json({ status: 'healthy', service: 'falcon-mcp', version: '1.0.0', timestamp: new Date().toISOString() }); }); // Get policy endpoint app.post('/api/getPolicy', async (req, res) => { try { console.error(`[Falcon MCP HTTP] getPolicy called with policyID: "${req.body.policyID}"`); // Validate request const { policyID, authToken } = GetPolicySchema.parse(req.body); // Configuration for the Honeycomb Falcon API const config = { baseURL: process.env.FALCON_API_BASE_URL || 'https://sandbox-api-falcon.honeycombinsurance.com', authToken, reduced: false, timeout: 30000 }; // Call the real API const policyData = await (0, policyService_1.getPolicyById)(policyID, config); console.error(`[Falcon MCP HTTP] getPolicy completed successfully`); res.json({ success: true, data: policyData, timestamp: new Date().toISOString() }); } catch (error) { console.error(`[Falcon MCP HTTP] getPolicy failed: ${error.message}`); if (error instanceof zod_1.z.ZodError) { return res.status(400).json({ success: false, error: 'Invalid request data', details: error.errors, timestamp: new Date().toISOString() }); } res.status(500).json({ success: false, error: `Error retrieving policy: ${error.message}`, timestamp: new Date().toISOString() }); } }); // Get submission endpoint app.post('/api/getSubmission', async (req, res) => { try { console.error(`[Falcon MCP HTTP] getSubmission called with submissionID: "${req.body.submissionID}"`); // Validate request const { submissionID, authToken } = GetSubmissionSchema.parse(req.body); // Configuration for the Honeycomb Falcon API const config = { baseURL: 'https://sandbox-api-falcon.honeycombinsurance.com', authToken, reduced: false, timeout: 30000 }; // Call the real API using the same endpoint as getPolicy const submissionData = await (0, policyService_1.getPolicyById)(submissionID, config); console.error(`[Falcon MCP HTTP] getSubmission completed successfully`); res.json({ success: true, data: submissionData, timestamp: new Date().toISOString() }); } catch (error) { console.error(`[Falcon MCP HTTP] getSubmission failed: ${error.message}`); if (error instanceof zod_1.z.ZodError) { return res.status(400).json({ success: false, error: 'Invalid request data', details: error.errors, timestamp: new Date().toISOString() }); } res.status(500).json({ success: false, error: `Error retrieving submission: ${error.message}`, timestamp: new Date().toISOString() }); } }); // API documentation endpoint app.get('/api', (req, res) => { console.log(`[Falcon MCP HTTP] API documentation endpoint called`); res.json({ service: 'Falcon MCP HTTP Server', version: '1.0.0', endpoints: { 'GET /health': 'Health check endpoint', 'POST /api/getPolicy': { description: 'Retrieve policy data by ID', body: { policyID: 'string (required)', authToken: 'string (required)' } }, 'POST /api/getSubmission': { description: 'Retrieve submission data by ID', body: { submissionID: 'string (required)', authToken: 'string (required)' } } }, timestamp: new Date().toISOString() }); }); // MCP Methods endpoint for Streamable HTTP transport app.get('/methods', (req, res) => { console.error('[Falcon MCP HTTP] Methods endpoint called (GET)'); res.json({ jsonrpc: "2.0", id: req.query.id || 1, result: { tools: [ { name: "getPolicy", description: "Retrieve policy data by ID from the Falcon API", inputSchema: { type: "object", properties: { policyID: { type: "string", description: "The policy ID to retrieve" }, authToken: { type: "string", description: "Authentication token for the Falcon API" } }, required: ["policyID", "authToken"] } }, { name: "getSubmission", description: "Retrieve submission data by ID from the Falcon API", inputSchema: { type: "object", properties: { submissionID: { type: "string", description: "The submission ID to retrieve" }, authToken: { type: "string", description: "Authentication token for the Falcon API" } }, required: ["submissionID", "authToken"] } } ] } }); }); app.post('/methods', (req, res) => { console.error('[Falcon MCP HTTP] Methods endpoint called (POST)'); res.json({ jsonrpc: "2.0", id: req.body.id || 1, result: { tools: [ { name: "getPolicy", description: "Retrieve policy data by ID from the Falcon API", inputSchema: { type: "object", properties: { policyID: { type: "string", description: "The policy ID to retrieve" }, authToken: { type: "string", description: "Authentication token for the Falcon API" } }, required: ["policyID", "authToken"] } }, { name: "getSubmission", description: "Retrieve submission data by ID from the Falcon API", inputSchema: { type: "object", properties: { submissionID: { type: "string", description: "The submission ID to retrieve" }, authToken: { type: "string", description: "Authentication token for the Falcon API" } }, required: ["submissionID", "authToken"] } } ] } }); }); // MCP Call endpoint for Streamable HTTP transport app.post('/call', async (req, res) => { try { console.error(`[Falcon MCP HTTP] Call endpoint called with params:`, req.body); const { name, arguments: args } = req.body; if (!name || !args) { return res.status(400).json({ jsonrpc: "2.0", id: req.body.id || 1, error: { code: -32602, message: 'Missing required fields: name and arguments' } }); } switch (name) { case 'getPolicy': const { policyID, authToken } = args; if (!policyID || !authToken) { return res.status(400).json({ jsonrpc: "2.0", id: req.body.id || 1, error: { code: -32602, message: 'Missing required arguments: policyID and authToken' } }); } // Configuration for the Honeycomb Falcon API const config = { baseURL: process.env.FALCON_API_BASE_URL || 'https://sandbox-api-falcon.honeycombinsurance.com', authToken, reduced: false, timeout: 30000 }; // Call the real API const policyData = await (0, policyService_1.getPolicyById)(policyID, config); console.error(`[Falcon MCP HTTP] getPolicy completed successfully`); return res.json({ jsonrpc: "2.0", id: req.body.id || 1, result: { content: [ { type: "text", text: JSON.stringify(policyData, null, 2) } ] } }); case 'getSubmission': const { submissionID, authToken: subAuthToken } = args; if (!submissionID || !subAuthToken) { return res.status(400).json({ jsonrpc: "2.0", id: req.body.id || 1, error: { code: -32602, message: 'Missing required arguments: submissionID and authToken' } }); } // Configuration for the Honeycomb Falcon API const subConfig = { baseURL: 'https://sandbox-api-falcon.honeycombinsurance.com', authToken: subAuthToken, reduced: false, timeout: 30000 }; // Call the real API using the same endpoint as getPolicy const submissionData = await (0, policyService_1.getPolicyById)(submissionID, subConfig); console.error(`[Falcon MCP HTTP] getSubmission completed successfully`); return res.json({ jsonrpc: "2.0", id: req.body.id || 1, result: { content: [ { type: "text", text: JSON.stringify(submissionData, null, 2) } ] } }); default: return res.status(400).json({ jsonrpc: "2.0", id: req.body.id || 1, error: { code: -32601, message: `Unknown tool: ${name}` } }); } } catch (error) { console.error(`[Falcon MCP HTTP] Call endpoint failed: ${error.message}`); res.status(500).json({ jsonrpc: "2.0", id: req.body.id || 1, error: { code: -32603, message: `Error executing tool: ${error.message}` } }); } }); // 404 handler app.use('*', (req, res) => { res.status(404).json({ success: false, error: 'Endpoint not found', availableEndpoints: ['/health', '/api', '/api/getPolicy', '/api/getSubmission', '/methods', '/call'], timestamp: new Date().toISOString() }); }); // Error handler app.use((error, req, res, next) => { console.error('[Falcon MCP HTTP] Unhandled error:', error); res.status(500).json({ success: false, error: 'Internal server error', timestamp: new Date().toISOString() }); }); // Start the server app.listen(PORT, () => { console.error(`[Falcon MCP HTTP] Server running on port ${PORT}`); console.error(`[Falcon MCP HTTP] Health check: http://localhost:${PORT}/health`); console.error(`[Falcon MCP HTTP] API docs: http://localhost:${PORT}/api`); }); // Graceful shutdown process.on('SIGTERM', () => { console.error('[Falcon MCP HTTP] Received SIGTERM, shutting down gracefully'); process.exit(0); }); process.on('SIGINT', () => { console.error('[Falcon MCP HTTP] Received SIGINT, shutting down gracefully'); process.exit(0); });