Jeremiah Lowin commited on
Commit
e0dcb2d
·
unverified ·
2 Parent(s): 2e1c8b254dc4d4

Merge pull request #1103 from jlowin/docs

Browse files
.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
@@ -62,7 +62,11 @@
62
  {
63
  "group": "Servers",
64
  "pages": [
65
- "servers/server",
 
 
 
 
66
  {
67
  "group": "Core Components",
68
  "icon": "toolbox",
@@ -80,29 +84,27 @@
80
  "servers/elicitation",
81
  "servers/logging",
82
  "servers/progress",
83
- "servers/sampling"
 
 
 
84
  ]
85
  },
86
  {
87
  "group": "Authentication",
88
  "icon": "shield-check",
89
  "pages": ["servers/auth/bearer"]
90
- },
91
- "servers/middleware",
92
- "servers/openapi",
93
- "servers/proxy",
94
- "servers/composition",
95
- {
96
- "group": "Deployment",
97
- "icon": "upload",
98
- "pages": ["deployment/running-server", "deployment/asgi"]
99
  }
100
  ]
101
  },
102
  {
103
  "group": "Clients",
104
  "pages": [
105
- "clients/client",
 
 
 
 
106
  {
107
  "group": "Core Operations",
108
  "icon": "handshake",
@@ -124,7 +126,6 @@
124
  "clients/roots"
125
  ]
126
  },
127
- "clients/transports",
128
  {
129
  "group": "Authentication",
130
  "icon": "user-shield",
@@ -141,9 +142,12 @@
141
  "integrations/claude-desktop",
142
  "integrations/cursor",
143
  "integrations/eunomia-authorization",
 
144
  "integrations/gemini",
145
  "integrations/mcp-json-configuration",
146
- "integrations/openai"
 
 
147
  ]
148
  },
149
  {
 
62
  {
63
  "group": "Servers",
64
  "pages": [
65
+ {
66
+ "group": "Essentials",
67
+ "icon": "cube",
68
+ "pages": ["servers/server", "deployment/running-server"]
69
+ },
70
  {
71
  "group": "Core Components",
72
  "icon": "toolbox",
 
84
  "servers/elicitation",
85
  "servers/logging",
86
  "servers/progress",
87
+ "servers/sampling",
88
+ "servers/middleware",
89
+ "servers/composition",
90
+ "servers/proxy"
91
  ]
92
  },
93
  {
94
  "group": "Authentication",
95
  "icon": "shield-check",
96
  "pages": ["servers/auth/bearer"]
 
 
 
 
 
 
 
 
 
97
  }
98
  ]
99
  },
100
  {
101
  "group": "Clients",
102
  "pages": [
103
+ {
104
+ "group": "Essentials",
105
+ "icon": "cube",
106
+ "pages": ["clients/client", "clients/transports"]
107
+ },
108
  {
109
  "group": "Core Operations",
110
  "icon": "handshake",
 
126
  "clients/roots"
127
  ]
128
  },
 
129
  {
130
  "group": "Authentication",
131
  "icon": "user-shield",
 
142
  "integrations/claude-desktop",
143
  "integrations/cursor",
144
  "integrations/eunomia-authorization",
145
+ "integrations/fastapi",
146
  "integrations/gemini",
147
  "integrations/mcp-json-configuration",
148
+ "integrations/openai",
149
+ "integrations/openapi",
150
+ "integrations/starlette"
151
  ]
152
  },
153
  {
docs/integrations/fastapi.mdx ADDED
@@ -0,0 +1,229 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: FastAPI 🤝 FastMCP
3
+ sidebarTitle: FastAPI
4
+ description: Integrate FastMCP with FastAPI applications
5
+ icon: bolt
6
+ ---
7
+
8
+ import { VersionBadge } from '/snippets/version-badge.mdx'
9
+
10
+ FastMCP provides two powerful ways to integrate with FastAPI applications, both of which are documented below.
11
+
12
+ 1. You can [generate an MCP server FROM your FastAPI app](#generating-an-mcp-server) by converting existing API endpoints into MCP tools. This is useful for bootstrapping and quickly attaching LLMs to your API.
13
+ 2. You can [mount an MCP server INTO your FastAPI app](#mounting-an-mcp-server) by adding MCP functionality to your web application. This is useful for exposing your MCP tools alongside regular API endpoints.
14
+
15
+ You can even combine both approaches to create a single FastAPI app that serves both regular API endpoints and MCP tools!
16
+
17
+ <Tip>
18
+ Generating MCP servers from FastAPI apps is a great way to get started with FastMCP, but in practice LLMs achieve **significantly better performance** with well-designed and curated MCP servers than with auto-converted FastAPI servers. This is especially true for complex APIs with many endpoints and parameters.
19
+ </Tip>
20
+
21
+ <Note>
22
+ FastMCP does *not* include FastAPI as a dependency; you must install it separately to use this integration.
23
+ </Note>
24
+
25
+ ## Generating an MCP Server
26
+
27
+ <VersionBadge version="2.0.0" />
28
+
29
+ FastMCP can directly convert your existing FastAPI applications into MCP servers, allowing AI models to interact with your API endpoints through the MCP protocol.
30
+
31
+
32
+ <Tip>
33
+ Under the hood, the FastAPI integration is built on top of FastMCP's OpenAPI integration. See the [OpenAPI docs](/integrations/openapi) for more details.
34
+ </Tip>
35
+
36
+ ### Create a Server
37
+
38
+ The simplest way to convert a FastAPI app is using the `FastMCP.from_fastapi()` method:
39
+
40
+ ```python server.py
41
+ from fastapi import FastAPI
42
+ from fastmcp import FastMCP
43
+
44
+ # Your existing FastAPI app
45
+ app = FastAPI(title="My API", version="1.0.0")
46
+
47
+ @app.get("/items", tags=["items"], operation_id="list_items")
48
+ def list_items():
49
+ return [{"id": 1, "name": "Item 1"}, {"id": 2, "name": "Item 2"}]
50
+
51
+ @app.get("/items/{item_id}", tags=["items", "detail"], operation_id="get_item")
52
+ def get_item(item_id: int):
53
+ return {"id": item_id, "name": f"Item {item_id}"}
54
+
55
+ @app.post("/items", tags=["items", "create"], operation_id="create_item")
56
+ def create_item(name: str):
57
+ return {"id": 3, "name": name}
58
+
59
+ # Convert FastAPI app to MCP server
60
+ mcp = FastMCP.from_fastapi(app=app)
61
+
62
+ if __name__ == "__main__":
63
+ mcp.run() # Run as MCP server
64
+ ```
65
+
66
+ ### Component Mapping
67
+
68
+ By default, FastMCP converts **every endpoint** in your FastAPI app into an MCP **Tool**. This provides maximum compatibility with LLM clients that primarily support MCP tools.
69
+
70
+ You can customize this behavior using route maps to control which endpoints become tools, resources, or resource templates:
71
+
72
+ ```python
73
+ from fastmcp.server.openapi import RouteMap, MCPType
74
+
75
+ # Custom route mapping
76
+ mcp = FastMCP.from_fastapi(
77
+ app=app,
78
+ route_maps=[
79
+ # GET requests with path parameters become ResourceTemplates
80
+ RouteMap(methods=["GET"], pattern=r".*\{.*\}.*", mcp_type=MCPType.RESOURCE_TEMPLATE),
81
+ # All other GET requests become Resources
82
+ RouteMap(methods=["GET"], pattern=r".*", mcp_type=MCPType.RESOURCE),
83
+ # POST/PUT/DELETE become Tools (handled by default rule)
84
+ ],
85
+ )
86
+ ```
87
+
88
+ The `FastMCP.from_fastapi()` method accepts all the same configuration options as `FastMCP.from_openapi()`, including route maps, custom tags, component naming, timeouts, and component customization functions. For comprehensive configuration details, see the [OpenAPI Integration guide](/integrations/openapi).
89
+
90
+ ### Key Considerations
91
+
92
+ #### Operation IDs
93
+
94
+ FastMCP uses your FastAPI operation IDs to name MCP components. Ensure your endpoints have meaningful operation IDs:
95
+
96
+ ```python
97
+ @app.get("/users/{user_id}", operation_id="get_user_detail") # ✅ Good
98
+ @app.get("/users/{user_id}") # ❌ Auto-generated name might be unclear
99
+ ```
100
+
101
+ #### Pydantic Models
102
+
103
+ Your Pydantic models are automatically converted to JSON schema for MCP tool parameters:
104
+
105
+ ```python
106
+ from pydantic import BaseModel
107
+
108
+ class CreateItemRequest(BaseModel):
109
+ name: str
110
+ description: str | None = None
111
+ price: float
112
+
113
+ @app.post("/items")
114
+ def create_item(item: CreateItemRequest):
115
+ return {"id": 123, **item.dict()}
116
+ ```
117
+
118
+ The MCP tool will have properly typed parameters matching your Pydantic model.
119
+
120
+ #### Error Handling
121
+
122
+ FastAPI error handling carries over to the MCP server. HTTPExceptions are automatically converted to appropriate MCP errors.
123
+
124
+ Since FastAPI integration is built on OpenAPI, all the same configuration options are available including authentication setup, timeout configuration, and request parameter handling. For detailed information on these features, see the [OpenAPI Integration guide](/integrations/openapi).
125
+
126
+ ## Mounting an MCP Server
127
+
128
+ <VersionBadge version="2.3.1" />
129
+
130
+ You can also mount an existing FastMCP server into your FastAPI application, adding MCP functionality to your web application. This is useful for exposing your MCP tools alongside regular API endpoints.
131
+
132
+ ### Basic Integration
133
+
134
+ ```python
135
+ from fastmcp import FastMCP
136
+ from fastapi import FastAPI
137
+ from starlette.routing import Mount
138
+
139
+ # Create your FastMCP server
140
+ mcp = FastMCP("MyServer")
141
+
142
+ @mcp.tool
143
+ def analyze_data(query: str) -> dict:
144
+ """Analyze data based on the query."""
145
+ return {"result": f"Analysis for: {query}"}
146
+
147
+ # Create the ASGI app from your MCP server
148
+ mcp_app = mcp.http_app(path='/mcp')
149
+
150
+ # Create a FastAPI app and mount the MCP server
151
+ app = FastAPI(lifespan=mcp_app.lifespan)
152
+ app.mount("/mcp-server", mcp_app)
153
+
154
+ # Add regular FastAPI routes
155
+ @app.get("/health")
156
+ def health_check():
157
+ return {"status": "healthy"}
158
+ ```
159
+
160
+ The MCP endpoint will be available at `/mcp-server/mcp/` of your FastAPI application.
161
+
162
+ <Warning>
163
+ For Streamable HTTP transport, you **must** pass the lifespan context from the FastMCP app to the FastAPI app. Otherwise, the FastMCP server's session manager will not be properly initialized.
164
+ </Warning>
165
+
166
+ ### Advanced Integration
167
+
168
+ You can combine both approaches - generate an MCP server from your FastAPI app AND mount additional MCP servers:
169
+
170
+ ```python
171
+ from fastmcp import FastMCP
172
+ from fastapi import FastAPI
173
+
174
+ # Your existing FastAPI app
175
+ app = FastAPI()
176
+
177
+ @app.get("/items")
178
+ def list_items():
179
+ return [{"id": 1, "name": "Item 1"}]
180
+
181
+ # Generate MCP server from FastAPI app
182
+ api_mcp = FastMCP.from_fastapi(app=app, name="API Server")
183
+
184
+ # Create additional purpose-built MCP server
185
+ tools_mcp = FastMCP("Tools Server")
186
+
187
+ @tools_mcp.tool
188
+ def advanced_analysis(data: dict) -> dict:
189
+ """Perform advanced analysis not available via API."""
190
+ return {"analysis": "complex results"}
191
+
192
+ # Mount the tools server into the same FastAPI app
193
+ tools_app = tools_mcp.http_app(path='/mcp')
194
+ app.mount("/tools", tools_app, lifespan=tools_app.lifespan)
195
+ ```
196
+
197
+ Now you have:
198
+ - API endpoints converted to MCP tools (via `api_mcp`)
199
+ - Additional MCP tools available at `/tools/mcp/`
200
+ - Regular FastAPI endpoints at their original paths
201
+
202
+ ### Authentication and Middleware
203
+
204
+ When mounting MCP servers into FastAPI, you can leverage FastAPI's authentication and middleware:
205
+
206
+ ```python
207
+ from fastapi import FastAPI, Depends, HTTPException
208
+ from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
209
+
210
+ security = HTTPBearer()
211
+
212
+ def verify_token(credentials: HTTPAuthorizationCredentials = Depends(security)):
213
+ if credentials.credentials != "secret-token":
214
+ raise HTTPException(status_code=401, detail="Invalid token")
215
+ return credentials
216
+
217
+ app = FastAPI()
218
+
219
+ # Mount MCP server with authentication
220
+ @app.get("/secure")
221
+ def secure_endpoint(auth=Depends(verify_token)):
222
+ return {"message": "Authenticated"}
223
+
224
+ # The mounted MCP server inherits the app's security
225
+ mcp_app = mcp.http_app()
226
+ app.mount("/mcp", mcp_app, lifespan=mcp_app.lifespan)
227
+ ```
228
+
229
+ For more advanced ASGI integration patterns, see the [ASGI Integration guide](/integrations/asgi).
docs/{servers → integrations}/openapi.mdx RENAMED
@@ -1,21 +1,25 @@
1
  ---
2
- title: OpenAPI Integration
3
- sidebarTitle: OpenAPI Integration
4
- description: Generate MCP servers from OpenAPI specs and FastAPI apps
5
- icon: code-branch
6
  ---
 
7
  import { VersionBadge } from '/snippets/version-badge.mdx'
8
 
9
  <VersionBadge version="2.0.0" />
10
 
11
- FastMCP can automatically generate an MCP server from an OpenAPI specification or FastAPI app. Instead of manually creating tools and resources, you provide an OpenAPI spec and FastMCP intelligently converts your API endpoints into the appropriate MCP components.
 
 
 
 
12
 
13
- ## Quick Start
14
 
15
- To convert an OpenAPI specification to an MCP server, you can use the `FastMCP.from_openapi` class method. This method takes an OpenAPI specification and an async HTTPX client that can be used to make requests to the API, and returns an MCP server.
16
 
17
- Here's an example:
18
- ```python {11-15}
19
  import httpx
20
  from fastmcp import FastMCP
21
 
@@ -36,8 +40,27 @@ if __name__ == "__main__":
36
  mcp.run()
37
  ```
38
 
39
- That's it! Your entire API is now available as an MCP server. Clients can discover and interact with your API endpoints through the MCP protocol, with full schema validation and type safety.
 
 
 
 
 
 
 
 
 
 
 
 
40
 
 
 
 
 
 
 
 
41
 
42
  ## Route Mapping
43
 
@@ -51,7 +74,7 @@ Each `RouteMap` specifies a combination of methods, patterns, and tags, as well
51
  - **Pattern**: Regex pattern to match the route path (e.g. `r"^/users/.*"` or `r".*"` for all)
52
  - **Tags**: A set of OpenAPI tags that must all be present. An empty set (`{}`) means no tag filtering, so the route matches regardless of its tags.
53
  - **MCP type**: What MCP component type to create (`TOOL`, `RESOURCE`, `RESOURCE_TEMPLATE`, or `EXCLUDE`)
54
- - **MCP tags** A set of custom tags to add to components created from matching routes
55
 
56
  Here is FastMCP's default rule:
57
 
@@ -70,7 +93,7 @@ When creating your FastMCP server, you can customize routing behavior by providi
70
 
71
  For example, prior to FastMCP 2.8.0, GET requests were automatically mapped to `Resource` and `ResourceTemplate` components based on whether they had path parameters. (This was changed solely for client compatibility reasons.) You can restore this behavior by providing custom route maps:
72
 
73
- ```python {2, 5-10}
74
  from fastmcp import FastMCP
75
  from fastmcp.server.openapi import RouteMap, MCPType
76
 
@@ -83,7 +106,8 @@ semantic_maps = [
83
  ]
84
 
85
  mcp = FastMCP.from_openapi(
86
- ...,
 
87
  route_maps=semantic_maps,
88
  )
89
  ```
@@ -97,9 +121,9 @@ from fastmcp import FastMCP
97
  from fastmcp.server.openapi import RouteMap, MCPType
98
 
99
  mcp = FastMCP.from_openapi(
100
- ...,
 
101
  route_maps=[
102
-
103
  # Analytics `GET` endpoints are tools
104
  RouteMap(
105
  methods=["GET"],
@@ -132,12 +156,13 @@ To exclude routes from the MCP server, use a route map to assign them to `MCPTyp
132
 
133
  You can use this to remove sensitive or internal routes by targeting them specifically:
134
 
135
- ```python {7,8}
136
  from fastmcp import FastMCP
137
  from fastmcp.server.openapi import RouteMap, MCPType
138
 
139
  mcp = FastMCP.from_openapi(
140
- ...,
 
141
  route_maps=[
142
  RouteMap(pattern=r"^/admin/.*", mcp_type=MCPType.EXCLUDE),
143
  RouteMap(tags={"internal"}, mcp_type=MCPType.EXCLUDE),
@@ -146,15 +171,17 @@ mcp = FastMCP.from_openapi(
146
  ```
147
 
148
  Or you can use a catch-all rule to exclude everything that your maps don't handle explicitly:
149
- ```python {10}
 
150
  from fastmcp import FastMCP
151
  from fastmcp.server.openapi import RouteMap, MCPType
152
 
153
  mcp = FastMCP.from_openapi(
154
- ...,
 
155
  route_maps=[
156
  # custom mapping logic goes here
157
- ...,
158
  # exclude all remaining routes
159
  RouteMap(mcp_type=MCPType.EXCLUDE),
160
  ],
@@ -165,7 +192,6 @@ mcp = FastMCP.from_openapi(
165
  Using a catch-all exclusion rule will prevent the default route mappings from being applied, since it will match every remaining route. This is useful if you want to explicitly allow-list certain routes.
166
  </Tip>
167
 
168
-
169
  ### Advanced Route Mapping
170
 
171
  <VersionBadge version="2.5.0" />
@@ -178,7 +204,6 @@ In addition to more precise targeting of methods, patterns, and tags, this funct
178
  The `route_map_fn` **is** called on routes that matched `MCPType.EXCLUDE` in your custom maps, giving you an opportunity to override the exclusion.
179
  </Tip>
180
 
181
-
182
  ```python
183
  from fastmcp import FastMCP
184
  from fastmcp.server.openapi import RouteMap, MCPType, HTTPRoute
@@ -200,12 +225,40 @@ def custom_route_mapper(route: HTTPRoute, mcp_type: MCPType) -> MCPType | None:
200
  return None
201
 
202
  mcp = FastMCP.from_openapi(
203
- ...,
 
204
  route_map_fn=custom_route_mapper,
205
  )
206
  ```
207
 
208
- ## Customizing MCP Components
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
209
 
210
  ### Tags
211
 
@@ -217,12 +270,12 @@ FastMCP provides several ways to add tags to your MCP components, allowing you t
217
 
218
  You can add custom tags to components created from specific routes using the `mcp_tags` parameter in `RouteMap`. These tags will be applied to all components created from routes that match that particular route map.
219
 
220
- ```python {12, 20, 28}
221
- from fastmcp import FastMCP
222
  from fastmcp.server.openapi import RouteMap, MCPType
223
 
224
  mcp = FastMCP.from_openapi(
225
- ...,
 
226
  route_maps=[
227
  # Add custom tags to all POST endpoints
228
  RouteMap(
@@ -253,59 +306,18 @@ mcp = FastMCP.from_openapi(
253
 
254
  #### Global Tags
255
 
256
- You can add tags to **all** components by providing a `tags` parameter when creating your FastMCP server with `from_openapi` or `from_fastapi`. These global tags will be applied to every component created from your OpenAPI specification.
257
-
258
- <CodeGroup>
259
- ```python {6} from_openapi()
260
- from fastmcp import FastMCP
261
 
 
262
  mcp = FastMCP.from_openapi(
263
  openapi_spec=spec,
264
  client=client,
265
  tags={"api-v2", "production", "external"}
266
  )
267
  ```
268
- ```python {5} from_fastapi()
269
- from fastmcp import FastMCP
270
-
271
- mcp = FastMCP.from_fastapi(
272
- app=app,
273
- tags={"internal-api", "microservice"}
274
- )
275
- ```
276
- </CodeGroup>
277
-
278
-
279
- ### Names
280
-
281
- <VersionBadge version="2.5.0" />
282
-
283
- FastMCP automatically generates names for MCP components based on the OpenAPI specification. By default, it uses the `operationId` from your OpenAPI spec, up to the first double underscore (`__`).
284
-
285
- All component names are automatically:
286
- - **Slugified**: Spaces and special characters are converted to underscores or removed
287
- - **Truncated**: Limited to 56 characters maximum to ensure compatibility
288
- - **Unique**: If multiple components have the same name, a number is automatically appended to make them unique
289
-
290
- For more control over component names, you can provide an `mcp_names` dictionary that maps `operationId` values to your desired names. The `operationId` must be exactly as it appears in the OpenAPI spec. The provided name will always be slugified and truncated.
291
-
292
- ```python {5-9}
293
- from fastmcp import FastMCP
294
-
295
- mcp = FastMCP.from_openapi(
296
- ...
297
- mcp_names={
298
- "list_users__with_pagination": "user_list",
299
- "create_user__admin_required": "create_user",
300
- "get_user_details__admin_required": "user_detail",
301
- }
302
- )
303
- ```
304
-
305
- Any `operationId` not found in `mcp_names` will use the default strategy (operationId up to the first `__`).
306
-
307
 
308
  ### Advanced Customization
 
309
  <VersionBadge version="2.5.0" />
310
 
311
  By default, FastMCP creates MCP components using a variety of metadata from the OpenAPI spec, such as incorporating the OpenAPI description into the MCP component description.
@@ -316,8 +328,7 @@ At times you may want to modify those MCP components in a variety of ways, such
316
  Your `mcp_component_fn` is expected to modify the component in-place, not to return a new component. The result of the function is ignored.
317
  </Tip>
318
 
319
- ```python {27}
320
- from fastmcp import FastMCP
321
  from fastmcp.server.openapi import (
322
  HTTPRoute,
323
  OpenAPITool,
@@ -329,7 +340,6 @@ def customize_components(
329
  route: HTTPRoute,
330
  component: OpenAPITool | OpenAPIResource | OpenAPIResourceTemplate,
331
  ) -> None:
332
-
333
  # Add custom tags to all components
334
  component.tags.add("openapi")
335
 
@@ -342,10 +352,12 @@ def customize_components(
342
  component.tags.add("data")
343
 
344
  mcp = FastMCP.from_openapi(
345
- ...,
 
346
  mcp_component_fn=customize_components,
347
  )
348
  ```
 
349
  ## Request Parameter Handling
350
 
351
  FastMCP intelligently handles different types of parameters in OpenAPI requests:
@@ -401,118 +413,4 @@ FastMCP handles array parameters according to OpenAPI specifications:
401
 
402
  ### Headers
403
 
404
- Header parameters are automatically converted to strings and included in the HTTP request.
405
-
406
- ## Auth
407
-
408
- If your API requires authentication, configure it on the HTTP client before creating the MCP server:
409
-
410
- ```python
411
- import httpx
412
- from fastmcp import FastMCP
413
-
414
- # Bearer token authentication
415
- api_client = httpx.AsyncClient(
416
- base_url="https://api.example.com",
417
- headers={"Authorization": "Bearer YOUR_TOKEN"}
418
- )
419
-
420
- # Create MCP server with authenticated client
421
- mcp = FastMCP.from_openapi(..., client=api_client)
422
- ```
423
- ## Timeouts
424
-
425
- Set a timeout for all API requests:
426
-
427
- ```python
428
- mcp = FastMCP.from_openapi(
429
- openapi_spec=spec,
430
- client=api_client,
431
- timeout=30.0 # 30 second timeout for all requests
432
- )
433
- ```
434
-
435
-
436
- ## FastAPI Integration
437
-
438
- <VersionBadge version="2.0.0" />
439
-
440
- FastMCP can directly convert FastAPI applications into MCP servers by extracting their OpenAPI specifications:
441
-
442
- <Tip>
443
- FastMCP does *not* include FastAPI as a dependency; you must install it separately to use this integration.
444
- </Tip>
445
-
446
- ```python
447
- from fastapi import FastAPI
448
- from fastmcp import FastMCP
449
-
450
- # Your FastAPI app
451
- app = FastAPI(title="My API", version="1.0.0")
452
-
453
- @app.get("/items", tags=["items"], operation_id="list_items")
454
- def list_items():
455
- return [{"id": 1, "name": "Item 1"}, {"id": 2, "name": "Item 2"}]
456
-
457
- @app.get("/items/{item_id}", tags=["items", "detail"], operation_id="get_item")
458
- def get_item(item_id: int):
459
- return {"id": item_id, "name": f"Item {item_id}"}
460
-
461
- @app.post("/items", tags=["items", "create"], operation_id="create_item")
462
- def create_item(name: str):
463
- return {"id": 3, "name": name}
464
-
465
- # Convert FastAPI app to MCP server
466
- mcp = FastMCP.from_fastapi(app=app)
467
-
468
- if __name__ == "__main__":
469
- mcp.run() # Run as MCP server
470
- ```
471
-
472
- Note that operation ids are optional, but are used to create component names. You can also provide custom names, just like with OpenAPI specs.
473
-
474
- <Warning>
475
- FastMCP servers are not FastAPI apps, even when created from one. To learn how to deploy them as an ASGI app, see the [ASGI Integration](/deployment/asgi) documentation.
476
- </Warning>
477
-
478
-
479
-
480
- ### FastAPI Configuration
481
-
482
- All OpenAPI integration features work with FastAPI apps:
483
-
484
- ```python
485
- from fastmcp.server.openapi import RouteMap, MCPType
486
-
487
- # Custom route mapping with FastAPI
488
- mcp = FastMCP.from_fastapi(
489
- app=app,
490
- name="My Custom Server",
491
- timeout=5.0,
492
- tags={"api-v1", "fastapi"}, # Global tags for all components
493
- mcp_names={"operationId": "friendly_name"}, # Custom component names
494
- route_maps=[
495
- # Admin endpoints become tools with custom tags
496
- RouteMap(
497
- methods="*",
498
- pattern=r"^/admin/.*",
499
- mcp_type=MCPType.TOOL,
500
- mcp_tags={"admin", "privileged"}
501
- ),
502
- # Internal endpoints are excluded
503
- RouteMap(methods="*", pattern=r".*", mcp_type=MCPType.EXCLUDE, tags={"internal"}),
504
- ],
505
- route_map_fn=my_route_mapper,
506
- mcp_component_fn=my_component_customizer,
507
- mcp_names={
508
- "get_user_details_users__user_id__get": "get_user_details",
509
- }
510
- )
511
- ```
512
-
513
- ### FastAPI Benefits
514
-
515
- - **Zero code duplication**: Reuse existing FastAPI endpoints
516
- - **Schema inheritance**: Pydantic models and validation are preserved
517
- - **ASGI transport**: Direct in-memory communication (no HTTP overhead)
518
- - **Full FastAPI features**: Dependencies, middleware, authentication all work
 
1
  ---
2
+ title: OpenAPI 🤝 FastMCP
3
+ sidebarTitle: OpenAPI
4
+ description: Generate MCP servers from any OpenAPI specification
5
+ icon: list-tree
6
  ---
7
+
8
  import { VersionBadge } from '/snippets/version-badge.mdx'
9
 
10
  <VersionBadge version="2.0.0" />
11
 
12
+ FastMCP can automatically generate an MCP server from any OpenAPI specification, allowing AI models to interact with existing APIs through the MCP protocol. Instead of manually creating tools and resources, you provide an OpenAPI spec and FastMCP intelligently converts API endpoints into the appropriate MCP components.
13
+
14
+ <Tip>
15
+ Generating MCP servers from OpenAPI is a great way to get started with FastMCP, but in practice LLMs achieve **significantly better performance** with well-designed and curated MCP servers than with auto-converted OpenAPI servers. This is especially true for complex APIs with many endpoints and parameters.
16
+ </Tip>
17
 
18
+ ## Create a Server
19
 
20
+ To convert an OpenAPI specification to an MCP server, use the `FastMCP.from_openapi()` class method:
21
 
22
+ ```python server.py
 
23
  import httpx
24
  from fastmcp import FastMCP
25
 
 
40
  mcp.run()
41
  ```
42
 
43
+ ### Authentication
44
+
45
+ If your API requires authentication, configure it on the HTTP client:
46
+
47
+ ```python
48
+ import httpx
49
+ from fastmcp import FastMCP
50
+
51
+ # Bearer token authentication
52
+ api_client = httpx.AsyncClient(
53
+ base_url="https://api.example.com",
54
+ headers={"Authorization": "Bearer YOUR_TOKEN"}
55
+ )
56
 
57
+ # Create MCP server with authenticated client
58
+ mcp = FastMCP.from_openapi(
59
+ openapi_spec=spec,
60
+ client=api_client,
61
+ timeout=30.0 # 30 second timeout for all requests
62
+ )
63
+ ```
64
 
65
  ## Route Mapping
66
 
 
74
  - **Pattern**: Regex pattern to match the route path (e.g. `r"^/users/.*"` or `r".*"` for all)
75
  - **Tags**: A set of OpenAPI tags that must all be present. An empty set (`{}`) means no tag filtering, so the route matches regardless of its tags.
76
  - **MCP type**: What MCP component type to create (`TOOL`, `RESOURCE`, `RESOURCE_TEMPLATE`, or `EXCLUDE`)
77
+ - **MCP tags**: A set of custom tags to add to components created from matching routes
78
 
79
  Here is FastMCP's default rule:
80
 
 
93
 
94
  For example, prior to FastMCP 2.8.0, GET requests were automatically mapped to `Resource` and `ResourceTemplate` components based on whether they had path parameters. (This was changed solely for client compatibility reasons.) You can restore this behavior by providing custom route maps:
95
 
96
+ ```python
97
  from fastmcp import FastMCP
98
  from fastmcp.server.openapi import RouteMap, MCPType
99
 
 
106
  ]
107
 
108
  mcp = FastMCP.from_openapi(
109
+ openapi_spec=spec,
110
+ client=client,
111
  route_maps=semantic_maps,
112
  )
113
  ```
 
121
  from fastmcp.server.openapi import RouteMap, MCPType
122
 
123
  mcp = FastMCP.from_openapi(
124
+ openapi_spec=spec,
125
+ client=client,
126
  route_maps=[
 
127
  # Analytics `GET` endpoints are tools
128
  RouteMap(
129
  methods=["GET"],
 
156
 
157
  You can use this to remove sensitive or internal routes by targeting them specifically:
158
 
159
+ ```python
160
  from fastmcp import FastMCP
161
  from fastmcp.server.openapi import RouteMap, MCPType
162
 
163
  mcp = FastMCP.from_openapi(
164
+ openapi_spec=spec,
165
+ client=client,
166
  route_maps=[
167
  RouteMap(pattern=r"^/admin/.*", mcp_type=MCPType.EXCLUDE),
168
  RouteMap(tags={"internal"}, mcp_type=MCPType.EXCLUDE),
 
171
  ```
172
 
173
  Or you can use a catch-all rule to exclude everything that your maps don't handle explicitly:
174
+
175
+ ```python
176
  from fastmcp import FastMCP
177
  from fastmcp.server.openapi import RouteMap, MCPType
178
 
179
  mcp = FastMCP.from_openapi(
180
+ openapi_spec=spec,
181
+ client=client,
182
  route_maps=[
183
  # custom mapping logic goes here
184
+ # ... your specific route maps ...
185
  # exclude all remaining routes
186
  RouteMap(mcp_type=MCPType.EXCLUDE),
187
  ],
 
192
  Using a catch-all exclusion rule will prevent the default route mappings from being applied, since it will match every remaining route. This is useful if you want to explicitly allow-list certain routes.
193
  </Tip>
194
 
 
195
  ### Advanced Route Mapping
196
 
197
  <VersionBadge version="2.5.0" />
 
204
  The `route_map_fn` **is** called on routes that matched `MCPType.EXCLUDE` in your custom maps, giving you an opportunity to override the exclusion.
205
  </Tip>
206
 
 
207
  ```python
208
  from fastmcp import FastMCP
209
  from fastmcp.server.openapi import RouteMap, MCPType, HTTPRoute
 
225
  return None
226
 
227
  mcp = FastMCP.from_openapi(
228
+ openapi_spec=spec,
229
+ client=client,
230
  route_map_fn=custom_route_mapper,
231
  )
232
  ```
233
 
234
+ ## Customization
235
+
236
+ ### Component Names
237
+
238
+ <VersionBadge version="2.5.0" />
239
+
240
+ FastMCP automatically generates names for MCP components based on the OpenAPI specification. By default, it uses the `operationId` from your OpenAPI spec, up to the first double underscore (`__`).
241
+
242
+ All component names are automatically:
243
+ - **Slugified**: Spaces and special characters are converted to underscores or removed
244
+ - **Truncated**: Limited to 56 characters maximum to ensure compatibility
245
+ - **Unique**: If multiple components have the same name, a number is automatically appended to make them unique
246
+
247
+ For more control over component names, you can provide an `mcp_names` dictionary that maps `operationId` values to your desired names. The `operationId` must be exactly as it appears in the OpenAPI spec. The provided name will always be slugified and truncated.
248
+
249
+ ```python
250
+ mcp = FastMCP.from_openapi(
251
+ openapi_spec=spec,
252
+ client=client,
253
+ mcp_names={
254
+ "list_users__with_pagination": "user_list",
255
+ "create_user__admin_required": "create_user",
256
+ "get_user_details__admin_required": "user_detail",
257
+ }
258
+ )
259
+ ```
260
+
261
+ Any `operationId` not found in `mcp_names` will use the default strategy (operationId up to the first `__`).
262
 
263
  ### Tags
264
 
 
270
 
271
  You can add custom tags to components created from specific routes using the `mcp_tags` parameter in `RouteMap`. These tags will be applied to all components created from routes that match that particular route map.
272
 
273
+ ```python
 
274
  from fastmcp.server.openapi import RouteMap, MCPType
275
 
276
  mcp = FastMCP.from_openapi(
277
+ openapi_spec=spec,
278
+ client=client,
279
  route_maps=[
280
  # Add custom tags to all POST endpoints
281
  RouteMap(
 
306
 
307
  #### Global Tags
308
 
309
+ You can add tags to **all** components by providing a `tags` parameter when creating your MCP server. These global tags will be applied to every component created from your OpenAPI specification.
 
 
 
 
310
 
311
+ ```python
312
  mcp = FastMCP.from_openapi(
313
  openapi_spec=spec,
314
  client=client,
315
  tags={"api-v2", "production", "external"}
316
  )
317
  ```
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
318
 
319
  ### Advanced Customization
320
+
321
  <VersionBadge version="2.5.0" />
322
 
323
  By default, FastMCP creates MCP components using a variety of metadata from the OpenAPI spec, such as incorporating the OpenAPI description into the MCP component description.
 
328
  Your `mcp_component_fn` is expected to modify the component in-place, not to return a new component. The result of the function is ignored.
329
  </Tip>
330
 
331
+ ```python
 
332
  from fastmcp.server.openapi import (
333
  HTTPRoute,
334
  OpenAPITool,
 
340
  route: HTTPRoute,
341
  component: OpenAPITool | OpenAPIResource | OpenAPIResourceTemplate,
342
  ) -> None:
 
343
  # Add custom tags to all components
344
  component.tags.add("openapi")
345
 
 
352
  component.tags.add("data")
353
 
354
  mcp = FastMCP.from_openapi(
355
+ openapi_spec=spec,
356
+ client=client,
357
  mcp_component_fn=customize_components,
358
  )
359
  ```
360
+
361
  ## Request Parameter Handling
362
 
363
  FastMCP intelligently handles different types of parameters in OpenAPI requests:
 
413
 
414
  ### Headers
415
 
416
+ Header parameters are automatically converted to strings and included in the HTTP request.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
docs/{deployment/asgi.mdx → integrations/starlette.mdx} RENAMED
@@ -1,27 +1,24 @@
1
  ---
2
- title: Integrating FastMCP in ASGI Applications
3
- sidebarTitle: ASGI Integration
4
- description: Integrate FastMCP servers into existing Starlette, FastAPI, or other ASGI applications
5
- icon: plug
6
  ---
7
 
8
  import { VersionBadge } from '/snippets/version-badge.mdx'
9
 
 
10
 
11
- While FastMCP provides standalone server capabilities, you can also integrate your FastMCP server into existing web applications. This approach is useful for:
12
 
13
  - Adding MCP functionality to an existing website or API
14
  - Mounting MCP servers under specific URL paths
15
  - Combining multiple services in a single application
16
  - Leveraging existing authentication and middleware
17
 
18
- Please note that all FastMCP servers have a `run()` method that can be used to start the server. This guide focuses on integration with broader ASGI frameworks.
19
-
20
- ## ASGI Server
21
-
22
- FastMCP servers can be created as [Starlette](https://www.starlette.io/) ASGI apps for straightforward hosting or integration into existing applications.
23
 
24
- The first step is to obtain a Starlette application instance from your FastMCP server using the `http_app()` method:
25
 
26
  <Tip>
27
  The `http_app()` method is new in FastMCP 2.3.2. In older versions, use `sse_app()` for SSE transport or `streamable_http_app()` for Streamable HTTP transport.
@@ -43,87 +40,74 @@ http_app = mcp.http_app()
43
  sse_app = mcp.http_app(transport="sse")
44
  ```
45
 
46
- Both approaches return a Starlette application that can be integrated with other ASGI-compatible web frameworks.
47
 
48
- The returned app stores the `FastMCP` instance on `app.state.fastmcp_server`, so you
49
- can access it from custom middleware or routes via `request.app.state.fastmcp_server`.
50
 
51
- The MCP server's endpoint is mounted at the root path `/mcp/` for Streamable HTTP transport, and `/sse/` for SSE transport, though you can change these paths by passing a `path` argument to the `http_app()` method:
52
 
53
  ```python
54
- # For Streamable HTTP transport
55
  http_app = mcp.http_app(path="/custom-mcp-path")
56
 
57
- # For SSE transport (deprecated)
58
- sse_app = mcp.http_app(path="/custom-sse-path", transport="sse")
59
  ```
60
 
61
- ### Running the Server
62
 
63
- To run the FastMCP server, you can use the `uvicorn` ASGI server:
64
 
65
  ```python
66
  from fastmcp import FastMCP
67
- import uvicorn
 
68
 
69
  mcp = FastMCP("MyServer")
70
 
71
- http_app = mcp.http_app()
72
-
73
- if __name__ == "__main__":
74
- uvicorn.run(http_app, host="0.0.0.0", port=8000)
75
- ```
76
 
77
- Or, from the command line:
78
-
79
- ```bash
80
- uvicorn path.to.your.app:http_app --host 0.0.0.0 --port 8000
81
  ```
82
 
83
- ### Custom Middleware
84
-
85
- <VersionBadge version="2.3.2" />
86
 
87
- You can add custom Starlette middleware to your FastMCP ASGI apps by passing a list of middleware instances to the app creation methods:
88
 
89
  ```python
90
  from fastmcp import FastMCP
91
- from starlette.middleware import Middleware
92
- from starlette.middleware.cors import CORSMiddleware
93
 
94
- # Create your FastMCP server
95
  mcp = FastMCP("MyServer")
96
 
97
- # Define custom middleware
98
- custom_middleware = [
99
- Middleware(
100
- CORSMiddleware,
101
- allow_origins=["https://example.com", "https://app.example.com"],
102
- allow_credentials=True,
103
- allow_methods=["GET", "POST", "OPTIONS"],
104
- allow_headers=["Content-Type", "Authorization"],
105
- ),
106
- ]
107
 
108
- # Create ASGI app with custom middleware
109
- http_app = mcp.http_app(middleware=custom_middleware)
110
  ```
111
 
 
112
 
113
  ## Starlette Integration
114
 
115
- <VersionBadge version="2.3.1" />
116
-
117
- You can mount your FastMCP server in another Starlette application:
118
 
119
  ```python
120
  from fastmcp import FastMCP
121
  from starlette.applications import Starlette
122
  from starlette.routing import Mount
123
 
124
- # Create your FastMCP server as well as any tools, resources, etc.
125
  mcp = FastMCP("MyServer")
126
 
 
 
 
 
127
  # Create the ASGI app
128
  mcp_app = mcp.http_app(path='/mcp')
129
 
@@ -145,7 +129,6 @@ For Streamable HTTP transport, you **must** pass the lifespan context from the F
145
 
146
  ### Nested Mounts
147
 
148
-
149
  You can create complex routing structures by nesting mounts:
150
 
151
  ```python
@@ -153,7 +136,7 @@ from fastmcp import FastMCP
153
  from starlette.applications import Starlette
154
  from starlette.routing import Mount
155
 
156
- # Create your FastMCP server as well as any tools, resources, etc.
157
  mcp = FastMCP("MyServer")
158
 
159
  # Create the ASGI app
@@ -167,54 +150,64 @@ app = Starlette(
167
  )
168
  ```
169
 
170
- In this setup, the MCP server is accessible at the `/outer/inner/mcp/` path of the resulting Starlette app.
171
 
172
- <Warning>
173
- For Streamable HTTP transport, you **must** pass the lifespan context from the FastMCP app to the *outer* Starlette app, as nested lifespans are not recognized. Otherwise, the FastMCP server's session manager will not be properly initialized.
174
- </Warning>
175
- ## FastAPI Integration
176
 
177
- <VersionBadge version="2.3.1" />
178
 
179
- FastAPI is built on Starlette, so you can mount your FastMCP server in a similar way:
180
 
181
  ```python
182
  from fastmcp import FastMCP
183
- from fastapi import FastAPI
184
- from starlette.routing import Mount
185
 
186
- # Create your FastMCP server as well as any tools, resources, etc.
187
  mcp = FastMCP("MyServer")
188
 
189
- # Create the ASGI app
190
- mcp_app = mcp.http_app(path='/mcp')
 
 
 
 
 
 
 
191
 
192
- # Create a FastAPI app and mount the MCP server
193
- app = FastAPI(lifespan=mcp_app.lifespan)
194
- app.mount("/mcp-server", mcp_app)
195
  ```
196
 
197
- The MCP endpoint will be available at `/mcp-server/mcp/` of the resulting FastAPI app.
198
 
199
- <Warning>
200
- For Streamable HTTP transport, you **must** pass the lifespan context from the FastMCP app to the resulting FastAPI app, as nested lifespans are not recognized. Otherwise, the FastMCP server's session manager will not be properly initialized.
201
- </Warning>
202
 
 
 
203
 
204
- ## Custom Routes
 
 
205
 
206
- In addition to adding your FastMCP server to an existing ASGI app, you can also add custom web routes to your FastMCP server, which will be exposed alongside the MCP endpoint. To do so, use the `@custom_route` decorator. Note that this is less flexible than using a full ASGI framework, but can be useful for adding simple endpoints like health checks to your standalone server.
207
 
208
- ```python
209
- from fastmcp import FastMCP
210
- from starlette.requests import Request
211
- from starlette.responses import PlainTextResponse
212
 
213
- mcp = FastMCP("MyServer")
214
 
215
- @mcp.custom_route("/health", methods=["GET"])
216
- async def health_check(request: Request) -> PlainTextResponse:
217
- return PlainTextResponse("OK")
218
- ```
 
 
 
 
 
 
 
219
 
220
- These routes will be included in the FastMCP app when mounted in your web application.
 
1
  ---
2
+ title: Starlette / ASGI 🤝 FastMCP
3
+ sidebarTitle: Starlette / ASGI
4
+ description: Integrate FastMCP servers into ASGI applications
5
+ icon: server
6
  ---
7
 
8
  import { VersionBadge } from '/snippets/version-badge.mdx'
9
 
10
+ <VersionBadge version="2.3.1" />
11
 
12
+ FastMCP servers can be integrated into existing ASGI applications, allowing you to add MCP functionality to your web applications. This is useful for:
13
 
14
  - Adding MCP functionality to an existing website or API
15
  - Mounting MCP servers under specific URL paths
16
  - Combining multiple services in a single application
17
  - Leveraging existing authentication and middleware
18
 
19
+ ## Basic Usage
 
 
 
 
20
 
21
+ To integrate a FastMCP server into an ASGI application, use the `http_app()` method to obtain a Starlette application instance:
22
 
23
  <Tip>
24
  The `http_app()` method is new in FastMCP 2.3.2. In older versions, use `sse_app()` for SSE transport or `streamable_http_app()` for Streamable HTTP transport.
 
40
  sse_app = mcp.http_app(transport="sse")
41
  ```
42
 
43
+ The returned Starlette application can be integrated with other ASGI-compatible web frameworks. The MCP server's endpoint is mounted at `/mcp/` for Streamable HTTP transport and `/sse/` for SSE transport.
44
 
45
+ ### Configuration Options
 
46
 
47
+ You can customize the endpoint path and access the FastMCP server instance:
48
 
49
  ```python
50
+ # Custom endpoint path
51
  http_app = mcp.http_app(path="/custom-mcp-path")
52
 
53
+ # Access the FastMCP server from middleware/routes
54
+ # The server is available at: request.app.state.fastmcp_server
55
  ```
56
 
57
+ ### Adding Custom Routes
58
 
59
+ You can add custom web routes directly to your FastMCP server using the `@custom_route` decorator:
60
 
61
  ```python
62
  from fastmcp import FastMCP
63
+ from starlette.requests import Request
64
+ from starlette.responses import JSONResponse
65
 
66
  mcp = FastMCP("MyServer")
67
 
68
+ @mcp.custom_route("/api/status", methods=["GET"])
69
+ async def get_status(request: Request):
70
+ return JSONResponse({"server": "running"})
 
 
71
 
72
+ http_app = mcp.http_app()
 
 
 
73
  ```
74
 
75
+ #### Health Check Endpoints
 
 
76
 
77
+ Health checks are commonly needed for monitoring and load balancing:
78
 
79
  ```python
80
  from fastmcp import FastMCP
81
+ from starlette.requests import Request
82
+ from starlette.responses import JSONResponse
83
 
 
84
  mcp = FastMCP("MyServer")
85
 
86
+ @mcp.custom_route("/health", methods=["GET"])
87
+ async def health_check(request: Request):
88
+ return JSONResponse({"status": "healthy"})
 
 
 
 
 
 
 
89
 
90
+ http_app = mcp.http_app()
 
91
  ```
92
 
93
+ The health endpoint will be available at `/health` alongside your MCP endpoint at `/mcp/`.
94
 
95
  ## Starlette Integration
96
 
97
+ Mount your FastMCP server in another Starlette application:
 
 
98
 
99
  ```python
100
  from fastmcp import FastMCP
101
  from starlette.applications import Starlette
102
  from starlette.routing import Mount
103
 
104
+ # Create your FastMCP server
105
  mcp = FastMCP("MyServer")
106
 
107
+ @mcp.tool
108
+ def analyze(data: str) -> dict:
109
+ return {"result": f"Analyzed: {data}"}
110
+
111
  # Create the ASGI app
112
  mcp_app = mcp.http_app(path='/mcp')
113
 
 
129
 
130
  ### Nested Mounts
131
 
 
132
  You can create complex routing structures by nesting mounts:
133
 
134
  ```python
 
136
  from starlette.applications import Starlette
137
  from starlette.routing import Mount
138
 
139
+ # Create your FastMCP server
140
  mcp = FastMCP("MyServer")
141
 
142
  # Create the ASGI app
 
150
  )
151
  ```
152
 
153
+ In this setup, the MCP server is accessible at the `/outer/inner/mcp/` path.
154
 
155
+ ## Custom Middleware
 
 
 
156
 
157
+ <VersionBadge version="2.3.2" />
158
 
159
+ Add custom Starlette middleware to your FastMCP ASGI apps by passing a list of middleware instances:
160
 
161
  ```python
162
  from fastmcp import FastMCP
163
+ from starlette.middleware import Middleware
164
+ from starlette.middleware.cors import CORSMiddleware
165
 
166
+ # Create your FastMCP server
167
  mcp = FastMCP("MyServer")
168
 
169
+ # Define custom middleware
170
+ custom_middleware = [
171
+ Middleware(
172
+ CORSMiddleware,
173
+ allow_origins=["*"],
174
+ allow_methods=["*"],
175
+ allow_headers=["*"],
176
+ )
177
+ ]
178
 
179
+ # Create ASGI app with middleware
180
+ http_app = mcp.http_app(custom_middleware=custom_middleware)
 
181
  ```
182
 
183
+ ## Running the Server
184
 
185
+ To run your ASGI application, use an ASGI server like `uvicorn`:
 
 
186
 
187
+ ```python
188
+ import uvicorn
189
 
190
+ if __name__ == "__main__":
191
+ uvicorn.run(app, host="0.0.0.0", port=8000)
192
+ ```
193
 
194
+ Or from the command line:
195
 
196
+ ```bash
197
+ uvicorn path.to.your.app:app --host 0.0.0.0 --port 8000
198
+ ```
 
199
 
200
+ ## Framework-Specific Integration
201
 
202
+ ### FastAPI
203
+
204
+ For FastAPI-specific integration patterns including both mounting MCP servers into FastAPI apps and generating MCP servers from FastAPI apps, see the [FastAPI Integration guide](/integrations/fastapi).
205
+
206
+ ### Other ASGI Frameworks
207
+
208
+ The patterns shown here work with any ASGI-compatible framework. The key requirements are:
209
+
210
+ 1. Mount the FastMCP ASGI app at your desired path
211
+ 2. Pass the lifespan context to your root application
212
+ 3. Configure any necessary middleware or authentication
213
 
 
docs/servers/server.mdx CHANGED
@@ -232,6 +232,28 @@ proxy = FastMCP.as_proxy(backend, name="ProxyServer")
232
  # Now use the proxy like any FastMCP server
233
  ```
234
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
235
  ## Server Configuration
236
 
237
  Servers can be configured using a combination of initialization arguments, global settings, and transport-specific settings.
@@ -322,12 +344,12 @@ await mcp.run_async(
322
  )
323
  ```
324
 
325
- ### Environment Variables
326
 
327
- Settings can be configured via environment variables:
328
 
329
  ```bash
330
- # Global settings
331
  export FASTMCP_LOG_LEVEL=DEBUG
332
  export FASTMCP_MASK_ERROR_DETAILS=True
333
  export FASTMCP_RESOURCE_PREFIX_FORMAT=protocol
 
232
  # Now use the proxy like any FastMCP server
233
  ```
234
 
235
+ ## OpenAPI Integration
236
+
237
+ <VersionBadge version="2.0.0" />
238
+
239
+ FastMCP can automatically generate servers from OpenAPI specifications or existing FastAPI applications using `FastMCP.from_openapi()` and `FastMCP.from_fastapi()`. This allows you to instantly convert existing APIs into MCP servers without manual tool creation.
240
+
241
+ See the [FastAPI Integration](/integrations/fastapi) and [OpenAPI Integration](/integrations/openapi) guides for detailed examples and configuration options.
242
+
243
+ ```python
244
+ import httpx
245
+ from fastmcp import FastMCP
246
+
247
+ # From OpenAPI spec
248
+ spec = httpx.get("https://api.example.com/openapi.json").json()
249
+ mcp = FastMCP.from_openapi(openapi_spec=spec, client=httpx.AsyncClient())
250
+
251
+ # From FastAPI app
252
+ from fastapi import FastAPI
253
+ app = FastAPI()
254
+ mcp = FastMCP.from_fastapi(app=app)
255
+ ```
256
+
257
  ## Server Configuration
258
 
259
  Servers can be configured using a combination of initialization arguments, global settings, and transport-specific settings.
 
344
  )
345
  ```
346
 
347
+ ### Setting Global Configuration
348
 
349
+ Global FastMCP settings can be configured via environment variables (prefixed with `FASTMCP_`):
350
 
351
  ```bash
352
+ # Configure global FastMCP behavior
353
  export FASTMCP_LOG_LEVEL=DEBUG
354
  export FASTMCP_MASK_ERROR_DETAILS=True
355
  export FASTMCP_RESOURCE_PREFIX_FORMAT=protocol