Transports

ℹ️
Protocol Revision: draft

MCP uses JSON-RPC to encode messages. JSON-RPC messages MUST be UTF-8 encoded.

The protocol currently defines two standard transport mechanisms for client-server communication:

  1. stdio, communication over standard in and standard out
  2. Streamable HTTP

Clients SHOULD support stdio whenever possible.

It is also possible for clients and servers to implement custom transports in a pluggable fashion.

stdio

In the stdio transport:

  • The client launches the MCP server as a subprocess.
  • The server receives JSON-RPC messages on its standard input (stdin) and writes responses to its standard output (stdout).
  • Messages are delimited by newlines, and MUST NOT contain embedded newlines.
  • The server MAY write UTF-8 strings to its standard error (stderr) for logging purposes. Clients MAY capture, forward, or ignore this logging.
  • The server MUST NOT write anything to its stdout that is not a valid MCP message.
  • The client MUST NOT write anything to the server’s stdin that is not a valid MCP message.
sequenceDiagram
    participant Client
    participant Server Process

    Client->>+Server Process: Launch subprocess
    loop Message Exchange
        Client->>Server Process: Write to stdin
        Server Process->>Client: Write to stdout
        Server Process--)Client: Optional logs on stderr
    end
    Client->>Server Process: Close stdin, terminate subprocess
    deactivate Server Process

Streamable HTTP

ℹ️
This replaces the HTTP+SSE transport from protocol version 2024-11-05. See the backwards compatibility guide below.

In the Streamable HTTP transport, the server operates as an independent process that can handle multiple client connections. This transport uses HTTP POST and GET requests. Server can optionally make use of Server-Sent Events (SSE) to stream multiple server messages. This permits basic MCP servers, as well as more feature-rich servers supporting streaming and 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 https://example.com/mcp.

Message Exchange

  1. Every JSON-RPC message sent from the client MUST be a new HTTP POST request to the MCP endpoint.

  2. When the client sends a JSON-RPC request to the MCP endpoint via POST:

    • The client MUST include an Accept header, listing both application/json and 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.
    • If the server initiates an SSE stream:
      • The SSE stream SHOULD eventually include a JSON-RPC response message.
      • The server MAY send JSON-RPC requests and notifications before sending a JSON-RPC response. These messages SHOULD relate to the originating client request.
      • The server SHOULD NOT close the SSE stream before sending the JSON-RPC response, unless the session expires.
      • After the JSON-RPC response has been sent, the server MAY close the SSE stream at any time.
      • Disconnection MAY occur at any time (e.g., due to network conditions). Therefore:
        • Disconnection SHOULD NOT be interpreted as the client cancelling its request.
        • To cancel, the client SHOULD explicitly send an MCP CancelledNotification.
        • To avoid message loss due to disconnection, the server MAY make the stream resumable.
  3. When the client sends a JSON-RPC notification or response to the MCP endpoint via POST:

    • If the server accepts the message, it MUST return HTTP status code 202 Accepted with no body.
    • If the server cannot accept the message, it MUST return an HTTP error status code (e.g., 400 Bad Request). The HTTP response body MAY comprise a JSON-RPC error response that has no id.
  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 the client first sending a JSON-RPC request.

    • The client MUST include an Accept header, listing text/event-stream as a supported content type.
    • The server MUST either return Content-Type: text/event-stream in response to this HTTP GET, or else return HTTP 405 Method Not Allowed, indicating that the server does not offer an SSE stream at this endpoint.
    • If the server initiates an SSE stream:
      • The server MAY send JSON-RPC requests and notifications on the stream. These messages SHOULD be unrelated to any concurrently-running JSON-RPC request from the client.
      • The server MUST NOT send a JSON-RPC response on the stream unless resuming 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

  1. The client MAY remain connected to multiple SSE streams simultaneously.
  2. The server MUST send each of its JSON-RPC messages on only one of the connected streams; that is, it MUST NOT broadcast the same message across multiple streams.
    • The risk of message loss MAY be mitigated by making the stream resumable.

Resumability and Redelivery

To support resuming broken connections, and redelivering messages that might otherwise be lost:

  1. Servers MAY attach an id field to their SSE events, as described in the SSE standard.
    • If present, the ID MUST be globally unique across all streams within that session—or all streams with that specific client, if session management is not in use.
  2. If the client wishes to resume after a broken connection, it SHOULD issue an HTTP GET to the MCP endpoint, and include the Last-Event-ID header to indicate the last event ID it received.
    • The server MAY use this header to replay messages that would have been sent after the last event ID, on the stream that was disconnected, and to resume the stream from that point.
    • The server MUST NOT replay messages that would have been delivered on a different stream.

In other words, these event IDs should be assigned by servers on a per-stream basis, to act as a cursor within that particular stream.

Session Management

An MCP “session” consists of logically related interactions between a client and a server, beginning with the initialization phase. To support servers which want to establish stateful sessions:

  1. A server using the Streamable HTTP transport MAY assign a session ID at initialization time, by including it in an Mcp-Session-Id header on the HTTP response containing the InitializeResult.
    • The session ID SHOULD be globally unique and cryptographically secure (e.g., a securely generated UUID, a JWT, or a cryptographic hash).
    • The session ID MUST only contain visible ASCII characters (ranging from 0x21 to 0x7E).
  2. If an Mcp-Session-Id is returned by the server during initialization, clients using the Streamable HTTP transport MUST include it in the Mcp-Session-Id header on all of their subsequent HTTP requests.
    • Servers that require a session ID SHOULD respond to requests without an Mcp-Session-Id header (other than initialization) with HTTP 400 Bad Request.
  3. The server MAY terminate the session at any time, after which it MUST respond to requests containing that session ID with HTTP 404 Not Found.
  4. When a client receives HTTP 404 in response to a request containing an Mcp-Session-Id, it MUST start a new session by sending a new InitializeRequest without a session ID attached.
  5. Clients that no longer need a particular session (e.g., because the user is leaving the client application) SHOULD send an HTTP DELETE to the MCP endpoint with the Mcp-Session-Id header, to explicitly terminate the session.
    • The server MAY respond to this request with HTTP 405 Method Not Allowed, indicating that the server does not allow clients to terminate sessions.

Sequence Diagram

sequenceDiagram
    participant Client
    participant Server

    note over Client, Server: initialization

    Client->>+Server: POST InitializeRequest
    Server->>-Client: InitializeResponse
Mcp-Session-Id: 1868a90c... Client->>+Server: POST InitializedNotification
Mcp-Session-Id: 1868a90c... Server->>-Client: 202 Accepted note over Client, Server: client requests Client->>+Server: POST ... request ...
Mcp-Session-Id: 1868a90c... alt single HTTP response Server->>Client: ... response ... else server opens SSE stream loop while connection remains open Server-)Client: ... SSE messages from server ... end Server-)Client: SSE event: ... response ... end deactivate Server note over Client, Server: client notifications/responses Client->>+Server: POST ... notification/response ...
Mcp-Session-Id: 1868a90c... Server->>-Client: 202 Accepted note over Client, Server: server requests Client->>+Server: GET
Mcp-Session-Id: 1868a90c... loop while connection remains open Server-)Client: ... SSE messages from server ... end deactivate Server

Backwards Compatibility

Clients and servers can maintain backwards compatibility with the deprecated HTTP+SSE transport (from protocol version 2024-11-05) as follows:

Servers wanting to support older clients should:

  • Continue to host both the SSE and POST endpoints of the old transport, alongside the new “MCP endpoint” defined for the Streamable HTTP transport.
    • It is also possible to combine the old POST endpoint and the new MCP endpoint, but this may introduce unneeded complexity.

Clients wanting to support older servers should:

  1. Accept an MCP server URL from the user, which may point to either a server using the old transport or the new transport.
  2. Attempt to POST an InitializeRequest to the server URL, with an Accept header as defined above:
    • If it succeeds, the client can assume this is a server supporting the new Streamable HTTP transport.
    • If it fails with an HTTP 4xx status code (e.g., 405 Method Not Allowed or 404 Not Found):
      • 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.
      • 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.

Custom Transports

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.

Implementers who choose to support custom transports MUST ensure they preserve the JSON-RPC message format and lifecycle requirements defined by MCP. Custom transports SHOULD document their specific connection establishment and message exchange patterns to aid interoperability.