From 824e914eb124ca66d8c131ef6b8fc447debe5c60 Mon Sep 17 00:00:00 2001 From: Ben Senescu <44480372+bensenescu@users.noreply.github.com> Date: Wed, 26 Aug 2026 11:48:20 -0400 Subject: [PATCH] =?UTF-8?q?fix(mcp):=20refuse=20subscriptions/listen=20str?= =?UTF-8?q?eams=20=E2=80=94=20MCP=20serving=20is=20stateless=20(EVE-95)=20?= =?UTF-8?q?(#548)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/server/mcp/server.ts | 5 +++++ src/server/mcp/transport.ts | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/src/server/mcp/server.ts b/src/server/mcp/server.ts index bc5f858..806d1d5 100644 --- a/src/server/mcp/server.ts +++ b/src/server/mcp/server.ts @@ -143,6 +143,11 @@ export function createOpenSeoMcpServer(authProps: McpProps) { ], }, { + // The tool list is fixed per request and no list_changed notification + // is ever published, so don't advertise the capability — modern clients + // use it to decide whether to open a subscriptions/listen stream. + // Without the pre-declaration, registerTool defaults it to true. + capabilities: { tools: { listChanged: false } }, instructions: "OpenSEO research tools use credits. Proceed with normal focused research, but ask the user for confirmation before planned batches over 2,000 credits.", }, diff --git a/src/server/mcp/transport.ts b/src/server/mcp/transport.ts index de1cd02..42faef3 100644 --- a/src/server/mcp/transport.ts +++ b/src/server/mcp/transport.ts @@ -128,6 +128,12 @@ function createRequestHandler( route: MCP_ROUTE, allowedOriginHostnames, legacy: "reject", + // MCP serving is strictly stateless: no notification is ever published, + // so refuse subscriptions/listen outright (in-band -32603 before the + // ack). The SSE streams it would otherwise hold open pin isolates for + // hours and turn every isolate death into a burst of exceededMemory + // request outcomes (EVE-95). + maxSubscriptions: 0, }); return async (request: Request, env: unknown, ctx: ExecutionContext) => {