Transports compared: stdio vs SSE vs HTTP vs WebSocket

Francisc Toth · NOV 12, 2025 · 8 minutes
Transports compared: stdio vs SSE vs HTTP vs WebSocket

MCP runs over four transports. Pick the wrong one and you'll fight your stack for weeks. Pick the right one and the protocol stays out of your way. Here's how to choose.

stdio: the default for local clients

stdio runs the server as a subprocess of the client. The client writes JSON-RPC messages to stdin, reads responses from stdout. No network involved.

This is what Claude Desktop, Cursor, Cline, and most other local clients use by default. It's the simplest setup and the safest: no ports exposed, no auth headaches, no certificates to manage.

The cost: the server only lives as long as the client process. Restart Claude, restart the server. Memory state resets. Long-running tasks that need to outlive a single chat session don't fit here.

stdio also can't be shared. If two clients on the same machine want the same server, they each spawn their own subprocess. That's fine for local tools but doesn't scale to team or production use.

Use it when: the client is on your laptop and the server has no state that needs to persist beyond a session. This covers most personal dev tools.

SSE: one-way streaming for web clients

Server-Sent Events is HTTP with a long-lived response. The client opens a single connection, the server streams events back over time, the client sends tool calls via separate POST requests to the same endpoint.

SSE is the right answer for web-based AI clients like chatbots, internal dashboards, and browser extensions. It works through firewalls because it's just HTTP, survives behind any standard load balancer, and doesn't need WebSocket support on the proxy layer.

The asymmetry trips people up. SSE is one-way: server-to-client. Tool calls go back via a parallel POST channel. If you're writing an SSE client by hand, that bidirectional setup needs care. Most SDKs hide it.

Use it when: the client runs in a browser or behind a corporate proxy. SSE survives where WebSocket gets blocked.

HTTP: stateless, simple, slow

Plain HTTP. The client sends a JSON-RPC request, the server returns the response. No streaming, no persistent connection.

This is the easiest transport to debug. Every interaction is a single curl command. It's also the easiest to host: any web framework or serverless platform supports it. Lambda, Cloud Run, Vercel all work fine.

The cost is latency. Every tool call pays the cost of a fresh HTTP request: DNS lookup, TLS handshake, server cold start if you're on serverless. For chatty workflows that fire ten tool calls in a turn, that latency compounds.

HTTP also can't stream partial results. A tool that scans a million rows and returns 10MB of data sends the entire response in one shot. SSE handles that better.

Use it when: tool calls are infrequent, latency-tolerant, or you need the simplest possible deployment. Internal admin tools and cron-style automation fit here.

WebSocket: bidirectional, stateful, finicky

A single persistent connection in both directions. The client and server can push messages whenever they want. The lowest-overhead option once the connection is established.

WebSocket is the right transport for high-throughput agentic workflows: multi-turn tool chaining, real-time collaboration, live data feeds. The handshake happens once. Subsequent tool calls don't pay the connection setup cost.

The downside is operational. Corporate proxies and CDNs frequently mangle WebSocket connections. Sticky sessions are required if you're behind a load balancer. Reconnection logic has to handle dropped connections gracefully.

If you've ever maintained a WebSocket service in production, you know the failure modes. They're not impossible to solve, but they're real work.

Use it when: throughput matters more than simplicity, and you control the network path end-to-end. Internal tools at companies with one VPC, sure. Public-facing MCP servers on the open internet, probably not.

How to pick in practice

Start with stdio for any local development. If you need persistence or sharing, move to SSE for web clients or HTTP for backend-only services. Reach for WebSocket only when you've measured a real latency problem and the other options can't solve it.

Most production MCP deployments we've seen end up on SSE. It's the right default for hosted servers because it works with standard web infrastructure, supports streaming, and doesn't require sticky sessions. The few teams using WebSocket are either at high call volume or running on infrastructure that already standardized on it.

The protocol is the same across all four transports. The handshake, capability negotiation, JSON-RPC framing are identical. Only the bytes-on-the-wire layer changes. That means you can prototype on stdio and switch transports later without rewriting tool implementations.

What we did

Toolcall supports all four. We default new servers to SSE because it's the safest production choice. stdio is available for local-only servers. HTTP and WebSocket are opt-in for teams that have specific reasons.

If you're not sure which one you need, start with the default and move only when you have data.

Transports compared: stdio vs SSE vs HTTP vs WebSocket

Francisc Toth · NOV 12, 2025 · 8 minutes
Transports compared: stdio vs SSE vs HTTP vs WebSocket

MCP runs over four transports. Pick the wrong one and you'll fight your stack for weeks. Pick the right one and the protocol stays out of your way. Here's how to choose.

stdio: the default for local clients

stdio runs the server as a subprocess of the client. The client writes JSON-RPC messages to stdin, reads responses from stdout. No network involved.

This is what Claude Desktop, Cursor, Cline, and most other local clients use by default. It's the simplest setup and the safest: no ports exposed, no auth headaches, no certificates to manage.

The cost: the server only lives as long as the client process. Restart Claude, restart the server. Memory state resets. Long-running tasks that need to outlive a single chat session don't fit here.

stdio also can't be shared. If two clients on the same machine want the same server, they each spawn their own subprocess. That's fine for local tools but doesn't scale to team or production use.

Use it when: the client is on your laptop and the server has no state that needs to persist beyond a session. This covers most personal dev tools.

SSE: one-way streaming for web clients

Server-Sent Events is HTTP with a long-lived response. The client opens a single connection, the server streams events back over time, the client sends tool calls via separate POST requests to the same endpoint.

SSE is the right answer for web-based AI clients like chatbots, internal dashboards, and browser extensions. It works through firewalls because it's just HTTP, survives behind any standard load balancer, and doesn't need WebSocket support on the proxy layer.

The asymmetry trips people up. SSE is one-way: server-to-client. Tool calls go back via a parallel POST channel. If you're writing an SSE client by hand, that bidirectional setup needs care. Most SDKs hide it.

Use it when: the client runs in a browser or behind a corporate proxy. SSE survives where WebSocket gets blocked.

HTTP: stateless, simple, slow

Plain HTTP. The client sends a JSON-RPC request, the server returns the response. No streaming, no persistent connection.

This is the easiest transport to debug. Every interaction is a single curl command. It's also the easiest to host: any web framework or serverless platform supports it. Lambda, Cloud Run, Vercel all work fine.

The cost is latency. Every tool call pays the cost of a fresh HTTP request: DNS lookup, TLS handshake, server cold start if you're on serverless. For chatty workflows that fire ten tool calls in a turn, that latency compounds.

HTTP also can't stream partial results. A tool that scans a million rows and returns 10MB of data sends the entire response in one shot. SSE handles that better.

Use it when: tool calls are infrequent, latency-tolerant, or you need the simplest possible deployment. Internal admin tools and cron-style automation fit here.

WebSocket: bidirectional, stateful, finicky

A single persistent connection in both directions. The client and server can push messages whenever they want. The lowest-overhead option once the connection is established.

WebSocket is the right transport for high-throughput agentic workflows: multi-turn tool chaining, real-time collaboration, live data feeds. The handshake happens once. Subsequent tool calls don't pay the connection setup cost.

The downside is operational. Corporate proxies and CDNs frequently mangle WebSocket connections. Sticky sessions are required if you're behind a load balancer. Reconnection logic has to handle dropped connections gracefully.

If you've ever maintained a WebSocket service in production, you know the failure modes. They're not impossible to solve, but they're real work.

Use it when: throughput matters more than simplicity, and you control the network path end-to-end. Internal tools at companies with one VPC, sure. Public-facing MCP servers on the open internet, probably not.

How to pick in practice

Start with stdio for any local development. If you need persistence or sharing, move to SSE for web clients or HTTP for backend-only services. Reach for WebSocket only when you've measured a real latency problem and the other options can't solve it.

Most production MCP deployments we've seen end up on SSE. It's the right default for hosted servers because it works with standard web infrastructure, supports streaming, and doesn't require sticky sessions. The few teams using WebSocket are either at high call volume or running on infrastructure that already standardized on it.

The protocol is the same across all four transports. The handshake, capability negotiation, JSON-RPC framing are identical. Only the bytes-on-the-wire layer changes. That means you can prototype on stdio and switch transports later without rewriting tool implementations.

What we did

Toolcall supports all four. We default new servers to SSE because it's the safest production choice. stdio is available for local-only servers. HTTP and WebSocket are opt-in for teams that have specific reasons.

If you're not sure which one you need, start with the default and move only when you have data.

// READY TO SHIP

START YOUR FIRST MCP SERVER
IN UNDER FIVE MINUTES

No credit card required. Hobby plan is free forever.

Create a free website with Framer, the website builder loved by startups, designers and agencies.