MCP defines two standard transports today: stdio, where the client launches the server as a subprocess, and streamable HTTP, a single endpoint taking POST and returning either JSON or an SSE stream. The older HTTP+SSE transport, with its separate /sse and POST endpoints, was deprecated in the 2025-03-26 spec revision and formally reclassified as Deprecated on 2026-07-28 under a policy that keeps it functional for at least twelve more months. Claude Code and Cursor still support SSE explicitly; Codex never did. Point a new server at streamable HTTP and only reach for SSE when the vendor exposes nothing else.
- Two current transports: stdio and streamable HTTP. SSE is the deprecated third.
- HTTP+SSE was deprecated in
2025-03-26and reclassified Deprecated in2026-07-28. - Streamable HTTP still uses server-sent events, on the POST response. That is the naming trap.
- Claude Code:
--transport sseworks and warns. Cursor:"type": "sse". Codex: no SSE at all. - A
urlin a Claude Code JSON entry with notypeis silently skipped, not defaulted. - One
/ssein a URL is usually the whole diagnosis.
The three names, and which one you want
A transport is only the pipe the JSON-RPC messages travel down. It has nothing to do with what a server can do, and picking the wrong one produces a connection failure rather than a degraded server, which is at least an honest failure mode.
| Transport | Shape | Status |
|---|---|---|
| stdio | Client launches the server as a subprocess, messages over stdin and stdout | Current. Clients SHOULD support it whenever possible |
| Streamable HTTP | One HTTP endpoint taking POST, replying with JSON or an SSE stream | Current. The remote transport |
| HTTP+SSE | A GET /sse stream plus a separate POST endpoint the stream announces | Deprecated since 2025-03-26 |
stdio, and why it is still the default
The client spawns the server as a child process and speaks newline-delimited JSON-RPC over its stdin and stdout. Anything on stderr is treated as logging. The server must not write anything to stdout that is not a valid MCP message, which is the single most common way a home-grown stdio server breaks: one stray print() during startup corrupts the stream.
# Claude Code
claude mcp add playwright -- npx @playwright/mcp@latest
# Codex
codex mcp add context7 -- npx -y @upstash/context7-mcp
stdio wins on latency, needs no auth layer, and keeps data on your machine. It loses when the server should be shared, when it needs to survive your editor restarting, or when the vendor would rather run it themselves. That is the entire case for the remote transports.
MCP SSE: what the SSE transport was, and why it went away
The original remote transport, introduced in protocol version 2024-11-05, used two endpoints. The client opened a long-lived GET to something like https://example.com/sse, the server replied with an endpoint event naming a second URL, and every client-to-server message was POSTed there while every server-to-client message came back down the original stream.
It worked, and it had three problems that a single-endpoint design does not.
- It requires a long-lived connection for everything. A server that only answers requests still had to hold an open stream per client, which serverless platforms and ordinary load balancers are both bad at.
- Two endpoints means two places to get auth, CORS, and routing wrong. Most reported "SSE MCP server" failures were the POST endpoint being unreachable while the stream itself connected fine, which reads as a mysterious hang rather than an error.
- Resumption was ill-defined. Dropping the stream dropped the session, and there was no agreed way to pick it back up.
| Revision | What happened to SSE |
|---|---|
2024-11-05 | HTTP+SSE introduced as the remote transport |
2025-03-26 | Streamable HTTP replaces it. SSE marked deprecated, with a documented backwards-compatibility probe |
2025-11-25 | Unchanged, still deprecated |
2026-07-28 | Reclassified as Deprecated under the new feature lifecycle policy, with a minimum twelve-month window before removal |
Streamable HTTP, and what the 2026-07-28 revision changed
One endpoint, for example https://example.com/mcp, accepting POST. Each JSON-RPC message is a new POST. The server answers with either application/json for a single result, or text/event-stream when it wants to stream progress notifications before the result. That is the whole design, and it is why a plain request-response server no longer needs any streaming machinery at all.
The current revision, released 28 July 2026, took the design considerably further in the same direction.
- Protocol-level sessions are gone. The
Mcp-Session-Idheader was removed. Servers needing cross-call state mint an explicit handle and pass it as an ordinary tool argument. - The initialize handshake is gone. Every request carries its protocol version and client capabilities in
_meta, and a newserver/discoverRPC advertises what a server supports. - The GET endpoint is gone. Server-to-client change notifications now ride a single long-lived
subscriptions/listenPOST stream that the client opts into. - SSE resumability is gone.
Last-Event-IDand SSE event ids were removed. A broken response stream loses the in-flight request and the client must reissue it with a new request id.
Configuring each transport, per client
Claude Code
# streamable HTTP, the default choice
claude mcp add --transport http notion https://mcp.notion.com/mcp
# SSE, for a vendor that exposes nothing else
claude mcp add --transport sse asana https://mcp.asana.com/sse
# with an auth header, either transport
claude mcp add --transport http secure https://api.example.com/mcp \
--header "Authorization: Bearer $TOKEN"
# local stdio
claude mcp add playwright -- npx @playwright/mcp@latest
Claude Code prints a deprecation warning on --transport sse and points you at HTTP. In JSON, whether that is .mcp.json, ~/.claude.json, or claude mcp add-json, the type field takes http, streamable-http as an alias for it, sse, or ws.
Cursor
{
"mcpServers": {
"modern": {
"url": "https://mcp.example.com/mcp",
"type": "http"
},
"legacy": {
"url": "https://mcp.example.com/sse",
"type": "sse"
},
"local": {
"command": "npx",
"args": ["-y", "some-mcp-server"]
}
}
}
Codex
[mcp_servers.context7]
command = "npx"
args = ["-y", "@upstash/context7-mcp"]
[mcp_servers.figma]
url = "https://mcp.figma.com/mcp"
bearer_token_env_var = "FIGMA_OAUTH_TOKEN"
codex mcp add linear --url https://mcp.linear.app/mcp \
--bearer-token-env-var LINEAR_TOKEN
codex mcp login linear # for servers behind OAuth
codex mcp list
Migrating an SSE MCP server to streamable HTTP
If you run the server, the migration is smaller than it looks, because both transports can live side by side while clients catch up.
Add the new endpoint, keep the old one
Serve a single MCP endpoint that accepts POST, alongside the existing /sse and POST pair. The spec's own backwards-compatibility guidance is to host both, and it costs you one route.
Return JSON when you can
Only open an SSE stream on a POST response when you have progress notifications to send before the result. A tool that answers in 200ms should reply application/json and close, which removes a whole class of proxy and timeout problem.
Validate Origin and bind to localhost
The spec requires servers to validate the Origin header on incoming connections, and local servers should bind to 127.0.0.1 rather than 0.0.0.0. Without both, a web page can reach a local MCP server through DNS rebinding.
Stop depending on the session id
The 2026-07-28 revision removed Mcp-Session-Id entirely. If your server keeps per-connection state, move it behind an explicit handle you mint and return as a tool argument, which works under both the old and new revisions.
Announce it, then retire the old pair
Clients pin URLs in config files that nobody revisits. Publish the new endpoint, leave the old one up through the deprecation window, and expect the tail to be long.
If you only consume servers, migration is one line: change --transport sse to --transport http and the URL from /sse to /mcp, then check claude mcp list. If the vendor has not shipped a streamable HTTP endpoint, staying on SSE is correct for now, and the twelve-month policy window means it is not urgent.
The connection errors, and what each one means
| Symptom | Cause | Fix |
|---|---|---|
405 Method Not Allowed on a GET | The server offers no SSE stream at that endpoint | Expected on streamable HTTP. Not an error |
| Connects, then hangs with no tools | SSE stream opened but its POST endpoint is unreachable | Check the second URL the endpoint event named |
400 Bad Request on every call after the first | A pre-2026 server wants Mcp-Session-Id echoed back | Client is too old or too new for the server |
404 mid-session on an HTTP server | The session expired | The client must reinitialise. Older revisions only |
| Server silently missing from the list | A JSON entry has url but no type | Add "type": "http" or "sse" |
initialize POST fails, 404 or 405 | An /sse URL added with --transport http | Match the flag to the endpoint |
401 on first use | OAuth never completed | Run /mcp and finish the browser sign-in |
| Codex skips a remote server entirely | Codex has no SSE transport | Bridge the SSE endpoint to stdio locally |
Two operational details worth knowing before you debug anything deeper. Claude Code reconnects a dropped HTTP or SSE server automatically with exponential backoff, up to five attempts, so an intermittent server shows as pending rather than failed. And remote servers carry a per-request timer covering the time to first response byte, defaulting to 60 seconds, which is separate from the per-tool-call wall clock. A server that is merely slow to start streaming will trip the first timer while looking healthy by the second.
Questions people ask
Is MCP SSE deprecated?
Yes. The HTTP+SSE transport was deprecated in the 2025-03-26 spec revision when streamable HTTP replaced it, and the 2026-07-28 revision reclassified it as Deprecated under a formal lifecycle policy with a minimum twelve-month window before removal. It still works today in clients that support it.
What is the difference between MCP SSE and streamable HTTP?
SSE used two endpoints: a long-lived GET stream that announced a separate POST URL for client messages. Streamable HTTP uses one endpoint taking POST, which replies with either JSON or an SSE stream. Streamable HTTP still uses server-sent events, it just no longer needs a standing connection for servers that only answer requests.
How do I add an SSE MCP server to Claude Code?
claude mcp add --transport sse <name> <url>, for example claude mcp add --transport sse asana https://mcp.asana.com/sse. Add credentials with --header. Claude Code warns that the transport is deprecated and suggests HTTP where the vendor offers it.
Does Codex support SSE MCP servers?
No. Codex accepts command for a stdio server or url for a streamable HTTP server, and nothing else. Native SSE support has been an open request rather than a shipped feature. To use an SSE-only server with Codex, run a local bridge that presents it as stdio.
Why does my MCP server return 405 on GET?
That is correct behaviour for a streamable HTTP server that does not offer a server-initiated stream at its endpoint. The spec allows a server to answer the optional GET with 405 Method Not Allowed. Nothing is wrong.
What transport should a new MCP server use?
stdio if it runs on the user machine, streamable HTTP if it is remote. Do not build a new HTTP+SSE server. If you must serve older clients, host both and let them probe, which is the migration path the specification documents.
What happened to Mcp-Session-Id?
The 2026-07-28 revision removed protocol-level sessions and the Mcp-Session-Id header from streamable HTTP. Servers needing state across calls now mint an explicit handle and take it back as an ordinary tool argument. Older servers still using the header are not broken, they are on an earlier revision.
Do I need to change my MCP config because of the deprecation?
Not urgently. If your vendor publishes a streamable HTTP endpoint, switching is one flag and one URL. If SSE is all they offer, the twelve-month lifecycle window means you have notice before anything stops working.
Sources
Every figure above was read from these pages on August 2026. Vendors reprice without notice; if you find a stale number, tell us.
- MCP specification: transports read 19 August 2026
- MCP 2026-07-28: key changes session removal, SSE reclassification, resumability removal
- MCP feature lifecycle and deprecation policy the minimum twelve-month deprecation window
- MCP 2025-03-26 transports the revision that deprecated HTTP+SSE
- Claude Code MCP documentation
- Cursor documentation: MCP
- Codex documentation: MCP the mcp_servers schema, stdio and streamable HTTP only