@sethdouglasford/claude-flow
Version:
Claude Code Flow - Advanced AI-powered development workflows with SPARC methodology
276 lines • 9.03 kB
JavaScript
/**
* Request router for MCP
*/
import { MCPMethodNotFoundError } from "../utils/errors.js";
/**
* Request router implementation
*/
export class RequestRouter {
toolRegistry;
promptRegistry;
logger;
totalRequests = 0;
successfulRequests = 0;
failedRequests = 0;
constructor(toolRegistry, promptRegistry, logger) {
this.toolRegistry = toolRegistry;
this.promptRegistry = promptRegistry;
this.logger = logger;
}
/**
* Routes a request to the appropriate handler
*/
async route(request) {
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);
}
// Handle prompt methods
if (method.startsWith("prompts/")) {
return await this.handlePromptMethod(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() {
return {
totalRequests: this.totalRequests,
successfulRequests: this.successfulRequests,
failedRequests: this.failedRequests,
};
}
/**
* Handles built-in RPC methods
*/
handleRPCMethod(method, params) {
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
*/
async handleToolMethod(method, params) {
switch (method) {
case "tools/list":
return this.toolRegistry.listTools();
case "tools/call":
return await this.invokeTool(params);
case "tools/describe":
return this.describeTool(params);
default:
throw new MCPMethodNotFoundError(method);
}
}
/**
* Handles prompt-related methods
*/
async handlePromptMethod(method, params) {
switch (method) {
case "prompts/list":
return {
prompts: this.promptRegistry.listPrompts()
};
case "prompts/get":
return await this.getPrompt(params);
default:
throw new MCPMethodNotFoundError(method);
}
}
/**
* Discovers all available methods
*/
discoverMethods() {
const methods = {
"rpc.discover": "Discover all available methods",
"rpc.ping": "Ping the server",
"rpc.describe": "Describe a specific method",
"tools/list": "List all available tools",
"tools/call": "Call a specific tool",
"tools/describe": "Describe a specific tool",
"prompts/list": "List all available prompts",
"prompts/get": "Get a specific prompt",
};
// Add all registered tools
for (const tool of this.toolRegistry.listTools()) {
methods[tool.name] = tool.description;
}
// Add all registered prompts
for (const prompt of this.promptRegistry.listPrompts()) {
methods[`prompt/${prompt.name}`] = prompt.description || "Custom prompt";
}
return methods;
}
/**
* Describes a specific method
*/
describeMethod(params) {
if (!params || typeof params !== "object" || !("method" in params)) {
throw new Error("Invalid params: method required");
}
const { method } = params;
// 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 if it's a prompt
const prompt = this.promptRegistry.getPrompt(method);
if (prompt) {
return {
name: prompt.name,
description: prompt.description,
arguments: prompt.arguments,
};
}
// Check built-in methods
const builtInMethods = {
"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/call": {
description: "Call a specific tool",
inputSchema: {
type: "object",
properties: {
name: { type: "string" },
arguments: { type: "object" },
},
required: ["name"],
},
},
"tools/describe": {
description: "Describe a specific tool",
inputSchema: {
type: "object",
properties: {
name: { type: "string" },
},
required: ["name"],
},
},
"prompts/list": {
description: "List all available prompts",
inputSchema: { type: "object", properties: {} },
},
"prompts/get": {
description: "Get a specific prompt",
inputSchema: {
type: "object",
properties: {
name: { type: "string" },
arguments: { type: "object" },
},
required: ["name"],
},
},
};
if (method in builtInMethods) {
return builtInMethods[method];
}
throw new MCPMethodNotFoundError(method);
}
/**
* Invokes a tool with the given parameters
*/
async invokeTool(params) {
if (!params || typeof params !== "object" || !("name" in params)) {
throw new Error("Invalid params: name required");
}
const { name, arguments: args } = params;
return await this.toolRegistry.executeTool(name, args);
}
/**
* Gets a prompt with the given parameters
*/
async getPrompt(params) {
if (!params || typeof params !== "object" || !("name" in params)) {
throw new Error("Invalid params: name required");
}
const { name, arguments: args } = params;
const promptContent = await this.promptRegistry.executePrompt(name, args || {});
return {
messages: [
{
role: "user",
content: {
type: "text",
text: promptContent
}
}
]
};
}
/**
* Describes a tool
*/
describeTool(params) {
if (!params || typeof params !== "object" || !("name" in params)) {
throw new Error("Invalid params: name required");
}
const { name } = params;
const tool = this.toolRegistry.getTool(name);
if (!tool) {
throw new Error(`Tool not found: ${name}`);
}
return {
name: tool.name,
description: tool.description,
inputSchema: tool.inputSchema,
};
}
}
//# sourceMappingURL=router.js.map