From b6bb74ed9fbb58533bf7707e0cdb9dff176447fc Mon Sep 17 00:00:00 2001 From: Edgar Arakelyan Date: Sun, 18 Oct 2026 16:25:57 -0700 Subject: [PATCH] fix(mcp): close the listener before dropping open connections closeAllConnections() ran before close(), so a connection accepted in between missed the forced-close pass and close() could wait for its request timeout. close() now starts first and closeAllConnections() follows immediately, as Node documents. Co-Authored-By: Claude Opus 5.5 --- src/server/http/serveStreamableHttp.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/server/http/serveStreamableHttp.ts b/src/server/http/serveStreamableHttp.ts index a134bacc57..2a90062040 100644 --- a/src/server/http/serveStreamableHttp.ts +++ b/src/server/http/serveStreamableHttp.ts @@ -385,16 +385,18 @@ export const serveStreamableHttp = async ( return { url, close }; }; -/** Drop open connections and release the port. */ +/** Stop accepting, drop open connections and release the port. */ const closeHttpServer = ( httpServer: ReturnType, ): Promise => { - httpServer.closeAllConnections(); - return new Promise((resolve, reject) => { + // close() first, as Node documents: a connection accepted before it would otherwise miss the forced-close pass. + const closed = new Promise((resolve, reject) => { httpServer.close((error) => error === undefined ? resolve() : reject(error), ); }); + httpServer.closeAllConnections(); + return closed; }; /** Translate one node:http exchange through `route`, logging a failure and answering it when headers are still open. */