What Is MCP Transport?
MCP transport is the communication layer that carries Model Context Protocol messages between an MCP client and an MCP server. The transport is responsible for encoding messages, managing the connection, and delivering responses β but it knows nothing about what the messages mean. That separation is intentional: it lets you deploy the same MCP server locally over stdio, remotely over HTTP, or in real-time over WebSocket without changing a single line of your tool implementation code.
Quick Definition#
MCP transport is the networking layer beneath MCP. It moves JSON-RPC 2.0 messages between client and server. The MCP specification defines three transports: stdio, HTTP/SSE, and WebSocket.
All three transports carry the same message format (JSON-RPC 2.0). Only the wire protocol and connection model differ.
Why Transport Choice Matters#
Transport affects four key properties of your MCP deployment:
- Locality: Is the server on the same machine as the client or remote?
- Scalability: Can multiple clients connect to the same server instance?
- Firewall traversal: Does it work through standard HTTP proxies and load balancers?
- Latency: Is it optimized for request-response or streaming?
Choosing the wrong transport creates avoidable problems. Running a production server over stdio means every user gets their own isolated process β you cannot share state or scale horizontally. Running an interactive real-time tool over HTTP polling adds latency that a WebSocket would eliminate.
The Three MCP Transports#
1. Stdio Transport (Local Subprocess)#
How it works: The MCP client launches the server as a child process using an OS command. Client-to-server messages are written to the server's stdin; server-to-client messages are written to the server's stdout. Everything runs through standard OS IPC β no sockets, no ports.
When to use it:
- Local development and testing
- Claude Desktop integrations (this is how
claude_desktop_config.jsonworks) - Servers that access local resources (file system, local database, local Docker daemon)
- Single-user deployments where isolation per user is desirable
Advantages:
- Zero network configuration β no ports to open, no firewall rules
- Secure by default β server runs with the same user permissions as the client
- Simple setup β just specify the command in the client config
- Works offline
Limitations:
- Local only β remote clients cannot connect
- One server process per client connection β no shared state across users
- Not suitable for high-concurrency or multi-tenant deployments
Example (Claude Desktop config):
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/you/projects"]
}
}
}
Example (TypeScript client):
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
const transport = new StdioClientTransport({
command: "python",
args: ["my_server.py"],
});
2. HTTP with Server-Sent Events (SSE) Transport#
How it works: The client makes standard HTTP POST requests to send messages to the server. The server uses Server-Sent Events (a standard browser streaming technology) to push responses and notifications back to the client over a persistent HTTP connection. This is a hybrid: request messages go over standard HTTP POST; response messages and server-initiated events come over a long-lived SSE stream.
When to use it:
- Remote MCP servers hosted on cloud infrastructure
- Servers shared across multiple users or teams
- Deployments on serverless platforms (Vercel, Cloudflare Workers, AWS Lambda with response streaming)
- Any scenario where clients need to connect from different machines
Advantages:
- Works through standard HTTP proxies, load balancers, and CDNs
- Compatible with serverless and edge deployments
- Supports multiple simultaneous client connections
- SSE streams work through most firewalls without special configuration
Limitations:
- Higher latency than stdio or WebSocket for rapid back-and-forth exchanges
- Requires authentication setup (see MCP authentication)
- More complex deployment than stdio
Example (TypeScript server):
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
import express from "express";
const app = express();
const server = new McpServer({ name: "my-server", version: "1.0.0" });
// SSE endpoint β client connects here to receive events
app.get("/sse", async (req, res) => {
const transport = new SSEServerTransport("/messages", res);
await server.connect(transport);
});
// POST endpoint β client sends messages here
app.post("/messages", express.json(), async (req, res) => {
// transport handles routing to the connected SSE session
});
app.listen(3000);
Example (TypeScript client connecting to remote):
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
const transport = new SSEClientTransport(
new URL("https://my-mcp-server.example.com/sse")
);
See the full deployment walkthrough in the deploy remote MCP server tutorial.
3. WebSocket Transport#
How it works: A standard WebSocket connection provides a persistent, full-duplex channel. Both client and server can send messages at any time without the request-response constraint. JSON-RPC messages are sent as WebSocket text frames.
When to use it:
- Real-time tools that push frequent updates (live market data, log tailing, event streams)
- Low-latency interactive tools where the round-trip of HTTP/SSE adds measurable delay
- Long-running sessions with many rapid exchanges
When not to use it:
- Serverless deployments (WebSockets require persistent connections that serverless functions do not support natively)
- Clients behind strict corporate proxies that block WebSocket upgrades
- Simple request-response tool patterns where HTTP/SSE works fine
WebSocket transport is less commonly needed than stdio or HTTP/SSE for typical MCP use cases, but it is the right choice for high-frequency streaming scenarios.
Transport Comparison Table#
| Property | Stdio | HTTP/SSE | WebSocket |
|---|---|---|---|
| Locality | Local only | Local or remote | Local or remote |
| Multi-client | No (per-process) | Yes | Yes |
| Serverless compatible | No | Yes | No |
| Firewall friendly | N/A (no network) | Yes | Sometimes |
| Setup complexity | Very low | Medium | Medium |
| Latency | Very low | Lowβmedium | Very low |
| Best for | Dev + local tools | Production remote | Real-time streaming |
Custom Transports#
The MCP specification defines a transport interface, not just three fixed implementations. If you have an unusual deployment requirement β for example, running MCP over a message queue like Redis Pub/Sub, or over gRPC β you can implement a custom transport by satisfying the Transport interface in the SDK.
A custom transport must:
- Implement
start()to establish the connection - Implement
send(message)to deliver outbound messages - Call
onmessage(message)when inbound messages arrive - Implement
close()to cleanly terminate the session
Custom transports are advanced and rarely needed. Most production use cases are served by stdio or HTTP/SSE.
Choosing a Transport for Your Deployment#
Use this decision flow:
- Is the server local (same machine as client)? β Use stdio
- Do multiple users or clients need to share one server? β Use HTTP/SSE
- Does the server push real-time events at high frequency? β Use WebSocket
- Deploying on serverless (Vercel, Lambda, Cloudflare)? β Use HTTP/SSE
- Behind a strict corporate proxy? β Use HTTP/SSE (most compatible)
Related Terms#
Browse all terms in the AI agent glossary.
- MCP Client β the host application that initiates transport connections
- MCP Server β the capability provider that accepts transport connections
- MCP Authentication β how to secure remote HTTP/SSE transports
- Model Context Protocol β the full protocol built on top of transport
Frequently Asked Questions#
Can I switch transports without changing my tool code?
Yes. The MCP SDK separates transport from tool logic. Your tool implementations, resource handlers, and prompt templates are registered on the server object and have no knowledge of which transport is being used. Switching from stdio to HTTP/SSE requires changing only the server startup code β the part that creates and connects the transport β not the tool definitions themselves.
Does stdio transport work on Windows?
Yes. Stdio transport uses standard OS-level stdin/stdout piping, which works on Windows, macOS, and Linux. The MCP SDK handles platform differences automatically. The only requirement is that the server command can be launched as a subprocess from the client process.
How does HTTP/SSE handle connection drops?
The client is responsible for reconnection. If the SSE stream drops, a well-implemented client detects the connection close event and re-establishes the SSE connection, replaying the initialize handshake. The MCP specification does not mandate session persistence across reconnections, so stateful servers should design their tool implementations to handle fresh connections gracefully.
See also: comparisons for practical examples.