-
Notifications
You must be signed in to change notification settings - Fork 212
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
[RFC] Replace HTTP+SSE with new "Streamable HTTP" transport #206
Conversation
Firstly - thanks for the effort in driving this forward 🙃
An alternative would be for the header to be set on the first response after the initialise request and then for the client to reuse/share it in whatever way they deem appropriate for their use-case. |
I completely agree with this decision. While WebSocket and other transports will certainly be needed for some use cases, perhaps a separate "Extended" working group could be officially created and maintained by the community to address these needs - similar to how we could have Core and Extended working groups in the future. |
Related to the point discussed above about session IDs I think it would be reasonable to ensure that either session IDs are communicated in a way that make routing on a basic load balancer possible or a separate header is added that enables that. (That’s for folks who do not have fancy-pantsy durable objects ;)) |
This comment was marked as off-topic.
This comment was marked as off-topic.
`text/event-stream` as supported content types. | ||
- The server **MUST** either return `Content-Type: text/event-stream`, to initiate an | ||
SSE stream, or `Content-Type: application/json`, to return a single JSON-RPC | ||
_response_. The client **MUST** support both these cases. |
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.
Given that EventSource
already does not support POST requests meaning that fetch
will have to be used by browser-based clients, why not go all the way and allow more than one JSON-RPC message in POST request's streaming request body? That's certainly where my mind goes to when renaming the transport from "HTTP with SSE" to "Streamable HTTP".
While this wouldn't solve the resumability issue by itself, it would vastly simplify the transport. It would be much closer to the stdio transport, and it could potentially support binary data.
And I think it would help with the resumability issue. It greatly simplifies resumability to only have one logical stream per connection like the stdio transport does. That way, you're not stuck managing multiple last-message-ids on the server which seems like a pain.
If a core design principal is that clients should handle complexity where it exists, I'd suggest forcing the client to only have one resumable server-to-client message stream at a time.
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.
JSON-RPC supports batching. You can pass an array of requests as a JSON-RPC body.
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.
FWIW - in OpenID Provider Commands we are proposing a POST that returns either application/json or text/event-stream https://openid.github.io/openid-provider-commands/main.html
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.
Supporting batched client -> server messages makes sense! I honestly had forgotten that aspect of JSON-RPC, since we ignored it for so long. 😬
I would like to extend support to streaming request bodies, but I think we should kick the can on this a bit, as it will probably involve significant discussion of its own.
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.
I'll punt on batching in this PR as well, as it also affects the stdio transport and has some wider-ranging implications, but basically I agree we should support it.
So this wouldd be bringing httptreansport and quic protocol to the mix? |
This comment was marked as spam.
This comment was marked as spam.
Super excited to see this through. P.S. @jirispilka The schema.ts link in the release notes is broken. Sending in a PR #248 |
Came here looking for this! Awaiting the SDKs to enable Streamable HTTP 🤓 |
Am sure the official ones will be along soon, but If you're working with the JVM, you might find the http4k SDK useful - it offers a functional approach with strong testing capabilities. 😉 |
It’s hard to fully follow these threads, but the new proposal still uses HTTP and SSE—just in a revised structure. The arguments in the “Why not WebSocket?” section seem weak. The first three technical points are factually incorrect or misleading. Basing architecture on protocol misunderstandings risks designing the wrong solution. Choose the right transport for the job: |
@CaliViking I've been thinking about this a lot lately. It does give that impression at times. Maybe we could have a much more constructive conversation all together, it would be useful if someone implemented WS (or the one in sdk) alongside the new http specification, and performs extensive stress testing on it in an environment that approximates production. We should have real data and numbers to be able to argument what the overhead would be, and what tradeoffs that would imply |
Shipped https://inspect.mcp.garden for anyone interested in trying out HTTP+SSE (or just SSE) without needing to run the MCP Inspector locally! |
Add Claude Code to client list and create documentation guidelines
we need #1 for agent base turn pattern. Does the SDK have any pre-release version that we can try? |
Glad you were able to deploy mcp-debug :) super cool to see my fork in the wild. did you like the stats page? i'm thinking of creating a PR for that to the inspector. good luck with the mcp garden project🚀 |
this is not in main, what branch are you running? |
Does anyone have a Python SDK version for the server and client for the new HTTP protocol? |
This PR introduces the Streamable HTTP transport for MCP, addressing key limitations of the current HTTP+SSE transport while maintaining its advantages.
Our deep appreciation to @atesgoral and @topherbullock (Shopify), @samuelcolvin and @Kludex (Pydantic), @calclavia, Cloudflare, LangChain, Vercel, the Anthropic team, and many others in the MCP community for their thoughts and input! This proposal was only possible thanks to the valuable feedback received in the GitHub Discussion.
TL;DR
As compared with the current HTTP+SSE transport:
/sse
endpoint/message
(or similar) endpoint/message
This approach can be implemented backwards compatibly, and allows servers to be fully stateless if desired.
Motivation
Remote MCP currently works over HTTP+SSE transport which:
Benefits
Example use cases
Stateless server
A completely stateless server, without support for long-lived connections, can be implemented in this proposal.
For example, a server that just offers LLM tools and utilizes no other features could be implemented like so:
ToolListRequest
with a single JSON-RPC responseCallToolRequest
by executing the tool, waiting for it to complete, then sending a singleCallToolResponse
as the HTTP response bodyStateless server with streaming
A server that is fully stateless and does not support long-lived connections can still take advantage of streaming in this design.
For example, to issue progress notifications during a tool call:
CallToolRequest
, server indicates the response will be SSEProgressNotification
s over SSE while the tool is executingCallToolResponse
over SSEStateful server
A stateful server would be implemented very similarly to today. The main difference is that the server will need to generate a session ID, and the client will need to pass that back with every request.
The server can then use the session ID for sticky routing or routing messages on a message bus—that is, a POST message can arrive at any server node in a horizontally-scaled deployment, so must be routed to the existing session using a broker like Redis.
Why not WebSocket?
The core team thoroughly discussed making WebSocket the primary remote transport (instead of SSE), and applying similar work to it to make it disconnectable and resumable. We ultimately decided not to pursue WS right now because:
Authorization
), and unlike SSE, third-party libraries cannot reimplement WebSocket from scratch in the browser.We're also avoiding making WebSocket an additional option in the spec, because we want to limit the number of transports officially specified for MCP, to avoid a combinatorial compatibility problem between clients and servers. (Although this does not prevent community adoption of a non-standard WebSocket transport.)
The proposal in this doc does not preclude further exploration of WebSocket in future, if we conclude that SSE has not worked well.
To do
Follow ups