Skip to main content
Glama
tool-registry.ts3.9 kB
import { ServerCapabilities, CallToolParams, CallToolResult, ErrorCodes } from './protocol-types.js'; import { McpProtocolError } from './base-server.js'; export interface ToolDefinition { name: string; description: string; inputSchema?: any; execute: (args: any) => Promise<any>; } export class ToolRegistry { private tools: Map<string, ToolDefinition> = new Map(); constructor() {} /** * Register a new tool with the registry */ public registerTool(tool: ToolDefinition): void { if (this.tools.has(tool.name)) { throw new Error(`Tool '${tool.name}' is already registered`); } this.tools.set(tool.name, tool); } /** * Get the capabilities object for all registered tools */ public getCapabilities(): ServerCapabilities { const tools: ServerCapabilities['tools'] = {}; for (const [name, tool] of this.tools.entries()) { tools[name] = { description: tool.description, inputSchema: tool.inputSchema }; } return { tools }; } /** * Execute a tool by name with the provided arguments */ public async executeTool(params: CallToolParams): Promise<CallToolResult> { const tool = this.tools.get(params.name); if (!tool) { throw new McpProtocolError( ErrorCodes.MethodNotFound, `Tool '${params.name}' not found` ); } try { // Validate input if schema is provided if (tool.inputSchema) { this.validateInput(params.arguments, tool.inputSchema); } // Execute the tool const result = await tool.execute(params.arguments); // Format the result return this.formatResult(result); } catch (error) { if (error instanceof McpProtocolError) { throw error; } throw new McpProtocolError( ErrorCodes.InternalError, error instanceof Error ? error.message : 'Tool execution failed' ); } } /** * Validate tool input against its schema */ private validateInput(input: any, schema: any): void { // Basic schema validation // In a production environment, you would use a proper JSON Schema validator if (schema.type === 'object' && typeof input !== 'object') { throw new McpProtocolError( ErrorCodes.InvalidParams, 'Input must be an object' ); } if (schema.required) { for (const required of schema.required) { if (!(required in input)) { throw new McpProtocolError( ErrorCodes.InvalidParams, `Missing required parameter: ${required}` ); } } } } /** * Format tool execution result into standard response format */ private formatResult(result: any): CallToolResult { // If result is already in CallToolResult format, return as is if ( typeof result === 'object' && result !== null && Array.isArray(result.content) ) { return result; } // Convert simple result to standard format let content = result; if (typeof result !== 'string') { content = JSON.stringify(result, null, 2); } return { content: [ { type: 'text', text: content } ] }; } /** * Check if a tool exists */ public hasTool(name: string): boolean { return this.tools.has(name); } /** * Get a tool definition by name */ public getTool(name: string): ToolDefinition | undefined { return this.tools.get(name); } /** * List all registered tools */ public listTools(): ToolDefinition[] { return Array.from(this.tools.values()); } /** * Remove a tool from the registry */ public unregisterTool(name: string): boolean { return this.tools.delete(name); } /** * Clear all registered tools */ public clear(): void { this.tools.clear(); } }

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/docherty/contextmgr-mcp'

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