Repository navigation
[v2] Allow MCPServer to disable subscriptions/listen #3357
Description
Activity
I had this exact issue yesterday as well. Bump! ^^
Wow! Coincidentally I have the exact same issue! Would really love this resolved, cause leads to some confusing situations
- addedv2Affects the v2 line (2.x on main)Affects the v2 line (2.x on main)spec-2026-07-28Concerns the SDK's implementation of the 2026-07-28 MCP spec revisionConcerns the SDK's implementation of the 2026-07-28 MCP spec revision
on Aug 21, 2026 Might actually be better off mirroring the Go SDK here and passing
ServerCapabilitiesas a parameter instead ofenable_subscriptions=False.Serverdoesn't currently take capabilities as param, but this should be an easy fix.Reacted by mikervaIndependent reproduction of the same problem, same stack (stateless Streamable HTTP on AWS Lambda, clients = Claude Code 2.1.2xx and a hosted connector). Details, a Lambda-free reproduction script and production numbers are in #3493 — filed before I found this issue, so treat #3357 as the primary and #3493 as supporting data:
- 19 of 19
subscriptions/listenPOSTs in a 30-minute sample never completed (ack event, then the stream stays open); every other method completed in milliseconds. - ~1,300–1,800 invocations/day ran to the 900 s Lambda timeout because of this — 99% of the function's billed GB-seconds — and clients re-sent listen immediately after each timeout, so the streams were permanently occupied.
server/discoveradvertisedlistChanged: true/subscribe: truefor a server that never publishes anything.
Our workaround (works on 2.1.1 and 2.2.0, but relies on private attributes):
mcp._lowlevel_server._request_handlers.pop("subscriptions/listen"). With the handler gone,get_capabilities()flips tolistChanged: false / subscribe: falseand a listen POST gets the standard404+-32601; the TypeScript client treats that as a soft error and the connection keeps working.+1 to a public knob. Either an explicit flag or a
ServerCapabilitiesparameter (as suggested above) would do, as long asget_capabilities()follows it.- 19 of 19
Independent verification from XBSTACK on 2026-09-20 confirms the same behavior on both
mcp==2.1.1andmcp==2.2.0with a minimal local Streamable HTTP harness (no Lambda required).Observed:
server/discoveradvertiseslistChanged/subscribe=trueby default.subscriptions/listenstays open beyond the test window when no disconnect is propagated.- Removing the private
subscriptions/listenhandler flips the advertised subscription capability off and the same listen call returns-32601 Method not foundimmediately. - The containment works, but it depends on
_lowlevel_server._request_handlers, so it is not a supported long-term solution.
Repro, logs, and version matrix:
https://github.com/xbstack/mcp-subscriptions-listen-serverless-reproRelated deployment notes:
https://www.xbstack.com/ai/mcp-streamable-http-deployment/?utm_source=github&utm_medium=referral&utm_campaign=mcp_subscriptions_listen_serverless&utm_content=issue_reply&ref=githubThis supports the request for a public capability/opt-out surface rather than relying on middleware rejection or private handler mutation.
I had this exact issue yesterday as well. Bump! ^^
MCPServer(..., subscriptions=False)landed in #3626. Thanks for the clear report, and to everyone who added numbers and repros.It leaves
subscriptions/listenunregistered, soserver/discoverreports thelistChangedandsubscribeflags as false and a stray listen call gets Method not found. The default is unchanged. Turning it off has an example.Once it's released, you can drop the
_lowlevel_server._request_handlersworkaround.The
ServerCapabilities-style parameter suggested above isn't part of this. It fits better with the capabilities work in #2896.If it doesn't cover your setup, feel free to open a new issue.
1320800521 commented
on Oct 8, 2026 More actionsXBSTACK follow-up to our September
mcp==2.1.1/2.2.0reproductions: the official Python SDK v2.3.0 release notes now explicitly includeMCPServer(subscriptions=False)from #3626. For a static/serverless MCP server, this is the supported opt-out to test instead of deleting_lowlevel_server._request_handlersprivately. After upgrading, please verifyserver/discoveradvertises the expected false capabilities, an unsolicitedsubscriptions/listenis rejected, and your real client and adapter behave correctly. Note the v2.3.0httpx2>=2.10.0requirement too.Our existing measurements cover 2.1.1 / 2.2.0 only; we have not yet rerun a production Lambda integration on 2.3.0. We've updated the bilingual deployment troubleshooting guide with that boundary: https://www.xbstack.com/en/ai/mcp-streamable-http-deployment/?utm_source=github&utm_medium=referral&utm_campaign=mcp_subscriptions_optout_v230&utm_content=issue_followup
Initial Checks
Release line
2.x (current stable)
Description
What happened?
MCPServeralways installs asubscriptions/listenhandler:The constructor exposes
subscriptions: SubscriptionBus | None = None, butNonecreates anInMemorySubscriptionBus; it does not disable subscriptions.This causes
server/discoverto advertise:{ "tools": {"listChanged": true}, "prompts": {"listChanged": true}, "resources": {"listChanged": true, "subscribe": true} }Our MCP server has a static catalog and never publishes change notifications. It runs as a stateless Streamable HTTP server on AWS Lambda.
Claude Code 2.1.235 automatically opened four subscriptions/listen streams during discovery. Each request followed the long-lived SSE path and held a Lambda invocation until timeout.
We currently reject these requests in ASGI middleware. This prevents the timeout, but the server still advertises subscription support, so clients continue attempting the requests.
The low-level Server supports disabling this correctly through:
The high-level
MCPServerhas no equivalent public option. Removing the handler through_lowlevel_server._request_handlersworks, but relies on private internals.What did you expect?
MCPServershould provide a supported opt-out, for example:or:
When disabled:
subscriptions/listenshould not be registered.This matches SEP-2575’s stateless-first, “pay as you go” design. Long-lived streams should only be enabled when the server uses them.
Area
ServerReferences
AI assistance disclosure: I used an AI coding assistant to inspect the SDK source and help draft this report. I reviewed and verified the contents.
Example Code
Python & MCP Python SDK