From d5f2229c42b7b9f465084cffc192133071f96a78 Mon Sep 17 00:00:00 2001 From: Genmin Date: Wed, 29 Apr 2026 16:28:07 -0700 Subject: [PATCH 1/5] fix: debounce MCP list changed notifications --- packages/server/src/server/mcp.ts | 13 +++++++++- test/integration/test/server/mcp.test.ts | 32 ++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/packages/server/src/server/mcp.ts b/packages/server/src/server/mcp.ts index fb45fd5db6..6a4da4df89 100644 --- a/packages/server/src/server/mcp.ts +++ b/packages/server/src/server/mcp.ts @@ -47,6 +47,12 @@ import { getCompleter, isCompletable } from './completable.js'; import type { ServerOptions } from './server.js'; import { Server } from './server.js'; +const DEFAULT_DEBOUNCED_NOTIFICATION_METHODS = [ + 'notifications/resources/list_changed', + 'notifications/tools/list_changed', + 'notifications/prompts/list_changed' +]; + /** * High-level MCP server that provides a simpler API for working with resources, tools, and prompts. * For advanced usage (like sending notifications or setting custom request handlers), use the underlying @@ -75,7 +81,12 @@ export class McpServer { private _experimental?: { tasks: ExperimentalMcpServerTasks }; constructor(serverInfo: Implementation, options?: ServerOptions) { - this.server = new Server(serverInfo, options); + this.server = new Server(serverInfo, { + ...options, + debouncedNotificationMethods: [ + ...new Set([...DEFAULT_DEBOUNCED_NOTIFICATION_METHODS, ...(options?.debouncedNotificationMethods ?? [])]) + ] + }); } /** diff --git a/test/integration/test/server/mcp.test.ts b/test/integration/test/server/mcp.test.ts index 92af09744c..d07c45fd96 100644 --- a/test/integration/test/server/mcp.test.ts +++ b/test/integration/test/server/mcp.test.ts @@ -809,6 +809,38 @@ describe('Zod v4', () => { ]); }); + test('should debounce synchronous tool list changed notifications', async () => { + const mcpServer = new McpServer({ + name: 'test server', + version: '1.0' + }); + const notifications: Notification[] = []; + const client = new Client({ + name: 'test client', + version: '1.0' + }); + client.fallbackNotificationHandler = async notification => { + notifications.push(notification); + }; + + mcpServer.registerTool('initial', {}, async () => ({ + content: [{ type: 'text', text: 'Initial response' }] + })); + + const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair(); + await Promise.all([client.connect(clientTransport), mcpServer.connect(serverTransport)]); + + for (let i = 0; i < 20; i++) { + mcpServer.registerTool(`tool-${i}`, {}, async () => ({ + content: [{ type: 'text', text: `Tool ${i} response` }] + })); + } + + await new Promise(process.nextTick); + + expect(notifications).toMatchObject([{ method: 'notifications/tools/list_changed' }]); + }); + /*** * Test: listChanged capability should default to true when not specified */ From 30d4ff1a0acec532b5640a3f77c642d6eb3d02a0 Mon Sep 17 00:00:00 2001 From: Genmin Date: Thu, 30 Apr 2026 07:39:47 -0700 Subject: [PATCH 2/5] chore: add list notification changeset --- .changeset/fix-debounce-list-changed-notifications.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/fix-debounce-list-changed-notifications.md diff --git a/.changeset/fix-debounce-list-changed-notifications.md b/.changeset/fix-debounce-list-changed-notifications.md new file mode 100644 index 0000000000..8c47acbb11 --- /dev/null +++ b/.changeset/fix-debounce-list-changed-notifications.md @@ -0,0 +1,6 @@ +--- +"@modelcontextprotocol/server": patch +"@modelcontextprotocol/test-integration": patch +--- + +fix(server): debounce list changed notifications From 7ffea597cd80766c5e9d8db2800164af62ecc51d Mon Sep 17 00:00:00 2001 From: Genmin Date: Thu, 30 Apr 2026 10:04:13 -0700 Subject: [PATCH 3/5] chore: retry transient CI From 7ef708ac61fad6b7e41db6970adab3cd1756a9ee Mon Sep 17 00:00:00 2001 From: Genmin Date: Thu, 30 Apr 2026 10:23:22 -0700 Subject: [PATCH 4/5] chore: retry transient Cloudflare worker CI From a89aa4f7cd3ffd0490ecc5da5ab830a187458b5f Mon Sep 17 00:00:00 2001 From: Genmin Date: Thu, 30 Apr 2026 10:35:02 -0700 Subject: [PATCH 5/5] chore: retry transient Miniflare CI