> ## Documentation Index
> Fetch the complete documentation index at: https://gofastmcp.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Client Transports

> Configure how clients connect to and communicate with MCP servers.

New in version `2.0.0`

Transports handle the underlying connection between your client and MCP servers. While the client can automatically select a transport based on what you pass to it, instantiating transports explicitly gives you full control over configuration.

## STDIO Transport

STDIO transport communicates with MCP servers through subprocess pipes. When using STDIO, your client launches and manages the server process, controlling its lifecycle and environment.

> [!WARNING]
>
> STDIO servers inherit only a small allowlist of environment variables — just enough to locate an interpreter and a home directory. Anything else in your shell, including API keys and other credentials, does not reach the server unless you pass it through `env` explicitly.
>
> The allowlist is platform-specific. On POSIX systems it is `HOME`, `LOGNAME`, `PATH`, `SHELL`, `TERM`, and `USER`; on Windows it is `APPDATA`, `HOMEDRIVE`, `HOMEPATH`, `LOCALAPPDATA`, `PATH`, `PATHEXT`, `PROCESSOR_ARCHITECTURE`, `SYSTEMDRIVE`, `SYSTEMROOT`, `TEMP`, `USERNAME`, and `USERPROFILE`.

```python theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
from fastmcp import Client
from fastmcp.client.transports import StdioTransport

transport = StdioTransport(
    command="python",
    args=["my_server.py", "--verbose"],
    env={"API_KEY": "secret", "LOG_LEVEL": "DEBUG"},
    cwd="/path/to/server"
)
client = Client(transport)
```

For convenience, the client can infer STDIO transport from file paths, though this limits configuration options. Pass a `Path`: inferring a subprocess from a bare *string* like `Client("my_server.py")` is deprecated as of 4.0 — it warns, and in FastMCP 5 a string will only ever mean a URL:

```python theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
from pathlib import Path
from fastmcp import Client

client = Client(Path("my_server.py"))  # Limited - no configuration options
```

> [!WARNING]
>
> Transport inference treats its input as trusted configuration. A string naming an existing `.py` or `.js` file starts that file as a subprocess, and a configuration dictionary can run any command with any arguments. An application that accepts server locations from users should validate them at its own boundary and construct the transport explicitly, for example `StreamableHttpTransport(url=...)` for a URL, rather than passing the raw value to `Client`.

### Environment Variables

Values you pass through `env` are merged on top of the inherited allowlist, so you add configuration rather than replacing the base environment. Anything your server needs beyond those six variables has to be listed explicitly.

**Selective forwarding** passes only the variables your server needs:

```python theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
import os
from fastmcp.client.transports import StdioTransport

required_vars = ["API_KEY", "DATABASE_URL", "REDIS_HOST"]
env = {var: os.environ[var] for var in required_vars if var in os.environ}

transport = StdioTransport(command="python", args=["server.py"], env=env)
client = Client(transport)
```

**Loading from .env files** keeps configuration separate from code:

```python theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
from dotenv import dotenv_values
from fastmcp.client.transports import StdioTransport

env = {
    key: value
    for key, value in dotenv_values(".env").items()
    if value is not None
}
transport = StdioTransport(command="python", args=["server.py"], env=env)
client = Client(transport)
```

### Session Persistence

STDIO transports maintain sessions across multiple client contexts by default (`keep_alive=True`). This reuses the same subprocess for multiple connections, improving performance.

```python theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
from fastmcp.client.transports import StdioTransport

transport = StdioTransport(command="python", args=["server.py"])
client = Client(transport)

async def efficient_multiple_operations():
    async with client:
        await client.list_tools()

    async with client:  # Reuses the same subprocess
        await client.call_tool("process_data", {"file": "data.csv"})
```

For complete isolation between connections, disable session persistence:

```python theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
transport = StdioTransport(command="python", args=["server.py"], keep_alive=False)
```

## HTTP Transport

New in version `2.3.0`

HTTP transport connects to MCP servers running as web services. This is the recommended transport for production deployments.

Incoming SSE events are limited to 1 MiB by default. If a server returns larger
tool results or resources, set `max_sse_event_size` on `StreamableHttpTransport`
to a byte limit that accommodates them, or use `None` to disable the limit:

```python theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
from fastmcp import Client
from fastmcp.client.transports import StreamableHttpTransport

transport = StreamableHttpTransport(
    "https://api.example.com/mcp",
    max_sse_event_size=8 * 1024 * 1024,
)
client = Client(transport)
```

The same field is available as `max_sse_event_size` on an [MCP config](https://gofastmcp.com/docs/integrations/mcp-json-configuration.md)'s remote server entry, which forwards it when building the transport. A client created from a bare URL (`Client("https://api.example.com/mcp")`) keeps the 1 MiB default; pass an explicit `StreamableHttpTransport` as above to raise or disable it.

```python theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
from fastmcp import Client
from fastmcp.client.transports import StreamableHttpTransport

transport = StreamableHttpTransport(
    url="https://api.example.com/mcp",
    headers={
        "Authorization": "Bearer your-token-here",
        "X-Custom-Header": "value"
    }
)
client = Client(transport)
```

FastMCP also provides authentication helpers:

```python theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
from fastmcp import Client
from fastmcp.client.auth import BearerAuth

client = Client(
    "https://api.example.com/mcp",
    auth=BearerAuth("your-token-here")
)
```

### SSL Verification

By default, HTTPS connections verify the server's SSL certificate using the operating system's trust store through HTTPX2. You can customize this behavior with the `verify` parameter; see [HTTPX2's SSL guide](https://pydantic.dev/docs/httpx2/advanced/ssl/).

Keep the trust store used by your deployment current. Updating certifi does not update the operating system's CA store or a custom bundle selected by `SSL_CERT_FILE`, `SSL_CERT_DIR`, or `verify`. Custom client factories configure their own TLS verification. Rebuild containers and restart processes after updating trust stores. This also matters for servers making outbound HTTPS requests to OAuth providers, JWKS endpoints, and upstream APIs.

For the October 2026 eMudhra CA incident, follow the [FastMCP security notice](https://github.com/PrefectHQ/fastmcp/blob/main/SECURITY.md#certificate-authority-incident-october-2026). A FastMCP package upgrade alone does not remediate every trust store.

```python theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
from fastmcp import Client

# Disable SSL verification (e.g., for self-signed certs in development)
client = Client("https://dev-server.internal/mcp", verify=False)

# Use a custom CA bundle
client = Client("https://corp-server.internal/mcp", verify="/path/to/ca-bundle.pem")

# Use a custom SSL context for full control
import ssl
ctx = ssl.create_default_context()
ctx.load_verify_locations("/path/to/internal-ca.pem")
client = Client("https://corp-server.internal/mcp", verify=ctx)
```

The `verify` parameter is also available directly on `StreamableHttpTransport` and `SSETransport`:

```python theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
from fastmcp.client.transports import StreamableHttpTransport

transport = StreamableHttpTransport(
    url="https://dev-server.internal/mcp",
    verify=False,
)
client = Client(transport)
```

### SSE Transport

Server-Sent Events transport is maintained for backward compatibility. Use Streamable HTTP for new deployments unless you have specific infrastructure requirements.

```python theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
from fastmcp.client.transports import SSETransport

transport = SSETransport(
    url="https://api.example.com/sse",
    headers={"Authorization": "Bearer token"}
)
client = Client(transport)
```

## In-Memory Transport

In-memory transport connects directly to a FastMCP server instance within the same Python process. This eliminates both subprocess management and network overhead, making it ideal for testing.

```python theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
from fastmcp import FastMCP, Client
import os

mcp = FastMCP("TestServer")

@mcp.tool
def greet(name: str) -> str:
    prefix = os.environ.get("GREETING_PREFIX", "Hello")
    return f"{prefix}, {name}!"

client = Client(mcp)

async with client:
    result = await client.call_tool("greet", {"name": "World"})
```

> [!NOTE]
>
> Unlike STDIO transports, in-memory servers share the same memory space and environment variables as your client code.

## Multi-Server Configuration

New in version `2.4.0`

Connect to multiple servers defined in a configuration dictionary:

```python theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
from fastmcp import Client

config = {
    "mcpServers": {
        "weather": {
            "url": "https://weather.example.com/mcp",
            "transport": "http"
        },
        "assistant": {
            "command": "python",
            "args": ["./assistant.py"],
            "env": {"LOG_LEVEL": "INFO"}
        }
    }
}

client = Client(config)

async with client:
    # Tools are namespaced by server
    weather = await client.call_tool("weather_get_forecast", {"city": "NYC"})
    answer = await client.call_tool("assistant_ask", {"question": "What?"})
```

### Per-server Timeouts

Set `timeout` on a server entry to limit how long its requests can wait. Entry timeouts use **milliseconds**, apply to HTTP, SSE, and STDIO servers, and take precedence over the timeout passed to `Client`. An omitted or `null` entry timeout uses the client timeout; `0` disables the timeout for that backend session.

For example, give the weather server 5 seconds and use a 30-second client timeout for entries without their own limit:

```python theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
from fastmcp import Client

config = {
    "mcpServers": {
        "weather": {
            "url": "https://weather.example.com/mcp",
            "timeout": 5000,
        },
        "assistant": {
            "command": "python",
            "args": ["./assistant.py"],
        },
    }
}

client = Client(config, timeout=30)
```

With multiple servers, the client timeout also limits the entire routed request, so a backend timeout cannot extend that outer limit. Composite clients and configurations with tool transformations or tag filters use backend proxy sessions: a per-call `timeout` cannot extend those sessions' configured limits. `sse_read_timeout` remains a separate setting for the SSE connection.

### Tool Transformations

FastMCP supports tool transformations within the configuration. You can change names, descriptions, tags, and arguments for tools from a server.

```python theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
config = {
    "mcpServers": {
        "weather": {
            "url": "https://weather.example.com/mcp",
            "transport": "http",
            "tools": {
                "weather_get_forecast": {
                    "name": "miami_weather",
                    "description": "Get the weather for Miami",
                    "arguments": {
                        "city": {
                            "default": "Miami",
                            "hide": True,
                        }
                    }
                }
            }
        }
    }
}
```

To filter tools by tag, use `include_tags` or `exclude_tags` at the server level:

```python theme={"theme":{"light":"snazzy-light","dark":"dark-plus"}}
config = {
    "mcpServers": {
        "weather": {
            "url": "https://weather.example.com/mcp",
            "include_tags": ["forecast"]  # Only tools with this tag
        }
    }
}
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.