# stdio and streamable-http Transport Modes in MCP-Airflow-API: A Complete Guide

> Understand stdio vs streamable-http transport modes in MCP-Airflow-API. Learn how to select between local pipes and remote aiohttp servers using environment variables or CLI flags for efficient API communication.

- Repository: [JungJungIn/mcp-airflow-api](https://github.com/call518/mcp-airflow-api)
- Tags: how-to-guide
- Published: 2026-02-26

---

**The stdio transport mode uses direct stdin/stdout pipes for local communication, while streamable-http runs an aiohttp server for remote network access, with the mode selected via the `FASTMCP_TYPE` environment variable or `--type` CLI flag.**

The `call518/mcp-airflow-api` repository implements a Model Context Protocol (MCP) server that supports two distinct transport modes: stdio and streamable-http. Understanding the differences between these stdio and streamable-http transport modes is essential for choosing the right deployment strategy, whether you are running local development tools or exposing Airflow APIs through containerized services.

## What Are stdio and streamable-http Transport Modes?

Transport modes define how the MCP server communicates with its clients. In `mcp-airflow-api`, these modes are implemented using the `fastmcp` library and determine whether the server operates as a local subprocess or a network service.

**stdio** (Standard Input/Output) mode creates a direct pipe between the client and server processes. The server reads MCP requests from `stdin` and writes responses to `stdout`, making it ideal for local integrations where the client spawns the server as a subprocess.

**streamable-http** mode starts an HTTP server using `aiohttp` that listens on a configurable host and port. This mode allows remote clients to connect over TCP, making it suitable for Docker containers, Kubernetes deployments, or situations requiring reverse proxy support.

## Key Differences Between stdio and streamable-http Transport Modes

The following table summarizes the core distinctions between these transport modes:

| Feature | stdio | streamable-http |
|---------|-------|-----------------|
| **Communication Channel** | Direct stdin/stdout pipes | HTTP server streaming over TCP |
| **Typical Use Case** | Local development, Claude-Desktop integration | Docker containers, remote services, reverse proxies |
| **Startup Method** | Subprocess launch (`python -m mcp_airflow_api`) | `aiohttp` server on configured host/port |
| **Configuration** | `FASTMCP_TYPE=stdio` (default) or `--type stdio` | `FASTMCP_TYPE=streamable-http` with `FASTMCP_HOST`, `FASTMCP_PORT` |
| **Authentication** | None (direct process access) | Optional bearer token via `REMOTE_AUTH_ENABLE` and `REMOTE_SECRET_KEY` |
| **Performance** | Minimal latency (no network stack) | Slightly higher latency (HTTP/TCP overhead) but scalable |
| **Security Surface** | Minimal (local user only) | Network endpoint requires TLS/firewall protection |

### Implementation in mcp_main.py

The transport mode selection logic resides in [`src/mcp_airflow_api/mcp_main.py`](https://github.com/call518/mcp-airflow-api/blob/main/src/mcp_airflow_api/mcp_main.py). The argument parser defines the available choices at lines 274-276:

```python
parser.add_argument(
    "--type",
    dest="transport_type",
    help="Transport type. Default: env FASTMCP_TYPE or stdio",
    choices=["stdio", "streamable-http"],
    default=None,
)

```

The effective transport is resolved by checking the CLI flag first, then the `FASTMCP_TYPE` environment variable, falling back to `"stdio"` at line 329:

```python
transport_type = args.transport_type or os.getenv("FASTMCP_TYPE", "stdio")

```

Finally, the server branches based on the resolved transport type at lines 376-381:

```python
if transport_type == "streamable-http":
    logger.info(f"Starting streamable-http server on {host}:{port}")
    mcp.run(transport="streamable-http", host=host, port=port)
else:
    logger.info("Starting stdio transport for local usage")
    mcp.run(transport='stdio')

```

In **stdio** mode, `mcp.run(transport='stdio')` instantiates `FastMCPStdIOTransport`, which reads from `stdin` and writes to `stdout`. In **streamable-http** mode, `FastMCPStreamableHTTPTransport` starts an `aiohttp` server on the specified host and port, optionally wrapping requests with `StaticTokenVerifier` when `REMOTE_AUTH_ENABLE` is true.

## Configuration and Usage Examples

### Running in stdio Mode (Local Development)

For local development or integration with Claude-Desktop, use the default stdio transport. Create a configuration file like `mcp-config.json.stdio`:

```json
{
  "mcpServers": {
    "mcp-airflow-api": {
      "command": "python",
      "args": ["-m", "mcp_airflow_api"],
      "env": {
        "PYTHONPATH": "/app/src",
        "AIRFLOW_API_VERSION": "v1",
        "MCP_LOG_LEVEL": "INFO"
      }
    }
  }
}

```

Start the server:

```bash
export FASTMCP_TYPE=stdio
python -m mcp_airflow_api

```

### Running in streamable-http Mode (Docker/Remote)

For containerized deployments, use the streamable-http transport. The repository includes [`scripts/mcp-server-docker-cmd.sh`](https://github.com/call518/mcp-airflow-api/blob/main/scripts/mcp-server-docker-cmd.sh) which demonstrates the typical Docker startup:

```bash
#!/bin/bash
export FASTMCP_TYPE=streamable-http
export FASTMCP_HOST=0.0.0.0
export FASTMCP_PORT=8000
export REMOTE_AUTH_ENABLE=true
export REMOTE_SECRET_KEY=${REMOTE_SECRET_KEY:-default-secret-key}

python -m mcp_airflow_api \
  --type streamable-http \
  --host $FASTMCP_HOST \
  --port $FASTMCP_PORT \
  --auth-enable \
  --secret-key $REMOTE_SECRET_KEY

```

Client configuration for remote access:

```json
{
  "mcpServers": {
    "mcp-airflow-api": {
      "type": "streamable-http",
      "url": "http://localhost:8000/mcp",
      "headers": {
        "Authorization": "Bearer my-secret"
      }
    }
  }
}

```

## When to Use Each Transport Mode

Choose the transport mode based on your deployment architecture and security requirements:

- **Use stdio** when running the MCP server locally alongside the client, such as during development, unit testing, or when integrating with Claude-Desktop. This mode offers minimal latency and zero network configuration.

- **Use streamable-http** when deploying the server in Docker containers, Kubernetes pods, or behind reverse proxies where the client and server run on different hosts. This mode supports optional bearer-token authentication via `StaticTokenVerifier` and scales to multiple concurrent clients.

- **Use streamable-http with authentication** when exposing the Airflow API to remote clients over untrusted networks. Set `REMOTE_AUTH_ENABLE=true` and configure `REMOTE_SECRET_KEY` to enforce bearer-token validation on every request.

## Summary

- **stdio transport mode** uses direct stdin/stdout pipes for local process communication, configured via `FASTMCP_TYPE=stdio` or the `--type stdio` flag, and is implemented in [`src/mcp_airflow_api/mcp_main.py`](https://github.com/call518/mcp-airflow-api/blob/main/src/mcp_airflow_api/mcp_main.py) using `FastMCPStdIOTransport`.

- **streamable-http transport mode** starts an `aiohttp` server on configurable host/port, supports optional bearer-token authentication via `REMOTE_AUTH_ENABLE` and `REMOTE_SECRET_KEY`, and is suitable for Docker deployments and remote clients.

- The transport selection logic resolves the effective mode by checking CLI arguments first, then the `FASTMCP_TYPE` environment variable, defaulting to `"stdio"` if neither is specified.

- Configuration examples for both modes are provided in `mcp-config.json.stdio` and the [`scripts/mcp-server-docker-cmd.sh`](https://github.com/call518/mcp-airflow-api/blob/main/scripts/mcp-server-docker-cmd.sh) helper script.

## Frequently Asked Questions

### What is the default transport mode in mcp-airflow-api?

The default transport mode is **stdio**. If you do not specify the `--type` argument or set the `FASTMCP_TYPE` environment variable, the server automatically defaults to stdio mode as implemented in [`src/mcp_airflow_api/mcp_main.py`](https://github.com/call518/mcp-airflow-api/blob/main/src/mcp_airflow_api/mcp_main.py) at line 329.

### Can I enable authentication in stdio mode?

No, authentication is not applicable to stdio mode. Because the client communicates directly with the server process via stdin/stdout pipes, access is inherently restricted to the local user running the process. Authentication via bearer tokens is only available in streamable-http mode using the `REMOTE_AUTH_ENABLE` and `REMOTE_SECRET_KEY` environment variables.

### How do I switch between transport modes in a Docker deployment?

To run in stdio mode inside a container, launch the process with `FASTMCP_TYPE=stdio` or without any transport-specific configuration. For streamable-http mode, set `FASTMCP_TYPE=streamable-http`, expose the desired port (e.g., 8000), and optionally enable authentication. The repository provides [`scripts/mcp-server-docker-cmd.sh`](https://github.com/call518/mcp-airflow-api/blob/main/scripts/mcp-server-docker-cmd.sh) as a reference implementation for containerized streamable-http deployments.

### Does streamable-http mode support concurrent client connections?

Yes, the streamable-http transport uses an `aiohttp` server that can handle multiple concurrent client connections, making it suitable for production deployments where multiple clients need to access the Airflow API simultaneously. In contrast, stdio mode is limited to a single client process communicating directly with the server via pipes.