diff --git a/src/server/mcp.test.ts b/src/server/mcp.test.ts index 4bb42d7fc..0ff01ba0b 100644 --- a/src/server/mcp.test.ts +++ b/src/server/mcp.test.ts @@ -505,6 +505,80 @@ describe('tool()', () => { ]); }); + /*** + * Test: Tool disable, enable, and remove via tool instance + */ + test('should manage tool when using tool instance', async () => { + const mcpServer = new McpServer({ + name: 'test server', + version: '1.0' + }); + + // Register initial tool + const tool = mcpServer.tool('test', async () => ({ + content: [ + { + type: 'text', + text: 'Test response' + } + ] + })); + + expect(mcpServer['_registeredTools'].test).toBeDefined(); + + // Now disable the tool + tool.disable(); + + expect(mcpServer['_registeredTools'].test.enabled).toBe(false); + + // Now enable the tool + tool.enable(); + + expect(mcpServer['_registeredTools'].test.enabled).toBe(true); + + // Now delete the tool + tool.remove(); + + expect(mcpServer['_registeredTools'].test).toBeUndefined(); + }); + + /*** + * Test: Tool disable, enable, and remove via server instance + */ + test('should manage tool when using server instance', async () => { + const mcpServer = new McpServer({ + name: 'test server', + version: '1.0' + }); + + // Register initial tool + mcpServer.tool('test', async () => ({ + content: [ + { + type: 'text', + text: 'Test response' + } + ] + })); + + expect(mcpServer['_registeredTools'].test).toBeDefined(); + + // Now disable the tool + mcpServer.disableTool('test'); + + expect(mcpServer['_registeredTools'].test.enabled).toBe(false); + + // Now enable the tool + mcpServer.enableTool('test'); + + expect(mcpServer['_registeredTools'].test.enabled).toBe(true); + + // Now delete the tool + mcpServer.removeTool('test'); + + expect(mcpServer['_registeredTools'].test).toBeUndefined(); + }); + /*** * Test: Tool Registration with Parameters */ diff --git a/src/server/mcp.ts b/src/server/mcp.ts index cef1722d6..8b638326b 100644 --- a/src/server/mcp.ts +++ b/src/server/mcp.ts @@ -816,6 +816,50 @@ export class McpServer { ); } + /** + * Enables a tool from the server by name. + * Does nothing if the tool is not registered. + */ + enableTool(name: string) { + const tool = this._registeredTools[name]; + if (tool) { + tool.enable(); + } + } + + /** + * Disables a tool from the server by name. + * Does nothing if the tool is not registered. + */ + disableTool(name: string) { + const tool = this._registeredTools[name]; + if (tool) { + tool.disable(); + } + } + + /** + * Updates a tool from the server by name. + * Does nothing if the tool is not registered. + */ + updateTool(name: string, updates: ToolUpdates) { + const tool = this._registeredTools[name]; + if (tool) { + tool.update(updates); + } + } + + /** + * Removes a tool from the server by name. + * Does nothing if the tool is not registered. + */ + removeTool(name: string) { + const tool = this._registeredTools[name]; + if (tool) { + tool.update({ name: null }); + } + } + /** * Registers a zero-argument prompt `name`, which will run the given function when the client calls it. */ @@ -1018,6 +1062,18 @@ export type ToolCallback = Arg ) => CallToolResult | Promise : (extra: RequestHandlerExtra) => CallToolResult | Promise; +export type ToolUpdates = { + name?: string | null; + title?: string; + description?: string; + paramsSchema?: InputArgs; + outputSchema?: OutputArgs; + annotations?: ToolAnnotations; + _meta?: Record; + callback?: ToolCallback; + enabled?: boolean; +}; + export type RegisteredTool = { title?: string; description?: string; @@ -1029,17 +1085,7 @@ export type RegisteredTool = { enabled: boolean; enable(): void; disable(): void; - update(updates: { - name?: string | null; - title?: string; - description?: string; - paramsSchema?: InputArgs; - outputSchema?: OutputArgs; - annotations?: ToolAnnotations; - _meta?: Record; - callback?: ToolCallback; - enabled?: boolean; - }): void; + update(updates: ToolUpdates): void; remove(): void; };