# How to Choose Between stdio, HTTP, and SSE Transport for MCP Clients

> Learn when to use stdio, HTTP, and SSE transport for MCP clients. Optimize your development by choosing the right transport for local, streaming, or full-duplex connections.

- Repository: [Composio/awesome-codex-skills](https://github.com/composiohq/awesome-codex-skills)
- Tags: deep-dive
- Published: 2026-04-26

---

**TLDR:** Choose `stdio` for local subprocess communication during development, `sse` for server-to-client streaming over HTTP, and `http` for full-duplex streamable connections behind API gateways.

When integrating with Model Context Protocol (MCP) servers in the ComposioHQ/awesome-codex-skills repository, selecting the correct transport mechanism determines how your client establishes and maintains communication. The `create_connection()` factory in [`mcp-builder/scripts/connections.py`](https://github.com/ComposioHQ/awesome-codex-skills/blob/main/mcp-builder/scripts/connections.py) instantiates one of three concrete implementations—`MCPConnectionStdio`, `MCPConnectionSSE`, or `MCPConnectionHTTP`—based on your deployment environment and latency requirements (source lines 12–51).

## Understanding MCP Transport Options

Each transport offers distinct advantages for connecting MCP clients to servers, ranging from local process spawning to remote HTTP streaming.

### stdio Transport

The **`stdio`** transport spawns the server as a local subprocess and communicates over standard input/output streams. This approach eliminates network overhead entirely.

**Best for:**
- Development on a single machine with fast feedback loops
- CI jobs and local evaluation environments where you control the runtime
- Scenarios requiring the lowest possible latency

**Advantages:**
- **No network hop** provides the lowest latency of the three options
- **No public URLs or certificates** required
- **Simple configuration:** supply only the command and arguments

**Limitations:**
- Only works with locally available binaries or scripts
- Process crashes immediately terminate the connection
- Cannot scale across multiple machines or containers

### SSE Transport

The **`sse`** (Server-Sent Events) transport creates a persistent HTTP connection where the server pushes JSON-encoded MCP messages as events. This works well for services running as web applications.

**Best for:**
- Servers running as web services (e.g., FastAPI, Flask)
- Environments where firewalls allow outbound HTTP but not inbound connections
- Lightweight clients that should remain stateless

**Advantages:**
- **Works over the internet** without opening additional ports
- **Naturally integrates** with server-side HTTP frameworks
- **Keeps clients lightweight** by offloading connection state to the server

**Limitations:**
- **Unidirectional streaming only:** server-to-client via SSE; client-to-server requests require separate HTTP calls (handled internally by the MCP SDK)
- Slightly higher latency than `stdio` due to HTTP overhead

### HTTP Transport

The **`http`** (streamable HTTP) transport enables full-duplex communication over a single HTTP request/response that streams chunks of MCP data. This suits REST-like architectures and gateway-proxied environments.

**Best for:**
- Existing REST-like endpoints requiring single-request interactions
- Serverless functions and environments behind API gateways
- Scenarios requiring load balancer compatibility

**Advantages:**
- **Works behind most load-balancers and API gateways**
- **Supports bidirectional streaming** within a single connection
- **Compatible with standard HTTP infrastructure**

**Limitations:**
- Requires the server to implement the **streamable-HTTP contract**
- More complex server implementation compared to `stdio`

## Decision Flow for Selecting a Transport

Follow this sequence to determine which transport suits your MCP deployment:

1. **Is the server a local executable or script?**  
   Use **`stdio`**. This avoids network configuration and provides immediate feedback during skill development.

2. **Do you have a publicly reachable URL that supports server-sent events?**  
   Use **`sse`**. This suits long-running services where the server maintains connection state and pushes updates to clients.

3. **Does your infrastructure require a single HTTP endpoint that streams both requests and responses?**  
   Use **`http`**. This is necessary for serverless deployments or when routing through reverse proxies and API gateways that don't support persistent SSE connections.

If uncertain, start with `stdio` for rapid iteration, then migrate to `sse` or `http` for production deployments requiring remote access.

## Implementation Examples

The repository provides both programmatic and CLI interfaces for configuring each transport.

### Programmatic Connection Creation

Import the factory from [`mcp-builder/scripts/connections.py`](https://github.com/ComposioHQ/awesome-codex-skills/blob/main/mcp-builder/scripts/connections.py) and specify the transport type:

```python
from mcp_builder.scripts.connections import create_connection

# Local subprocess (stdio)

stdio_conn = create_connection(
    transport="stdio",
    command="python",
    args=["my_mcp_server.py"],
    env={"API_KEY": "abc123"}
)

# Server-Sent Events

sse_conn = create_connection(
    transport="sse",
    url="https://my-mcp.example.com/events",
    headers={"Authorization": "Bearer secret-token"}
)

# Streamable HTTP

http_conn = create_connection(
    transport="http",
    url="https://my-mcp.example.com/stream",
    headers={"Authorization": "Bearer secret-token"}
)

```

Each connection object supports async context manager usage:

```python
async with stdio_conn as conn:
    tools = await conn.list_tools()
    result = await conn.call_tool("search_documents", {"query": "AI ethics"})

```

### CLI Evaluation Harness

The evaluation script at [`scripts/evaluation.py`](https://github.com/ComposioHQ/awesome-codex-skills/blob/main/scripts/evaluation.py) accepts transport-specific flags (documented in [`mcp-builder/reference/evaluation.md`](https://github.com/ComposioHQ/awesome-codex-skills/blob/main/mcp-builder/reference/evaluation.md), lines 20–30):

**stdio:**

```bash
python scripts/evaluation.py \
  -t stdio \
  -c python \
  -a my_mcp_server.py \
  -e API_KEY=abc123 \
  my_evaluation.xml

```

**SSE:**

```bash
python scripts/evaluation.py \
  -t sse \
  -u https://my-mcp.example.com/events \
  -H "Authorization: Bearer abc123" \
  my_evaluation.xml

```

**HTTP:**

```bash
python scripts/evaluation.py \
  -t http \
  -u https://my-mcp.example.com/stream \
  -H "Authorization: Bearer abc123" \
  my_evaluation.xml

```

## Summary

- **Use `stdio`** when spawning local subprocesses for development and testing; it offers the lowest latency but requires local access to the server binary.
  
- **Use `sse`** for server-to-client streaming over HTTP when deploying publicly accessible services that need to push events to lightweight clients.

- **Use `http`** for streamable full-duplex connections required by serverless functions, API gateways, or load-balanced environments.

- **Implementation:** Configure your choice via `create_connection()` in [`mcp-builder/scripts/connections.py`](https://github.com/ComposioHQ/awesome-codex-skills/blob/main/mcp-builder/scripts/connections.py) or through the `-t` flag in [`scripts/evaluation.py`](https://github.com/ComposioHQ/awesome-codex-skills/blob/main/scripts/evaluation.py).

## Frequently Asked Questions

### Can I switch between stdio and HTTP without modifying my server?

No. Each transport requires specific server-side implementation. The `stdio` transport expects a CLI executable, while `http` and `sse` require your server to implement the streamable-HTTP contract or SSE protocol, respectively. According to the ComposioHQ/awesome-codex-skills source, `MCPConnectionHTTP` specifically validates that the server supports chunked transfer encoding for streaming.

### Why does stdio have lower latency than HTTP-based transports?

The `stdio` transport communicates via local process pipes (stdin/stdout) without network stack overhead. As implemented in [`mcp-builder/scripts/connections.py`](https://github.com/ComposioHQ/awesome-codex-skills/blob/main/mcp-builder/scripts/connections.py), `MCPConnectionStdio` spawns a subprocess directly on the client machine, eliminating TCP handshake, TLS negotiation, and HTTP header parsing that occur in `MCPConnectionSSE` and `MCPConnectionHTTP`.

### Does SSE support bidirectional communication?

No. Server-Sent Events only stream from server to client. When using `MCPConnectionSSE`, client-to-server requests travel via separate HTTP POST calls managed by the underlying MCP SDK. For true bidirectional streaming over a single connection, use the `http` transport with `MCPConnectionHTTP`, which maintains a full-duplex streamable HTTP connection.

### How do I secure connections when using HTTP or SSE transports?

Pass authentication headers via the `headers` parameter in `create_connection()` or the `-H` flag in the evaluation CLI. For `stdio` connections, use the `env` parameter to inject secrets as environment variables into the subprocess. The evaluation harness examples demonstrate both patterns: `headers={"Authorization": "Bearer ..."}` for HTTP/SSE and `-e API_KEY=value` for stdio.