Initial Checks
Description
When a Streamable HTTP server is configured with stateless_http=True, GET /mcp is still accepted and opens an SSE stream that has no session context and can never receive server-initiated messages — a dead-end.
The MCP Streamable HTTP spec explicitly permits returning 405 Method Not Allowed when the server does not offer an SSE stream at the endpoint
(spec):
The server MUST return HTTP 405 Method Not Allowed if an SSE stream is
not offered at the endpoint.
A stateless server cannot offer one — there is no session to push to — so GET should 405. The TypeScript SDK already behaves this way in its stateless example.
A prior PR (#2262) proposed essentially this change but was closed for lack of a corresponding issue per CONTRIBUTING.md.
Opening this issue to agree on scope so the fix can be re-submitted.
Example Code
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("my-server", stateless_http=True, json_response=True)
@mcp.tool()
def ping() -> str:
return "pong"
app = mcp.streamable_http_app()
A couple of clarifications for triage:
Current vs expected behavior
Today (v1.27.0):
$ curl -i -X GET http://localhost:8000/mcp
HTTP/1.1 200 OK
content-type: text/event-stream
... (stream idles until platform timeout)
Expected:
$ curl -i -X GET http://localhost:8000/mcp
HTTP/1.1 405 Method Not Allowed
Allow: POST
Concrete impact
The idle GET SSE stream holds a long-lived connection per client with no useful payload, exhausting concurrent connection limits on serverless platforms like Cloud Run. Background previously raised in #2232 / #1941.
Proposed resolution
PR #2262 already has a working implementation. Once this issue is labeled ready for work, reopening it (narrowed to GET per this issue's scope) should be sufficient — no new PR needed.
Python & MCP Python SDK
Initial Checks
Description
When a Streamable HTTP server is configured with
stateless_http=True,GET /mcpis still accepted and opens an SSE stream that has no session context and can never receive server-initiated messages — a dead-end.The MCP Streamable HTTP spec explicitly permits returning
405 Method Not Allowedwhen the server does not offer an SSE stream at the endpoint(spec):
A stateless server cannot offer one — there is no session to push to — so GET should 405. The TypeScript SDK already behaves this way in its stateless example.
A prior PR (#2262) proposed essentially this change but was closed for lack of a corresponding issue per CONTRIBUTING.md.
Opening this issue to agree on scope so the fix can be re-submitted.
Example Code
A couple of clarifications for triage:
Current vs expected behavior
Today (v1.27.0):
Expected:
Concrete impact
The idle GET SSE stream holds a long-lived connection per client with no useful payload, exhausting concurrent connection limits on serverless platforms like Cloud Run. Background previously raised in #2232 / #1941.
Proposed resolution
PR #2262 already has a working implementation. Once this issue is labeled
ready for work, reopening it (narrowed to GET per this issue's scope) should be sufficient — no new PR needed.Python & MCP Python SDK