Skip to content

Commit ec96e58

Browse files
committed
"Streamable HTTP" spec
1 parent bb8f4b7 commit ec96e58

File tree

1 file changed

+101
-20
lines changed

1 file changed

+101
-20
lines changed

docs/specification/draft/basic/transports.md

Lines changed: 101 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ The protocol currently defines two standard transport mechanisms for client-serv
1212
communication:
1313

1414
1. [stdio](#stdio), communication over standard in and standard out
15-
2. [HTTP with Server-Sent Events](#http-with-sse) (SSE)
15+
2. [Streamable HTTP](#streamable-http)
1616

1717
Clients **SHOULD** support stdio whenever possible.
1818

@@ -48,38 +48,119 @@ sequenceDiagram
4848
deactivate Server Process
4949
```
5050

51-
## HTTP with SSE
51+
## Streamable HTTP
5252

53-
In the **SSE** transport, the server operates as an independent process that can handle
54-
multiple client connections.
53+
{{< callout type="info" >}} This replaces the [HTTP+SSE transport]({{< ref "/specification/2024-11-05/basic/transports#http-with-sse" >}}) from protocol version 2024-11-05. See the [backwards compatibility](#backwards-compatibility) guide below. {{< /callout >}}
5554

56-
The server **MUST** provide two endpoints:
55+
In the **Streamable HTTP** transport, the server operates as an independent process that can handle multiple client connections. This transport uses standard HTTP with optional [Server-Sent Events](https://en.wikipedia.org/wiki/Server-sent_events) (SSE) for streaming multiple server messages. This permits "plain HTTP" MCP servers, as well as more feature-rich servers supporting streaming and bidirectional communication.
5756

58-
1. An SSE endpoint, for clients to establish a connection and receive messages from the
59-
server
60-
2. A regular HTTP POST endpoint for clients to send messages to the server
57+
The server **MUST** provide a single HTTP endpoint (hereafter referred to as the **MCP endpoint**) that supports both POST and GET methods. For example, this could be a URL like `https://example.com/mcp`.
6158

62-
When a client connects, the server **MUST** send an `endpoint` event containing a URI for
63-
the client to use for sending messages. All subsequent client messages **MUST** be sent
64-
as HTTP POST requests to this endpoint.
59+
### Message Exchange
6560

66-
Server messages are sent as SSE `message` events, with the message content encoded as
67-
JSON in the event data.
61+
1. Every JSON-RPC message sent from the client **MUST** be a new HTTP POST request to the MCP endpoint.
62+
63+
2. When the client sends a JSON-RPC _request_ message to the MCP endpoint via POST:
64+
- The client **MUST** include an `Accept` header, listing both `application/json` and `text/event-stream` as supported content types.
65+
- 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.
66+
- If the server initiates an SSE stream:
67+
- The SSE stream **SHOULD** eventually include a JSON-RPC _response_ message.
68+
- The server **MAY** send JSON-RPC _requests_ and JSON-RPC _notifications_ before sending a JSON-RPC _response_.
69+
- The server **SHOULD NOT** close the SSE stream before sending the JSON-RPC _response_.
70+
- After the JSON-RPC _response_ has been sent, the server **MAY** close the SSE stream at any time.
71+
- The client **MAY** close the SSE stream at any time. The server **SHOULD** interpret this as the client cancelling the request, if it is still in-flight.
72+
73+
3. When the client sends a JSON-RPC _notification_ or _response_ to the MCP endpoint via POST:
74+
- The client **MUST** include an `Accept` header, listing `text/event-stream` as a supported content type.
75+
- The server **MUST** either return `Content-Type: text/event-stream`, to initiate an SSE stream, or else HTTP status code 202 Accepted with no body. The client **MUST** support both these cases.
76+
- If the server initiates an SSE stream:
77+
- The receipt of the message is acknowledged as soon as the HTTP status code is received (before the SSE stream begins).
78+
- The server **MAY** close the SSE stream at any time.
79+
- The client **MAY** close the SSE stream at any time.
80+
81+
4. The client **MAY** also issue an HTTP GET to the MCP endpoint. This can be used to open an SSE stream (allowing the server to communicate to the client) without having first sent a _request_, _notification_, or _response_.
82+
- The client **MUST** include an `Accept` header, listing `text/event-stream` as a supported content type.
83+
- The server **MUST** either return `Content-Type: text/event-stream` in response to this HTTP GET, or else HTTP status code 204 No Content with no body. The client **MUST** support both these cases.
84+
- If the server initiates an SSE stream:
85+
- The server **MAY** close the SSE stream at any time.
86+
- The client **MAY** close the SSE stream at any time.
87+
88+
### Session Management
89+
90+
Where a client desires to share a single logical session across multiple requests, it **MAY** attach an `Mcp-Session-Id` HTTP header to its requests. This permits resumability and maintenance of session state across separate POSTs.
91+
92+
1. It is the client's responsibility to generate or select the session ID.
93+
2. This session ID **SHOULD** be globally unique and cryptographically secure (e.g., a UUID or a JWT), unless it is specifically desired to share a session ID across users or clients.
94+
3. The server **MAY** use this header to associate state with the logical session.
95+
4. If [authorization]({{< ref "authorization" >}}) is used _and_ the server makes use of the `Mcp-Session-Id` header:
96+
- The server **SHOULD** bind the session ID to the authorization context, and return an error if the session ID is reused in a different authorization context.
97+
98+
### Multiple Connections
99+
100+
1. The client **MAY** remain connected to multiple SSE streams simultaneously.
101+
2. The server **MAY** broadcast its JSON-RPC messages on all connected SSE streams, or it **MAY** limit its communication on any particular stream only to messages related to the client's original request on that stream.
102+
- The client **MUST** ignore duplicate _requests_ and _responses_ received in this way, by ignoring any duplicate JSON-RPC request IDs in either.
103+
- The client **MUST** be resilient to duplicate _notifications_, handling them with idempotency.
104+
105+
### Sequence Diagram
68106

69107
```mermaid
70108
sequenceDiagram
71109
participant Client
72110
participant Server
73-
74-
Client->>Server: Open SSE connection
75-
Server->>Client: endpoint event
76-
loop Message Exchange
77-
Client->>Server: HTTP POST messages
78-
Server->>Client: SSE message events
111+
112+
note over Client, Server: initialization
113+
114+
Client->>+Server: POST InitializeRequest<br>Mcp-Session-Id: foo
115+
Server->>Client: InitializeResponse
116+
deactivate Server
117+
118+
Client->>+Server: POST InitializedNotification<br>Mcp-Session-Id: foo
119+
120+
alt single HTTP response
121+
Server->>Client: 202 Accepted
122+
else server opens SSE stream
123+
loop while connection remains open
124+
Server-)Client: ... SSE messages from server ...
125+
end
126+
Client-->Server: (client or server MAY disconnect)
127+
end
128+
deactivate Server
129+
130+
note over Client, Server: normal operation (sequentially or concurrently)
131+
132+
Client->>+Server: POST ... other messages ...<br>Mcp-Session-Id: foo
133+
134+
alt single HTTP response
135+
Server->>Client: ... response ...
136+
else server opens SSE stream
137+
loop while connection remains open
138+
Server-)Client: ... SSE messages from server ...
139+
end
140+
opt if client message was a request
141+
Server-)Client: SSE event: (response)
142+
end
79143
end
80-
Client->>Server: Close SSE connection
144+
145+
deactivate Server
81146
```
82147

148+
### Backwards Compatibility
149+
150+
Clients and servers can maintain backwards compatibility with the deprecated [HTTP+SSE transport]({{< ref "/specification/2024-11-05/basic/transports#http-with-sse" >}}) (from protocol version 2024-11-05) as follows:
151+
152+
**Servers** wanting to support older clients should:
153+
- Continue to host both the SSE and POST endpoints of the old transport, alongside the new "MCP endpoint" defined for the Streamable HTTP transport.
154+
- It is also possible to combine the old POST endpoint and the new MCP endpoint, but this may introduce unneeded complexity.
155+
156+
**Clients** wanting to support older servers should:
157+
1. Accept an MCP server URL from the user, which may point to either a server using the old transport or the new transport.
158+
2. Attempt to POST an `InitializeRequest` to the server URL, with an `Accept` header as defined above:
159+
- If it succeeds or opens an SSE stream in response, the client can assume this is a server supporting the new Streamable HTTP transport.
160+
- If it fails with an HTTP 4xx status code (e.g., 405 Method Not Allowed or 404 Not Found):
161+
- Issue a GET request to the server URL, expecting that this will open an SSE stream and return an `endpoint` event as the first event.
162+
- When the `endpoint` event arrives, the client can assume this is a server running the old HTTP+SSE transport, and should use that transport for all subsequent communication.
163+
83164
## Custom Transports
84165

85166
Clients and servers **MAY** implement additional custom transport mechanisms to suit

0 commit comments

Comments
 (0)