falcon-mcp-server
Version:
MCP server for Honeycomb Falcon Insurance API integration
377 lines (376 loc) • 14.2 kB
JavaScript
"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);
});