In streamable HTTP transmission, the server operates as an independent process capable of handling multiple client connections. Streaming utilizes HTTP POST and GET request methods. The server can optionally use Server-Sent Events (SSE) to stream multiple server messages. This allows basic MCP servers as well as feature-rich servers to support streaming, server-to-client notifications, and requests.
The server must provide a single HTTP endpoint path (hereafter referred to as the MCP endpoint) that supports both POST and GET methods. For example, this could be a URL like <span>https://example.com/mcp</span>
.
Sending Messages to the Server
Each JSON-RPC message sent from the client must be a new HTTP POST request sent to the MCP endpoint.
- The client must use the HTTP POST method to send JSON-RPC messages to the MCP endpoint.
- The client must include an
<span>Accept</span>
header listing<span>application/json</span>
and<span>text/event-stream</span>
as supported content types. - The body of the POST request must be one of the following:
- A single JSON-RPC request, notification, or response.
- An array containing one or more requests and/or notifications in bulk.
- An array containing one or more responses in bulk.
If the input contains only (any number of) JSON-RPC responses or notifications:
- If the server accepts the input, it must return an HTTP status code 202 Accepted, with no body.
- If the server cannot accept the input, it must return an HTTP error status code (e.g., 400 Bad Request). The HTTP response body may contain a JSON-RPC error response without an
<span>id</span>
.
If the input contains any number of JSON-RPC requests, the server must return <span>Content-Type: text/event-stream</span>
to initiate an SSE stream, or return <span>Content-Type: application/json</span>
to return a JSON object. The client must support both cases.
If the server has initiated an SSE stream:
- The SSE stream should ultimately contain a JSON-RPC response for each JSON-RPC request sent in the POST body. These responses may be sent in bulk.
- The server may send JSON-RPC requests and notifications before sending JSON-RPC responses. These messages should be related to the original client request. These requests and notifications may be sent in bulk.
- The server should not close the SSE stream before sending a response to each received JSON-RPC request unless the session has expired.
- After all JSON-RPC responses have been sent, the server should close the SSE stream.
Disconnections may occur at any time (e.g., due to network conditions). Therefore:
- A disconnection should not be interpreted as the client canceling its request.
- To cancel, the client should explicitly send an MCP
<span>CancelledNotification</span>
. - To avoid message loss due to disconnections, the server may make the stream recoverable.
Listening for Server Messages
The client may initiate an HTTP GET request to the MCP endpoint. This can be used to open an SSE stream, allowing the server to communicate with the client without the client sending data via HTTP POST.
- The client must include an
<span>Accept</span>
header listing<span>text/event-stream</span>
as a supported content type. - The server must return
<span>Content-Type: text/event-stream</span>
in response to this HTTP GET, or return HTTP 405 Method Not Allowed, indicating that the server does not provide an SSE stream at this endpoint.
If the server has initiated an SSE stream:
- The server may send JSON-RPC requests and notifications in the stream. These requests and notifications may be sent in bulk.
- These messages should not be related to any JSON-RPC requests currently running on the client.
- The server must not send JSON-RPC responses in the stream unless recovering a stream associated with a previous client request.
- The server may close the SSE stream at any time.
- The client may close the SSE stream at any time.
Multiple Connections
The client may maintain multiple SSE stream connections simultaneously.
- The server must send each JSON-RPC message to only one connected stream; that is, it must not broadcast the same message across multiple streams.
- By making the stream recoverable, the risk of message loss can be reduced.
Recoverability and Retransmission
To support recovering from disconnected connections and retransmitting potentially lost messages:
- The server may attach an
<span>id</span>
field to SSE events according to the SSE standard. - If present, the ID must be globally unique across all streams in that session (or for all streams for that specific client if session management is not used).
- If the client wishes to recover after a disconnection, it should initiate an HTTP GET request to the MCP endpoint, including the
<span>Last-Event-ID</span>
header to indicate the last event ID it received. - The server may use this header to replay messages sent after the last event ID on the disconnected stream and recover the stream from that point.
- The server must not replay messages sent on different streams.
- In other words, these event IDs should be assigned by the server per stream to serve as a cursor within that specific stream.
Session Management
The MCP “session” consists of logically related interactions between the client and server, starting from the [initialization phase]. To support servers wishing to establish stateful sessions:
- Servers using streamable HTTP transmission may assign a session ID at initialization by including the
<span>Mcp-Session-Id</span>
header in the HTTP response containing<span>InitializeResult</span>
. - The session ID should be globally unique and cryptographically secure (e.g., a securely generated UUID, JWT, or cryptographic hash).
- The session ID must only contain visible ASCII characters (ranging from 0x21 to 0x7E).
- If the server returns a
<span>Mcp-Session-Id</span>
during initialization, the client using streamable HTTP transmission must include that header in all subsequent HTTP requests. - Servers requiring a session ID should return HTTP 400 Bad Request for requests that do not include the
<span>Mcp-Session-Id</span>
header (except for the initialization request). - The server may terminate the session at any time, after which it must return HTTP 404 Not Found for requests containing that session ID.
- When the client receives an HTTP 404 response for a request containing the
<span>Mcp-Session-Id</span>
, it must start a new session by sending a new<span>InitializeRequest</span>
without attaching the session ID. - If the client no longer needs a specific session (e.g., because the user is leaving the client application), should send an HTTP DELETE request to the MCP endpoint containing the
<span>Mcp-Session-Id</span>
header to explicitly terminate the session. - The server may return HTTP 405 Method Not Allowed for this request, indicating that the server does not allow the client to terminate the session.
Timing Diagram
Backward Compatibility
The client and server can maintain backward compatibility with the deprecated [HTTP+SSE transmission] (protocol version 2024-11-05) in the following ways:
-
Server wishing to support old clients should:
- Continue hosting the SSE and POST endpoints of the old transmission, as well as defining the new “MCP endpoint” for streamable HTTP transmission.
- It may also merge the old POST endpoint and the new MCP endpoint, but this may introduce unnecessary complexity.
-
Client wishing to support old servers should:
- If successful, the client can assume this is a server supporting the new streamable HTTP transmission.
- If it fails and returns an HTTP 4xx status code (e.g., 405 Method Not Allowed or 404 Not Found):
- Send a GET request to the server URL, expecting this to open an SSE stream and return an endpoint event as the first event.
- When the endpoint event arrives, the client can assume this is a server running the old HTTP+SSE transmission and use that transmission for all subsequent communications.
- Accept user-provided MCP server URLs that may point to servers using either the old or new transmission.
- Attempt to send an
<span>InitializeRequest</span><span> to the server URL, including the </span><code><span>Accept</span>
header as defined above: