/**
* Tool Registry
*
* Central registry for managing MCP tools.
* Supports dynamic tool registration and lookup.
*/
/**
* Tool registry for managing available tools
*/
export class ToolRegistry {
tools = new Map();
logger;
constructor(logger) {
this.logger = logger;
}
/**
* Register a tool with its handler
*
* @param definition - Tool definition
* @param handler - Tool execution handler
*/
register(definition, handler) {
if (this.tools.has(definition.name)) {
this.logger.warn('Tool already registered, overwriting', {
toolName: definition.name,
});
}
this.tools.set(definition.name, {
definition,
handler,
});
this.logger.info('Tool registered', {
toolName: definition.name,
});
}
/**
* Unregister a tool
*
* @param toolName - Name of tool to remove
* @returns true if tool was removed, false if not found
*/
unregister(toolName) {
const removed = this.tools.delete(toolName);
if (removed) {
this.logger.info('Tool unregistered', { toolName });
}
else {
this.logger.warn('Attempted to unregister non-existent tool', { toolName });
}
return removed;
}
/**
* Get all registered tool definitions
*
* @returns Array of tool definitions
*/
getToolDefinitions() {
return Array.from(this.tools.values()).map((tool) => tool.definition);
}
/**
* Get a tool handler by name
*
* @param toolName - Name of tool
* @returns Tool handler or undefined if not found
*/
getHandler(toolName) {
return this.tools.get(toolName)?.handler;
}
/**
* Check if a tool is registered
*
* @param toolName - Name of tool
* @returns true if tool exists
*/
has(toolName) {
return this.tools.has(toolName);
}
/**
* Get count of registered tools
*
* @returns Number of tools
*/
count() {
return this.tools.size;
}
/**
* Execute a tool by name
*
* @param toolName - Name of tool to execute
* @param args - Tool arguments
* @returns Tool result
* @throws Error if tool not found
*/
async execute(toolName, args) {
const handler = this.getHandler(toolName);
if (!handler) {
this.logger.error('Tool not found', new Error(`Tool not found: ${toolName}`), {
toolName,
availableTools: Array.from(this.tools.keys()),
});
throw new Error(`Tool not found: ${toolName}`);
}
this.logger.debug('Executing tool', {
toolName,
args,
});
try {
const result = await handler(args);
this.logger.debug('Tool executed successfully', {
toolName,
});
return result;
}
catch (error) {
this.logger.error('Tool execution failed', error instanceof Error ? error : new Error(String(error)), {
toolName,
args,
});
throw error;
}
}
}
/**
* Factory function to create tool registry
*/
export function createToolRegistry(logger) {
return new ToolRegistry(logger);
}