-
Notifications
You must be signed in to change notification settings - Fork 212
fix(mcp): treat 404 as 405 for streamable-http SSE GET #1080
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
nh2
wants to merge
1
commit into
Zoo-Code-Org:main
Choose a base branch
from
nh2:mcp-404-504-fallback
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+30
−0
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
Repository: Zoo-Code-Org/Zoo-Code
Length of output: 6673
🏁 Script executed:
Repository: Zoo-Code-Org/Zoo-Code
Length of output: 11695
🌐 Web query:
MCP Streamable HTTP transport GET 404 MCP-Session-Id expired session 405💡 Result:
The HTTP status codes 404 and 405 within the Model Context Protocol (MCP) Streamable HTTP transport have specific, distinct roles defined by the protocol specification [1][2]. HTTP 404 (Not Found) and Session Expiration When a server receives a request containing an MCP-Session-Id that it no longer recognizes—often because the session has expired or been terminated—it must return an HTTP 404 status code [3][1]. Upon receiving this 404, a compliant client is required to: 1. Clear the stale session ID [4][5]. 2. Initiate a new session by sending a fresh initialize request without any session ID attached [3][1]. Some client SDK implementations have historically struggled to handle this correctly, failing to clear the session ID before retrying, which leads to persistent 404 errors [4][5]. HTTP 405 (Method Not Allowed) The HTTP 405 status code is used to indicate that the requested HTTP method (such as GET or DELETE) is not supported at the targeted MCP endpoint [3][1]. - GET Requests: If a server does not offer a Server-Sent Events (SSE) stream at the MCP endpoint, it must return 405 for GET requests [3][1]. This is particularly common in stateless server configurations where no session exists to support server-initiated messages [6][7][8]. - DELETE Requests: If a server does not permit clients to explicitly terminate sessions, it may return 405 in response to a DELETE request [3][1]. In summary, 404 indicates a session-level state mismatch (the session is gone), while 405 indicates a transport-level capability mismatch (the method is not allowed) [3][1].
Citations:
🌐 Web query:
MCP 2025-11-25 transports Section session management 404 MCP-Session-Id💡 Result:
Under the Model Context Protocol (MCP) specification dated 2025-11-25, session management for the Streamable HTTP transport was handled via the Mcp-Session-Id header [1][2][3]. The specification explicitly defined how servers and clients must handle session IDs, including the use of HTTP 404 Not Found to signal that a session is no longer valid [1][2][3]. Specifically, per the 2025-11-25 specification: - If a server terminates a session, it must respond to any subsequent requests using that session ID with HTTP 404 Not Found [1][3]. - Upon receiving an HTTP 404 response for a request containing an Mcp-Session-Id, a client is required to start a new session by sending a new InitializeRequest without a session ID [1][3][4]. - This behavior was intended to differentiate between invalid/expired sessions (404) and missing session IDs in requests that require them (which should trigger an HTTP 400 Bad Request) [5][6]. Important Context: As of July 2026, the Model Context Protocol has evolved away from this stateful, session-based architecture [7]. In the latest specification updates (post-2025-11-25), the protocol-level concept of sessions and the Mcp-Session-Id header have been removed (SEP-2567) to enable a completely stateless protocol [8][7]. Servers that need to maintain state across calls now use explicit handles passed as arguments within tool calls, rather than relying on transport-layer sessions [7].
Citations:
🌐 Web query:
MCP spec 2025-11-25 transports 404 GET Last-Event-ID resumed stream💡 Result:
In the Model Context Protocol (MCP) specification version 2025-11-25, resumable SSE streams using the Last-Event-ID header were a supported feature of the Streamable HTTP transport [1][2]. The specification defined that if a client was disconnected, it should issue an HTTP GET request to the MCP endpoint, including the Last-Event-ID header [1][2]. The server was then permitted to use this ID to replay messages from the specific stream that was disconnected and resume the stream from that point [1][2]. Additionally, the server could proactively close connections (without terminating the stream) to save resources, relying on the client to reconnect using this mechanism [1][2]. However, it is important to note that this mechanism is no longer part of the current protocol as of later revisions (such as 2026-07-28) [3]. In these newer versions, resumable SSE streams via Last-Event-ID are explicitly not supported, and servers are instructed to ignore the Last-Event-ID header [3]. Regarding the HTTP 404 response mentioned in your query: in the 2025-11-25 specification, servers could terminate sessions at any time, after which they were required to respond to requests using that session ID with an HTTP 404 Not Found error [4][5]. When a client received this 404, it was required to initiate a new session by sending a new InitializeRequest [4][5]. In current versions of the specification, if a server does not implement a requested method, it must respond with 404 Not Found along with a specific JSON-RPC error code (-32601) to distinguish it from legacy 404 responses [3].
Citations:
Do not rewrite session-bound
GET/404responses as405.This wrapper normalizes every Streamable HTTP GET/404 before checking session context. A GET with
MCP-Session-Idthat returns404indicates an expired or terminated session, so the client must start a new session rather than treat it as “no SSE stream.” If the GET includes resumption context,404can also mean resumption failed. Scope the normalization to the initial optional SSE probe, or add session/resumption-aware recovery before rewriting the status.🤖 Prompt for AI Agents