Skip to main content
Glama
mkXultra
by mkXultra
ToolRegistry.ts5.27 kB
import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js'; import { z } from 'zod'; import { LockService } from '../services/LockService'; import { MessagingAdapter } from '../adapters/MessagingAdapter'; import { RoomsAdapter } from '../adapters/RoomsAdapter'; import { ManagementAdapter } from '../adapters/ManagementAdapter'; import { allTools, toolHandlers } from '../tools/index'; import { AppError } from '../errors/index'; // Type guard for tool names function isValidToolName(name: string): name is keyof typeof toolHandlers { return name in toolHandlers; } export class ToolRegistry { private lockService: LockService; private messagingAdapter: MessagingAdapter; private roomsAdapter: RoomsAdapter; private managementAdapter: ManagementAdapter; constructor(dataDir?: string) { this.lockService = new LockService(dataDir); this.messagingAdapter = new MessagingAdapter(this.lockService); this.roomsAdapter = new RoomsAdapter(this.lockService); this.managementAdapter = new ManagementAdapter(this.lockService); // Set up cross-adapter dependencies this.messagingAdapter.setRoomsAdapter(this.roomsAdapter); this.managementAdapter.setRoomsAdapter(this.roomsAdapter); this.managementAdapter.setMessageAdapter(this.messagingAdapter); } async registerAll(server: Server): Promise<void> { try { // Initialize all adapters await Promise.all([ this.messagingAdapter.initialize(), this.roomsAdapter.initialize(), this.managementAdapter.initialize() ]); // Define the request schemas const listToolsRequestSchema = z.object({ method: z.literal('tools/list'), params: z.object({ _meta: z.optional(z.object({})) }).optional() }); const callToolRequestSchema = z.object({ method: z.literal('tools/call'), params: z.object({ name: z.string(), arguments: z.any(), _meta: z.optional(z.object({})) }) }); // Register tools list handler server.setRequestHandler(listToolsRequestSchema, async () => ({ tools: allTools })); // Register tool call handler server.setRequestHandler(callToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; try { if (!isValidToolName(name)) { throw new AppError(`Unknown tool: ${name}`, 'UNKNOWN_TOOL', 404); } const handler = toolHandlers[name]; // Route to appropriate adapter let result; switch (name) { case 'agent_communication_list_rooms': case 'agent_communication_create_room': case 'agent_communication_enter_room': case 'agent_communication_leave_room': case 'agent_communication_list_room_users': result = await handler(args, this.roomsAdapter); break; case 'agent_communication_send_message': case 'agent_communication_get_messages': case 'agent_communication_wait_for_messages': result = await handler(args, this.messagingAdapter); break; case 'agent_communication_get_status': case 'agent_communication_clear_room_messages': result = await handler(args, this.managementAdapter); break; default: throw new AppError(`Unrouted tool: ${name}`, 'UNROUTED_TOOL', 500); } return result; } catch (error) { // Convert AppError to MCP error format if (error instanceof AppError) { // Map HTTP status codes to JSON-RPC error codes // 404 for resources (rooms, agents) should be InvalidParams, not MethodNotFound const errorCode = error.statusCode >= 400 && error.statusCode < 500 ? ErrorCode.InvalidParams : ErrorCode.InternalError; throw new McpError( errorCode, error.message, { errorCode: error.code } ); } // Handle validation errors (from zod) if (error instanceof Error && error.name === 'ZodError') { throw new McpError( ErrorCode.InvalidParams, `Validation error: ${error.message}`, { errorCode: 'VALIDATION_ERROR' } ); } // Handle unknown errors throw new McpError( ErrorCode.InternalError, error instanceof Error ? error.message : 'Internal server error', { errorCode: 'INTERNAL_ERROR' } ); } }); } catch (error) { throw new AppError( `Failed to register tools: ${error instanceof Error ? error.message : 'Unknown error'}`, 'TOOL_REGISTRATION_ERROR', 500 ); } } async shutdown(): Promise<void> { // Cleanup resources if needed // Currently no explicit cleanup required } }

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/mkXultra/agent-communication-mcp'

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