
This page is part of our MCP specification reference, a plain-English guide to the Model Context Protocol spec (version 2026-07-28), within The MCP Guide. Building a server? See MCP development.
An MCP transport is the delivery layer that carries messages between an AI app (the MCP client) and an MCP server. It decides how messages are framed and sent, not what they mean. The 2026-07-28 specification defines two standard transports: stdio, for servers running on your own machine, and Streamable HTTP, for servers running on the web.
Status in the 2026-07-28 spec: core
This page explains what a transport does, how the two standard ones differ, and what changed between spec versions. It was checked against the official transports overview on 28 October 2026.
Key Takeaways
- A transport is a "binding": it handles framing, delivery, request metadata and cancellation, while message meaning stays the same everywhere.
- The two standard transports are stdio (a local subprocess) and Streamable HTTP (one web endpoint that accepts POST).
- Every MCP message is JSON-RPC encoded in UTF-8, whichever transport carries it.
- Custom transports are allowed, but they must keep the JSON-RPC format, the message patterns and the per-request metadata model.
- The older HTTP+SSE transport has been deprecated since 2025-03-26 and should not be used for new work.
What a transport is
The spec describes a transport as "a binding: it defines how messages are framed and delivered, how request metadata is carried, and how cancellation and termination are signaled." It adds that a transport "does not define what the messages mean."
In plain terms, the transport is the envelope and the postal route. The letter inside, a JSON-RPC request such as tools/call, reads the same whether it travels over a pipe on your laptop or over HTTPS. If you are new to the message format, start with JSON-RPC in MCP.
Why MCP has more than one transport
MCP servers live in two very different places.
- Local servers run on the same computer as the AI app. A coding assistant that reads your project files is a typical example. The app can simply launch the server as a child process.
- Remote servers run on someone else's infrastructure, such as a SaaS vendor's MCP endpoint. These need a network protocol, authentication and support for many users at once.
One transport could not serve both well, so the spec defines one for each. Our guide to remote vs local servers in practice covers the business trade-offs.
The two standard transports
| stdio | Streamable HTTP | |
|---|---|---|
| Where the server runs | On the user's machine, launched by the client | As an independent process, often in the cloud |
| How messages travel | Newline-delimited JSON-RPC on stdin and stdout | One HTTP POST per message to a single MCP endpoint |
| How replies arrive | One line per message on stdout | A single JSON object or a request-scoped SSE stream |
| How to cancel a request | Send notifications/cancelled | Close that request's response stream |
| Sign-in | Credentials from the environment | OAuth-based authorization, when used |
The stdio page says "the client launches the MCP server as a subprocess." The Streamable HTTP page says "each message is an HTTP POST to a single MCP endpoint." We cover each one in depth in the MCP stdio transport and MCP Streamable HTTP transport.
The authorization rules also split by transport. The authorization spec says HTTP-based implementations "SHOULD conform" to it, while stdio implementations "SHOULD NOT follow this specification, and instead retrieve credentials from the environment."
How it works: rules every transport follows
The transports overview sets a few rules that apply to any binding:
- Encoding. "JSON-RPC messages MUST be UTF-8 encoded."
- Direction. A binding must deliver client requests and notifications to the server, and server responses and notifications to the client. "No other message direction exists": servers do not start JSON-RPC requests, and clients do not send JSON-RPC responses.
- Metadata in the body. Every request carries its protocol version and client capabilities inside
_meta. A binding may copy some of these into envelope fields, as Streamable HTTP does with headers, but "the body remains the source of truth." - Cancellation. Each binding defines how a client abandons an in-flight request.
Here is a request as it looks on either transport. This example is adapted from the Streamable HTTP page of the spec:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "get_weather",
"arguments": { "location": "Seattle, WA" },
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientInfo": { "name": "ExampleClient", "version": "1.0.0" },
"io.modelcontextprotocol/clientCapabilities": {}
}
}
}
On stdio, that object is written as one line to the server's stdin. On Streamable HTTP, it is the body of a POST, with headers such as Mcp-Method: tools/call copied from it.
Custom transports
Clients and servers "MAY implement additional custom transport mechanisms." The protocol "is transport-agnostic." Custom transports must keep the JSON-RPC format, the message patterns and the per-request metadata model.
For a byte stream such as a Unix domain socket or TCP connection, the spec says custom transports "SHOULD reuse the stdio framing rather than defining a new one."
What changed across spec versions
| Version | Transport change |
|---|---|
| 2024-11-05 | Two standard transports: stdio and HTTP with Server-Sent Events (HTTP+SSE) |
| 2025-03-26 | Streamable HTTP replaced HTTP+SSE, per the 2025-03-26 changelog |
| 2025-06-18 | MCP-Protocol-Version header required on HTTP requests after negotiation |
| 2025-11-25 | Invalid Origin headers must get HTTP 403; SSE polling clarified |
| 2026-07-28 | Sessions, the GET stream and stream resumability removed; Mcp-Method and Mcp-Name headers required |
The 2026-07-28 changelog also reclassified HTTP+SSE as Deprecated under the new feature lifecycle policy. One more small change: the 2024-11-05 through 2025-11-25 transport pages said "Clients SHOULD support stdio whenever possible." That sentence is not on the 2026-07-28 overview page.
Because the 2026-07-28 release removed the initialize handshake, each transport page now has a "Backward Compatibility" section. It explains how a client detects an older, handshake-based server and falls back. The versioning page calls 2025-11-25 and earlier "Legacy" and 2026-07-28 onward "Modern."
Common mistakes
- Treating transport choice as a feature choice. Tools, resources and prompts work the same on both transports. Pick the transport based on where the server runs.
- Exposing a local HTTP server to the network. The spec says local servers "SHOULD bind only to localhost (127.0.0.1)." See DNS rebinding and local MCP servers.
- Building new HTTP+SSE servers. It is deprecated. Use Streamable HTTP.
- Trusting headers over the body. On Streamable HTTP, servers must reject requests where headers and body disagree.
- Writing logs to stdout on stdio. Only valid MCP messages may go to stdout. Logs belong on stderr.
Next step
Most teams start with a local stdio server and later move to a hosted one. Read the MCP stdio transport next, or browse the full MCP specification reference.
Frequently asked questions
How many transports does MCP have?
As of October 2026, the 2026-07-28 spec defines two standard transports: stdio and Streamable HTTP. It also allows custom transports. The older HTTP+SSE transport still appears in the spec's deprecated features registry for backward compatibility.
Which transport should I use for a new MCP server?
Use stdio if the server runs on the user's own machine and is launched by the AI app. Use Streamable HTTP if the server is hosted and shared by many users. Many teams ship both from the same codebase.
Do tools behave differently on different transports?
No. The spec says protocol semantics are identical on every transport. Only framing, delivery, metadata and cancellation differ. One small exception: clients on stdio may ignore the x-mcp-header tool annotation, which exists to mirror values into HTTP headers.
Can MCP run over WebSockets?
The 2026-07-28 spec does not define a WebSocket transport. A WebSocket binding would be a custom transport, and it would need to keep the JSON-RPC format, message patterns and per-request metadata model.
What happened to HTTP+SSE?
It was replaced by Streamable HTTP in 2025-03-26. The 2026-07-28 spec lists it as Deprecated, and new implementations should not adopt it. See the legacy HTTP+SSE transport and how to migrate.











