Jeremiah Lowin commited on
Commit
bc18d08
·
1 Parent(s): 2e1c8b2

Update transport docs

Browse files
Files changed (3) hide show
  1. .gitignore +3 -0
  2. docs/clients/transports.mdx +169 -308
  3. docs/docs.json +1 -1
.gitignore CHANGED
@@ -60,3 +60,6 @@ dmypy.json
60
  *.sqlite
61
  *.db
62
  *.ddb
 
 
 
 
60
  *.sqlite
61
  *.db
62
  *.ddb
63
+
64
+ # Claude worktree management
65
+ .claude-wt/worktrees
docs/clients/transports.mdx CHANGED
@@ -1,7 +1,7 @@
1
  ---
2
  title: Client Transports
3
  sidebarTitle: Transports
4
- description: Understand the different ways FastMCP Clients can connect to servers.
5
  icon: link
6
  ---
7
 
@@ -9,441 +9,302 @@ import { VersionBadge } from "/snippets/version-badge.mdx"
9
 
10
  <VersionBadge version="2.0.0" />
11
 
12
- The FastMCP `Client` relies on a `ClientTransport` object to handle the specifics of connecting to and communicating with an MCP server. FastMCP provides several built-in transport implementations for common connection methods.
13
 
14
- While the `Client` often infers the correct transport automatically (see [Client Overview](/clients/client#transport-inference)), you can also instantiate transports explicitly for more control.
15
 
16
- <Tip>
17
- Clients are lightweight objects, so don't hesitate to create new ones as needed. However, be mindful of the context management - each time you open a client context (`async with client:`), a new connection or process starts. For best performance, keep client contexts open while performing multiple operations rather than repeatedly opening and closing them.
18
- </Tip>
19
 
20
- ## Choosing a Transport
 
 
 
21
 
22
- Choose the transport that best fits your use case:
23
 
24
- - **Connecting to Remote/Persistent Servers:** Use `StreamableHttpTransport` (recommended, default for HTTP URLs) or `SSETransport` (legacy option) for web-based deployments.
25
 
26
- - **Local Development/Testing:** Use `FastMCPTransport` for in-memory, same-process testing of your FastMCP servers.
27
 
28
- - **Running Local Servers:** Use `UvxStdioTransport` (Python/uv) or `NpxStdioTransport` (Node/npm) if you need to run MCP servers as packaged tools.
29
-
30
- ## Network Transports
31
-
32
- These transports connect to servers running over a network, typically long-running services accessible via URLs.
33
-
34
- ### Streamable HTTP
35
 
36
- <VersionBadge version="2.3.0" />
 
 
 
 
37
 
38
- Streamable HTTP is the recommended transport for web-based deployments, providing efficient bidirectional communication over HTTP.
39
 
40
- #### Overview
41
 
42
- - **Class:** `fastmcp.client.transports.StreamableHttpTransport`
43
- - **Inferred From:** URLs starting with `http://` or `https://` (default for HTTP URLs since v2.3.0) that do not contain `/sse/` in the path
44
- - **Server Compatibility:** Works with FastMCP servers running in `http` mode
45
 
46
- #### Basic Usage
 
 
 
47
 
48
- The simplest way to use Streamable HTTP is to let the transport be inferred from a URL:
49
 
50
  ```python
51
  from fastmcp import Client
52
- import asyncio
53
-
54
- # The Client automatically uses StreamableHttpTransport for HTTP URLs
55
- client = Client("https://example.com/mcp")
56
-
57
- async def main():
58
- async with client:
59
- tools = await client.list_tools()
60
- print(f"Available tools: {tools}")
61
-
62
- asyncio.run(main())
63
- ```
64
-
65
- You can also explicitly instantiate the transport:
66
 
67
- ```python
68
- from fastmcp.client.transports import StreamableHttpTransport
 
 
 
 
69
 
70
- transport = StreamableHttpTransport(url="https://example.com/mcp")
71
- client = Client(transport)
 
72
  ```
73
 
74
- #### Authentication with Headers
75
 
76
- For servers requiring authentication:
77
 
78
  ```python
79
- from fastmcp import Client
80
- from fastmcp.client.transports import StreamableHttpTransport
81
 
82
- # Create transport with authentication headers
83
- transport = StreamableHttpTransport(
84
- url="https://example.com/mcp",
85
- headers={"Authorization": "Bearer your-token-here"}
86
  )
87
-
88
  client = Client(transport)
89
  ```
90
 
91
- This can be written more concisely using the `BearerAuth` helper function:
92
 
93
  ```python
94
- from fastmcp import Client
95
- from fastmcp.client.auth import BearerAuth
96
-
97
- client = Client(
98
- "https://example.com/mcp",
99
- auth=BearerAuth("your-token-here"),
100
  )
 
101
  ```
102
 
103
- ### SSE (Server-Sent Events)
104
-
105
- <VersionBadge version="2.0.0" />
106
-
107
- Server-Sent Events (SSE) is a transport that allows servers to push data to clients over HTTP connections. While still supported, Streamable HTTP is now the recommended transport for new web-based deployments.
108
-
109
- #### Overview
110
-
111
- - **Class:** `fastmcp.client.transports.SSETransport`
112
- - **Inferred From:** HTTP URLs containing `/sse/` in the path
113
- - **Server Compatibility:** Works with FastMCP servers running in `sse` mode
114
-
115
- #### Basic Usage
116
-
117
- The simplest way to use SSE is to let the transport be inferred from a URL with `/sse/` in the path:
118
 
119
  ```python
120
  from fastmcp import Client
121
- import asyncio
122
 
123
- # The Client automatically uses SSETransport for URLs containing /sse/ in the path
124
- client = Client("https://example.com/sse")
125
 
126
- async def main():
127
- async with client:
128
- tools = await client.list_tools()
129
- print(f"Available tools: {tools}")
130
 
131
- asyncio.run(main())
132
- ```
133
 
134
- You can also explicitly instantiate the transport for URLs that do not contain `/sse/` in the path or for more control:
135
 
136
  ```python
137
- from fastmcp.client.transports import SSETransport
 
 
 
 
 
 
 
 
138
 
139
- transport = SSETransport(url="https://example.com/sse")
 
 
 
 
140
  client = Client(transport)
141
  ```
142
 
143
- #### Authentication with Headers
144
-
145
- SSE transport also supports custom headers for authentication:
146
 
147
  ```python
148
- from fastmcp import Client
149
- from fastmcp.client.transports import SSETransport
150
-
151
- # Create SSE transport with authentication headers
152
- transport = SSETransport(
153
- url="https://example.com/sse",
154
- headers={"Authorization": "Bearer your-token-here"}
 
155
  )
156
-
157
  client = Client(transport)
158
  ```
159
 
160
- #### When to Use SSE vs. Streamable HTTP
161
-
162
- - **Use Streamable HTTP when:**
163
- - Setting up new deployments (recommended default)
164
- - You need bidirectional streaming
165
- - You're connecting to FastMCP servers running in `http` mode
166
-
167
- - **Use SSE when:**
168
- - Connecting to legacy FastMCP servers running in `sse` mode
169
- - Working with infrastructure optimized for Server-Sent Events
170
-
171
- ## Local Transports
172
 
173
- These transports manage an MCP server running as a subprocess, communicating with it via standard input (stdin) and standard output (stdout). This is the standard mechanism used by clients like Claude Desktop.
174
 
175
- ### Session Management
176
-
177
- All stdio transports support a `keep_alive` parameter (default: `True`) that controls session persistence across multiple client context managers:
178
-
179
- - **`keep_alive=True` (default)**: The subprocess and session are maintained between client context exits and re-entries. This improves performance when making multiple separate connections to the same server.
180
- - **`keep_alive=False`**: A new subprocess is started for each client context, ensuring complete isolation between sessions.
181
-
182
- When `keep_alive=True`, you can manually close the session using `await client.close()` if needed. This will terminate the subprocess and require a new one to be started on the next connection.
183
-
184
- <CodeGroup>
185
- ```python keep_alive=True
186
- from fastmcp import Client
187
-
188
- # Client with keep_alive=True (default)
189
- client = Client("my_mcp_server.py")
190
-
191
- async def example():
192
- # First session
193
- async with client:
194
- await client.ping()
195
-
196
- # Second session - uses the same subprocess
197
- async with client:
198
- await client.ping()
199
-
200
- # Manually close the session
201
- await client.close()
202
-
203
- # Third session - will start a new subprocess
204
- async with client:
205
- await client.ping()
206
 
207
- asyncio.run(example())
208
- ```
209
- ```python keep_alive=False
210
- from fastmcp import Client
211
 
212
- # Client with keep_alive=False
213
- client = Client("my_mcp_server.py", keep_alive=False)
 
 
 
214
 
215
- async def example():
216
- # First session
217
  async with client:
218
  await client.ping()
219
 
220
- # Second session - will start a new subprocess
221
- async with client:
222
- await client.ping()
223
 
224
- # Third session - will start a new subprocess
225
- async with client:
226
- await client.ping()
227
 
228
- asyncio.run(example())
 
 
 
 
 
 
229
  ```
230
- </CodeGroup>
231
-
232
- ### Python Stdio
233
 
234
- - **Class:** `fastmcp.client.transports.PythonStdioTransport`
235
- - **Inferred From:** Paths to `.py` files
236
- - **Use Case:** Running a Python-based MCP server script in a subprocess
237
 
238
- This is the most common way to interact with local FastMCP servers during development or when integrating with tools that expect to launch a server script.
239
 
240
- ```python
241
- from fastmcp import Client
242
- from fastmcp.client.transports import PythonStdioTransport
243
 
244
- server_script = "my_mcp_server.py" # Path to your server script
 
 
 
245
 
246
- # Option 1: Inferred transport
247
- client = Client(server_script)
248
 
249
- # Option 2: Explicit transport with custom configuration
250
- transport = PythonStdioTransport(
251
- script_path=server_script,
252
- python_cmd="/usr/bin/python3.11", # Optional: specify Python interpreter
253
- # args=["--some-server-arg"], # Optional: pass arguments to the script
254
- # env={"MY_VAR": "value"}, # Optional: set environment variables
255
- )
256
- client = Client(transport)
257
 
258
- async def main():
259
- async with client:
260
- tools = await client.list_tools()
261
- print(f"Connected via Python Stdio, found tools: {tools}")
262
 
263
- asyncio.run(main())
264
- ```
265
 
266
- <Warning>
267
- The server script must include logic to start the MCP server and listen on stdio, typically via `mcp.run()` or `fastmcp.server.run()`. The Client only launches the script; it doesn't inject the server logic.
268
- </Warning>
269
 
270
- ### Node.js Stdio
271
 
272
- - **Class:** `fastmcp.client.transports.NodeStdioTransport`
273
- - **Inferred From:** Paths to `.js` files
274
- - **Use Case:** Running a Node.js-based MCP server script in a subprocess
275
 
276
- Similar to the Python transport, but for JavaScript servers.
277
 
278
  ```python
279
- from fastmcp import Client
280
- from fastmcp.client.transports import NodeStdioTransport
281
-
282
- node_server_script = "my_mcp_server.js" # Path to your Node.js server script
283
 
284
- # Option 1: Inferred transport
285
- client = Client(node_server_script)
 
286
 
287
- # Option 2: Explicit transport
288
- transport = NodeStdioTransport(
289
- script_path=node_server_script,
290
- node_cmd="node", # Optional: specify path to Node executable
 
 
 
291
  )
292
  client = Client(transport)
293
-
294
- async def main():
295
- async with client:
296
- tools = await client.list_tools()
297
- print(f"Connected via Node.js Stdio, found tools: {tools}")
298
-
299
- asyncio.run(main())
300
  ```
301
 
302
- ### UVX Stdio (Experimental)
303
-
304
- - **Class:** `fastmcp.client.transports.UvxStdioTransport`
305
- - **Inferred From:** Not automatically inferred
306
- - **Use Case:** Running an MCP server packaged as a Python tool using [`uvx`](https://docs.astral.sh/uv/reference/cli/#uvx)
307
-
308
- This is useful for executing MCP servers distributed as command-line tools or packages without installing them into your environment.
309
 
310
  ```python
311
- from fastmcp import Client
312
- from fastmcp.client.transports import UvxStdioTransport
313
 
314
- # Run a hypothetical 'cloud-analyzer-mcp' tool via uvx
315
- transport = UvxStdioTransport(
316
- tool_name="cloud-analyzer-mcp",
317
- # from_package="cloud-analyzer-cli", # Optional: specify package if tool name differs
318
- # with_packages=["boto3", "requests"] # Optional: add dependencies
319
  )
320
- client = Client(transport)
321
-
322
- async def main():
323
- async with client:
324
- result = await client.call_tool("analyze_bucket", {"name": "my-data"})
325
- print(f"Analysis result: {result}")
326
-
327
- asyncio.run(main())
328
  ```
329
 
330
- ### NPX Stdio (Experimental)
 
 
331
 
332
- - **Class:** `fastmcp.client.transports.NpxStdioTransport`
333
- - **Inferred From:** Not automatically inferred
334
- - **Use Case:** Running an MCP server packaged as an NPM package using `npx`
335
 
336
- Similar to `UvxStdioTransport`, but for the Node.js ecosystem.
337
 
338
  ```python
339
- from fastmcp import Client
340
- from fastmcp.client.transports import NpxStdioTransport
341
 
342
- # Run an MCP server from an NPM package
343
- transport = NpxStdioTransport(
344
- package="mcp-server-package",
345
- # args=["--port", "stdio"] # Optional: pass arguments to the package
346
  )
347
  client = Client(transport)
348
-
349
- async def main():
350
- async with client:
351
- result = await client.call_tool("get_npm_data", {})
352
- print(f"Result: {result}")
353
-
354
- asyncio.run(main())
355
  ```
356
 
357
- ## In-Memory Transports
358
 
359
- ### FastMCP Transport
360
 
361
- - **Class:** `fastmcp.client.transports.FastMCPTransport`
362
- - **Inferred From:** An instance of `fastmcp.server.FastMCP` or a **FastMCP 1.0 server** (`mcp.server.fastmcp.FastMCP`)
363
- - **Use Case:** Connecting directly to a FastMCP server instance in the same Python process
364
 
365
- This is extremely useful for testing your FastMCP servers.
 
 
 
 
366
 
367
  ```python
368
  from fastmcp import FastMCP, Client
369
- import asyncio
370
-
371
- # 1. Create your FastMCP server instance
372
- server = FastMCP(name="InMemoryServer")
373
 
374
- @server.tool
375
- def ping():
376
- return "pong"
377
 
378
- # 2. Create a client pointing directly to the server instance
379
- client = Client(server) # Transport is automatically inferred
 
 
380
 
381
- async def main():
382
- async with client:
383
- result = await client.call_tool("ping")
384
- print(f"In-memory call result: {result}")
385
 
386
- asyncio.run(main())
 
387
  ```
388
 
389
- Communication happens through efficient in-memory queues, making it very fast and ideal for unit testing.
390
-
391
- ## Configuration-Based Transports
392
-
393
- ### MCPConfig Transport
394
 
395
  <VersionBadge version="2.4.0" />
396
 
397
- - **Class:** `fastmcp.client.transports.MCPConfigTransport`
398
- - **Inferred From:** An instance of `MCPConfig` or a dictionary matching the MCPConfig schema
399
- - **Use Case:** Connecting to one or more MCP servers defined in a configuration object
400
 
401
- MCPConfig follows an emerging standard for MCP server configuration but is subject to change as the specification evolves. The standard supports both local servers (running via stdio) and remote servers (accessed via HTTP).
402
 
403
  ```python
404
- from fastmcp import Client
405
-
406
- # Configuration for multiple MCP servers (both local and remote)
407
  config = {
408
  "mcpServers": {
409
- # Remote HTTP server
410
  "weather": {
411
- "url": "https://weather-api.example.com/mcp",
412
  "transport": "http"
413
  },
414
- # Local stdio server
415
  "assistant": {
416
  "command": "python",
417
- "args": ["./assistant_server.py"],
418
- "env": {"DEBUG": "true"}
419
- },
420
- # Another remote server
421
- "calendar": {
422
- "url": "https://calendar-api.example.com/mcp",
423
- "transport": "http"
424
  }
425
  }
426
  }
427
 
428
- # Create a transport from the config (happens automatically with Client)
429
  client = Client(config)
430
 
431
- async def main():
432
- async with client:
433
- # Tools are accessible with server name prefixes
434
- weather = await client.call_tool("weather_get_forecast", {"city": "London"})
435
- answer = await client.call_tool("assistant_answer_question", {"query": "What is MCP?"})
436
- events = await client.call_tool("calendar_list_events", {"date": "2023-06-01"})
437
-
438
- # Resources use prefixed URI paths
439
- icons = await client.read_resource("weather://weather/icons/sunny")
440
- docs = await client.read_resource("resource://assistant/docs/mcp")
441
-
442
- asyncio.run(main())
443
  ```
444
 
445
- If your configuration has only a single server, the client will connect directly to that server without any prefixing. This makes it convenient to switch between single and multi-server configurations without changing your client code.
446
-
447
- <Note>
448
- The MCPConfig format is an emerging standard for MCP server configuration and may change as the MCP ecosystem evolves. While FastMCP aims to maintain compatibility with future versions, be aware that field names or structure might change.
449
- </Note>
 
1
  ---
2
  title: Client Transports
3
  sidebarTitle: Transports
4
+ description: Configure how FastMCP Clients connect to and communicate with servers.
5
  icon: link
6
  ---
7
 
 
9
 
10
  <VersionBadge version="2.0.0" />
11
 
12
+ The FastMCP `Client` communicates with MCP servers through transport objects that handle the underlying connection mechanics. While the client can automatically select a transport based on what you pass to it, instantiating transports explicitly gives you full control over configuration—environment variables, authentication, session management, and more.
13
 
14
+ Think of transports as configurable adapters between your client code and MCP servers. Each transport type handles a different communication pattern: subprocesses with pipes, HTTP connections, or direct in-memory calls.
15
 
16
+ ## Choosing the Right Transport
 
 
17
 
18
+ - **Use [STDIO Transport](#stdio-transport)** when you need to run local MCP servers with full control over their environment and lifecycle
19
+ - **Use [Remote Transports](#remote-transports)** when connecting to production services or shared MCP servers running independently
20
+ - **Use [In-Memory Transport](#in-memory-transport)** for testing FastMCP servers without subprocess or network overhead
21
+ - **Use [MCP JSON Configuration](#mcp-json-configuration-transport)** when you need to connect to multiple servers defined in configuration files
22
 
23
+ ## STDIO Transport
24
 
25
+ STDIO (Standard Input/Output) transport communicates with MCP servers through subprocess pipes. This is the standard mechanism used by desktop clients like Claude Desktop and is the primary way to run local MCP servers.
26
 
27
+ ### The Client Runs the Server
28
 
29
+ <Warning>
30
+ **Critical Concept**: When using STDIO transport, your client actually launches and manages the server process. This is fundamentally different from network transports where you connect to an already-running server. Understanding this relationship is key to using STDIO effectively.
31
+ </Warning>
 
 
 
 
32
 
33
+ With STDIO transport, your client:
34
+ - Starts the server as a subprocess when you connect
35
+ - Manages the server's lifecycle (start, stop, restart)
36
+ - Controls the server's environment and configuration
37
+ - Communicates through stdin/stdout pipes
38
 
39
+ This architecture enables powerful local integrations but requires understanding environment isolation and process management.
40
 
41
+ ### Environment Isolation
42
 
43
+ STDIO servers run in isolated environments by default. This is a security feature enforced by the MCP protocol to prevent accidental exposure of sensitive data.
 
 
44
 
45
+ When your client launches an MCP server:
46
+ - The server does NOT inherit your shell's environment variables
47
+ - API keys, paths, and other configuration must be explicitly passed
48
+ - The working directory and system paths may differ from your shell
49
 
50
+ To pass environment variables to your server, use the `env` parameter:
51
 
52
  ```python
53
  from fastmcp import Client
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
 
55
+ # If your server needs environment variables (like API keys),
56
+ # you must explicitly pass them:
57
+ client = Client(
58
+ "my_server.py",
59
+ env={"API_KEY": "secret", "DEBUG": "true"}
60
+ )
61
 
62
+ # This won't work - the server runs in isolation:
63
+ # export API_KEY="secret" # in your shell
64
+ # client = Client("my_server.py") # server can't see API_KEY
65
  ```
66
 
67
+ ### Basic Usage
68
 
69
+ To use STDIO transport, you create a transport instance with the command and arguments needed to run your server:
70
 
71
  ```python
72
+ from fastmcp.client.transports import StdioTransport
 
73
 
74
+ transport = StdioTransport(
75
+ command="python",
76
+ args=["my_server.py"]
 
77
  )
 
78
  client = Client(transport)
79
  ```
80
 
81
+ You can configure additional settings like environment variables, working directory, or command arguments:
82
 
83
  ```python
84
+ transport = StdioTransport(
85
+ command="python",
86
+ args=["my_server.py", "--verbose"],
87
+ env={"LOG_LEVEL": "DEBUG"},
88
+ cwd="/path/to/server"
 
89
  )
90
+ client = Client(transport)
91
  ```
92
 
93
+ For convenience, the client can also infer STDIO transport from file paths, but this doesn't allow configuration:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
 
95
  ```python
96
  from fastmcp import Client
 
97
 
98
+ client = Client("my_server.py") # Limited - no configuration options
99
+ ```
100
 
101
+ ### Environment Variables
 
 
 
102
 
103
+ Since STDIO servers don't inherit your environment, you need strategies for passing configuration. Here are two common approaches:
 
104
 
105
+ **Selective forwarding** passes only the variables your server actually needs:
106
 
107
  ```python
108
+ import os
109
+ from fastmcp.client.transports import StdioTransport
110
+
111
+ required_vars = ["API_KEY", "DATABASE_URL", "REDIS_HOST"]
112
+ env = {
113
+ var: os.environ[var]
114
+ for var in required_vars
115
+ if var in os.environ
116
+ }
117
 
118
+ transport = StdioTransport(
119
+ command="python",
120
+ args=["server.py"],
121
+ env=env
122
+ )
123
  client = Client(transport)
124
  ```
125
 
126
+ **Loading from .env files** keeps configuration separate from code:
 
 
127
 
128
  ```python
129
+ from dotenv import dotenv_values
130
+ from fastmcp.client.transports import StdioTransport
131
+
132
+ env = dotenv_values(".env")
133
+ transport = StdioTransport(
134
+ command="python",
135
+ args=["server.py"],
136
+ env=env
137
  )
 
138
  client = Client(transport)
139
  ```
140
 
141
+ ### Session Persistence
 
 
 
 
 
 
 
 
 
 
 
142
 
143
+ STDIO transports maintain sessions across multiple client contexts by default (`keep_alive=True`). This improves performance by reusing the same subprocess for multiple connections, but can be controlled when you need isolation.
144
 
145
+ By default, the subprocess persists between connections:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
 
147
+ ```python
148
+ from fastmcp.client.transports import StdioTransport
 
 
149
 
150
+ transport = StdioTransport(
151
+ command="python",
152
+ args=["server.py"]
153
+ )
154
+ client = Client(transport)
155
 
156
+ async def efficient_multiple_operations():
 
157
  async with client:
158
  await client.ping()
159
 
160
+ async with client: # Reuses the same subprocess
161
+ await client.call_tool("process_data", {"file": "data.csv"})
162
+ ```
163
 
164
+ For complete isolation between connections, disable session persistence:
 
 
165
 
166
+ ```python
167
+ transport = StdioTransport(
168
+ command="python",
169
+ args=["server.py"],
170
+ keep_alive=False
171
+ )
172
+ client = Client(transport)
173
  ```
 
 
 
174
 
175
+ Use `keep_alive=False` when you need complete isolation (e.g., in test suites) or when server state could cause issues between connections.
 
 
176
 
177
+ ### Specialized STDIO Transports
178
 
179
+ FastMCP provides convenience transports that are thin wrappers around `StdioTransport` with pre-configured commands:
 
 
180
 
181
+ - **`PythonStdioTransport`** - Uses `python` command for `.py` files
182
+ - **`NodeStdioTransport`** - Uses `node` command for `.js` files
183
+ - **`UvxStdioTransport`** - Uses `uvx` for Python packages (uses `env_vars` parameter)
184
+ - **`NpxStdioTransport`** - Uses `npx` for Node packages (uses `env_vars` parameter)
185
 
186
+ For most use cases, instantiate `StdioTransport` directly with your desired command. These specialized transports are primarily useful for client inference shortcuts.
 
187
 
188
+ ## Remote Transports
 
 
 
 
 
 
 
189
 
190
+ Remote transports connect to MCP servers running as web services. This is a fundamentally different model from STDIO transports—instead of your client launching and managing a server process, you connect to an already-running service that manages its own environment and lifecycle.
 
 
 
191
 
192
+ ### Streamable HTTP Transport
 
193
 
194
+ <VersionBadge version="2.3.0" />
 
 
195
 
196
+ Streamable HTTP is the recommended transport for production deployments, providing efficient bidirectional streaming over HTTP connections.
197
 
198
+ - **Class:** `StreamableHttpTransport`
199
+ - **Server compatibility:** FastMCP servers running with `mcp run --transport http`
 
200
 
201
+ The transport requires a URL and optionally supports custom headers for authentication and configuration:
202
 
203
  ```python
204
+ from fastmcp.client.transports import StreamableHttpTransport
 
 
 
205
 
206
+ # Basic connection
207
+ transport = StreamableHttpTransport(url="https://api.example.com/mcp")
208
+ client = Client(transport)
209
 
210
+ # With custom headers for authentication
211
+ transport = StreamableHttpTransport(
212
+ url="https://api.example.com/mcp",
213
+ headers={
214
+ "Authorization": "Bearer your-token-here",
215
+ "X-Custom-Header": "value"
216
+ }
217
  )
218
  client = Client(transport)
 
 
 
 
 
 
 
219
  ```
220
 
221
+ For convenience, FastMCP also provides authentication helpers:
 
 
 
 
 
 
222
 
223
  ```python
224
+ from fastmcp.client.auth import BearerAuth
 
225
 
226
+ client = Client(
227
+ "https://api.example.com/mcp",
228
+ auth=BearerAuth("your-token-here")
 
 
229
  )
 
 
 
 
 
 
 
 
230
  ```
231
 
232
+ ### SSE Transport (Legacy)
233
+
234
+ Server-Sent Events transport is maintained for backward compatibility but is superseded by Streamable HTTP for new deployments.
235
 
236
+ - **Class:** `SSETransport`
237
+ - **Server compatibility:** FastMCP servers running with `mcp run --transport sse`
 
238
 
239
+ SSE transport supports the same configuration options as Streamable HTTP:
240
 
241
  ```python
242
+ from fastmcp.client.transports import SSETransport
 
243
 
244
+ transport = SSETransport(
245
+ url="https://api.example.com/sse",
246
+ headers={"Authorization": "Bearer token"}
 
247
  )
248
  client = Client(transport)
 
 
 
 
 
 
 
249
  ```
250
 
251
+ Use Streamable HTTP for new deployments unless you have specific infrastructure requirements for SSE.
252
 
253
+ ## In-Memory Transport
254
 
255
+ 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 and development.
 
 
256
 
257
+ - **Class:** `FastMCPTransport`
258
+
259
+ <Note>
260
+ Unlike STDIO transports, in-memory servers have full access to your Python process's environment. They share the same memory space and environment variables as your client code—no isolation or explicit environment passing required.
261
+ </Note>
262
 
263
  ```python
264
  from fastmcp import FastMCP, Client
265
+ import os
 
 
 
266
 
267
+ mcp = FastMCP("TestServer")
 
 
268
 
269
+ @mcp.tool
270
+ def greet(name: str) -> str:
271
+ prefix = os.environ.get("GREETING_PREFIX", "Hello")
272
+ return f"{prefix}, {name}!"
273
 
274
+ client = Client(mcp)
 
 
 
275
 
276
+ async with client:
277
+ result = await client.call_tool("greet", {"name": "World"})
278
  ```
279
 
280
+ ## MCP JSON Configuration Transport
 
 
 
 
281
 
282
  <VersionBadge version="2.4.0" />
283
 
284
+ This transport supports the emerging MCP JSON configuration standard for defining multiple servers:
 
 
285
 
286
+ - **Class:** `MCPConfigTransport`
287
 
288
  ```python
 
 
 
289
  config = {
290
  "mcpServers": {
 
291
  "weather": {
292
+ "url": "https://weather.example.com/mcp",
293
  "transport": "http"
294
  },
 
295
  "assistant": {
296
  "command": "python",
297
+ "args": ["./assistant.py"],
298
+ "env": {"LOG_LEVEL": "INFO"}
 
 
 
 
 
299
  }
300
  }
301
  }
302
 
 
303
  client = Client(config)
304
 
305
+ async with client:
306
+ # Tools are namespaced by server
307
+ weather = await client.call_tool("weather_get_forecast", {"city": "NYC"})
308
+ answer = await client.call_tool("assistant_ask", {"question": "What?"})
 
 
 
 
 
 
 
 
309
  ```
310
 
 
 
 
 
 
docs/docs.json CHANGED
@@ -103,6 +103,7 @@
103
  "group": "Clients",
104
  "pages": [
105
  "clients/client",
 
106
  {
107
  "group": "Core Operations",
108
  "icon": "handshake",
@@ -124,7 +125,6 @@
124
  "clients/roots"
125
  ]
126
  },
127
- "clients/transports",
128
  {
129
  "group": "Authentication",
130
  "icon": "user-shield",
 
103
  "group": "Clients",
104
  "pages": [
105
  "clients/client",
106
+ "clients/transports",
107
  {
108
  "group": "Core Operations",
109
  "icon": "handshake",
 
125
  "clients/roots"
126
  ]
127
  },
 
128
  {
129
  "group": "Authentication",
130
  "icon": "user-shield",