UNPKG

claude-flow

Version:

Enterprise-grade AI agent orchestration with ruv-swarm integration (Alpha Release)

241 lines (208 loc) 6.16 kB
import { getErrorMessage } from '../utils/error-handler.js'; /** * Request router for MCP */ import type { MCPRequest } from '../utils/types.js'; import type { ILogger } from '../core/logger.js'; import { MCPMethodNotFoundError } from '../utils/errors.js'; import type { ToolRegistry } from './tools.js'; /** * Request router implementation */ export class RequestRouter { private totalRequests = 0; private successfulRequests = 0; private failedRequests = 0; constructor( private toolRegistry: ToolRegistry, private logger: ILogger, ) {} /** * Routes a request to the appropriate handler */ async route(request: MCPRequest): Promise<unknown> { this.totalRequests++; try { // Parse method to determine handler const { method, params } = request; // Handle built-in methods if (method.startsWith('rpc.')) { return await this.handleRPCMethod(method, params); } // Handle tool invocations if (method.startsWith('tools.')) { return await this.handleToolMethod(method, params); } // Try to execute as a tool directly const tool = this.toolRegistry.getTool(method); if (tool) { const result = await this.toolRegistry.executeTool(method, params); this.successfulRequests++; return result; } // Method not found throw new MCPMethodNotFoundError(method); } catch (error) { this.failedRequests++; throw error; } } /** * Gets router metrics */ getMetrics(): { totalRequests: number; successfulRequests: number; failedRequests: number; } { return { totalRequests: this.totalRequests, successfulRequests: this.successfulRequests, failedRequests: this.failedRequests, }; } /** * Handles built-in RPC methods */ private async handleRPCMethod(method: string, params: unknown): Promise<unknown> { switch (method) { case 'rpc.discover': return this.discoverMethods(); case 'rpc.ping': return { pong: true }; case 'rpc.describe': return this.describeMethod(params); default: throw new MCPMethodNotFoundError(method); } } /** * Handles tool-related methods */ private async handleToolMethod(method: string, params: unknown): Promise<unknown> { switch (method) { case 'tools.list': return this.toolRegistry.listTools(); case 'tools.invoke': return await this.invokeTool(params); case 'tools.describe': return this.describeTool(params); default: throw new MCPMethodNotFoundError(method); } } /** * Discovers all available methods */ private discoverMethods(): Record<string, string> { const methods: Record<string, string> = { 'rpc.discover': 'Discover all available methods', 'rpc.ping': 'Ping the server', 'rpc.describe': 'Describe a specific method', 'tools.list': 'List all available tools', 'tools.invoke': 'Invoke a specific tool', 'tools.describe': 'Describe a specific tool', }; // Add all registered tools for (const tool of this.toolRegistry.listTools()) { methods[tool.name] = tool.description; } return methods; } /** * Describes a specific method */ private describeMethod(params: unknown): unknown { if (!params || typeof params !== 'object' || !('method' in params)) { throw new Error('Invalid params: method required'); } const { method } = params as { method: string }; // Check if it's a tool const tool = this.toolRegistry.getTool(method); if (tool) { return { name: tool.name, description: tool.description, inputSchema: tool.inputSchema, }; } // Check built-in methods const builtInMethods: Record<string, unknown> = { 'rpc.discover': { description: 'Discover all available methods', inputSchema: { type: 'object', properties: {} }, }, 'rpc.ping': { description: 'Ping the server', inputSchema: { type: 'object', properties: {} }, }, 'rpc.describe': { description: 'Describe a specific method', inputSchema: { type: 'object', properties: { method: { type: 'string' }, }, required: ['method'], }, }, 'tools.list': { description: 'List all available tools', inputSchema: { type: 'object', properties: {} }, }, 'tools.invoke': { description: 'Invoke a specific tool', inputSchema: { type: 'object', properties: { tool: { type: 'string' }, input: { type: 'object' }, }, required: ['tool', 'input'], }, }, 'tools.describe': { description: 'Describe a specific tool', inputSchema: { type: 'object', properties: { tool: { type: 'string' }, }, required: ['tool'], }, }, }; if (method in builtInMethods) { return builtInMethods[method]; } throw new MCPMethodNotFoundError(method); } /** * Invokes a tool */ private async invokeTool(params: unknown): Promise<unknown> { if (!params || typeof params !== 'object' || !('tool' in params)) { throw new Error('Invalid params: tool required'); } const { tool, input } = params as { tool: string; input?: unknown }; return await this.toolRegistry.executeTool(tool, input || {}); } /** * Describes a specific tool */ private describeTool(params: unknown): unknown { if (!params || typeof params !== 'object' || !('tool' in params)) { throw new Error('Invalid params: tool required'); } const { tool: toolName } = params as { tool: string }; const tool = this.toolRegistry.getTool(toolName); if (!tool) { throw new Error(`Tool not found: ${toolName}`); } return { name: tool.name, description: tool.description, inputSchema: tool.inputSchema, }; } }