/** * MCP Server core implementation */ import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { CallToolRequestSchema, ListToolsRequestSchema, Tool, } from "@modelcontextprotocol/sdk/types.js"; import { logger } from "./utils/logger.js"; export type ToolHandler = ( args: Record ) => Promise<{ content: Array<{ type: string; text: string }> }>; class MCPServer { private server: Server; private tools: Map = new Map(); // Expose tools for testing getTools(): Map { return this.tools; } constructor() { this.server = new Server( { name: "cloud-mcp", version: "1.0.0", }, { capabilities: { tools: {}, }, } ); this.setupHandlers(); } private setupHandlers(): void { this.server.setRequestHandler(ListToolsRequestSchema, async () => { const tools: Tool[] = Array.from(this.tools.values()).map( (entry) => entry.tool ); return { tools }; }); this.server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; const toolEntry = this.tools.get(name); if (!toolEntry) { throw new Error(`Tool ${name} not found`); } try { logger.info(`Calling tool: ${name}`, args); const result = await toolEntry.handler(args || {}); return result; } catch (error) { logger.error(`Error executing tool ${name}:`, error); const errorMessage = error instanceof Error ? error.message : String(error); return { content: [ { type: "text", text: `Error: ${errorMessage}`, }, ], isError: true, }; } }); } registerTool(tool: Tool, handler: ToolHandler): void { this.tools.set(tool.name, { tool, handler }); logger.debug(`Registered tool: ${tool.name}`); } async start(): Promise { const transport = new StdioServerTransport(); await this.server.connect(transport); logger.info("MCP Server started"); } } export const mcpServer = new MCPServer();