From 52ac301711d888db4a5929e6befd1433fca9d55a Mon Sep 17 00:00:00 2001 From: billythegod <1906308+billythegod@users.noreply.github.com> Date: Tue, 20 Oct 2026 22:13:10 +0800 Subject: [PATCH] fix(server): deliver in-flight tool responses before closing transports Wait for tracked tool activities before closing the MCP handler during graceful shutdown, and yield to the macrotask queue so the JSON-RPC response chain settles first; previously in-flight tool call responses were rejected as HTTP 499 even though their side effects completed. --- src/server.test.ts | 8 +++++++- src/server.ts | 7 ++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/server.test.ts b/src/server.test.ts index 59bcc5d37..8979b831f 100644 --- a/src/server.test.ts +++ b/src/server.test.ts @@ -632,7 +632,13 @@ test("server shutdown waits for an active MCP tool call", async (t) => { assert.equal(shutdownFinished, false); await writeFile(join(root, "release"), ""); - await toolCall; + const response = await toolCall; + assert.equal(response.status, 200, await response.clone().text()); + const responseBody = await response.json() as { + result?: { structuredContent?: { exit_code?: number; running?: boolean } }; + }; + assert.equal(responseBody.result?.structuredContent?.exit_code, 0); + assert.equal(responseBody.result?.structuredContent?.running, false); await shutdown; assert.equal(shutdownFinished, true); }); diff --git a/src/server.ts b/src/server.ts index 0a2792f3f..58496d27a 100644 --- a/src/server.ts +++ b/src/server.ts @@ -966,6 +966,12 @@ export function createServer( localAgentProviders, close: () => { closePromise ??= (async () => { + await toolActivities.waitForIdle(); + // Tool handlers resolving only starts the JSON-RPC response chain; + // it settles several microtasks later. Yield to the macrotask queue + // so in-flight responses are delivered before mcpHandler.close() + // rejects their still-open exchanges (HTTP 499). + await new Promise((resolve) => setImmediate(resolve)); try { await mcpHandler.close(); } catch (error) { @@ -973,7 +979,6 @@ export function createServer( error: error instanceof Error ? error.message : String(error), }); } - await toolActivities.waitForIdle(); processSessions.shutdown(); oauthProvider.close(); workspaceStore.close?.();