From ab4b16f46a3cd14e70234a1c048e1076f0a1ab43 Mon Sep 17 00:00:00 2001 From: Yufeng He <40085740+he-yufeng@users.noreply.github.com> Date: Sat, 30 May 2026 18:45:57 +0800 Subject: [PATCH] fix(server): handle empty declared lists --- packages/server/src/server/mcp.ts | 9 ++++ test/integration/test/server/mcp.test.ts | 65 ++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/packages/server/src/server/mcp.ts b/packages/server/src/server/mcp.ts index fb45fd5db6..573c54e671 100644 --- a/packages/server/src/server/mcp.ts +++ b/packages/server/src/server/mcp.ts @@ -76,6 +76,15 @@ export class McpServer { constructor(serverInfo: Implementation, options?: ServerOptions) { this.server = new Server(serverInfo, options); + if (options?.capabilities?.tools) { + this.setToolRequestHandlers(); + } + if (options?.capabilities?.resources) { + this.setResourceRequestHandlers(); + } + if (options?.capabilities?.prompts) { + this.setPromptRequestHandlers(); + } } /** diff --git a/test/integration/test/server/mcp.test.ts b/test/integration/test/server/mcp.test.ts index 92af09744c..4537223078 100644 --- a/test/integration/test/server/mcp.test.ts +++ b/test/integration/test/server/mcp.test.ts @@ -1280,6 +1280,71 @@ describe('Zod v4', () => { mcpServer.registerTool('tool2', {}, () => ({ content: [] })); }); + test('should list no tools when the tools capability is declared without registrations', async () => { + const mcpServer = new McpServer( + { + name: 'test server', + version: '1.0' + }, + { capabilities: { tools: {} } } + ); + const client = new Client({ + name: 'test client', + version: '1.0' + }); + + const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair(); + await Promise.all([client.connect(clientTransport), mcpServer.server.connect(serverTransport)]); + + const result = await client.request({ method: 'tools/list' }); + + expect(result.tools).toEqual([]); + }); + + test('should list no prompts when the prompts capability is declared without registrations', async () => { + const mcpServer = new McpServer( + { + name: 'test server', + version: '1.0' + }, + { capabilities: { prompts: {} } } + ); + const client = new Client({ + name: 'test client', + version: '1.0' + }); + + const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair(); + await Promise.all([client.connect(clientTransport), mcpServer.server.connect(serverTransport)]); + + const result = await client.request({ method: 'prompts/list' }); + + expect(result.prompts).toEqual([]); + }); + + test('should list no resources when the resources capability is declared without registrations', async () => { + const mcpServer = new McpServer( + { + name: 'test server', + version: '1.0' + }, + { capabilities: { resources: {} } } + ); + const client = new Client({ + name: 'test client', + version: '1.0' + }); + + const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair(); + await Promise.all([client.connect(clientTransport), mcpServer.server.connect(serverTransport)]); + + const resources = await client.request({ method: 'resources/list' }); + const templates = await client.request({ method: 'resources/templates/list' }); + + expect(resources.resources).toEqual([]); + expect(templates.resourceTemplates).toEqual([]); + }); + /*** * Test: Tool with Output Schema and Structured Content */