A transport is the mechanism by which a client and server exchange MCP messages. The protocol is transport-agnostic — the same JSON-RPC messages flow over any transport. Your choice of transport affects how the server is deployed and how clients connect to it.
MCP defines two standard transports: stdio and HTTP with Server-Sent Events (SSE).
With stdio transport, the host process spawns your server as a child process. Messages flow over stdin/stdout:
The server lives and dies with the connection. When the host terminates the process, the session ends.
Use stdio when:
stdio is the default for all local MCP servers. It is the transport you should start with.
mcp.run() defaults to stdio:
if __name__ == "__main__":
mcp.run() # stdio transport, default
# or equivalently:
mcp.run(transport="stdio")
With stdio transport, any output written to stdout (other than valid JSON-RPC) will corrupt the protocol stream and crash the connection. This means:
logging to stderr, not print statementsprint() in your tool code (use return instead)Configure logging to stderr:
import logging
import sys
logging.basicConfig(stream=sys.stderr, level=logging.INFO)
logger = logging.getLogger(__name__)
With HTTP/SSE transport, your server runs as a persistent HTTP service. The client connects over the network:
This is a long-lived HTTP connection. The server runs independently of any client and can serve multiple clients simultaneously.
Use HTTP/SSE when:
if __name__ == "__main__":
mcp.run(transport="sse")
By default this starts on http://localhost:8000/sse. Configure the host and port:
mcp.run(transport="sse", host="0.0.0.0", port=9000)
Full example: code/05_http_sse_server.py
In client configuration, instead of a command to run, you provide the server URL. See Chapters 7–9 for client-specific configuration details.
| Factor | stdio | HTTP/SSE |
|---|---|---|
| Deployment | Local process | Network service |
| Multi-client | No (1:1) | Yes |
| Setup complexity | Minimal | Requires running server |
| Security | Process isolation | Network security needed |
| Latency | Minimal | Network overhead |
| Best for | Local tools, dev | Shared services, remote |
Start with stdio. It is simpler to develop, test, and configure. Move to HTTP/SSE only when you need remote access or multi-client support.
The MCP specification also defines a newer “Streamable HTTP” transport that unifies request and response over a single HTTP endpoint (without requiring SSE). As of early 2026, the Python SDK supports this as transport="streamable-http".
Streamable HTTP is better suited for serverless environments (AWS Lambda, Cloudflare Workers) where long-lived SSE connections are impractical.
mcp.run(transport="streamable-http", host="0.0.0.0", port=8000)
Check the SDK documentation for the latest transport options.
For production HTTP/SSE servers, run behind a reverse proxy like nginx or Caddy:
X-Forwarded-For, etc.)Example nginx location block:
location /mcp/ {
proxy_pass http://localhost:8000/;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_buffering off;
proxy_cache off;
}
The proxy_buffering off setting is critical for SSE — buffering breaks the streaming connection.
| ← Chapter 5: Prompt Templates | Table of Contents | Chapter 7: Connecting to Claude Desktop → |