MCP Transport Types: stdio, Streamable HTTP, and SSE
MCP transport types come down to two current choices: stdio for local servers, Streamable HTTP for production. SSE is deprecated. Here's which to pick when.
>This is the transport pick. Claude Certified Architect Foundations: Crash Course boils all five exam domains to a weekend, decodes the trick-question craft, and ships one realistic mock.

Claude Certified Architect Foundations: Crash Course
Pass the CCA-F Exam in a Weekend. The 5 Domains Boiled Down, the Judgment Patterns Decoded, and One Realistic Mock.
Summary:
- MCP defines exactly two current transports: stdio and Streamable HTTP.
- stdio is for a local, single-user server; Streamable HTTP is for a shared, production one.
- SSE is the deprecated predecessor, replaced since protocol version 2024-11-05.
- You get the transport table, the exact
claude mcp addcommands, and the tools-vs-resources boundary that trips people up.
MCP transport types come down to a choice most builders overcomplicate: a Model Context Protocol server has exactly two current transports, and picking the right one is one sentence of judgment, not a research project. The trap is a third name that looks modern and is actually a ghost. Get the pick reflexive and you save yourself a wrong deploy. On the Claude Certified Architect exam it is a nearly guaranteed point, since Tool Design and MCP is Domain 4, worth 18% of your score.
Which MCP transport should you use?
You use stdio for a local, single-user server and Streamable HTTP for a remote, shared, production one. That is the whole decision. Here is what the spec actually defines, pulled straight from the current version:
| Transport | Use it for | Status |
|---|---|---|
| stdio | Client launches the server as a subprocess; the server reads JSON-RPC from stdin and writes to stdout. Local, single user. | Current. “Clients SHOULD support stdio whenever possible.” |
| Streamable HTTP | Server runs as an independent process handling multiple clients over HTTP POST and GET, at one endpoint path. Remote, shared, production. | Current. |
| HTTP+SSE (old) | The prior HTTP+SSE transport from protocol version 2024-11-05. | Deprecated. “This replaces the HTTP+SSE transport.” |
From the MCP specification: “The protocol currently defines two standard transport mechanisms for client-server communication: 1. stdio … 2. Streamable HTTP.”

Two current transports, never three. That count is the fact the whole thing rests on.
When do you use stdio?
You use stdio when the server runs on one machine for one user. The client launches the server as a subprocess and talks to it over standard in and standard out, so there is no network, no port, no auth handshake to stand up. It is the simplest thing that works, and the spec says clients should support it whenever they can.
Adding a local server from the CLI is one line:
# stdio: local, single-user. The client launches the server as a subprocess.
claude mcp add my-local-server -- python3 server.py
If the scenario in front of you is a tool on your own laptop, or a dev-only helper nobody else connects to, it is stdio. You do not reach for HTTP to talk to a process you just spawned yourself.
When do you use Streamable HTTP?
You use Streamable HTTP when the server is remote and more than one client connects to it. It handles multiple connections over HTTP POST and GET at a single endpoint path, which is what a production server behind a URL needs. The moment a second service or a teammate has to reach the same server, stdio is out and Streamable HTTP is in.
The command has one detail that bites people:
# Streamable HTTP: remote, shared, production.
# The flag VALUE is http, NOT streamable-http.
claude mcp add --transport http my-server https://example.com/mcp \
--header "Authorization: Bearer $TOKEN"
# confirm what got wired up
claude mcp list
The spec calls the transport “Streamable HTTP,” but the CLI flag value is http. Type --transport streamable-http to match the prose name and the command errors. The list output confirms the server as (HTTP), which is the CLI telling you the value took. Small thing, real copy-paste failure.
Why is SSE the wrong answer?
SSE is the wrong answer because it is not a current transport. It is the deprecated predecessor, the old HTTP+SSE transport from protocol version 2024-11-05, and Streamable HTTP explicitly replaced it. It survives only for backward compatibility. On a certification question it is the option written to be picked by someone who half-remembers that MCP does something with server-sent events.
Here is the nuance that keeps you honest: Streamable HTTP itself may use server-sent events internally to stream a response. That is a wire detail. A standalone “SSE transport” as a deployment choice is still the dead one. The two facts do not conflict, and the framing that matters is this: MCP has two current transports, and SSE is the legacy one, not a co-equal third. Anyone who tells you “MCP has three transports” is repeating the exact mistake the ghost answer is built on.
Tools, resources, or prompts: the other boundary
Transports are how the server talks. The other thing to get right is what it exposes, because MCP servers expose three kinds of thing and they are controlled by three different parties:
- Tools are model-controlled. They are actions with side effects, the operations the model decides to call.
- Resources are app-controlled. They are passive, read-only context exposed through URIs.
- Prompts are user-controlled. They are pre-crafted workflows a user explicitly selects.
The boundary error is exposing an action as a Resource, or read-only context as a Tool. A payment has side effects, so it is a Tool, never a Resource. Reference data the model should see but not act on is a Resource. Make the question a function and the boundary stops being a judgment call:
def primitive_for(has_side_effect, user_selects):
if has_side_effect: return "tool" # model-controlled action
if user_selects: return "prompt" # user-controlled workflow
return "resource" # app-controlled read-only context
cases = [("process a payment", True, False),
("read an account record", False, False),
("run the 'summarize ticket' workflow", False, True)]
for name, side_effect, selects in cases:
print(f"{name:36} -> {primitive_for(side_effect, selects)}")
Run it and the payment lands in tool while the account read lands in resource:
process a payment -> tool
read an account record -> resource
run the 'summarize ticket' workflow -> prompt
Actions are tools; passive context is a resource; user-selected workflows are prompts. That one question settles most primitive-boundary decisions.
What should you actually do?
- If the server runs locally for one user → stdio, launched as a subprocess.
- If the server is remote and several clients hit it → Streamable HTTP, flag value
http. - If an option offers standalone SSE for a production server → eliminate it; SSE is deprecated.
- If you are exposing an operation with side effects → it is a Tool, not a Resource.
- If you typed
--transport streamable-httpand the command failed → change the value tohttp.
The bottom line
- Two current transports, and the pick is deployment, not preference. Local single-user is stdio; remote shared production is Streamable HTTP.
- SSE is a decoy. It is the deprecated 2024-11-05 transport, so a standalone SSE deployment choice is always wrong, even though Streamable HTTP may stream over SSE under the hood.
- The CLI value is
http. The spec name is prose; the flag is not. Match the flag or the command errors. - Actions are tools, read-only data is a resource. Exposing an action as a resource is the boundary error the design half of MCP is really testing.
Frequently Asked Questions
How many transports does MCP have?+
Two current ones: stdio and Streamable HTTP. The old HTTP+SSE transport from protocol version 2024-11-05 is deprecated, so a standalone SSE choice is not a third live option.
Should I use stdio or Streamable HTTP for my MCP server?+
Use stdio when the server runs locally for one user as a subprocess of the client. Use Streamable HTTP when the server is remote and several clients or services connect to it over HTTP.
What is the MCP CLI flag value for an HTTP server?+
The flag value is http, as in claude mcp add --transport http. The spec calls the transport Streamable HTTP, but the CLI value stays http, so do not type streamable-http or the command errors.