UNPKG

combined-memory-mcp

Version:

MCP server for Combined Memory API - AI-powered chat with unlimited context, memory management, voice agents, and 500+ tool integrations

176 lines (175 loc) 9.99 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.startServer = startServer; const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js"); const types_js_1 = require("@modelcontextprotocol/sdk/types.js"); const openapiProcessor_1 = require("./openapiProcessor"); const mcpMapper_1 = require("./mcpMapper"); const apiClient_1 = require("./apiClient"); const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js"); const zod_1 = require("zod"); // Import zod for schema definition function startServer() { return __awaiter(this, void 0, void 0, function* () { var _a, _b, _c, _d; console.error('Starting Dynamic OpenAPI MCP Server...'); let openapiSpec; try { openapiSpec = yield (0, openapiProcessor_1.getProcessedOpenApi)(); } catch (error) { console.error('Failed to initialize OpenAPI specification. Server cannot start.', error); process.exit(1); } let mappedTools; try { mappedTools = (0, mcpMapper_1.mapOpenApiToMcpTools)(openapiSpec); if (mappedTools.length === 0) { console.error('No tools were mapped from the OpenAPI spec based on current configuration/filtering.'); // Decide if the server should run with no tools or exit } } catch (error) { console.error('Failed to map OpenAPI spec to MCP tools. Server cannot start.', error); process.exit(1); } // Construct the server with metadata from OpenAPI spec const server = new mcp_js_1.McpServer({ name: ((_a = openapiSpec.info) === null || _a === void 0 ? void 0 : _a.title) || "OpenAPI to MCP Generator", version: ((_b = openapiSpec.info) === null || _b === void 0 ? void 0 : _b.version) || "1.0.0" }); // Add OpenAPI metadata to server capabilities or log it if ((_c = openapiSpec.info) === null || _c === void 0 ? void 0 : _c.description) { console.error(`API Description: ${openapiSpec.info.description}`); // Note: description is not directly supported in McpServer constructor // but we can log it or potentially use it elsewhere } // Register each tool with the server for (const tool of mappedTools) { const { mcpToolDefinition, apiCallDetails } = tool; console.error(`Registering MCP tool: ${mcpToolDefinition.name}`); try { // Convert JSON Schema properties to zod schema const params = {}; if (mcpToolDefinition.inputSchema && mcpToolDefinition.inputSchema.properties) { // Loop through all properties and create appropriate Zod schemas based on data type for (const [propName, propSchema] of Object.entries(mcpToolDefinition.inputSchema.properties)) { if (typeof propSchema !== 'object') continue; const description = propSchema.description || `Parameter: ${propName}`; const required = ((_d = mcpToolDefinition.inputSchema.required) === null || _d === void 0 ? void 0 : _d.includes(propName)) || false; // Map JSON Schema types to Zod schema types let zodSchema; const schemaType = Array.isArray(propSchema.type) ? propSchema.type[0] // If type is an array (for nullable union types), use first type : propSchema.type; // Handle different types with proper Zod schemas switch (schemaType) { case 'integer': zodSchema = zod_1.z.number().int().describe(description); break; case 'number': zodSchema = zod_1.z.number().describe(description); break; case 'boolean': zodSchema = zod_1.z.boolean().describe(description); break; case 'object': // For objects, create a more permissive schema zodSchema = zod_1.z.object({}).passthrough().describe(description); break; case 'array': // For arrays, allow any array content zodSchema = zod_1.z.array(zod_1.z.any()).describe(description); break; case 'string': default: zodSchema = zod_1.z.string().describe(description); break; } // Make it optional if not required params[propName] = required ? zodSchema : zodSchema.optional(); // Add this for debugging console.error(`Registered parameter ${propName} with type: ${schemaType}, required: ${required}`); } } // Register the tool using proper MCP SDK format server.tool(mcpToolDefinition.name, params, // This schema will be visible in the MCP Inspector (toolParams) => __awaiter(this, void 0, void 0, function* () { const requestId = 'req-' + Math.random().toString(36).substring(2, 9); console.error(`MCP Tool '${mcpToolDefinition.name}' invoked. Request ID: ${requestId}`); console.error(`Parameters received:`, toolParams); try { // Execute the API call with the provided parameters const result = yield (0, apiClient_1.executeApiCall)(apiCallDetails, toolParams); if (result.success) { console.error(`[Request ID: ${requestId}] Tool '${mcpToolDefinition.name}' executed successfully.`); // Return success response return { content: [ { type: "text", text: JSON.stringify(result.data) } ] }; } else { console.error(`[Request ID: ${requestId}] Tool '${mcpToolDefinition.name}' execution failed: ${result.error}`); // Map API errors to MCP errors let errorCode = types_js_1.ErrorCode.InternalError; let errorMessage = result.error || `API Error ${result.statusCode}`; if (result.statusCode === 400) { errorCode = types_js_1.ErrorCode.InvalidParams; errorMessage = `Invalid parameters: ${result.error}`; } else if (result.statusCode === 404) { errorCode = types_js_1.ErrorCode.InvalidParams; errorMessage = `Resource not found: ${result.error}`; } throw new types_js_1.McpError(errorCode, errorMessage, result.data); } } catch (invocationError) { console.error(`[Request ID: ${requestId}] Error invoking tool:`, invocationError); if (invocationError instanceof types_js_1.McpError) { throw invocationError; // Re-throw known MCP errors } throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError, `Internal server error: ${invocationError.message}`); } })); console.error(`Registered Tool: ${mcpToolDefinition.name}`); } catch (registerError) { console.error(`Failed to register tool ${mcpToolDefinition.name}:`, registerError); } } console.error('Starting MCP server...'); // Create a server transport and connect the server const transport = new stdio_js_1.StdioServerTransport(); try { // Connect the server using the transport instead of listen() yield server.connect(transport); console.error(`MCP Server started and ready for connections`); } catch (error) { console.error('Error starting MCP server:', error); process.exit(1); } }); } // Only auto-start if this is the main module if (require.main === module) { startServer().catch(error => { console.error('Unhandled error during server startup:', error); process.exit(1); }); }