Skip to content

Simplify HTTP transport with Websockets and stateless request/response options #493

Closed

Description

@crholm

Is your feature request related to a problem? Please describe.

The current HTTP transport mechanisms for MCP (both HTTP+SSE and Streamable HTTP) introduce unnecessary complexity, state management challenges, and security concerns. As someone implementing an MCP server, I've encountered several issues:

  1. Excessive Complexity: The current approach requires maintaining session state across multiple connections and offers too many ways to achieve the same outcomes (multiple session creation methods, SSE opening options, and response delivery methods).

  2. Security and Scalability Concerns: Managing state across HTTP and SSE connections creates potential vulnerabilities and scalability challenges, particularly in enviorments with more then one node.

  3. Poor Developer Experience: The current transport mechanisms don't follow established web standards, have a lot of corner cases and is making implementation unnecessarily difficult.

  4. Implementation Burden: The server must maintain complex state management to "join" connections across calls, which significantly complicates any redundant/distributed deployment scenarios. Eg. The answer to a rpc POST coming in to one server in Europe might have to be returned through a SSE established to a server in the US.

  5. Distributed System Challenges: The current approach forces implementations to maintain cross-server state for sessions. In a distributed environment (load balancers, multiple regions, autoscaling), this requires implementing complex shared session state management that could be entirely avoided with Websockets, where the state remains local to a single connection.

Describe the solution you'd like

I propose replacing the current HTTP+SSE and Streamable HTTP transports with two simpler, well-established alternatives:

  1. Websockets for full-duplex communication, GET /mcp:

    • Websockets provide a true socket-like experience similar to stdio but over HTTP
    • They eliminate the need for complex session state management across multiple connections
    • They're widely supported by all modern browsers, servers, and client libraries
    • They follow established web standards and patterns
  2. Simple HTTP request/response for stateless operations, POST /mcp:

    • A straightforward REST-style API for single request/response interactions
    • No session state to maintain
    • Perfect for simple tool invocations or short interactions
    • Follows standard HTTP patterns that developers already understand
    • Some concessions probably have to be made in terms of the initial handshake of the MCP protocol
      • On top of my head...
      • POST /mcp/capabilities might return the standard initialize response
      • POST /mcp can contain initialize request and the rpc call

This approach would:

  • Dramatically simplify the protocol
  • Reduce implementation complexity
  • Improve security by reducing the attack surface
  • Make the protocol more accessible to developers
  • Better align with the stdio transport model (Websockets are conceptually similar to stdio streams)

Describe alternatives you've considered

  1. Refining the current Streamable HTTP approach: While Streamable HTTP could potentially be simplified and better documented, its fundamental design still introduces unnecessary complexity compared to Websockets, is a mismatch conceptually to stdio and will still forces state management over multiple sockets/threads/server/regions.

  2. gRPC: While powerful for service-to-service communication, gRPC is overkill for this use case, doesn't really play nice in the browser and isn't as universally supported in browsers as Websockets.

Additional context

The current approach seems to be attempting to reinvent Websockets using a combination of SSE and HTTP requests, creating what is essentially a more complex, less standard, and less secure version of Websockets.

Addressing objections to Websockets (from PR #206)

I've reviewed the objections to Websockets stated in PR #206 and would like to address them, and the issue comment #206 (comment):

  1. "RPC-like use would incur unnecessary overhead": This is incorrect. Websockets actually reduce overhead for RPC-like interactions by eliminating the need to establish new connections and perform TLS handshakes for each call. For stateless operations, a simple HTTP endpoint can be provided alongside Websockets, giving developers the best of both worlds if this turns out to be a real problem.

  2. "Cannot attach headers like Authorization in browser Websockets": While true that headers can't be added after connection establishment, there are standard, well-established patterns for this:

    • Authorization tokens can be passed during the initial connection as header, cookies or via query parameters
    • Post-connection authentication can occur in the first or subsequent message
      • Authorization can be part of the MCP protocol or a subprotocol. Eg. sending key-value pairs over the socket
  3. "Only GET requests can be upgraded to Websocket": This is true as well but really does not matter. The Websocket standard specifies the use of GET, and this is not a limitation but simply how the protocol works. Every Websocket library handles this transparently. To do a GET and open a socket to then send down a rpc message over the socker doesn't introduce additional complexity or realy latency compared to the current approach in any mening full way.

  4. Regarding compatibility concerns: Supporting both Websockets and a simple stateless HTTP API would simplify the compatibility matrix compared to the current complex state management across multiple HTTP connections and SSE streams.

State management advantages of Websockets

The current approach requires maintaining complex session state across multiple connections, which becomes particularly problematic in distributed environments:

  • In a load-balanced environment, SSE connections and HTTP requests may be routed to different servers, requiring shared state.
  • Session resurrection/resumption requires complex distributed state management and introduces a DoS risk since the cliend does not need to stick around.
  • With Websockets, the entire session state remains local to a single connection, dramatically simplifying implementation.
  • For redundancy, standard Websocket failover patterns are possible as well.

Websockets provide exactly the bidirectional message exchange in a standardized, widely-supported way that closely mimics the preferred stdio transport. As the specification itself notes:

"Clients and servers MAY implement additional custom transport mechanisms to suit their specific needs. The protocol is transport-agnostic and can be implemented over any communication channel that supports bidirectional message exchange."

But it does not seem that the standard way of doing things should be this complex

Activity

  1. Marlinski commented on May 13, 2025

    @Marlinski

    Also supporting stateless transport! It would be very useful to facilitate MCP deployment in the cloud. Current transport (both SSE and Streamable HTTP) adds unnecessary complexities.

  2. rev1si0n commented on May 14, 2025

    @rev1si0n

    It’s unclear to me why HTTP+SSE was originally chosen as a communication method, given its awkward design. I’ve implemented an MCP SSE server myself, and I still feel that this approach seems more like something a novice programmer would come up with—especially considering that WebSocket is clearly a more suitable communication protocol.

  3. rev1si0n commented on May 14, 2025

    @rev1si0n

    Aside from the convenience of using GET/POST for firewall traversal and authentication, except for being easier to convert to stdio locally, it is unsuitable for use at network level. I can’t think of any other advantages. Moreover, if an MCP SSE server is deployed behind Nginx for load balancing, and a path prefix is added before the connection—such as proxy_pass example.com/route1/ -> mcp.server/sse—it leads to significant complications. I have to implement path rewriting within the MCP framework, and Nginx must also provide additional parameters like /route1/, since the endpoint: /sse returned by SSE also needs to be rewritten to endpoint: /route1/sse. All in all, it's a protocol with poor design considerations.

  4. Bit0r commented on May 14, 2025

    @Bit0r

    It’s unclear to me why HTTP+SSE was originally chosen as a communication method, given its awkward design. I’ve implemented an MCP SSE server myself, and I still feel that this approach seems more like something a novice programmer would come up with—especially considering that WebSocket is clearly a more suitable communication protocol.

    Because this protocol might be created by an LLM.

  5. lmaccherone commented on May 30, 2025

    @lmaccherone

    I agree with everything in this thread plus I'll add another reason for HTTP request/response + WebSockets... edge serverless. WebSockets have been around long enough that edge serverless vendors now have 1st class support for them. Cloudflare is a great example. They have hibernatable WebSocket support. The underlying infrastructure handles keepalive functionality while your serverless code can run and self-evict from memory at will. Their implementation allows one unit of serverless functionality (called a Durable Object) to have up to 32,000 hibernated WebSocket connections.

  6. RoseSecurity commented on Jun 6, 2025

    @RoseSecurity

    The initial arguments against Websockets felt extremely brittle to me. I think this implementation will ultimately need to be addressed going forward to gain more community support as developers create MCP servers and have to battle the awkwardness of HTTP+SSE

  7. Kludex commented on Jun 12, 2025

    @Kludex
    Member

    I help maintain the MCP Python SDK, and I completely agree with this issue. I had previously suggested to use WebSockets as well, given that it seems the obvious choice for bidirectional message support.

    Now that I see how complex the Python SDK has become due to the handling of session, streams and issues during development about long-lived HTTP connections (as web servers treat those differently than WebSockets) I can be even more sure about it.

  8. Kludex commented on Jul 25, 2025

    @Kludex
    Member

    It seems I can sponsor this idea if it becomes a SEP, which I'm willing to.

    Anyone wants to write a draft for it? I'm happy to sponsor it.

  9. lmaccherone commented on Jul 28, 2025

    @lmaccherone

    I am willing to take a stab at drafting one. I have a reference implementation in the works so I can draw from that learning.

  10. lmaccherone commented on Jul 29, 2025

    @lmaccherone

    Question for everyone on this thread... @crholm's original suggestion was for both Websockets for full-duplex communication and Simple HTTP request/response for stateless operations. I'm working on the draft SEP right now, and I don't believe we need the latter as the Streamable HTTP transport already supports that. Server initiated notifications are optoinal in the main spec. The MCP server need only specify update capabilities (subscribe, listChanged). It also states that you can return application/json for simple HTTP request/response use.

    I think that's already covered and it strengthens the SEP to be simpler and focused on WebSockets.

    Thoughts?

  11. Kludex commented on Jul 30, 2025

    @Kludex
    Member

    I honestly didn't even pay attention to the stateless HTTP proposal. I think it should be ONLY WebSockets.

    It's far easy to reason about layers:

    • WebSockets is on top of HTTP
    • MCP is on top of WebSockets

    I also find it weird that you would restrict MCP operations like sampling.

  12. crholm commented on Jul 30, 2025

    @crholm
    Author

    Nice to see that this is being picked up

    ... I don't believe we need the latter as the Streamable HTTP transport already supports that. ...

    Thoughts?

    I think you are correct to focus on the ws part. My initial suggestion was made a more suitable way forward to replace all the SSE/Streamable HTTP nonsens to address most of the needs in those transport options. But with Streamable HTTP not going away, adding websockets would be the focus imho.

  13. lmaccherone commented on Aug 2, 2025

    @lmaccherone

    OK. Here it is: #1288

    Please provide feedback either to the PR review (if you have that permission) or comments here, to the PR, or the issue. Not sure which is the best place of those three, but I'll try to keep an eye on all three and respond accordingly.

  14. localden commented on Jun 26, 2026

    @localden
    Contributor

    Closing the loop here - thank you again folks for the discussion. Looks like this proposal hasn't been picked up. Additionally, the upcoming spec (2026-07-28) will be moving to a stateless model.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions