Skip to main content
Glama
mcp.ts3.45 kB
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { z } from 'zod'; import type { MCPToolDefinition } from '../types/mcp-tool.js'; import type { Config } from '../config/schema.js'; import { executeTool, type ToolArgs } from '../proxy/executor.js'; import { log } from '../utils/logger.js'; /** * Convert our JSONSchema to Zod schema for MCP SDK registration * Note: This is a simplified conversion for common types */ function jsonSchemaToZodShape(schema: MCPToolDefinition['inputSchema']): Record<string, z.ZodTypeAny> { const shape: Record<string, z.ZodTypeAny> = {}; if (!schema.properties) { return shape; } const requiredSet = new Set(schema.required ?? []); for (const [name, prop] of Object.entries(schema.properties)) { let zodType: z.ZodTypeAny; switch (prop.type) { case 'string': zodType = z.string(); if (prop.enum) { zodType = z.enum(prop.enum as [string, ...string[]]); } break; case 'number': zodType = z.number(); if (prop.minimum !== undefined) { zodType = (zodType as z.ZodNumber).min(prop.minimum); } if (prop.maximum !== undefined) { zodType = (zodType as z.ZodNumber).max(prop.maximum); } break; case 'integer': zodType = z.number().int(); break; case 'boolean': zodType = z.boolean(); break; case 'array': zodType = z.array(z.unknown()); break; case 'object': zodType = z.record(z.unknown()); break; default: zodType = z.unknown(); } // Add description if (prop.description) { zodType = zodType.describe(prop.description); } // Make optional if not required if (!requiredSet.has(name)) { zodType = zodType.optional(); } shape[name] = zodType; } return shape; } /** * Create and configure an MCP server with tools */ export function createMcpServer( tools: MCPToolDefinition[], config: Config ): McpServer { const server = new McpServer({ name: 'openapi-mcp', version: '1.0.0', }); // Register enabled tools const enabledTools = tools.filter((t) => t._ui.enabled); log.info('Registering MCP tools', { count: enabledTools.length }); for (const tool of enabledTools) { const inputShape = jsonSchemaToZodShape(tool.inputSchema); server.registerTool( tool.name, { title: tool.title, description: tool.description, inputSchema: inputShape, }, async (args: ToolArgs) => { log.debug('Tool called', { tool: tool.name }); const result = await executeTool(tool, args, config); // Return in the format expected by MCP SDK return { content: result.content.map((c) => ({ type: 'text' as const, text: c.text, })), isError: result.isError, }; } ); log.debug('Registered tool', { name: tool.name, title: tool.title }); } return server; } /** * Get list of registered tools for diagnostics */ export function getToolList(tools: MCPToolDefinition[]): Array<{ name: string; title: string; enabled: boolean; method: string; path: string; }> { return tools.map((t) => ({ name: t.name, title: t.title, enabled: t._ui.enabled, method: t._proxy.method, path: t._proxy.path, })); }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/procoders/openapi-mcp-ts'

If you have feedback or need assistance with the MCP directory API, please join our Discord server