Spaces:
Running
Running
Merge branch 'main' into protocol-update
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .pre-commit-config.yaml +1 -1
- CLAUDE.md +6 -1
- docs/changelog.mdx +1 -1
- docs/clients/advanced-features.mdx +0 -152
- docs/clients/auth/bearer.mdx +1 -1
- docs/clients/auth/oauth.mdx +1 -1
- docs/clients/client.mdx +185 -266
- docs/clients/logging.mdx +63 -0
- docs/clients/progress.mdx +59 -0
- docs/clients/prompts.mdx +187 -0
- docs/clients/resources.mdx +171 -0
- docs/clients/roots.mdx +42 -0
- docs/clients/sampling.mdx +91 -0
- docs/clients/tools.mdx +143 -0
- docs/deployment/asgi.mdx +11 -5
- docs/deployment/running-server.mdx +4 -4
- docs/docs.json +285 -167
- docs/integrations/anthropic.mdx +1 -1
- docs/integrations/gemini.mdx +1 -1
- docs/integrations/openai.mdx +1 -1
- docs/patterns/cli.mdx +24 -0
- docs/python-sdk/fastmcp-cli-__init__.mdx +9 -0
- docs/python-sdk/fastmcp-cli-claude.mdx +43 -0
- docs/python-sdk/fastmcp-cli-cli.mdx +65 -0
- docs/python-sdk/fastmcp-cli-run.mdx +106 -0
- docs/python-sdk/fastmcp-client-__init__.mdx +8 -0
- docs/python-sdk/fastmcp-client-auth-__init__.mdx +8 -0
- docs/python-sdk/fastmcp-client-auth-bearer.mdx +18 -0
- docs/python-sdk/fastmcp-client-auth-oauth.mdx +102 -0
- docs/python-sdk/fastmcp-client-client.mdx +94 -0
- docs/python-sdk/fastmcp-client-logging.mdx +14 -0
- docs/python-sdk/fastmcp-client-oauth_callback.mdx +63 -0
- docs/python-sdk/fastmcp-client-progress.mdx +8 -0
- docs/python-sdk/fastmcp-client-roots.mdx +20 -0
- docs/python-sdk/fastmcp-client-sampling.mdx +14 -0
- docs/python-sdk/fastmcp-client-transports.mdx +191 -0
- docs/python-sdk/fastmcp-exceptions.mdx +65 -0
- docs/python-sdk/fastmcp-prompts-__init__.mdx +8 -0
- docs/python-sdk/fastmcp-prompts-prompt.mdx +84 -0
- docs/python-sdk/fastmcp-prompts-prompt_manager.mdx +43 -0
- docs/python-sdk/fastmcp-resources-__init__.mdx +8 -0
- docs/python-sdk/fastmcp-resources-resource.mdx +90 -0
- docs/python-sdk/fastmcp-resources-resource_manager.mdx +111 -0
- docs/python-sdk/fastmcp-resources-template.mdx +104 -0
- docs/python-sdk/fastmcp-resources-types.mdx +83 -0
- docs/python-sdk/fastmcp-server-__init__.mdx +8 -0
- docs/python-sdk/fastmcp-server-auth-__init__.mdx +8 -0
- docs/python-sdk/fastmcp-server-auth-auth.mdx +10 -0
- docs/python-sdk/fastmcp-server-auth-providers-__init__.mdx +8 -0
- docs/python-sdk/fastmcp-server-auth-providers-bearer.mdx +69 -0
.pre-commit-config.yaml
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
fail_fast:
|
| 2 |
|
| 3 |
repos:
|
| 4 |
- repo: https://github.com/abravalheri/validate-pyproject
|
|
|
|
| 1 |
+
fail_fast: false
|
| 2 |
|
| 3 |
repos:
|
| 4 |
- repo: https://github.com/abravalheri/validate-pyproject
|
CLAUDE.md
CHANGED
|
@@ -27,4 +27,9 @@ Only use HTTP transport when testing network-specific features. Prefer Streamabl
|
|
| 27 |
# Only when network testing is required
|
| 28 |
async with Client(transport=StreamableHttpTransport(server_url)) as client:
|
| 29 |
result = await client.ping()
|
| 30 |
-
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
# Only when network testing is required
|
| 28 |
async with Client(transport=StreamableHttpTransport(server_url)) as client:
|
| 29 |
result = await client.ping()
|
| 30 |
+
```
|
| 31 |
+
|
| 32 |
+
## Development Workflow
|
| 33 |
+
|
| 34 |
+
- You must always run pre-commit if you open a PR, because it is run as part of a required check.
|
| 35 |
+
- When opening PRs, apply labels appropriately for bugs/breaking changes/enhancements/features. Generally, improvements are enhancements (not features) unless told otherwise.
|
docs/changelog.mdx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
---
|
| 2 |
-
|
| 3 |
---
|
| 4 |
|
| 5 |
<Update label="v2.8.0" description="2024-06-10">
|
|
|
|
| 1 |
---
|
| 2 |
+
icon: "list-check"
|
| 3 |
---
|
| 4 |
|
| 5 |
<Update label="v2.8.0" description="2024-06-10">
|
docs/clients/advanced-features.mdx
DELETED
|
@@ -1,152 +0,0 @@
|
|
| 1 |
-
---
|
| 2 |
-
title: Advanced Features
|
| 3 |
-
sidebarTitle: Advanced Features
|
| 4 |
-
description: Learn about the advanced features of the FastMCP Client.
|
| 5 |
-
icon: stars
|
| 6 |
-
---
|
| 7 |
-
|
| 8 |
-
import { VersionBadge } from '/snippets/version-badge.mdx'
|
| 9 |
-
|
| 10 |
-
In addition to basic server interaction, FastMCP clients can also handle more advanced features and server interaction patterns. The `Client` constructor accepts additional configuration to handle these server requests.
|
| 11 |
-
|
| 12 |
-
<Tip>
|
| 13 |
-
To enable many of these features, you must provide an appropriate handler or callback function. For example. In most cases, if you do not provide a handler, FastMCP's default handler will emit a `DEBUG` level log.
|
| 14 |
-
</Tip>
|
| 15 |
-
|
| 16 |
-
## Logging and Notifications
|
| 17 |
-
|
| 18 |
-
<VersionBadge version="2.0.0" />
|
| 19 |
-
MCP servers can emit logs to clients. To process these logs, you can provide a `log_handler` to the client.
|
| 20 |
-
|
| 21 |
-
The `log_handler` must be an async function that accepts a single argument, which is an instance of `fastmcp.client.logging.LogMessage`. This has attributes like `level`, `logger`, and `data`.
|
| 22 |
-
|
| 23 |
-
```python {2, 12}
|
| 24 |
-
from fastmcp import Client
|
| 25 |
-
from fastmcp.client.logging import LogMessage
|
| 26 |
-
|
| 27 |
-
async def log_handler(message: LogMessage):
|
| 28 |
-
level = message.level.upper()
|
| 29 |
-
logger = message.logger or 'default'
|
| 30 |
-
data = message.data
|
| 31 |
-
print(f"[Server Log - {level}] {logger}: {data}")
|
| 32 |
-
|
| 33 |
-
client_with_logging = Client(
|
| 34 |
-
...,
|
| 35 |
-
log_handler=log_handler,
|
| 36 |
-
)
|
| 37 |
-
```
|
| 38 |
-
## Progress Monitoring
|
| 39 |
-
|
| 40 |
-
<VersionBadge version="2.3.5" />
|
| 41 |
-
|
| 42 |
-
MCP servers can report progress during long-running operations. The client can set a progress handler to receive and process these updates.
|
| 43 |
-
|
| 44 |
-
```python {2, 13}
|
| 45 |
-
from fastmcp import Client
|
| 46 |
-
from fastmcp.client.progress import ProgressHandler
|
| 47 |
-
|
| 48 |
-
async def my_progress_handler(
|
| 49 |
-
progress: float,
|
| 50 |
-
total: float | None,
|
| 51 |
-
message: str | None
|
| 52 |
-
) -> None:
|
| 53 |
-
print(f"Progress: {progress} / {total} ({message})")
|
| 54 |
-
|
| 55 |
-
client = Client(
|
| 56 |
-
...,
|
| 57 |
-
progress_handler=my_progress_handler
|
| 58 |
-
)
|
| 59 |
-
```
|
| 60 |
-
|
| 61 |
-
By default, FastMCP uses a handler that logs progress updates at the debug level. This default handler properly handles cases where `total` or `message` might be None.
|
| 62 |
-
|
| 63 |
-
You can override the progress handler for specific tool calls:
|
| 64 |
-
|
| 65 |
-
```python
|
| 66 |
-
# Client uses the default debug logger for progress
|
| 67 |
-
client = Client(...)
|
| 68 |
-
|
| 69 |
-
async with client:
|
| 70 |
-
# Use default progress handler (debug logging)
|
| 71 |
-
result1 = await client.call_tool("long_task", {"param": "value"})
|
| 72 |
-
|
| 73 |
-
# Override with custom progress handler just for this call
|
| 74 |
-
result2 = await client.call_tool(
|
| 75 |
-
"another_task",
|
| 76 |
-
{"param": "value"},
|
| 77 |
-
progress_handler=my_progress_handler
|
| 78 |
-
)
|
| 79 |
-
```
|
| 80 |
-
|
| 81 |
-
A typical progress update includes:
|
| 82 |
-
- Current progress value (e.g., 2 of 5 steps completed)
|
| 83 |
-
- Total expected value (may be None)
|
| 84 |
-
- Status message (may be None)
|
| 85 |
-
|
| 86 |
-
## LLM Sampling
|
| 87 |
-
|
| 88 |
-
<VersionBadge version="2.0.0" />
|
| 89 |
-
|
| 90 |
-
MCP Servers can request LLM completions from clients. The client can provide a `sampling_handler` to handle these requests. The sampling handler receives a list of messages and other parameters from the server, and should return a string completion.
|
| 91 |
-
|
| 92 |
-
The following example uses the `marvin` library to generate a completion:
|
| 93 |
-
|
| 94 |
-
```python {8-17, 21}
|
| 95 |
-
import marvin
|
| 96 |
-
from fastmcp import Client
|
| 97 |
-
from fastmcp.client.sampling import (
|
| 98 |
-
SamplingMessage,
|
| 99 |
-
SamplingParams,
|
| 100 |
-
RequestContext,
|
| 101 |
-
)
|
| 102 |
-
|
| 103 |
-
async def sampling_handler(
|
| 104 |
-
messages: list[SamplingMessage],
|
| 105 |
-
params: SamplingParams,
|
| 106 |
-
context: RequestContext
|
| 107 |
-
) -> str:
|
| 108 |
-
return await marvin.say_async(
|
| 109 |
-
message=[m.content.text for m in messages],
|
| 110 |
-
instructions=params.systemPrompt,
|
| 111 |
-
)
|
| 112 |
-
|
| 113 |
-
client = Client(
|
| 114 |
-
...,
|
| 115 |
-
sampling_handler=sampling_handler,
|
| 116 |
-
)
|
| 117 |
-
```
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
## Roots
|
| 121 |
-
|
| 122 |
-
<VersionBadge version="2.0.0" />
|
| 123 |
-
|
| 124 |
-
Roots are a way for clients to inform servers about the resources they have access to or certain boundaries on their access. The server can use this information to adjust behavior or provide more accurate responses.
|
| 125 |
-
|
| 126 |
-
Servers can request roots from clients, and clients can notify servers when their roots change.
|
| 127 |
-
|
| 128 |
-
To set the roots when creating a client, users can either provide a list of roots (which can be a list of strings) or an async function that returns a list of roots.
|
| 129 |
-
|
| 130 |
-
<CodeGroup>
|
| 131 |
-
```python Static Roots {5}
|
| 132 |
-
from fastmcp import Client
|
| 133 |
-
|
| 134 |
-
client = Client(
|
| 135 |
-
...,
|
| 136 |
-
roots=["/path/to/root1", "/path/to/root2"],
|
| 137 |
-
)
|
| 138 |
-
```
|
| 139 |
-
```python Dynamic Roots Callback {4-6, 10}
|
| 140 |
-
from fastmcp import Client
|
| 141 |
-
from fastmcp.client.roots import RequestContext
|
| 142 |
-
|
| 143 |
-
async def roots_callback(context: RequestContext) -> list[str]:
|
| 144 |
-
print(f"Server requested roots (Request ID: {context.request_id})")
|
| 145 |
-
return ["/path/to/root1", "/path/to/root2"]
|
| 146 |
-
|
| 147 |
-
client = Client(
|
| 148 |
-
...,
|
| 149 |
-
roots=roots_callback,
|
| 150 |
-
)
|
| 151 |
-
```
|
| 152 |
-
</CodeGroup>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/clients/auth/bearer.mdx
CHANGED
|
@@ -3,7 +3,7 @@ title: Bearer Token Authentication
|
|
| 3 |
sidebarTitle: Bearer Auth
|
| 4 |
description: Authenticate your FastMCP client with a Bearer token.
|
| 5 |
icon: key
|
| 6 |
-
tag:
|
| 7 |
---
|
| 8 |
|
| 9 |
import { VersionBadge } from "/snippets/version-badge.mdx"
|
|
|
|
| 3 |
sidebarTitle: Bearer Auth
|
| 4 |
description: Authenticate your FastMCP client with a Bearer token.
|
| 5 |
icon: key
|
| 6 |
+
tag: NEW
|
| 7 |
---
|
| 8 |
|
| 9 |
import { VersionBadge } from "/snippets/version-badge.mdx"
|
docs/clients/auth/oauth.mdx
CHANGED
|
@@ -3,7 +3,7 @@ title: OAuth Authentication
|
|
| 3 |
sidebarTitle: OAuth
|
| 4 |
description: Authenticate your FastMCP client via OAuth 2.1.
|
| 5 |
icon: window
|
| 6 |
-
tag:
|
| 7 |
---
|
| 8 |
|
| 9 |
import { VersionBadge } from "/snippets/version-badge.mdx"
|
|
|
|
| 3 |
sidebarTitle: OAuth
|
| 4 |
description: Authenticate your FastMCP client via OAuth 2.1.
|
| 5 |
icon: window
|
| 6 |
+
tag: NEW
|
| 7 |
---
|
| 8 |
|
| 9 |
import { VersionBadge } from "/snippets/version-badge.mdx"
|
docs/clients/client.mdx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
| 1 |
---
|
| 2 |
-
title:
|
| 3 |
sidebarTitle: Overview
|
| 4 |
-
description:
|
| 5 |
icon: user-robot
|
| 6 |
---
|
| 7 |
|
|
@@ -9,270 +9,213 @@ import { VersionBadge } from '/snippets/version-badge.mdx'
|
|
| 9 |
|
| 10 |
<VersionBadge version="2.0.0" />
|
| 11 |
|
| 12 |
-
The `fastmcp.Client` provides a
|
| 13 |
|
| 14 |
-
|
| 15 |
|
| 16 |
-
|
|
|
|
|
|
|
| 17 |
|
| 18 |
-
|
| 19 |
-
- **`Transport`**: Responsible for establishing and maintaining the connection to the server (e.g., via WebSockets, SSE, Stdio, or in-memory).
|
| 20 |
|
| 21 |
-
### Transports
|
| 22 |
|
| 23 |
-
|
|
|
|
|
|
|
| 24 |
|
| 25 |
-
|
| 26 |
|
| 27 |
-
|
| 28 |
-
2. **`FastMCP` Instance**: Creates a `FastMCPTransport` for efficient in-memory communication (ideal for testing). This also works with a **FastMCP 1.0 server** created via `mcp.server.fastmcp.FastMCP`.
|
| 29 |
-
3. **`Path` or `str` pointing to an existing file**:
|
| 30 |
-
* If it ends with `.py`: Creates a `PythonStdioTransport` to run the script using `python`.
|
| 31 |
-
* If it ends with `.js`: Creates a `NodeStdioTransport` to run the script using `node`.
|
| 32 |
-
4. **`AnyUrl` or `str` pointing to a URL that begins with `http://` or `https://`**:
|
| 33 |
-
* Creates a `StreamableHttpTransport`
|
| 34 |
-
5. **`MCPConfig` or dictionary matching MCPConfig schema**: Creates a client that connects to one or more MCP servers specified in the config.
|
| 35 |
-
6. **Other**: Raises a `ValueError` if the type cannot be inferred.
|
| 36 |
|
| 37 |
```python
|
| 38 |
import asyncio
|
| 39 |
from fastmcp import Client, FastMCP
|
| 40 |
|
| 41 |
-
#
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
server_script = "my_mcp_server.py" # Path to a Python server file
|
| 45 |
|
| 46 |
-
#
|
| 47 |
-
|
| 48 |
-
client_http = Client(http_url)
|
| 49 |
|
| 50 |
-
|
|
|
|
| 51 |
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
|
| 56 |
-
|
| 57 |
-
# <FastMCP(server='TestServer')>
|
| 58 |
-
# <StreamableHttp(url='https://example.com/mcp')>
|
| 59 |
-
# <PythonStdioTransport(command='python', args=['/path/to/your/my_mcp_server.py'])>
|
| 60 |
```
|
| 61 |
|
| 62 |
-
|
| 63 |
|
| 64 |
-
|
| 65 |
-
from fastmcp import Client
|
| 66 |
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 73 |
|
| 74 |
-
|
|
|
|
|
|
|
|
|
|
| 75 |
```
|
|
|
|
| 76 |
<Tip>
|
| 77 |
-
For
|
| 78 |
</Tip>
|
| 79 |
|
| 80 |
-
##
|
| 81 |
|
| 82 |
<VersionBadge version="2.4.0" />
|
| 83 |
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
<Note>
|
| 87 |
-
The MCP configuration format follows an emerging standard and may evolve as the specification matures. FastMCP will strive to maintain compatibility with future versions, but be aware that field names or structure might change.
|
| 88 |
-
</Note>
|
| 89 |
-
|
| 90 |
-
When you create a client with an `MCPConfig` containing multiple servers:
|
| 91 |
|
| 92 |
-
|
| 93 |
-
2. Tools and resources from each server are accessible with appropriate prefixes in the format `servername_toolname` and `protocol://servername/resource/path`
|
| 94 |
-
3. You interact with this as a single unified client, with requests automatically routed to the appropriate server
|
| 95 |
|
| 96 |
```python
|
| 97 |
-
from fastmcp import Client
|
| 98 |
-
|
| 99 |
-
# Create a standard MCP configuration with multiple servers
|
| 100 |
config = {
|
| 101 |
"mcpServers": {
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
"
|
| 105 |
-
"
|
|
|
|
|
|
|
| 106 |
},
|
| 107 |
-
|
| 108 |
-
|
|
|
|
| 109 |
"command": "python",
|
| 110 |
-
"args": ["./
|
| 111 |
-
"env": {"DEBUG": "true"}
|
|
|
|
| 112 |
}
|
| 113 |
}
|
| 114 |
}
|
| 115 |
-
|
| 116 |
-
# Create a client that connects to both servers
|
| 117 |
-
client = Client(config)
|
| 118 |
-
|
| 119 |
-
async def main():
|
| 120 |
-
async with client:
|
| 121 |
-
# Access tools from different servers with prefixes
|
| 122 |
-
weather_data = await client.call_tool("weather_get_forecast", {"city": "London"})
|
| 123 |
-
response = await client.call_tool("assistant_answer_question", {"question": "What's the capital of France?"})
|
| 124 |
-
|
| 125 |
-
# Access resources with prefixed URIs
|
| 126 |
-
weather_icons = await client.read_resource("weather://weather/icons/sunny")
|
| 127 |
-
templates = await client.read_resource("resource://assistant/templates/list")
|
| 128 |
-
|
| 129 |
-
print(f"Weather: {weather_data}")
|
| 130 |
-
print(f"Assistant: {response}")
|
| 131 |
-
|
| 132 |
-
if __name__ == "__main__":
|
| 133 |
-
asyncio.run(main())
|
| 134 |
```
|
| 135 |
|
| 136 |
-
|
| 137 |
|
| 138 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 139 |
|
| 140 |
-
|
| 141 |
|
| 142 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 143 |
|
| 144 |
-
|
| 145 |
-
import asyncio
|
| 146 |
-
from fastmcp import Client
|
| 147 |
|
| 148 |
-
client
|
| 149 |
|
| 150 |
-
|
| 151 |
-
|
|
|
|
|
|
|
|
|
|
| 152 |
async with client:
|
| 153 |
-
print(f"
|
| 154 |
-
|
| 155 |
-
# Make
|
| 156 |
tools = await client.list_tools()
|
| 157 |
-
|
| 158 |
-
|
| 159 |
-
|
| 160 |
-
|
| 161 |
-
print(f"Greet result: {result}")
|
| 162 |
-
|
| 163 |
-
# Connection is closed automatically here
|
| 164 |
-
print(f"Client connected: {client.is_connected()}")
|
| 165 |
-
|
| 166 |
-
if __name__ == "__main__":
|
| 167 |
-
asyncio.run(main())
|
| 168 |
```
|
| 169 |
|
| 170 |
-
|
| 171 |
-
|
| 172 |
-
### Client Methods
|
| 173 |
|
| 174 |
-
|
| 175 |
|
| 176 |
-
|
| 177 |
-
The standard client methods return user-friendly representations that may change as the protocol evolves. For consistent access to the complete data structure, use the `*_mcp` methods described later.
|
| 178 |
-
</Warning>
|
| 179 |
|
| 180 |
-
|
| 181 |
|
| 182 |
-
|
| 183 |
-
|
|
|
|
| 184 |
tools = await client.list_tools()
|
| 185 |
-
# tools -> list[mcp.types.Tool]
|
| 186 |
-
```
|
| 187 |
-
* **`call_tool(name: str, arguments: dict[str, Any] | None = None, timeout: float | None = None, progress_handler: ProgressHandler | None = None)`**: Executes a tool on the server.
|
| 188 |
-
```python
|
| 189 |
-
result = await client.call_tool("add", {"a": 5, "b": 3})
|
| 190 |
-
# result -> list[mcp.types.TextContent | mcp.types.ImageContent | ...]
|
| 191 |
-
print(result[0].text) # Assuming TextContent, e.g., '8'
|
| 192 |
-
|
| 193 |
-
# With timeout (aborts if execution takes longer than 2 seconds)
|
| 194 |
-
result = await client.call_tool("long_running_task", {"param": "value"}, timeout=2.0)
|
| 195 |
|
| 196 |
-
#
|
| 197 |
-
result = await client.call_tool(
|
| 198 |
-
|
| 199 |
-
|
| 200 |
-
progress_handler=my_progress_handler
|
| 201 |
-
)
|
| 202 |
-
```
|
| 203 |
-
* Arguments are passed as a dictionary. FastMCP servers automatically handle JSON string parsing for complex types if needed.
|
| 204 |
-
* Returns a list of content objects (usually `TextContent` or `ImageContent`).
|
| 205 |
-
* The optional `timeout` parameter limits the maximum execution time (in seconds) for this specific call, overriding any client-level timeout.
|
| 206 |
-
* The optional `progress_handler` parameter receives progress updates during execution, overriding any client-level progress handler.
|
| 207 |
-
|
| 208 |
-
#### Resource Operations
|
| 209 |
-
|
| 210 |
-
* **`list_resources()`**: Retrieves a list of static resources.
|
| 211 |
-
```python
|
| 212 |
-
resources = await client.list_resources()
|
| 213 |
-
# resources -> list[mcp.types.Resource]
|
| 214 |
-
```
|
| 215 |
-
* **`list_resource_templates()`**: Retrieves a list of resource templates.
|
| 216 |
-
```python
|
| 217 |
-
templates = await client.list_resource_templates()
|
| 218 |
-
# templates -> list[mcp.types.ResourceTemplate]
|
| 219 |
-
```
|
| 220 |
-
* **`read_resource(uri: str | AnyUrl)`**: Reads the content of a resource or a resolved template.
|
| 221 |
-
```python
|
| 222 |
-
# Read a static resource
|
| 223 |
-
readme_content = await client.read_resource("file:///path/to/README.md")
|
| 224 |
-
# readme_content -> list[mcp.types.TextResourceContents | mcp.types.BlobResourceContents]
|
| 225 |
-
print(readme_content[0].text) # Assuming text
|
| 226 |
|
| 227 |
-
|
| 228 |
-
weather_content = await client.read_resource("data://weather/london")
|
| 229 |
-
print(weather_content[0].text) # Assuming text JSON
|
| 230 |
-
```
|
| 231 |
|
| 232 |
-
###
|
| 233 |
|
| 234 |
-
|
| 235 |
-
* **`get_prompt(name: str, arguments: dict[str, Any] | None = None)`**: Retrieves a rendered prompt message list.
|
| 236 |
|
| 237 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 238 |
|
| 239 |
-
|
| 240 |
|
| 241 |
-
|
| 242 |
|
| 243 |
-
|
| 244 |
-
The standard client methods (without `_mcp`) return user-friendly representations of MCP data, while `*_mcp` methods will always return the complete MCP protocol objects. As the protocol evolves, changes to these user-friendly representations may occur and could potentially be breaking. If you need consistent, stable access to the full data structure, prefer using the `*_mcp` methods.
|
| 245 |
-
</Warning>
|
| 246 |
|
| 247 |
```python
|
| 248 |
-
|
| 249 |
-
|
| 250 |
-
|
| 251 |
-
|
| 252 |
-
#
|
| 253 |
-
|
| 254 |
-
|
| 255 |
-
tools = result.tools
|
| 256 |
```
|
| 257 |
|
| 258 |
-
|
| 259 |
-
|
| 260 |
-
* **`list_tools_mcp()`**: Returns `mcp.types.ListToolsResult`
|
| 261 |
-
* **`call_tool_mcp(name, arguments)`**: Returns `mcp.types.CallToolResult`
|
| 262 |
-
* **`list_resources_mcp()`**: Returns `mcp.types.ListResourcesResult`
|
| 263 |
-
* **`list_resource_templates_mcp()`**: Returns `mcp.types.ListResourceTemplatesResult`
|
| 264 |
-
* **`read_resource_mcp(uri)`**: Returns `mcp.types.ReadResourceResult`
|
| 265 |
-
* **`list_prompts_mcp()`**: Returns `mcp.types.ListPromptsResult`
|
| 266 |
-
* **`get_prompt_mcp(name, arguments)`**: Returns `mcp.types.GetPromptResult`
|
| 267 |
-
* **`complete_mcp(ref, argument)`**: Returns `mcp.types.CompleteResult`
|
| 268 |
|
| 269 |
-
|
| 270 |
|
| 271 |
-
|
| 272 |
-
|
| 273 |
-
#### Pinging the Server
|
| 274 |
-
|
| 275 |
-
The client can be used to ping the server to verify connectivity.
|
| 276 |
|
| 277 |
```python
|
| 278 |
async with client:
|
|
@@ -280,93 +223,69 @@ async with client:
|
|
| 280 |
print("Server is reachable")
|
| 281 |
```
|
| 282 |
|
| 283 |
-
##
|
|
|
|
|
|
|
| 284 |
|
| 285 |
-
|
| 286 |
|
| 287 |
-
|
| 288 |
|
| 289 |
```python
|
| 290 |
from fastmcp import Client
|
|
|
|
| 291 |
|
| 292 |
-
|
|
|
|
| 293 |
|
| 294 |
-
async def
|
| 295 |
-
|
| 296 |
-
await client.ping()
|
| 297 |
-
|
| 298 |
-
async with client:
|
| 299 |
-
await client.ping() # Same subprocess as above
|
| 300 |
-
```
|
| 301 |
-
|
| 302 |
-
<Note>
|
| 303 |
-
For detailed examples and configuration options, see [Session Management in Transports](/clients/transports#session-management).
|
| 304 |
-
</Note>
|
| 305 |
-
|
| 306 |
-
#### Timeouts
|
| 307 |
-
|
| 308 |
-
<VersionBadge version="2.3.4" />
|
| 309 |
-
|
| 310 |
-
You can control request timeouts at both the client level and individual request level:
|
| 311 |
|
| 312 |
-
|
| 313 |
-
|
| 314 |
-
|
| 315 |
|
| 316 |
-
# Client with a global 5-second timeout for all requests
|
| 317 |
client = Client(
|
| 318 |
-
my_mcp_server,
|
| 319 |
-
|
|
|
|
|
|
|
|
|
|
| 320 |
)
|
| 321 |
-
|
| 322 |
-
async with client:
|
| 323 |
-
# This uses the global 5-second timeout
|
| 324 |
-
result1 = await client.call_tool("quick_task", {"param": "value"})
|
| 325 |
-
|
| 326 |
-
# This specifies a 10-second timeout for this specific call
|
| 327 |
-
result2 = await client.call_tool("slow_task", {"param": "value"}, timeout=10.0)
|
| 328 |
-
|
| 329 |
-
try:
|
| 330 |
-
# This will likely timeout
|
| 331 |
-
result3 = await client.call_tool("medium_task", {"param": "value"}, timeout=0.01)
|
| 332 |
-
except McpError as e:
|
| 333 |
-
# Handle timeout error
|
| 334 |
-
print(f"The task timed out: {e}")
|
| 335 |
```
|
| 336 |
|
| 337 |
-
|
| 338 |
-
Timeout behavior varies between transport types:
|
| 339 |
|
| 340 |
-
-
|
| 341 |
-
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 342 |
|
| 343 |
-
|
| 344 |
-
</Warning>
|
| 345 |
|
| 346 |
-
|
| 347 |
|
| 348 |
-
|
| 349 |
|
| 350 |
-
|
| 351 |
-
async def safe_call_tool():
|
| 352 |
-
async with client:
|
| 353 |
-
try:
|
| 354 |
-
# Assume 'divide' tool exists and might raise ZeroDivisionError
|
| 355 |
-
result = await client.call_tool("divide", {"a": 10, "b": 0})
|
| 356 |
-
print(f"Result: {result}")
|
| 357 |
-
except ClientError as e:
|
| 358 |
-
print(f"Tool call failed: {e}")
|
| 359 |
-
except ConnectionError as e:
|
| 360 |
-
print(f"Connection failed: {e}")
|
| 361 |
-
except Exception as e:
|
| 362 |
-
print(f"An unexpected error occurred: {e}")
|
| 363 |
-
|
| 364 |
-
# Example Output if division by zero occurs:
|
| 365 |
-
# Tool call failed: Division by zero is not allowed.
|
| 366 |
-
```
|
| 367 |
|
| 368 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 369 |
|
| 370 |
<Tip>
|
| 371 |
-
The
|
| 372 |
-
</Tip>
|
|
|
|
| 1 |
---
|
| 2 |
+
title: The FastMCP Client
|
| 3 |
sidebarTitle: Overview
|
| 4 |
+
description: Programmatic client for interacting with MCP servers through a well-typed, Pythonic interface.
|
| 5 |
icon: user-robot
|
| 6 |
---
|
| 7 |
|
|
|
|
| 9 |
|
| 10 |
<VersionBadge version="2.0.0" />
|
| 11 |
|
| 12 |
+
The central piece of MCP client applications is the `fastmcp.Client` class. This class provides a **programmatic interface** for interacting with any Model Context Protocol (MCP) server, handling protocol details and connection management automatically.
|
| 13 |
|
| 14 |
+
The FastMCP Client is designed for deterministic, controlled interactions rather than autonomous behavior, making it ideal for:
|
| 15 |
|
| 16 |
+
- **Testing MCP servers** during development
|
| 17 |
+
- **Building deterministic applications** that need reliable MCP interactions
|
| 18 |
+
- **Creating the foundation for agentic or LLM-based clients** with structured, type-safe operations
|
| 19 |
|
| 20 |
+
All client operations require using the `async with` context manager for proper connection lifecycle management.
|
|
|
|
| 21 |
|
|
|
|
| 22 |
|
| 23 |
+
<Note>
|
| 24 |
+
This is not an agentic client - it requires explicit function calls and provides direct control over all MCP operations. Use it as a building block for higher-level systems.
|
| 25 |
+
</Note>
|
| 26 |
|
| 27 |
+
## Creating a Client
|
| 28 |
|
| 29 |
+
Creating a client is straightforward. You provide a server source and the client automatically infers the appropriate transport mechanism.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
|
| 31 |
```python
|
| 32 |
import asyncio
|
| 33 |
from fastmcp import Client, FastMCP
|
| 34 |
|
| 35 |
+
# In-memory server (ideal for testing)
|
| 36 |
+
server = FastMCP("TestServer")
|
| 37 |
+
client = Client(server)
|
|
|
|
| 38 |
|
| 39 |
+
# HTTP server
|
| 40 |
+
client = Client("https://example.com/mcp")
|
|
|
|
| 41 |
|
| 42 |
+
# Local Python script
|
| 43 |
+
client = Client("my_mcp_server.py")
|
| 44 |
|
| 45 |
+
async def main():
|
| 46 |
+
async with client:
|
| 47 |
+
# Basic server interaction
|
| 48 |
+
await client.ping()
|
| 49 |
+
|
| 50 |
+
# List available operations
|
| 51 |
+
tools = await client.list_tools()
|
| 52 |
+
resources = await client.list_resources()
|
| 53 |
+
prompts = await client.list_prompts()
|
| 54 |
+
|
| 55 |
+
# Execute operations
|
| 56 |
+
result = await client.call_tool("example_tool", {"param": "value"})
|
| 57 |
+
print(result)
|
| 58 |
|
| 59 |
+
asyncio.run(main())
|
|
|
|
|
|
|
|
|
|
| 60 |
```
|
| 61 |
|
| 62 |
+
## Client-Transport Architecture
|
| 63 |
|
| 64 |
+
The FastMCP Client separates concerns between protocol and connection:
|
|
|
|
| 65 |
|
| 66 |
+
- **`Client`**: Handles MCP protocol operations (tools, resources, prompts) and manages callbacks
|
| 67 |
+
- **`Transport`**: Establishes and maintains the connection (WebSockets, HTTP, Stdio, in-memory)
|
| 68 |
+
|
| 69 |
+
### Transport Inference
|
| 70 |
+
|
| 71 |
+
The client automatically infers the appropriate transport based on the input:
|
| 72 |
+
|
| 73 |
+
1. **`FastMCP` instance** → In-memory transport (perfect for testing)
|
| 74 |
+
2. **File path ending in `.py`** → Python Stdio transport
|
| 75 |
+
3. **File path ending in `.js`** → Node.js Stdio transport
|
| 76 |
+
4. **URL starting with `http://` or `https://`** → HTTP transport
|
| 77 |
+
5. **`MCPConfig` dictionary** → Multi-server client
|
| 78 |
+
|
| 79 |
+
```python
|
| 80 |
+
from fastmcp import Client, FastMCP
|
| 81 |
|
| 82 |
+
# Examples of transport inference
|
| 83 |
+
client_memory = Client(FastMCP("TestServer"))
|
| 84 |
+
client_script = Client("./server.py")
|
| 85 |
+
client_http = Client("https://api.example.com/mcp")
|
| 86 |
```
|
| 87 |
+
|
| 88 |
<Tip>
|
| 89 |
+
For testing and development, always prefer the in-memory transport by passing a `FastMCP` server directly to the client. This eliminates network complexity and separate processes.
|
| 90 |
</Tip>
|
| 91 |
|
| 92 |
+
## Configuration-Based Clients
|
| 93 |
|
| 94 |
<VersionBadge version="2.4.0" />
|
| 95 |
|
| 96 |
+
Create clients from MCP configuration dictionaries, which can include multiple servers. While there is no official standard for MCP configuration format, FastMCP follows established conventions used by tools like Claude Desktop.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 97 |
|
| 98 |
+
### Configuration Format
|
|
|
|
|
|
|
| 99 |
|
| 100 |
```python
|
|
|
|
|
|
|
|
|
|
| 101 |
config = {
|
| 102 |
"mcpServers": {
|
| 103 |
+
"server_name": {
|
| 104 |
+
# Remote HTTP/SSE server
|
| 105 |
+
"transport": "streamable-http", # or "sse"
|
| 106 |
+
"url": "https://api.example.com/mcp",
|
| 107 |
+
"headers": {"Authorization": "Bearer token"},
|
| 108 |
+
"auth": "oauth" # or bearer token string
|
| 109 |
},
|
| 110 |
+
"local_server": {
|
| 111 |
+
# Local stdio server
|
| 112 |
+
"transport": "stdio"
|
| 113 |
"command": "python",
|
| 114 |
+
"args": ["./server.py", "--verbose"],
|
| 115 |
+
"env": {"DEBUG": "true"},
|
| 116 |
+
"cwd": "/path/to/server",
|
| 117 |
}
|
| 118 |
}
|
| 119 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 120 |
```
|
| 121 |
|
| 122 |
+
### Multi-Server Example
|
| 123 |
|
| 124 |
+
```python
|
| 125 |
+
config = {
|
| 126 |
+
"mcpServers": {
|
| 127 |
+
"weather": {"url": "https://weather-api.example.com/mcp"},
|
| 128 |
+
"assistant": {"command": "python", "args": ["./assistant_server.py"]}
|
| 129 |
+
}
|
| 130 |
+
}
|
| 131 |
|
| 132 |
+
client = Client(config)
|
| 133 |
|
| 134 |
+
async with client:
|
| 135 |
+
# Tools are prefixed with server names
|
| 136 |
+
weather_data = await client.call_tool("weather_get_forecast", {"city": "London"})
|
| 137 |
+
response = await client.call_tool("assistant_answer_question", {"question": "What's the capital of France?"})
|
| 138 |
+
|
| 139 |
+
# Resources use prefixed URIs
|
| 140 |
+
icons = await client.read_resource("weather://weather/icons/sunny")
|
| 141 |
+
templates = await client.read_resource("resource://assistant/templates/list")
|
| 142 |
+
```
|
| 143 |
|
| 144 |
+
## Connection Lifecycle
|
|
|
|
|
|
|
| 145 |
|
| 146 |
+
The client operates asynchronously and uses context managers for connection management:
|
| 147 |
|
| 148 |
+
```python
|
| 149 |
+
async def example():
|
| 150 |
+
client = Client("my_mcp_server.py")
|
| 151 |
+
|
| 152 |
+
# Connection established here
|
| 153 |
async with client:
|
| 154 |
+
print(f"Connected: {client.is_connected()}")
|
| 155 |
+
|
| 156 |
+
# Make multiple calls within the same session
|
| 157 |
tools = await client.list_tools()
|
| 158 |
+
result = await client.call_tool("greet", {"name": "World"})
|
| 159 |
+
|
| 160 |
+
# Connection closed automatically here
|
| 161 |
+
print(f"Connected: {client.is_connected()}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 162 |
```
|
| 163 |
|
| 164 |
+
## Operations
|
|
|
|
|
|
|
| 165 |
|
| 166 |
+
FastMCP clients can interact with several types of server components:
|
| 167 |
|
| 168 |
+
### Tools
|
|
|
|
|
|
|
| 169 |
|
| 170 |
+
Tools are server-side functions that the client can execute with arguments.
|
| 171 |
|
| 172 |
+
```python
|
| 173 |
+
async with client:
|
| 174 |
+
# List available tools
|
| 175 |
tools = await client.list_tools()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 176 |
|
| 177 |
+
# Execute a tool
|
| 178 |
+
result = await client.call_tool("multiply", {"a": 5, "b": 3})
|
| 179 |
+
print(result[0].text) # "15"
|
| 180 |
+
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 181 |
|
| 182 |
+
See [Tools](/clients/tools) for detailed documentation.
|
|
|
|
|
|
|
|
|
|
| 183 |
|
| 184 |
+
### Resources
|
| 185 |
|
| 186 |
+
Resources are data sources that the client can read, either static or templated.
|
|
|
|
| 187 |
|
| 188 |
+
```python
|
| 189 |
+
async with client:
|
| 190 |
+
# List available resources
|
| 191 |
+
resources = await client.list_resources()
|
| 192 |
+
|
| 193 |
+
# Read a resource
|
| 194 |
+
content = await client.read_resource("file:///config/settings.json")
|
| 195 |
+
print(content[0].text)
|
| 196 |
+
```
|
| 197 |
|
| 198 |
+
See [Resources](/clients/resources) for detailed documentation.
|
| 199 |
|
| 200 |
+
### Prompts
|
| 201 |
|
| 202 |
+
Prompts are reusable message templates that can accept arguments.
|
|
|
|
|
|
|
| 203 |
|
| 204 |
```python
|
| 205 |
+
async with client:
|
| 206 |
+
# List available prompts
|
| 207 |
+
prompts = await client.list_prompts()
|
| 208 |
+
|
| 209 |
+
# Get a rendered prompt
|
| 210 |
+
messages = await client.get_prompt("analyze_data", {"data": [1, 2, 3]})
|
| 211 |
+
print(messages.messages)
|
|
|
|
| 212 |
```
|
| 213 |
|
| 214 |
+
See [Prompts](/clients/prompts) for detailed documentation.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 215 |
|
| 216 |
+
### Server Connectivity
|
| 217 |
|
| 218 |
+
Use `ping()` to verify the server is reachable:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 219 |
|
| 220 |
```python
|
| 221 |
async with client:
|
|
|
|
| 223 |
print("Server is reachable")
|
| 224 |
```
|
| 225 |
|
| 226 |
+
## Client Configuration
|
| 227 |
+
|
| 228 |
+
Clients can be configured with additional handlers and settings for specialized use cases.
|
| 229 |
|
| 230 |
+
### Callback Handlers
|
| 231 |
|
| 232 |
+
The client supports several callback handlers for advanced server interactions:
|
| 233 |
|
| 234 |
```python
|
| 235 |
from fastmcp import Client
|
| 236 |
+
from fastmcp.client.logging import LogMessage
|
| 237 |
|
| 238 |
+
async def log_handler(message: LogMessage):
|
| 239 |
+
print(f"Server log: {message.data}")
|
| 240 |
|
| 241 |
+
async def progress_handler(progress: float, total: float | None, message: str | None):
|
| 242 |
+
print(f"Progress: {progress}/{total} - {message}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 243 |
|
| 244 |
+
async def sampling_handler(messages, params, context):
|
| 245 |
+
# Integrate with your LLM service here
|
| 246 |
+
return "Generated response"
|
| 247 |
|
|
|
|
| 248 |
client = Client(
|
| 249 |
+
"my_mcp_server.py",
|
| 250 |
+
log_handler=log_handler,
|
| 251 |
+
progress_handler=progress_handler,
|
| 252 |
+
sampling_handler=sampling_handler,
|
| 253 |
+
timeout=30.0
|
| 254 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 255 |
```
|
| 256 |
|
| 257 |
+
The `Client` constructor accepts several configuration options:
|
|
|
|
| 258 |
|
| 259 |
+
- `transport`: Transport instance or source for automatic inference
|
| 260 |
+
- `log_handler`: Handle server log messages
|
| 261 |
+
- `progress_handler`: Monitor long-running operations
|
| 262 |
+
- `sampling_handler`: Respond to server LLM requests
|
| 263 |
+
- `roots`: Provide local context to servers
|
| 264 |
+
- `timeout`: Default timeout for requests (in seconds)
|
| 265 |
|
| 266 |
+
### Transport Configuration
|
|
|
|
| 267 |
|
| 268 |
+
For detailed transport configuration (headers, authentication, environment variables), see the [Transports](/clients/transports) documentation.
|
| 269 |
|
| 270 |
+
## Next Steps
|
| 271 |
|
| 272 |
+
Explore the detailed documentation for each operation type:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 273 |
|
| 274 |
+
### Core Operations
|
| 275 |
+
- **[Tools](/clients/tools)** - Execute server-side functions and handle results
|
| 276 |
+
- **[Resources](/clients/resources)** - Access static and templated resources
|
| 277 |
+
- **[Prompts](/clients/prompts)** - Work with message templates and argument serialization
|
| 278 |
+
|
| 279 |
+
### Advanced Features
|
| 280 |
+
- **[Logging](/clients/logging)** - Handle server log messages
|
| 281 |
+
- **[Progress](/clients/progress)** - Monitor long-running operations
|
| 282 |
+
- **[Sampling](/clients/sampling)** - Respond to server LLM requests
|
| 283 |
+
- **[Roots](/clients/roots)** - Provide local context to servers
|
| 284 |
+
|
| 285 |
+
### Connection Details
|
| 286 |
+
- **[Transports](/clients/transports)** - Configure connection methods and parameters
|
| 287 |
+
- **[Authentication](/clients/auth/oauth)** - Set up OAuth and bearer token authentication
|
| 288 |
|
| 289 |
<Tip>
|
| 290 |
+
The FastMCP Client is designed as a foundational tool. Use it directly for deterministic operations, or build higher-level agentic systems on top of its reliable, type-safe interface.
|
| 291 |
+
</Tip>
|
docs/clients/logging.mdx
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: Server Logging
|
| 3 |
+
sidebarTitle: Logging
|
| 4 |
+
description: Receive and handle log messages from MCP servers.
|
| 5 |
+
icon: receipt
|
| 6 |
+
---
|
| 7 |
+
|
| 8 |
+
import { VersionBadge } from '/snippets/version-badge.mdx'
|
| 9 |
+
|
| 10 |
+
<VersionBadge version="2.0.0" />
|
| 11 |
+
|
| 12 |
+
MCP servers can emit log messages to clients. The client can handle these logs through a log handler callback.
|
| 13 |
+
|
| 14 |
+
## Setting Up Log Handling
|
| 15 |
+
|
| 16 |
+
Provide a `log_handler` function when creating the client:
|
| 17 |
+
|
| 18 |
+
```python
|
| 19 |
+
from fastmcp import Client
|
| 20 |
+
from fastmcp.client.logging import LogMessage
|
| 21 |
+
|
| 22 |
+
async def log_handler(message: LogMessage):
|
| 23 |
+
level = message.level.upper()
|
| 24 |
+
logger = message.logger or 'server'
|
| 25 |
+
data = message.data
|
| 26 |
+
print(f"[{level}] {logger}: {data}")
|
| 27 |
+
|
| 28 |
+
client = Client(
|
| 29 |
+
"my_mcp_server.py",
|
| 30 |
+
log_handler=log_handler,
|
| 31 |
+
)
|
| 32 |
+
```
|
| 33 |
+
|
| 34 |
+
## LogMessage Structure
|
| 35 |
+
|
| 36 |
+
The `log_handler` receives a `LogMessage` object with:
|
| 37 |
+
|
| 38 |
+
- **`level`**: Log level (e.g., "debug", "info", "warning", "error")
|
| 39 |
+
- **`logger`**: Logger name (optional, may be None)
|
| 40 |
+
- **`data`**: The actual log message content
|
| 41 |
+
|
| 42 |
+
```python
|
| 43 |
+
async def detailed_log_handler(message: LogMessage):
|
| 44 |
+
if message.level == "error":
|
| 45 |
+
print(f"ERROR: {message.data}")
|
| 46 |
+
elif message.level == "warning":
|
| 47 |
+
print(f"WARNING: {message.data}")
|
| 48 |
+
else:
|
| 49 |
+
print(f"{message.level.upper()}: {message.data}")
|
| 50 |
+
```
|
| 51 |
+
|
| 52 |
+
## Default Log Handling
|
| 53 |
+
|
| 54 |
+
If you don't provide a custom `log_handler`, FastMCP uses a default handler that emits DEBUG level logs:
|
| 55 |
+
|
| 56 |
+
```python
|
| 57 |
+
# Without custom handler - uses default DEBUG logging
|
| 58 |
+
client = Client("my_mcp_server.py")
|
| 59 |
+
|
| 60 |
+
async with client:
|
| 61 |
+
# Server logs will be emitted at DEBUG level
|
| 62 |
+
await client.call_tool("some_tool")
|
| 63 |
+
```
|
docs/clients/progress.mdx
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: Progress Monitoring
|
| 3 |
+
sidebarTitle: Progress
|
| 4 |
+
description: Handle progress notifications from long-running server operations.
|
| 5 |
+
icon: bars-progress
|
| 6 |
+
---
|
| 7 |
+
|
| 8 |
+
import { VersionBadge } from '/snippets/version-badge.mdx'
|
| 9 |
+
|
| 10 |
+
<VersionBadge version="2.3.5" />
|
| 11 |
+
|
| 12 |
+
MCP servers can report progress during long-running operations. The client can receive these updates through a progress handler.
|
| 13 |
+
|
| 14 |
+
## Setting Up Progress Handling
|
| 15 |
+
|
| 16 |
+
Set a progress handler when creating the client:
|
| 17 |
+
|
| 18 |
+
```python
|
| 19 |
+
from fastmcp import Client
|
| 20 |
+
|
| 21 |
+
async def my_progress_handler(
|
| 22 |
+
progress: float,
|
| 23 |
+
total: float | None,
|
| 24 |
+
message: str | None
|
| 25 |
+
) -> None:
|
| 26 |
+
if total is not None:
|
| 27 |
+
percentage = (progress / total) * 100
|
| 28 |
+
print(f"Progress: {percentage:.1f}% - {message or ''}")
|
| 29 |
+
else:
|
| 30 |
+
print(f"Progress: {progress} - {message or ''}")
|
| 31 |
+
|
| 32 |
+
client = Client(
|
| 33 |
+
"my_mcp_server.py",
|
| 34 |
+
progress_handler=my_progress_handler
|
| 35 |
+
)
|
| 36 |
+
```
|
| 37 |
+
|
| 38 |
+
## Per-Call Progress Handler
|
| 39 |
+
|
| 40 |
+
Override the progress handler for specific tool calls:
|
| 41 |
+
|
| 42 |
+
```python
|
| 43 |
+
async with client:
|
| 44 |
+
# Override with specific progress handler for this call
|
| 45 |
+
result = await client.call_tool(
|
| 46 |
+
"long_running_task",
|
| 47 |
+
{"param": "value"},
|
| 48 |
+
progress_handler=my_progress_handler
|
| 49 |
+
)
|
| 50 |
+
```
|
| 51 |
+
|
| 52 |
+
## Handler Parameters
|
| 53 |
+
|
| 54 |
+
The progress handler receives:
|
| 55 |
+
|
| 56 |
+
- **`progress`** (float): Current progress value
|
| 57 |
+
- **`total`** (float | None): Expected total value (may be None)
|
| 58 |
+
- **`message`** (str | None): Optional status message (may be None)
|
| 59 |
+
|
docs/clients/prompts.mdx
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: Prompts
|
| 3 |
+
sidebarTitle: Prompts
|
| 4 |
+
description: Use server-side prompt templates with automatic argument serialization.
|
| 5 |
+
icon: message-lines
|
| 6 |
+
---
|
| 7 |
+
|
| 8 |
+
import { VersionBadge } from '/snippets/version-badge.mdx'
|
| 9 |
+
|
| 10 |
+
<VersionBadge version="2.0.0" />
|
| 11 |
+
|
| 12 |
+
Prompts are reusable message templates exposed by MCP servers. They can accept arguments to generate personalized message sequences for LLM interactions.
|
| 13 |
+
|
| 14 |
+
## Listing Prompts
|
| 15 |
+
|
| 16 |
+
Use `list_prompts()` to retrieve all available prompt templates:
|
| 17 |
+
|
| 18 |
+
```python
|
| 19 |
+
async with client:
|
| 20 |
+
prompts = await client.list_prompts()
|
| 21 |
+
# prompts -> list[mcp.types.Prompt]
|
| 22 |
+
|
| 23 |
+
for prompt in prompts:
|
| 24 |
+
print(f"Prompt: {prompt.name}")
|
| 25 |
+
print(f"Description: {prompt.description}")
|
| 26 |
+
if prompt.arguments:
|
| 27 |
+
print(f"Arguments: {[arg.name for arg in prompt.arguments]}")
|
| 28 |
+
```
|
| 29 |
+
|
| 30 |
+
## Using Prompts
|
| 31 |
+
|
| 32 |
+
### Basic Usage
|
| 33 |
+
|
| 34 |
+
Request a rendered prompt using `get_prompt()` with the prompt name and arguments:
|
| 35 |
+
|
| 36 |
+
```python
|
| 37 |
+
async with client:
|
| 38 |
+
# Simple prompt without arguments
|
| 39 |
+
result = await client.get_prompt("welcome_message")
|
| 40 |
+
# result -> mcp.types.GetPromptResult
|
| 41 |
+
|
| 42 |
+
# Access the generated messages
|
| 43 |
+
for message in result.messages:
|
| 44 |
+
print(f"Role: {message.role}")
|
| 45 |
+
print(f"Content: {message.content}")
|
| 46 |
+
```
|
| 47 |
+
|
| 48 |
+
### Prompts with Arguments
|
| 49 |
+
|
| 50 |
+
Pass arguments as a dictionary to customize the prompt:
|
| 51 |
+
|
| 52 |
+
```python
|
| 53 |
+
async with client:
|
| 54 |
+
# Prompt with simple arguments
|
| 55 |
+
result = await client.get_prompt("user_greeting", {
|
| 56 |
+
"name": "Alice",
|
| 57 |
+
"role": "administrator"
|
| 58 |
+
})
|
| 59 |
+
|
| 60 |
+
# Access the personalized messages
|
| 61 |
+
for message in result.messages:
|
| 62 |
+
print(f"Generated message: {message.content}")
|
| 63 |
+
```
|
| 64 |
+
|
| 65 |
+
## Automatic Argument Serialization
|
| 66 |
+
|
| 67 |
+
<VersionBadge version="2.9.0" />
|
| 68 |
+
|
| 69 |
+
FastMCP automatically serializes complex arguments to JSON strings as required by the MCP specification. This allows you to pass typed objects directly:
|
| 70 |
+
|
| 71 |
+
```python
|
| 72 |
+
from dataclasses import dataclass
|
| 73 |
+
|
| 74 |
+
@dataclass
|
| 75 |
+
class UserData:
|
| 76 |
+
name: str
|
| 77 |
+
age: int
|
| 78 |
+
|
| 79 |
+
async with client:
|
| 80 |
+
# Complex arguments are automatically serialized
|
| 81 |
+
result = await client.get_prompt("analyze_user", {
|
| 82 |
+
"user": UserData(name="Alice", age=30), # Automatically serialized to JSON
|
| 83 |
+
"preferences": {"theme": "dark"}, # Dict serialized to JSON string
|
| 84 |
+
"scores": [85, 92, 78], # List serialized to JSON string
|
| 85 |
+
"simple_name": "Bob" # Strings passed through unchanged
|
| 86 |
+
})
|
| 87 |
+
```
|
| 88 |
+
|
| 89 |
+
The client handles serialization using `pydantic_core.to_json()` for consistent formatting. FastMCP servers can automatically deserialize these JSON strings back to the expected types.
|
| 90 |
+
|
| 91 |
+
### Serialization Examples
|
| 92 |
+
|
| 93 |
+
```python
|
| 94 |
+
async with client:
|
| 95 |
+
result = await client.get_prompt("data_analysis", {
|
| 96 |
+
# These will be automatically serialized to JSON strings:
|
| 97 |
+
"config": {
|
| 98 |
+
"format": "csv",
|
| 99 |
+
"include_headers": True,
|
| 100 |
+
"delimiter": ","
|
| 101 |
+
},
|
| 102 |
+
"filters": [
|
| 103 |
+
{"field": "age", "operator": ">", "value": 18},
|
| 104 |
+
{"field": "status", "operator": "==", "value": "active"}
|
| 105 |
+
],
|
| 106 |
+
# This remains a string:
|
| 107 |
+
"report_title": "Monthly Analytics Report"
|
| 108 |
+
})
|
| 109 |
+
```
|
| 110 |
+
|
| 111 |
+
## Working with Prompt Results
|
| 112 |
+
|
| 113 |
+
The `get_prompt()` method returns a `GetPromptResult` object containing a list of messages:
|
| 114 |
+
|
| 115 |
+
```python
|
| 116 |
+
async with client:
|
| 117 |
+
result = await client.get_prompt("conversation_starter", {"topic": "climate"})
|
| 118 |
+
|
| 119 |
+
# Access individual messages
|
| 120 |
+
for i, message in enumerate(result.messages):
|
| 121 |
+
print(f"Message {i + 1}:")
|
| 122 |
+
print(f" Role: {message.role}")
|
| 123 |
+
print(f" Content: {message.content.text if hasattr(message.content, 'text') else message.content}")
|
| 124 |
+
```
|
| 125 |
+
|
| 126 |
+
## Raw MCP Protocol Access
|
| 127 |
+
|
| 128 |
+
For access to the complete MCP protocol objects, use the `*_mcp` methods:
|
| 129 |
+
|
| 130 |
+
```python
|
| 131 |
+
async with client:
|
| 132 |
+
# Raw MCP method returns full protocol object
|
| 133 |
+
prompts_result = await client.list_prompts_mcp()
|
| 134 |
+
# prompts_result -> mcp.types.ListPromptsResult
|
| 135 |
+
|
| 136 |
+
prompt_result = await client.get_prompt_mcp("example_prompt", {"arg": "value"})
|
| 137 |
+
# prompt_result -> mcp.types.GetPromptResult
|
| 138 |
+
```
|
| 139 |
+
|
| 140 |
+
## Multi-Server Clients
|
| 141 |
+
|
| 142 |
+
When using multi-server clients, prompts are accessible without prefixing (unlike tools):
|
| 143 |
+
|
| 144 |
+
```python
|
| 145 |
+
async with client: # Multi-server client
|
| 146 |
+
# Prompts from any server are directly accessible
|
| 147 |
+
result1 = await client.get_prompt("weather_prompt", {"city": "London"})
|
| 148 |
+
result2 = await client.get_prompt("assistant_prompt", {"query": "help"})
|
| 149 |
+
```
|
| 150 |
+
|
| 151 |
+
## Common Prompt Patterns
|
| 152 |
+
|
| 153 |
+
### System Messages
|
| 154 |
+
|
| 155 |
+
Many prompts generate system messages for LLM configuration:
|
| 156 |
+
|
| 157 |
+
```python
|
| 158 |
+
async with client:
|
| 159 |
+
result = await client.get_prompt("system_configuration", {
|
| 160 |
+
"role": "helpful assistant",
|
| 161 |
+
"expertise": "python programming"
|
| 162 |
+
})
|
| 163 |
+
|
| 164 |
+
# Typically returns messages with role="system"
|
| 165 |
+
system_message = result.messages[0]
|
| 166 |
+
print(f"System prompt: {system_message.content}")
|
| 167 |
+
```
|
| 168 |
+
|
| 169 |
+
### Conversation Templates
|
| 170 |
+
|
| 171 |
+
Prompts can generate multi-turn conversation templates:
|
| 172 |
+
|
| 173 |
+
```python
|
| 174 |
+
async with client:
|
| 175 |
+
result = await client.get_prompt("interview_template", {
|
| 176 |
+
"candidate_name": "Alice",
|
| 177 |
+
"position": "Senior Developer"
|
| 178 |
+
})
|
| 179 |
+
|
| 180 |
+
# Multiple messages for a conversation flow
|
| 181 |
+
for message in result.messages:
|
| 182 |
+
print(f"{message.role}: {message.content}")
|
| 183 |
+
```
|
| 184 |
+
|
| 185 |
+
<Tip>
|
| 186 |
+
Prompt arguments and their expected types depend on the specific prompt implementation. Check the server's documentation or use `list_prompts()` to see available arguments for each prompt.
|
| 187 |
+
</Tip>
|
docs/clients/resources.mdx
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: Resource Operations
|
| 3 |
+
sidebarTitle: Resources
|
| 4 |
+
description: Access static and templated resources from MCP servers.
|
| 5 |
+
icon: folder-open
|
| 6 |
+
---
|
| 7 |
+
|
| 8 |
+
import { VersionBadge } from '/snippets/version-badge.mdx'
|
| 9 |
+
|
| 10 |
+
<VersionBadge version="2.0.0" />
|
| 11 |
+
|
| 12 |
+
Resources are data sources exposed by MCP servers. They can be static files or dynamic templates that generate content based on parameters.
|
| 13 |
+
|
| 14 |
+
## Types of Resources
|
| 15 |
+
|
| 16 |
+
MCP servers expose two types of resources:
|
| 17 |
+
|
| 18 |
+
- **Static Resources**: Fixed content accessible via URI (e.g., configuration files, documentation)
|
| 19 |
+
- **Resource Templates**: Dynamic resources that accept parameters to generate content (e.g., API endpoints, database queries)
|
| 20 |
+
|
| 21 |
+
## Listing Resources
|
| 22 |
+
|
| 23 |
+
### Static Resources
|
| 24 |
+
|
| 25 |
+
Use `list_resources()` to retrieve all static resources available on the server:
|
| 26 |
+
|
| 27 |
+
```python
|
| 28 |
+
async with client:
|
| 29 |
+
resources = await client.list_resources()
|
| 30 |
+
# resources -> list[mcp.types.Resource]
|
| 31 |
+
|
| 32 |
+
for resource in resources:
|
| 33 |
+
print(f"Resource URI: {resource.uri}")
|
| 34 |
+
print(f"Name: {resource.name}")
|
| 35 |
+
print(f"Description: {resource.description}")
|
| 36 |
+
print(f"MIME Type: {resource.mimeType}")
|
| 37 |
+
```
|
| 38 |
+
|
| 39 |
+
### Resource Templates
|
| 40 |
+
|
| 41 |
+
Use `list_resource_templates()` to retrieve available resource templates:
|
| 42 |
+
|
| 43 |
+
```python
|
| 44 |
+
async with client:
|
| 45 |
+
templates = await client.list_resource_templates()
|
| 46 |
+
# templates -> list[mcp.types.ResourceTemplate]
|
| 47 |
+
|
| 48 |
+
for template in templates:
|
| 49 |
+
print(f"Template URI: {template.uriTemplate}")
|
| 50 |
+
print(f"Name: {template.name}")
|
| 51 |
+
print(f"Description: {template.description}")
|
| 52 |
+
```
|
| 53 |
+
|
| 54 |
+
## Reading Resources
|
| 55 |
+
|
| 56 |
+
### Static Resources
|
| 57 |
+
|
| 58 |
+
Read a static resource using its URI:
|
| 59 |
+
|
| 60 |
+
```python
|
| 61 |
+
async with client:
|
| 62 |
+
# Read a static resource
|
| 63 |
+
content = await client.read_resource("file:///path/to/README.md")
|
| 64 |
+
# content -> list[mcp.types.TextResourceContents | mcp.types.BlobResourceContents]
|
| 65 |
+
|
| 66 |
+
# Access text content
|
| 67 |
+
if hasattr(content[0], 'text'):
|
| 68 |
+
print(content[0].text)
|
| 69 |
+
|
| 70 |
+
# Access binary content
|
| 71 |
+
if hasattr(content[0], 'blob'):
|
| 72 |
+
print(f"Binary data: {len(content[0].blob)} bytes")
|
| 73 |
+
```
|
| 74 |
+
|
| 75 |
+
### Resource Templates
|
| 76 |
+
|
| 77 |
+
Read from a resource template by providing the URI with parameters:
|
| 78 |
+
|
| 79 |
+
```python
|
| 80 |
+
async with client:
|
| 81 |
+
# Read a resource generated from a template
|
| 82 |
+
# For example, a template like "weather://{{city}}/current"
|
| 83 |
+
weather_content = await client.read_resource("weather://london/current")
|
| 84 |
+
|
| 85 |
+
# Access the generated content
|
| 86 |
+
print(weather_content[0].text) # Assuming text JSON response
|
| 87 |
+
```
|
| 88 |
+
|
| 89 |
+
## Content Types
|
| 90 |
+
|
| 91 |
+
Resources can return different content types:
|
| 92 |
+
|
| 93 |
+
### Text Resources
|
| 94 |
+
|
| 95 |
+
```python
|
| 96 |
+
async with client:
|
| 97 |
+
content = await client.read_resource("resource://config/settings.json")
|
| 98 |
+
|
| 99 |
+
for item in content:
|
| 100 |
+
if hasattr(item, 'text'):
|
| 101 |
+
print(f"Text content: {item.text}")
|
| 102 |
+
print(f"MIME type: {item.mimeType}")
|
| 103 |
+
```
|
| 104 |
+
|
| 105 |
+
### Binary Resources
|
| 106 |
+
|
| 107 |
+
```python
|
| 108 |
+
async with client:
|
| 109 |
+
content = await client.read_resource("resource://images/logo.png")
|
| 110 |
+
|
| 111 |
+
for item in content:
|
| 112 |
+
if hasattr(item, 'blob'):
|
| 113 |
+
print(f"Binary content: {len(item.blob)} bytes")
|
| 114 |
+
print(f"MIME type: {item.mimeType}")
|
| 115 |
+
|
| 116 |
+
# Save to file
|
| 117 |
+
with open("downloaded_logo.png", "wb") as f:
|
| 118 |
+
f.write(item.blob)
|
| 119 |
+
```
|
| 120 |
+
|
| 121 |
+
## Working with Multi-Server Clients
|
| 122 |
+
|
| 123 |
+
When using multi-server clients, resource URIs are automatically prefixed with the server name:
|
| 124 |
+
|
| 125 |
+
```python
|
| 126 |
+
async with client: # Multi-server client
|
| 127 |
+
# Access resources from different servers
|
| 128 |
+
weather_icons = await client.read_resource("weather://weather/icons/sunny")
|
| 129 |
+
templates = await client.read_resource("resource://assistant/templates/list")
|
| 130 |
+
|
| 131 |
+
print(f"Weather icon: {weather_icons[0].blob}")
|
| 132 |
+
print(f"Templates: {templates[0].text}")
|
| 133 |
+
```
|
| 134 |
+
|
| 135 |
+
## Raw MCP Protocol Access
|
| 136 |
+
|
| 137 |
+
For access to the complete MCP protocol objects, use the `*_mcp` methods:
|
| 138 |
+
|
| 139 |
+
```python
|
| 140 |
+
async with client:
|
| 141 |
+
# Raw MCP methods return full protocol objects
|
| 142 |
+
resources_result = await client.list_resources_mcp()
|
| 143 |
+
# resources_result -> mcp.types.ListResourcesResult
|
| 144 |
+
|
| 145 |
+
templates_result = await client.list_resource_templates_mcp()
|
| 146 |
+
# templates_result -> mcp.types.ListResourceTemplatesResult
|
| 147 |
+
|
| 148 |
+
content_result = await client.read_resource_mcp("resource://example")
|
| 149 |
+
# content_result -> mcp.types.ReadResourceResult
|
| 150 |
+
```
|
| 151 |
+
|
| 152 |
+
## Common Resource URI Patterns
|
| 153 |
+
|
| 154 |
+
Different MCP servers may use various URI schemes:
|
| 155 |
+
|
| 156 |
+
```python
|
| 157 |
+
# File system resources
|
| 158 |
+
"file:///path/to/file.txt"
|
| 159 |
+
|
| 160 |
+
# Custom protocol resources
|
| 161 |
+
"weather://london/current"
|
| 162 |
+
"database://users/123"
|
| 163 |
+
|
| 164 |
+
# Generic resource protocol
|
| 165 |
+
"resource://config/settings"
|
| 166 |
+
"resource://templates/email"
|
| 167 |
+
```
|
| 168 |
+
|
| 169 |
+
<Tip>
|
| 170 |
+
Resource URIs and their formats depend on the specific MCP server implementation. Check the server's documentation for available resources and their URI patterns.
|
| 171 |
+
</Tip>
|
docs/clients/roots.mdx
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: Client Roots
|
| 3 |
+
sidebarTitle: Roots
|
| 4 |
+
description: Provide local context and resource boundaries to MCP servers.
|
| 5 |
+
icon: folder-tree
|
| 6 |
+
---
|
| 7 |
+
|
| 8 |
+
import { VersionBadge } from '/snippets/version-badge.mdx'
|
| 9 |
+
|
| 10 |
+
<VersionBadge version="2.0.0" />
|
| 11 |
+
|
| 12 |
+
Roots are a way for clients to inform servers about the resources they have access to. Servers can use this information to adjust behavior or provide more relevant responses.
|
| 13 |
+
|
| 14 |
+
## Setting Static Roots
|
| 15 |
+
|
| 16 |
+
Provide a list of roots when creating the client:
|
| 17 |
+
|
| 18 |
+
<CodeGroup>
|
| 19 |
+
```python Static Roots
|
| 20 |
+
from fastmcp import Client
|
| 21 |
+
|
| 22 |
+
client = Client(
|
| 23 |
+
"my_mcp_server.py",
|
| 24 |
+
roots=["/path/to/root1", "/path/to/root2"]
|
| 25 |
+
)
|
| 26 |
+
```
|
| 27 |
+
|
| 28 |
+
```python Dynamic Roots Callback
|
| 29 |
+
from fastmcp import Client
|
| 30 |
+
from fastmcp.client.roots import RequestContext
|
| 31 |
+
|
| 32 |
+
async def roots_callback(context: RequestContext) -> list[str]:
|
| 33 |
+
print(f"Server requested roots (Request ID: {context.request_id})")
|
| 34 |
+
return ["/path/to/root1", "/path/to/root2"]
|
| 35 |
+
|
| 36 |
+
client = Client(
|
| 37 |
+
"my_mcp_server.py",
|
| 38 |
+
roots=roots_callback
|
| 39 |
+
)
|
| 40 |
+
```
|
| 41 |
+
</CodeGroup>
|
| 42 |
+
|
docs/clients/sampling.mdx
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: LLM Sampling
|
| 3 |
+
sidebarTitle: Sampling
|
| 4 |
+
description: Handle server-initiated LLM sampling requests.
|
| 5 |
+
icon: robot
|
| 6 |
+
---
|
| 7 |
+
|
| 8 |
+
import { VersionBadge } from '/snippets/version-badge.mdx'
|
| 9 |
+
|
| 10 |
+
<VersionBadge version="2.0.0" />
|
| 11 |
+
|
| 12 |
+
MCP servers can request LLM completions from clients. The client handles these requests through a sampling handler callback.
|
| 13 |
+
|
| 14 |
+
## Setting Up Sampling Handling
|
| 15 |
+
|
| 16 |
+
Provide a `sampling_handler` function when creating the client:
|
| 17 |
+
|
| 18 |
+
```python
|
| 19 |
+
from fastmcp import Client
|
| 20 |
+
from fastmcp.client.sampling import (
|
| 21 |
+
SamplingMessage,
|
| 22 |
+
SamplingParams,
|
| 23 |
+
RequestContext,
|
| 24 |
+
)
|
| 25 |
+
|
| 26 |
+
async def sampling_handler(
|
| 27 |
+
messages: list[SamplingMessage],
|
| 28 |
+
params: SamplingParams,
|
| 29 |
+
context: RequestContext
|
| 30 |
+
) -> str:
|
| 31 |
+
# Your LLM integration logic here
|
| 32 |
+
# Extract text from messages and generate a response
|
| 33 |
+
return "Generated response based on the messages"
|
| 34 |
+
|
| 35 |
+
client = Client(
|
| 36 |
+
"my_mcp_server.py",
|
| 37 |
+
sampling_handler=sampling_handler,
|
| 38 |
+
)
|
| 39 |
+
```
|
| 40 |
+
|
| 41 |
+
## Handler Parameters
|
| 42 |
+
|
| 43 |
+
The sampling handler receives three parameters:
|
| 44 |
+
|
| 45 |
+
### SamplingMessage
|
| 46 |
+
|
| 47 |
+
- **`role`**: Message role (e.g., "user", "assistant", "system")
|
| 48 |
+
- **`content`**: Message content (usually has `.text` attribute)
|
| 49 |
+
|
| 50 |
+
### SamplingParams
|
| 51 |
+
|
| 52 |
+
- **`systemPrompt`**: System prompt string (optional)
|
| 53 |
+
- **`maxTokens`**: Maximum tokens to generate (optional)
|
| 54 |
+
- **`temperature`**: Sampling temperature (optional)
|
| 55 |
+
- **`topP`**: Top-p sampling parameter (optional)
|
| 56 |
+
- **`stopSequences`**: List of stop sequences (optional)
|
| 57 |
+
|
| 58 |
+
### RequestContext
|
| 59 |
+
|
| 60 |
+
- **`request_id`**: Unique identifier for the sampling request
|
| 61 |
+
|
| 62 |
+
## Basic Example
|
| 63 |
+
|
| 64 |
+
```python
|
| 65 |
+
from fastmcp import Client
|
| 66 |
+
from fastmcp.client.sampling import SamplingMessage, SamplingParams, RequestContext
|
| 67 |
+
|
| 68 |
+
async def basic_sampling_handler(
|
| 69 |
+
messages: list[SamplingMessage],
|
| 70 |
+
params: SamplingParams,
|
| 71 |
+
context: RequestContext
|
| 72 |
+
) -> str:
|
| 73 |
+
# Extract message content
|
| 74 |
+
conversation = []
|
| 75 |
+
for message in messages:
|
| 76 |
+
content = message.content.text if hasattr(message.content, 'text') else str(message.content)
|
| 77 |
+
conversation.append(f"{message.role}: {content}")
|
| 78 |
+
|
| 79 |
+
# Use the system prompt if provided
|
| 80 |
+
system_prompt = params.systemPrompt or "You are a helpful assistant."
|
| 81 |
+
|
| 82 |
+
# Here you would integrate with your preferred LLM service
|
| 83 |
+
# This is just a placeholder response
|
| 84 |
+
return f"Response based on conversation: {' | '.join(conversation)}"
|
| 85 |
+
|
| 86 |
+
client = Client(
|
| 87 |
+
"my_mcp_server.py",
|
| 88 |
+
sampling_handler=basic_sampling_handler
|
| 89 |
+
)
|
| 90 |
+
```
|
| 91 |
+
|
docs/clients/tools.mdx
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: Tool Operations
|
| 3 |
+
sidebarTitle: Tools
|
| 4 |
+
description: Discover and execute server-side tools with the FastMCP client.
|
| 5 |
+
icon: wrench
|
| 6 |
+
---
|
| 7 |
+
|
| 8 |
+
import { VersionBadge } from '/snippets/version-badge.mdx'
|
| 9 |
+
|
| 10 |
+
<VersionBadge version="2.0.0" />
|
| 11 |
+
|
| 12 |
+
Tools are executable functions exposed by MCP servers. The FastMCP client provides methods to discover available tools and execute them with arguments.
|
| 13 |
+
|
| 14 |
+
## Discovering Tools
|
| 15 |
+
|
| 16 |
+
Use `list_tools()` to retrieve all tools available on the server:
|
| 17 |
+
|
| 18 |
+
```python
|
| 19 |
+
async with client:
|
| 20 |
+
tools = await client.list_tools()
|
| 21 |
+
# tools -> list[mcp.types.Tool]
|
| 22 |
+
|
| 23 |
+
for tool in tools:
|
| 24 |
+
print(f"Tool: {tool.name}")
|
| 25 |
+
print(f"Description: {tool.description}")
|
| 26 |
+
if tool.inputSchema:
|
| 27 |
+
print(f"Parameters: {tool.inputSchema}")
|
| 28 |
+
```
|
| 29 |
+
|
| 30 |
+
## Executing Tools
|
| 31 |
+
|
| 32 |
+
### Basic Execution
|
| 33 |
+
|
| 34 |
+
Execute a tool using `call_tool()` with the tool name and arguments:
|
| 35 |
+
|
| 36 |
+
```python
|
| 37 |
+
async with client:
|
| 38 |
+
# Simple tool call
|
| 39 |
+
result = await client.call_tool("add", {"a": 5, "b": 3})
|
| 40 |
+
# result -> list[mcp.types.TextContent | mcp.types.ImageContent | ...]
|
| 41 |
+
|
| 42 |
+
# Access the result content
|
| 43 |
+
print(result[0].text) # Assuming TextContent, e.g., '8'
|
| 44 |
+
```
|
| 45 |
+
|
| 46 |
+
### Advanced Execution Options
|
| 47 |
+
|
| 48 |
+
The `call_tool()` method supports additional parameters for timeout control and progress monitoring:
|
| 49 |
+
|
| 50 |
+
```python
|
| 51 |
+
async with client:
|
| 52 |
+
# With timeout (aborts if execution takes longer than 2 seconds)
|
| 53 |
+
result = await client.call_tool(
|
| 54 |
+
"long_running_task",
|
| 55 |
+
{"param": "value"},
|
| 56 |
+
timeout=2.0
|
| 57 |
+
)
|
| 58 |
+
|
| 59 |
+
# With progress handler (to track execution progress)
|
| 60 |
+
result = await client.call_tool(
|
| 61 |
+
"long_running_task",
|
| 62 |
+
{"param": "value"},
|
| 63 |
+
progress_handler=my_progress_handler
|
| 64 |
+
)
|
| 65 |
+
```
|
| 66 |
+
|
| 67 |
+
**Parameters:**
|
| 68 |
+
- `name`: The tool name (string)
|
| 69 |
+
- `arguments`: Dictionary of arguments to pass to the tool (optional)
|
| 70 |
+
- `timeout`: Maximum execution time in seconds (optional, overrides client-level timeout)
|
| 71 |
+
- `progress_handler`: Progress callback function (optional, overrides client-level handler)
|
| 72 |
+
|
| 73 |
+
## Handling Results
|
| 74 |
+
|
| 75 |
+
Tool execution returns a list of content objects. The most common types are:
|
| 76 |
+
|
| 77 |
+
- **`TextContent`**: Text-based results with a `.text` attribute
|
| 78 |
+
- **`ImageContent`**: Image data with image-specific attributes
|
| 79 |
+
- **`BlobContent`**: Binary data content
|
| 80 |
+
|
| 81 |
+
```python
|
| 82 |
+
async with client:
|
| 83 |
+
result = await client.call_tool("get_weather", {"city": "London"})
|
| 84 |
+
|
| 85 |
+
for content in result:
|
| 86 |
+
if hasattr(content, 'text'):
|
| 87 |
+
print(f"Text result: {content.text}")
|
| 88 |
+
elif hasattr(content, 'data'):
|
| 89 |
+
print(f"Binary data: {len(content.data)} bytes")
|
| 90 |
+
```
|
| 91 |
+
|
| 92 |
+
## Error Handling
|
| 93 |
+
|
| 94 |
+
### Exception-Based Error Handling
|
| 95 |
+
|
| 96 |
+
By default, `call_tool()` raises a `ToolError` if the tool execution fails:
|
| 97 |
+
|
| 98 |
+
```python
|
| 99 |
+
from fastmcp.exceptions import ToolError
|
| 100 |
+
|
| 101 |
+
async with client:
|
| 102 |
+
try:
|
| 103 |
+
result = await client.call_tool("potentially_failing_tool", {"param": "value"})
|
| 104 |
+
print("Tool succeeded:", result)
|
| 105 |
+
except ToolError as e:
|
| 106 |
+
print(f"Tool failed: {e}")
|
| 107 |
+
```
|
| 108 |
+
|
| 109 |
+
### Manual Error Checking
|
| 110 |
+
|
| 111 |
+
For more granular control, use `call_tool_mcp()` which returns the raw MCP protocol object with an `isError` flag:
|
| 112 |
+
|
| 113 |
+
```python
|
| 114 |
+
async with client:
|
| 115 |
+
result = await client.call_tool_mcp("potentially_failing_tool", {"param": "value"})
|
| 116 |
+
# result -> mcp.types.CallToolResult
|
| 117 |
+
|
| 118 |
+
if result.isError:
|
| 119 |
+
print(f"Tool failed: {result.content}")
|
| 120 |
+
else:
|
| 121 |
+
print(f"Tool succeeded: {result.content}")
|
| 122 |
+
```
|
| 123 |
+
|
| 124 |
+
## Argument Handling
|
| 125 |
+
|
| 126 |
+
Arguments are passed as a dictionary to the tool:
|
| 127 |
+
|
| 128 |
+
```python
|
| 129 |
+
async with client:
|
| 130 |
+
# Simple arguments
|
| 131 |
+
result = await client.call_tool("greet", {"name": "World"})
|
| 132 |
+
|
| 133 |
+
# Complex arguments
|
| 134 |
+
result = await client.call_tool("process_data", {
|
| 135 |
+
"config": {"format": "json", "validate": True},
|
| 136 |
+
"items": [1, 2, 3, 4, 5],
|
| 137 |
+
"metadata": {"source": "api", "version": "1.0"}
|
| 138 |
+
})
|
| 139 |
+
```
|
| 140 |
+
|
| 141 |
+
<Tip>
|
| 142 |
+
For multi-server clients, tool names are automatically prefixed with the server name (e.g., `weather_get_forecast` for a tool named `get_forecast` on the `weather` server).
|
| 143 |
+
</Tip>
|
docs/deployment/asgi.mdx
CHANGED
|
@@ -48,7 +48,7 @@ Both approaches return a Starlette application that can be integrated with other
|
|
| 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
|
|
@@ -96,7 +96,13 @@ mcp = FastMCP("MyServer")
|
|
| 96 |
|
| 97 |
# Define custom middleware
|
| 98 |
custom_middleware = [
|
| 99 |
-
Middleware(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 100 |
]
|
| 101 |
|
| 102 |
# Create ASGI app with custom middleware
|
|
@@ -131,7 +137,7 @@ app = Starlette(
|
|
| 131 |
)
|
| 132 |
```
|
| 133 |
|
| 134 |
-
The MCP endpoint will be available at `/mcp-server/mcp` of the resulting Starlette app.
|
| 135 |
|
| 136 |
<Warning>
|
| 137 |
For Streamable HTTP transport, you **must** pass the lifespan context from the FastMCP app to the resulting Starlette app, as nested lifespans are not recognized. Otherwise, the FastMCP server's session manager will not be properly initialized.
|
|
@@ -161,7 +167,7 @@ app = Starlette(
|
|
| 161 |
)
|
| 162 |
```
|
| 163 |
|
| 164 |
-
In this setup, the MCP server is accessible at the `/outer/inner/mcp` path of the resulting Starlette app.
|
| 165 |
|
| 166 |
<Warning>
|
| 167 |
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.
|
|
@@ -188,7 +194,7 @@ app = FastAPI(lifespan=mcp_app.lifespan)
|
|
| 188 |
app.mount("/mcp-server", mcp_app)
|
| 189 |
```
|
| 190 |
|
| 191 |
-
The MCP endpoint will be available at `/mcp-server/mcp` of the resulting FastAPI app.
|
| 192 |
|
| 193 |
<Warning>
|
| 194 |
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.
|
|
|
|
| 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
|
|
|
|
| 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
|
|
|
|
| 137 |
)
|
| 138 |
```
|
| 139 |
|
| 140 |
+
The MCP endpoint will be available at `/mcp-server/mcp/` of the resulting Starlette app.
|
| 141 |
|
| 142 |
<Warning>
|
| 143 |
For Streamable HTTP transport, you **must** pass the lifespan context from the FastMCP app to the resulting Starlette app, as nested lifespans are not recognized. Otherwise, the FastMCP server's session manager will not be properly initialized.
|
|
|
|
| 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.
|
|
|
|
| 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.
|
docs/deployment/running-server.mdx
CHANGED
|
@@ -105,7 +105,7 @@ When using Stdio transport, you will typically *not* run the server yourself as
|
|
| 105 |
|
| 106 |
Streamable HTTP is a modern, efficient transport for exposing your MCP server via HTTP. It is the recommended transport for web-based deployments.
|
| 107 |
|
| 108 |
-
To run a server using Streamable HTTP, you can use the `run()` method with the `transport` argument set to `"streamable-http"`. This will start a Uvicorn server on the default host (`127.0.0.1`), port (`8000`), and path (`/mcp`).
|
| 109 |
<CodeGroup>
|
| 110 |
```python {6} server.py
|
| 111 |
from fastmcp import FastMCP
|
|
@@ -120,7 +120,7 @@ import asyncio
|
|
| 120 |
from fastmcp import Client
|
| 121 |
|
| 122 |
async def example():
|
| 123 |
-
async with Client("http://127.0.0.1:8000/mcp") as client:
|
| 124 |
await client.ping()
|
| 125 |
|
| 126 |
if __name__ == "__main__":
|
|
@@ -168,7 +168,7 @@ New applications should use Streamable HTTP transport instead.
|
|
| 168 |
|
| 169 |
Server-Sent Events (SSE) is an HTTP-based protocol for server-to-client streaming. While FastMCP still supports SSE, it is deprecated and Streamable HTTP is preferred for new projects.
|
| 170 |
|
| 171 |
-
To run a server using SSE, you can use the `run()` method with the `transport` argument set to `"sse"`. This will start a Uvicorn server on the default host (`127.0.0.1`), port (`8000`), and with default SSE path (`/sse`) and message path (`/messages/`).
|
| 172 |
|
| 173 |
<CodeGroup>
|
| 174 |
```python {6} server.py
|
|
@@ -186,7 +186,7 @@ from fastmcp.client.transports import SSETransport
|
|
| 186 |
|
| 187 |
async def example():
|
| 188 |
async with Client(
|
| 189 |
-
transport=SSETransport("http://127.0.0.1:8000/sse")
|
| 190 |
) as client:
|
| 191 |
await client.ping()
|
| 192 |
|
|
|
|
| 105 |
|
| 106 |
Streamable HTTP is a modern, efficient transport for exposing your MCP server via HTTP. It is the recommended transport for web-based deployments.
|
| 107 |
|
| 108 |
+
To run a server using Streamable HTTP, you can use the `run()` method with the `transport` argument set to `"streamable-http"`. This will start a Uvicorn server on the default host (`127.0.0.1`), port (`8000`), and path (`/mcp/`).
|
| 109 |
<CodeGroup>
|
| 110 |
```python {6} server.py
|
| 111 |
from fastmcp import FastMCP
|
|
|
|
| 120 |
from fastmcp import Client
|
| 121 |
|
| 122 |
async def example():
|
| 123 |
+
async with Client("http://127.0.0.1:8000/mcp/") as client:
|
| 124 |
await client.ping()
|
| 125 |
|
| 126 |
if __name__ == "__main__":
|
|
|
|
| 168 |
|
| 169 |
Server-Sent Events (SSE) is an HTTP-based protocol for server-to-client streaming. While FastMCP still supports SSE, it is deprecated and Streamable HTTP is preferred for new projects.
|
| 170 |
|
| 171 |
+
To run a server using SSE, you can use the `run()` method with the `transport` argument set to `"sse"`. This will start a Uvicorn server on the default host (`127.0.0.1`), port (`8000`), and with default SSE path (`/sse/`) and message path (`/messages/`).
|
| 172 |
|
| 173 |
<CodeGroup>
|
| 174 |
```python {6} server.py
|
|
|
|
| 186 |
|
| 187 |
async def example():
|
| 188 |
async with Client(
|
| 189 |
+
transport=SSETransport("http://127.0.0.1:8000/sse/")
|
| 190 |
) as client:
|
| 191 |
await client.ping()
|
| 192 |
|
docs/docs.json
CHANGED
|
@@ -1,178 +1,296 @@
|
|
| 1 |
{
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6 |
},
|
| 7 |
-
"
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
"
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
"
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
},
|
| 46 |
-
"navigation": {
|
| 47 |
"anchors": [
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
|
| 132 |
-
"
|
| 133 |
-
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 139 |
"pages": [
|
| 140 |
-
|
| 141 |
-
|
| 142 |
-
|
|
|
|
| 143 |
]
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 151 |
"pages": [
|
| 152 |
-
|
|
|
|
|
|
|
|
|
|
| 153 |
]
|
| 154 |
-
|
| 155 |
-
|
| 156 |
-
"
|
| 157 |
-
"icon": "users",
|
| 158 |
"pages": [
|
| 159 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 160 |
]
|
| 161 |
-
|
|
|
|
|
|
|
| 162 |
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 163 |
},
|
| 164 |
-
|
| 165 |
-
|
| 166 |
-
|
| 167 |
-
|
| 168 |
-
|
| 169 |
-
|
| 170 |
-
|
| 171 |
-
|
| 172 |
-
|
| 173 |
-
|
| 174 |
-
"search": {
|
| 175 |
-
"prompt": "Search the docs..."
|
| 176 |
-
},
|
| 177 |
-
"theme": "mint"
|
| 178 |
-
}
|
|
|
|
| 1 |
{
|
| 2 |
+
"$schema": "https://mintlify.com/docs.json",
|
| 3 |
+
"appearance": {
|
| 4 |
+
"default": "system",
|
| 5 |
+
"strict": false
|
| 6 |
+
},
|
| 7 |
+
"background": {
|
| 8 |
+
"color": {
|
| 9 |
+
"dark": "#222831",
|
| 10 |
+
"light": "#EEEEEE"
|
| 11 |
},
|
| 12 |
+
"decoration": "windows"
|
| 13 |
+
},
|
| 14 |
+
"banner": {
|
| 15 |
+
"content": "[FastMCP Cloud](https://fastmcp.link/x0Kyhy2) is coming!"
|
| 16 |
+
},
|
| 17 |
+
"colors": {
|
| 18 |
+
"dark": "#f72585",
|
| 19 |
+
"light": "#4cc9f0",
|
| 20 |
+
"primary": "#2d00f7"
|
| 21 |
+
},
|
| 22 |
+
"description": "The fast, Pythonic way to build MCP servers and clients.",
|
| 23 |
+
"favicon": {
|
| 24 |
+
"dark": "/assets/favicon.ico",
|
| 25 |
+
"light": "/assets/favicon.ico"
|
| 26 |
+
},
|
| 27 |
+
"footer": {
|
| 28 |
+
"socials": {
|
| 29 |
+
"bluesky": "https://bsky.app/profile/jlowin.dev",
|
| 30 |
+
"github": "https://github.com/jlowin/fastmcp",
|
| 31 |
+
"x": "https://x.com/jlowin"
|
| 32 |
+
}
|
| 33 |
+
},
|
| 34 |
+
"integrations": {
|
| 35 |
+
"ga4": {
|
| 36 |
+
"measurementId": "G-64R5W1TJXG"
|
| 37 |
+
}
|
| 38 |
+
},
|
| 39 |
+
"name": "FastMCP",
|
| 40 |
+
"navbar": {
|
| 41 |
+
"primary": {
|
| 42 |
+
"href": "https://github.com/jlowin/fastmcp",
|
| 43 |
+
"type": "github"
|
| 44 |
+
}
|
| 45 |
+
},
|
| 46 |
+
"navigation": {
|
| 47 |
+
"tabs": [
|
| 48 |
+
{
|
| 49 |
+
"tab": "Documentation",
|
|
|
|
|
|
|
| 50 |
"anchors": [
|
| 51 |
+
{
|
| 52 |
+
"anchor": "Documentation",
|
| 53 |
+
"groups": [
|
| 54 |
+
{
|
| 55 |
+
"group": "Get Started",
|
| 56 |
+
"pages": [
|
| 57 |
+
"getting-started/welcome",
|
| 58 |
+
"getting-started/installation",
|
| 59 |
+
"getting-started/quickstart"
|
| 60 |
+
]
|
| 61 |
+
},
|
| 62 |
+
{
|
| 63 |
+
"group": "Servers",
|
| 64 |
+
"pages": [
|
| 65 |
+
"servers/server",
|
| 66 |
+
{
|
| 67 |
+
"group": "Core Components",
|
| 68 |
+
"icon": "toolbox",
|
| 69 |
+
"pages": [
|
| 70 |
+
"servers/tools",
|
| 71 |
+
"servers/resources",
|
| 72 |
+
"servers/prompts",
|
| 73 |
+
"servers/context"
|
| 74 |
+
]
|
| 75 |
+
},
|
| 76 |
+
{
|
| 77 |
+
"group": "Authentication",
|
| 78 |
+
"icon": "shield-check",
|
| 79 |
+
"pages": ["servers/auth/bearer"]
|
| 80 |
+
},
|
| 81 |
+
"servers/middleware",
|
| 82 |
+
"servers/openapi",
|
| 83 |
+
"servers/proxy",
|
| 84 |
+
"servers/composition",
|
| 85 |
+
{
|
| 86 |
+
"group": "Deployment",
|
| 87 |
+
"icon": "upload",
|
| 88 |
+
"pages": ["deployment/running-server", "deployment/asgi"]
|
| 89 |
+
}
|
| 90 |
+
]
|
| 91 |
+
},
|
| 92 |
+
{
|
| 93 |
+
"group": "Clients",
|
| 94 |
+
"pages": [
|
| 95 |
+
"clients/client",
|
| 96 |
+
{
|
| 97 |
+
"group": "Core Operations",
|
| 98 |
+
"icon": "handshake",
|
| 99 |
+
"pages": [
|
| 100 |
+
"clients/tools",
|
| 101 |
+
"clients/resources",
|
| 102 |
+
"clients/prompts"
|
| 103 |
+
]
|
| 104 |
+
},
|
| 105 |
+
{
|
| 106 |
+
"group": "Advanced Features",
|
| 107 |
+
"icon": "stars",
|
| 108 |
+
"pages": [
|
| 109 |
+
"clients/logging",
|
| 110 |
+
"clients/progress",
|
| 111 |
+
"clients/sampling",
|
| 112 |
+
"clients/roots"
|
| 113 |
+
]
|
| 114 |
+
},
|
| 115 |
+
"clients/transports",
|
| 116 |
+
{
|
| 117 |
+
"group": "Authentication",
|
| 118 |
+
"icon": "user-shield",
|
| 119 |
+
"pages": ["clients/auth/oauth", "clients/auth/bearer"]
|
| 120 |
+
}
|
| 121 |
+
]
|
| 122 |
+
},
|
| 123 |
+
{
|
| 124 |
+
"group": "Integrations",
|
| 125 |
+
"pages": [
|
| 126 |
+
"integrations/anthropic",
|
| 127 |
+
"integrations/claude-desktop",
|
| 128 |
+
"integrations/openai",
|
| 129 |
+
"integrations/gemini",
|
| 130 |
+
"integrations/contrib"
|
| 131 |
+
]
|
| 132 |
+
},
|
| 133 |
+
{
|
| 134 |
+
"group": "Patterns",
|
| 135 |
+
"pages": [
|
| 136 |
+
"patterns/tool-transformation",
|
| 137 |
+
"patterns/decorating-methods",
|
| 138 |
+
"patterns/http-requests",
|
| 139 |
+
"patterns/testing",
|
| 140 |
+
"patterns/cli"
|
| 141 |
+
]
|
| 142 |
+
},
|
| 143 |
+
{
|
| 144 |
+
"group": "Tutorials",
|
| 145 |
+
"pages": [
|
| 146 |
+
"tutorials/mcp",
|
| 147 |
+
"tutorials/create-mcp-server",
|
| 148 |
+
"tutorials/rest-api"
|
| 149 |
+
]
|
| 150 |
+
}
|
| 151 |
+
],
|
| 152 |
+
"icon": "book"
|
| 153 |
+
},
|
| 154 |
+
{
|
| 155 |
+
"anchor": "What's New",
|
| 156 |
+
"pages": ["updates", "changelog"]
|
| 157 |
+
},
|
| 158 |
+
|
| 159 |
+
{
|
| 160 |
+
"anchor": "Community",
|
| 161 |
+
"icon": "users",
|
| 162 |
+
"pages": ["community/showcase"]
|
| 163 |
+
}
|
| 164 |
+
]
|
| 165 |
+
},
|
| 166 |
+
{
|
| 167 |
+
"tab": "SDK Reference",
|
| 168 |
+
"anchors": [
|
| 169 |
+
{
|
| 170 |
+
"anchor": "Python SDK",
|
| 171 |
+
"icon": "python",
|
| 172 |
+
"pages": [
|
| 173 |
+
"python-sdk/fastmcp-exceptions",
|
| 174 |
+
"python-sdk/fastmcp-settings",
|
| 175 |
+
{
|
| 176 |
+
"group": "fastmcp.cli",
|
| 177 |
+
"pages": [
|
| 178 |
+
"python-sdk/fastmcp-cli-__init__",
|
| 179 |
+
"python-sdk/fastmcp-cli-claude",
|
| 180 |
+
"python-sdk/fastmcp-cli-cli",
|
| 181 |
+
"python-sdk/fastmcp-cli-run"
|
| 182 |
+
]
|
| 183 |
+
},
|
| 184 |
+
{
|
| 185 |
+
"group": "fastmcp.client",
|
| 186 |
+
"pages": [
|
| 187 |
+
"python-sdk/fastmcp-client-__init__",
|
| 188 |
+
{
|
| 189 |
+
"group": "auth",
|
| 190 |
+
"pages": [
|
| 191 |
+
"python-sdk/fastmcp-client-auth-__init__",
|
| 192 |
+
"python-sdk/fastmcp-client-auth-bearer",
|
| 193 |
+
"python-sdk/fastmcp-client-auth-oauth"
|
| 194 |
+
]
|
| 195 |
+
},
|
| 196 |
+
"python-sdk/fastmcp-client-client",
|
| 197 |
+
"python-sdk/fastmcp-client-logging",
|
| 198 |
+
"python-sdk/fastmcp-client-oauth_callback",
|
| 199 |
+
"python-sdk/fastmcp-client-progress",
|
| 200 |
+
"python-sdk/fastmcp-client-roots",
|
| 201 |
+
"python-sdk/fastmcp-client-sampling",
|
| 202 |
+
"python-sdk/fastmcp-client-transports"
|
| 203 |
+
]
|
| 204 |
+
},
|
| 205 |
+
{
|
| 206 |
+
"group": "fastmcp.prompts",
|
| 207 |
+
"pages": [
|
| 208 |
+
"python-sdk/fastmcp-prompts-__init__",
|
| 209 |
+
"python-sdk/fastmcp-prompts-prompt",
|
| 210 |
+
"python-sdk/fastmcp-prompts-prompt_manager"
|
| 211 |
+
]
|
| 212 |
+
},
|
| 213 |
+
{
|
| 214 |
+
"group": "fastmcp.resources",
|
| 215 |
+
"pages": [
|
| 216 |
+
"python-sdk/fastmcp-resources-__init__",
|
| 217 |
+
"python-sdk/fastmcp-resources-resource",
|
| 218 |
+
"python-sdk/fastmcp-resources-resource_manager",
|
| 219 |
+
"python-sdk/fastmcp-resources-template",
|
| 220 |
+
"python-sdk/fastmcp-resources-types"
|
| 221 |
+
]
|
| 222 |
+
},
|
| 223 |
+
{
|
| 224 |
+
"group": "fastmcp.server",
|
| 225 |
+
"pages": [
|
| 226 |
+
"python-sdk/fastmcp-server-__init__",
|
| 227 |
+
{
|
| 228 |
+
"group": "auth",
|
| 229 |
+
"pages": [
|
| 230 |
+
"python-sdk/fastmcp-server-auth-__init__",
|
| 231 |
+
"python-sdk/fastmcp-server-auth-auth",
|
| 232 |
+
{
|
| 233 |
+
"group": "providers",
|
| 234 |
"pages": [
|
| 235 |
+
"python-sdk/fastmcp-server-auth-providers-__init__",
|
| 236 |
+
"python-sdk/fastmcp-server-auth-providers-bearer",
|
| 237 |
+
"python-sdk/fastmcp-server-auth-providers-bearer_env",
|
| 238 |
+
"python-sdk/fastmcp-server-auth-providers-in_memory"
|
| 239 |
]
|
| 240 |
+
}
|
| 241 |
+
]
|
| 242 |
+
},
|
| 243 |
+
"python-sdk/fastmcp-server-context",
|
| 244 |
+
"python-sdk/fastmcp-server-dependencies",
|
| 245 |
+
"python-sdk/fastmcp-server-http",
|
| 246 |
+
"python-sdk/fastmcp-server-middleware",
|
| 247 |
+
"python-sdk/fastmcp-server-openapi",
|
| 248 |
+
"python-sdk/fastmcp-server-proxy",
|
| 249 |
+
"python-sdk/fastmcp-server-server"
|
| 250 |
+
]
|
| 251 |
+
},
|
| 252 |
+
{
|
| 253 |
+
"group": "fastmcp.tools",
|
| 254 |
"pages": [
|
| 255 |
+
"python-sdk/fastmcp-tools-__init__",
|
| 256 |
+
"python-sdk/fastmcp-tools-tool",
|
| 257 |
+
"python-sdk/fastmcp-tools-tool_manager",
|
| 258 |
+
"python-sdk/fastmcp-tools-tool_transform"
|
| 259 |
]
|
| 260 |
+
},
|
| 261 |
+
{
|
| 262 |
+
"group": "fastmcp.utilities",
|
|
|
|
| 263 |
"pages": [
|
| 264 |
+
"python-sdk/fastmcp-utilities-__init__",
|
| 265 |
+
"python-sdk/fastmcp-utilities-cache",
|
| 266 |
+
"python-sdk/fastmcp-utilities-components",
|
| 267 |
+
"python-sdk/fastmcp-utilities-exceptions",
|
| 268 |
+
"python-sdk/fastmcp-utilities-http",
|
| 269 |
+
"python-sdk/fastmcp-utilities-json_schema",
|
| 270 |
+
"python-sdk/fastmcp-utilities-logging",
|
| 271 |
+
"python-sdk/fastmcp-utilities-mcp_config",
|
| 272 |
+
"python-sdk/fastmcp-utilities-openapi",
|
| 273 |
+
"python-sdk/fastmcp-utilities-types"
|
| 274 |
]
|
| 275 |
+
}
|
| 276 |
+
]
|
| 277 |
+
}
|
| 278 |
]
|
| 279 |
+
}
|
| 280 |
+
]
|
| 281 |
+
},
|
| 282 |
+
"redirects": [
|
| 283 |
+
{
|
| 284 |
+
"destination": "/servers/proxy",
|
| 285 |
+
"source": "/patterns/proxy"
|
| 286 |
},
|
| 287 |
+
{
|
| 288 |
+
"destination": "/servers/composition",
|
| 289 |
+
"source": "/patterns/composition"
|
| 290 |
+
}
|
| 291 |
+
],
|
| 292 |
+
"search": {
|
| 293 |
+
"prompt": "Search the docs..."
|
| 294 |
+
},
|
| 295 |
+
"theme": "mint"
|
| 296 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/integrations/anthropic.mdx
CHANGED
|
@@ -3,7 +3,7 @@ title: Anthropic API + FastMCP
|
|
| 3 |
sidebarTitle: Anthropic API
|
| 4 |
description: Call FastMCP servers from the Anthropic API
|
| 5 |
icon: message-smile
|
| 6 |
-
tag:
|
| 7 |
---
|
| 8 |
|
| 9 |
import { VersionBadge } from "/snippets/version-badge.mdx"
|
|
|
|
| 3 |
sidebarTitle: Anthropic API
|
| 4 |
description: Call FastMCP servers from the Anthropic API
|
| 5 |
icon: message-smile
|
| 6 |
+
tag: NEW
|
| 7 |
---
|
| 8 |
|
| 9 |
import { VersionBadge } from "/snippets/version-badge.mdx"
|
docs/integrations/gemini.mdx
CHANGED
|
@@ -3,7 +3,7 @@ title: Gemini SDK + FastMCP
|
|
| 3 |
sidebarTitle: Gemini SDK
|
| 4 |
description: Call FastMCP servers from the Google Gemini SDK
|
| 5 |
icon: message-smile
|
| 6 |
-
tag:
|
| 7 |
---
|
| 8 |
|
| 9 |
import { VersionBadge } from "/snippets/version-badge.mdx"
|
|
|
|
| 3 |
sidebarTitle: Gemini SDK
|
| 4 |
description: Call FastMCP servers from the Google Gemini SDK
|
| 5 |
icon: message-smile
|
| 6 |
+
tag: NEW
|
| 7 |
---
|
| 8 |
|
| 9 |
import { VersionBadge } from "/snippets/version-badge.mdx"
|
docs/integrations/openai.mdx
CHANGED
|
@@ -3,7 +3,7 @@ title: OpenAI API + FastMCP
|
|
| 3 |
sidebarTitle: OpenAI API
|
| 4 |
description: Call FastMCP servers from the OpenAI API
|
| 5 |
icon: message-smile
|
| 6 |
-
tag:
|
| 7 |
---
|
| 8 |
|
| 9 |
import { VersionBadge } from "/snippets/version-badge.mdx"
|
|
|
|
| 3 |
sidebarTitle: OpenAI API
|
| 4 |
description: Call FastMCP servers from the OpenAI API
|
| 5 |
icon: message-smile
|
| 6 |
+
tag: NEW
|
| 7 |
---
|
| 8 |
|
| 9 |
import { VersionBadge } from "/snippets/version-badge.mdx"
|
docs/patterns/cli.mdx
CHANGED
|
@@ -21,6 +21,7 @@ fastmcp --help
|
|
| 21 |
| `run` | Run a FastMCP server directly | Uses your current environment; you are responsible for ensuring all dependencies are available |
|
| 22 |
| `dev` | Run a server with the MCP Inspector for testing | Creates an isolated environment; dependencies must be explicitly specified with `--with` and/or `--with-editable` |
|
| 23 |
| `install` | Install a server in the Claude desktop app | Creates an isolated environment; dependencies must be explicitly specified with `--with` and/or `--with-editable` |
|
|
|
|
| 24 |
| `version` | Display version information | N/A |
|
| 25 |
|
| 26 |
## Command Details
|
|
@@ -179,6 +180,29 @@ fastmcp install server.py:my_server
|
|
| 179 |
fastmcp install server.py:my_server -n "My Analysis Server" --with pandas
|
| 180 |
```
|
| 181 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 182 |
### `version`
|
| 183 |
|
| 184 |
Display version information about FastMCP and related components.
|
|
|
|
| 21 |
| `run` | Run a FastMCP server directly | Uses your current environment; you are responsible for ensuring all dependencies are available |
|
| 22 |
| `dev` | Run a server with the MCP Inspector for testing | Creates an isolated environment; dependencies must be explicitly specified with `--with` and/or `--with-editable` |
|
| 23 |
| `install` | Install a server in the Claude desktop app | Creates an isolated environment; dependencies must be explicitly specified with `--with` and/or `--with-editable` |
|
| 24 |
+
| `inspect` | Generate a JSON report about a FastMCP server | Uses your current environment; you are responsible for ensuring all dependencies are available |
|
| 25 |
| `version` | Display version information | N/A |
|
| 26 |
|
| 27 |
## Command Details
|
|
|
|
| 180 |
fastmcp install server.py:my_server -n "My Analysis Server" --with pandas
|
| 181 |
```
|
| 182 |
|
| 183 |
+
### `inspect`
|
| 184 |
+
|
| 185 |
+
<VersionBadge version="2.9.0" />
|
| 186 |
+
|
| 187 |
+
Generate a detailed JSON report about a FastMCP server, including information about its tools, prompts, resources, and capabilities.
|
| 188 |
+
|
| 189 |
+
```bash
|
| 190 |
+
fastmcp inspect server.py
|
| 191 |
+
```
|
| 192 |
+
|
| 193 |
+
The command supports the same server specification format as `run` and `install`:
|
| 194 |
+
|
| 195 |
+
```bash
|
| 196 |
+
# Auto-detect server object
|
| 197 |
+
fastmcp inspect server.py
|
| 198 |
+
|
| 199 |
+
# Specify server object
|
| 200 |
+
fastmcp inspect server.py:my_server
|
| 201 |
+
|
| 202 |
+
# Custom output location
|
| 203 |
+
fastmcp inspect server.py --output analysis.json
|
| 204 |
+
```
|
| 205 |
+
|
| 206 |
### `version`
|
| 207 |
|
| 208 |
Display version information about FastMCP and related components.
|
docs/python-sdk/fastmcp-cli-__init__.mdx
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: __init__
|
| 3 |
+
sidebarTitle: __init__
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
# `fastmcp.cli`
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
FastMCP CLI package.
|
docs/python-sdk/fastmcp-cli-claude.mdx
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: claude
|
| 3 |
+
sidebarTitle: claude
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
# `fastmcp.cli.claude`
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
Claude app integration utilities.
|
| 10 |
+
|
| 11 |
+
## Functions
|
| 12 |
+
|
| 13 |
+
### `get_claude_config_path`
|
| 14 |
+
|
| 15 |
+
```python
|
| 16 |
+
get_claude_config_path() -> Path | None
|
| 17 |
+
```
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
Get the Claude config directory based on platform.
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
### `update_claude_config`
|
| 24 |
+
|
| 25 |
+
```python
|
| 26 |
+
update_claude_config(file_spec: str, server_name: str) -> bool
|
| 27 |
+
```
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
Add or update a FastMCP server in Claude's configuration.
|
| 31 |
+
|
| 32 |
+
**Args:**
|
| 33 |
+
- `file_spec`: Path to the server file, optionally with \:object suffix
|
| 34 |
+
- `server_name`: Name for the server in Claude's config
|
| 35 |
+
- `with_editable`: Optional directory to install in editable mode
|
| 36 |
+
- `with_packages`: Optional list of additional packages to install
|
| 37 |
+
- `env_vars`: Optional dictionary of environment variables. These are merged with
|
| 38 |
+
any existing variables, with new values taking precedence.
|
| 39 |
+
|
| 40 |
+
**Raises:**
|
| 41 |
+
- `RuntimeError`: If Claude Desktop's config directory is not found, indicating
|
| 42 |
+
Claude Desktop may not be installed or properly set up.
|
| 43 |
+
|
docs/python-sdk/fastmcp-cli-cli.mdx
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: cli
|
| 3 |
+
sidebarTitle: cli
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
# `fastmcp.cli.cli`
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
FastMCP CLI tools.
|
| 10 |
+
|
| 11 |
+
## Functions
|
| 12 |
+
|
| 13 |
+
### `version`
|
| 14 |
+
|
| 15 |
+
```python
|
| 16 |
+
version(ctx: Context)
|
| 17 |
+
```
|
| 18 |
+
|
| 19 |
+
### `dev`
|
| 20 |
+
|
| 21 |
+
```python
|
| 22 |
+
dev(server_spec: str = typer.Argument(..., help='Python file to run, optionally with :object suffix'), with_editable: Annotated[Path | None, typer.Option('--with-editable', '-e', help='Directory containing pyproject.toml to install in editable mode', exists=True, file_okay=False, resolve_path=True)] = None, with_packages: Annotated[list[str], typer.Option('--with', help='Additional packages to install')] = [], inspector_version: Annotated[str | None, typer.Option('--inspector-version', help='Version of the MCP Inspector to use')] = None, ui_port: Annotated[int | None, typer.Option('--ui-port', help='Port for the MCP Inspector UI')] = None, server_port: Annotated[int | None, typer.Option('--server-port', help='Port for the MCP Inspector Proxy server')] = None) -> None
|
| 23 |
+
```
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
Run a MCP server with the MCP Inspector.
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
### `run`
|
| 30 |
+
|
| 31 |
+
```python
|
| 32 |
+
run(ctx: typer.Context, server_spec: str = typer.Argument(..., help='Python file, object specification (file:obj), or URL'), transport: Annotated[str | None, typer.Option('--transport', '-t', help='Transport protocol to use (stdio, streamable-http, or sse)')] = None, host: Annotated[str | None, typer.Option('--host', help='Host to bind to when using http transport (default: 127.0.0.1)')] = None, port: Annotated[int | None, typer.Option('--port', '-p', help='Port to bind to when using http transport (default: 8000)')] = None, log_level: Annotated[str | None, typer.Option('--log-level', '-l', help='Log level (DEBUG, INFO, WARNING, ERROR, CRITICAL)')] = None) -> None
|
| 33 |
+
```
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
Run a MCP server or connect to a remote one.
|
| 37 |
+
|
| 38 |
+
The server can be specified in three ways:
|
| 39 |
+
1. Module approach: server.py - runs the module directly, looking for an object named mcp/server/app.
|
| 40 |
+
|
| 41 |
+
2. Import approach: server.py:app - imports and runs the specified server object.
|
| 42 |
+
|
| 43 |
+
3. URL approach: http://server-url - connects to a remote server and creates a proxy.
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
Note: This command runs the server directly. You are responsible for ensuring
|
| 48 |
+
all dependencies are available.
|
| 49 |
+
|
| 50 |
+
Server arguments can be passed after -- :
|
| 51 |
+
fastmcp run server.py -- --config config.json --debug
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
### `install`
|
| 55 |
+
|
| 56 |
+
```python
|
| 57 |
+
install(server_spec: str = typer.Argument(..., help='Python file to run, optionally with :object suffix'), server_name: Annotated[str | None, typer.Option('--name', '-n', help="Custom name for the server (defaults to server's name attribute or file name)")] = None, with_editable: Annotated[Path | None, typer.Option('--with-editable', '-e', help='Directory containing pyproject.toml to install in editable mode', exists=True, file_okay=False, resolve_path=True)] = None, with_packages: Annotated[list[str], typer.Option('--with', help='Additional packages to install')] = [], env_vars: Annotated[list[str], typer.Option('--env-var', '-v', help='Environment variables in KEY=VALUE format')] = [], env_file: Annotated[Path | None, typer.Option('--env-file', '-f', help='Load environment variables from a .env file', exists=True, file_okay=True, dir_okay=False, resolve_path=True)] = None) -> None
|
| 58 |
+
```
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
Install a MCP server in the Claude desktop app.
|
| 62 |
+
|
| 63 |
+
Environment variables are preserved once added and only updated if new values
|
| 64 |
+
are explicitly provided.
|
| 65 |
+
|
docs/python-sdk/fastmcp-cli-run.mdx
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: run
|
| 3 |
+
sidebarTitle: run
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
# `fastmcp.cli.run`
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
FastMCP run command implementation.
|
| 10 |
+
|
| 11 |
+
## Functions
|
| 12 |
+
|
| 13 |
+
### `is_url`
|
| 14 |
+
|
| 15 |
+
```python
|
| 16 |
+
is_url(path: str) -> bool
|
| 17 |
+
```
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
Check if a string is a URL.
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
### `parse_file_path`
|
| 24 |
+
|
| 25 |
+
```python
|
| 26 |
+
parse_file_path(server_spec: str) -> tuple[Path, str | None]
|
| 27 |
+
```
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
Parse a file path that may include a server object specification.
|
| 31 |
+
|
| 32 |
+
**Args:**
|
| 33 |
+
- `server_spec`: Path to file, optionally with \:object suffix
|
| 34 |
+
|
| 35 |
+
**Returns:**
|
| 36 |
+
- Tuple of (file_path, server_object)
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
### `import_server`
|
| 40 |
+
|
| 41 |
+
```python
|
| 42 |
+
import_server(file: Path, server_object: str | None = None) -> Any
|
| 43 |
+
```
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
Import a MCP server from a file.
|
| 47 |
+
|
| 48 |
+
**Args:**
|
| 49 |
+
- `file`: Path to the file
|
| 50 |
+
- `server_object`: Optional object name in format "module\:object" or just "object"
|
| 51 |
+
|
| 52 |
+
**Returns:**
|
| 53 |
+
- The server object
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
### `create_client_server`
|
| 57 |
+
|
| 58 |
+
```python
|
| 59 |
+
create_client_server(url: str) -> Any
|
| 60 |
+
```
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
Create a FastMCP server from a client URL.
|
| 64 |
+
|
| 65 |
+
**Args:**
|
| 66 |
+
- `url`: The URL to connect to
|
| 67 |
+
|
| 68 |
+
**Returns:**
|
| 69 |
+
- A FastMCP server instance
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
### `import_server_with_args`
|
| 73 |
+
|
| 74 |
+
```python
|
| 75 |
+
import_server_with_args(file: Path, server_object: str | None = None, server_args: list[str] | None = None) -> Any
|
| 76 |
+
```
|
| 77 |
+
|
| 78 |
+
|
| 79 |
+
Import a server with optional command line arguments.
|
| 80 |
+
|
| 81 |
+
**Args:**
|
| 82 |
+
- `file`: Path to the server file
|
| 83 |
+
- `server_object`: Optional server object name
|
| 84 |
+
- `server_args`: Optional command line arguments to inject
|
| 85 |
+
|
| 86 |
+
**Returns:**
|
| 87 |
+
- The imported server object
|
| 88 |
+
|
| 89 |
+
|
| 90 |
+
### `run_command`
|
| 91 |
+
|
| 92 |
+
```python
|
| 93 |
+
run_command(server_spec: str, transport: str | None = None, host: str | None = None, port: int | None = None, log_level: str | None = None, server_args: list[str] | None = None) -> None
|
| 94 |
+
```
|
| 95 |
+
|
| 96 |
+
|
| 97 |
+
Run a MCP server or connect to a remote one.
|
| 98 |
+
|
| 99 |
+
**Args:**
|
| 100 |
+
- `server_spec`: Python file, object specification (file\:obj), or URL
|
| 101 |
+
- `transport`: Transport protocol to use
|
| 102 |
+
- `host`: Host to bind to when using http transport
|
| 103 |
+
- `port`: Port to bind to when using http transport
|
| 104 |
+
- `log_level`: Log level
|
| 105 |
+
- `server_args`: Additional arguments to pass to the server
|
| 106 |
+
|
docs/python-sdk/fastmcp-client-__init__.mdx
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: __init__
|
| 3 |
+
sidebarTitle: __init__
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
# `fastmcp.client`
|
| 7 |
+
|
| 8 |
+
*This module is empty or contains only private/internal implementations.*
|
docs/python-sdk/fastmcp-client-auth-__init__.mdx
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: __init__
|
| 3 |
+
sidebarTitle: __init__
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
# `fastmcp.client.auth`
|
| 7 |
+
|
| 8 |
+
*This module is empty or contains only private/internal implementations.*
|
docs/python-sdk/fastmcp-client-auth-bearer.mdx
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: bearer
|
| 3 |
+
sidebarTitle: bearer
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
# `fastmcp.client.auth.bearer`
|
| 7 |
+
|
| 8 |
+
## Classes
|
| 9 |
+
|
| 10 |
+
### `BearerAuth`
|
| 11 |
+
|
| 12 |
+
**Methods:**
|
| 13 |
+
|
| 14 |
+
#### `auth_flow`
|
| 15 |
+
|
| 16 |
+
```python
|
| 17 |
+
auth_flow(self, request)
|
| 18 |
+
```
|
docs/python-sdk/fastmcp-client-auth-oauth.mdx
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: oauth
|
| 3 |
+
sidebarTitle: oauth
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
# `fastmcp.client.auth.oauth`
|
| 7 |
+
|
| 8 |
+
## Functions
|
| 9 |
+
|
| 10 |
+
### `default_cache_dir`
|
| 11 |
+
|
| 12 |
+
```python
|
| 13 |
+
default_cache_dir() -> Path
|
| 14 |
+
```
|
| 15 |
+
|
| 16 |
+
### `OAuth`
|
| 17 |
+
|
| 18 |
+
```python
|
| 19 |
+
OAuth(mcp_url: str, scopes: str | list[str] | None = None, client_name: str = 'FastMCP Client', token_storage_cache_dir: Path | None = None, additional_client_metadata: dict[str, Any] | None = None) -> _MCPOAuthClientProvider
|
| 20 |
+
```
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
Create an OAuthClientProvider for an MCP server.
|
| 24 |
+
|
| 25 |
+
This is intended to be provided to the `auth` parameter of an
|
| 26 |
+
httpx.AsyncClient (or appropriate FastMCP client/transport instance)
|
| 27 |
+
|
| 28 |
+
**Args:**
|
| 29 |
+
- `mcp_url`: Full URL to the MCP endpoint (e.g. "http\://host/mcp/sse/")
|
| 30 |
+
- `scopes`: OAuth scopes to request. Can be a
|
| 31 |
+
- `client_name`: Name for this client during registration
|
| 32 |
+
- `token_storage_cache_dir`: Directory for FileTokenStorage
|
| 33 |
+
- `additional_client_metadata`: Extra fields for OAuthClientMetadata
|
| 34 |
+
|
| 35 |
+
**Returns:**
|
| 36 |
+
- OAuthClientProvider
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
## Classes
|
| 40 |
+
|
| 41 |
+
### `ServerOAuthMetadata`
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
More flexible OAuth metadata model that accepts broader ranges of values
|
| 45 |
+
than the restrictive MCP standard model.
|
| 46 |
+
|
| 47 |
+
This handles real-world OAuth servers like PayPal that may support
|
| 48 |
+
additional methods not in the MCP specification.
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
### `OAuthClientProvider`
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
OAuth client provider with more flexible OAuth metadata discovery.
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
### `FileTokenStorage`
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
File-based token storage implementation for OAuth credentials and tokens.
|
| 61 |
+
Implements the mcp.client.auth.TokenStorage protocol.
|
| 62 |
+
|
| 63 |
+
Each instance is tied to a specific server URL for proper token isolation.
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
**Methods:**
|
| 67 |
+
|
| 68 |
+
#### `get_base_url`
|
| 69 |
+
|
| 70 |
+
```python
|
| 71 |
+
get_base_url(url: str) -> str
|
| 72 |
+
```
|
| 73 |
+
|
| 74 |
+
Extract the base URL (scheme + host) from a URL.
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
#### `get_cache_key`
|
| 78 |
+
|
| 79 |
+
```python
|
| 80 |
+
get_cache_key(self) -> str
|
| 81 |
+
```
|
| 82 |
+
|
| 83 |
+
Generate a safe filesystem key from the server's base URL.
|
| 84 |
+
|
| 85 |
+
|
| 86 |
+
#### `clear`
|
| 87 |
+
|
| 88 |
+
```python
|
| 89 |
+
clear(self) -> None
|
| 90 |
+
```
|
| 91 |
+
|
| 92 |
+
Clear all cached data for this server.
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
#### `clear_all`
|
| 96 |
+
|
| 97 |
+
```python
|
| 98 |
+
clear_all(cls, cache_dir: Path | None = None) -> None
|
| 99 |
+
```
|
| 100 |
+
|
| 101 |
+
Clear all cached data for all servers.
|
| 102 |
+
|
docs/python-sdk/fastmcp-client-client.mdx
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: client
|
| 3 |
+
sidebarTitle: client
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
# `fastmcp.client.client`
|
| 7 |
+
|
| 8 |
+
## Classes
|
| 9 |
+
|
| 10 |
+
### `Client`
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
MCP client that delegates connection management to a Transport instance.
|
| 15 |
+
|
| 16 |
+
The Client class is responsible for MCP protocol logic, while the Transport
|
| 17 |
+
handles connection establishment and management. Client provides methods for
|
| 18 |
+
working with resources, prompts, tools and other MCP capabilities.
|
| 19 |
+
|
| 20 |
+
Args:
|
| 21 |
+
transport: Connection source specification, which can be:
|
| 22 |
+
- ClientTransport: Direct transport instance
|
| 23 |
+
- FastMCP: In-process FastMCP server
|
| 24 |
+
- AnyUrl | str: URL to connect to
|
| 25 |
+
- Path: File path for local socket
|
| 26 |
+
- MCPConfig: MCP server configuration
|
| 27 |
+
- dict: Transport configuration
|
| 28 |
+
roots: Optional RootsList or RootsHandler for filesystem access
|
| 29 |
+
sampling_handler: Optional handler for sampling requests
|
| 30 |
+
log_handler: Optional handler for log messages
|
| 31 |
+
message_handler: Optional handler for protocol messages
|
| 32 |
+
progress_handler: Optional handler for progress notifications
|
| 33 |
+
timeout: Optional timeout for requests (seconds or timedelta)
|
| 34 |
+
init_timeout: Optional timeout for initial connection (seconds or timedelta).
|
| 35 |
+
Set to 0 to disable. If None, uses the value in the FastMCP global settings.
|
| 36 |
+
|
| 37 |
+
Examples:
|
| 38 |
+
```python # Connect to FastMCP server client =
|
| 39 |
+
Client("http://localhost:8080")
|
| 40 |
+
|
| 41 |
+
async with client:
|
| 42 |
+
# List available resources resources = await client.list_resources()
|
| 43 |
+
|
| 44 |
+
# Call a tool result = await client.call_tool("my_tool", {"param":
|
| 45 |
+
"value"})
|
| 46 |
+
```
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
**Methods:**
|
| 50 |
+
|
| 51 |
+
#### `session`
|
| 52 |
+
|
| 53 |
+
```python
|
| 54 |
+
session(self) -> ClientSession
|
| 55 |
+
```
|
| 56 |
+
|
| 57 |
+
Get the current active session. Raises RuntimeError if not connected.
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
#### `initialize_result`
|
| 61 |
+
|
| 62 |
+
```python
|
| 63 |
+
initialize_result(self) -> mcp.types.InitializeResult
|
| 64 |
+
```
|
| 65 |
+
|
| 66 |
+
Get the result of the initialization request.
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
#### `set_roots`
|
| 70 |
+
|
| 71 |
+
```python
|
| 72 |
+
set_roots(self, roots: RootsList | RootsHandler) -> None
|
| 73 |
+
```
|
| 74 |
+
|
| 75 |
+
Set the roots for the client. This does not automatically call `send_roots_list_changed`.
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
#### `set_sampling_callback`
|
| 79 |
+
|
| 80 |
+
```python
|
| 81 |
+
set_sampling_callback(self, sampling_callback: SamplingHandler) -> None
|
| 82 |
+
```
|
| 83 |
+
|
| 84 |
+
Set the sampling callback for the client.
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
#### `is_connected`
|
| 88 |
+
|
| 89 |
+
```python
|
| 90 |
+
is_connected(self) -> bool
|
| 91 |
+
```
|
| 92 |
+
|
| 93 |
+
Check if the client is currently connected.
|
| 94 |
+
|
docs/python-sdk/fastmcp-client-logging.mdx
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: logging
|
| 3 |
+
sidebarTitle: logging
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
# `fastmcp.client.logging`
|
| 7 |
+
|
| 8 |
+
## Functions
|
| 9 |
+
|
| 10 |
+
### `create_log_callback`
|
| 11 |
+
|
| 12 |
+
```python
|
| 13 |
+
create_log_callback(handler: LogHandler | None = None) -> LoggingFnT
|
| 14 |
+
```
|
docs/python-sdk/fastmcp-client-oauth_callback.mdx
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: oauth_callback
|
| 3 |
+
sidebarTitle: oauth_callback
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
# `fastmcp.client.oauth_callback`
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
OAuth callback server for handling authorization code flows.
|
| 11 |
+
|
| 12 |
+
This module provides a reusable callback server that can handle OAuth redirects
|
| 13 |
+
and display styled responses to users.
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
## Functions
|
| 17 |
+
|
| 18 |
+
### `create_callback_html`
|
| 19 |
+
|
| 20 |
+
```python
|
| 21 |
+
create_callback_html(message: str, is_success: bool = True, title: str = 'FastMCP OAuth', server_url: str | None = None) -> str
|
| 22 |
+
```
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
Create a styled HTML response for OAuth callbacks.
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
### `create_oauth_callback_server`
|
| 29 |
+
|
| 30 |
+
```python
|
| 31 |
+
create_oauth_callback_server(port: int, callback_path: str = '/callback', server_url: str | None = None, response_future: asyncio.Future | None = None) -> Server
|
| 32 |
+
```
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
Create an OAuth callback server.
|
| 36 |
+
|
| 37 |
+
**Args:**
|
| 38 |
+
- `port`: The port to run the server on
|
| 39 |
+
- `callback_path`: The path to listen for OAuth redirects on
|
| 40 |
+
- `server_url`: Optional server URL to display in success messages
|
| 41 |
+
- `response_future`: Optional future to resolve when OAuth callback is received
|
| 42 |
+
|
| 43 |
+
**Returns:**
|
| 44 |
+
- Configured uvicorn Server instance (not yet running)
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
## Classes
|
| 48 |
+
|
| 49 |
+
### `CallbackResponse`
|
| 50 |
+
|
| 51 |
+
**Methods:**
|
| 52 |
+
|
| 53 |
+
#### `from_dict`
|
| 54 |
+
|
| 55 |
+
```python
|
| 56 |
+
from_dict(cls, data: dict[str, str]) -> CallbackResponse
|
| 57 |
+
```
|
| 58 |
+
|
| 59 |
+
#### `to_dict`
|
| 60 |
+
|
| 61 |
+
```python
|
| 62 |
+
to_dict(self) -> dict[str, str]
|
| 63 |
+
```
|
docs/python-sdk/fastmcp-client-progress.mdx
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: progress
|
| 3 |
+
sidebarTitle: progress
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
# `fastmcp.client.progress`
|
| 7 |
+
|
| 8 |
+
*This module is empty or contains only private/internal implementations.*
|
docs/python-sdk/fastmcp-client-roots.mdx
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: roots
|
| 3 |
+
sidebarTitle: roots
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
# `fastmcp.client.roots`
|
| 7 |
+
|
| 8 |
+
## Functions
|
| 9 |
+
|
| 10 |
+
### `convert_roots_list`
|
| 11 |
+
|
| 12 |
+
```python
|
| 13 |
+
convert_roots_list(roots: RootsList) -> list[mcp.types.Root]
|
| 14 |
+
```
|
| 15 |
+
|
| 16 |
+
### `create_roots_callback`
|
| 17 |
+
|
| 18 |
+
```python
|
| 19 |
+
create_roots_callback(handler: RootsList | RootsHandler) -> ListRootsFnT
|
| 20 |
+
```
|
docs/python-sdk/fastmcp-client-sampling.mdx
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: sampling
|
| 3 |
+
sidebarTitle: sampling
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
# `fastmcp.client.sampling`
|
| 7 |
+
|
| 8 |
+
## Functions
|
| 9 |
+
|
| 10 |
+
### `create_sampling_callback`
|
| 11 |
+
|
| 12 |
+
```python
|
| 13 |
+
create_sampling_callback(sampling_handler: SamplingHandler) -> SamplingFnT
|
| 14 |
+
```
|
docs/python-sdk/fastmcp-client-transports.mdx
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: transports
|
| 3 |
+
sidebarTitle: transports
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
# `fastmcp.client.transports`
|
| 7 |
+
|
| 8 |
+
## Functions
|
| 9 |
+
|
| 10 |
+
### `infer_transport`
|
| 11 |
+
|
| 12 |
+
```python
|
| 13 |
+
infer_transport(transport: ClientTransport | FastMCP | FastMCP1Server | AnyUrl | Path | MCPConfig | dict[str, Any] | str) -> ClientTransport
|
| 14 |
+
```
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
Infer the appropriate transport type from the given transport argument.
|
| 19 |
+
|
| 20 |
+
This function attempts to infer the correct transport type from the provided
|
| 21 |
+
argument, handling various input types and converting them to the appropriate
|
| 22 |
+
ClientTransport subclass.
|
| 23 |
+
|
| 24 |
+
The function supports these input types:
|
| 25 |
+
- ClientTransport: Used directly without modification
|
| 26 |
+
- FastMCP or FastMCP1Server: Creates an in-memory FastMCPTransport
|
| 27 |
+
- Path or str (file path): Creates PythonStdioTransport (.py) or NodeStdioTransport (.js)
|
| 28 |
+
- AnyUrl or str (URL): Creates StreamableHttpTransport (default) or SSETransport (for /sse endpoints)
|
| 29 |
+
- MCPConfig or dict: Creates MCPConfigTransport, potentially connecting to multiple servers
|
| 30 |
+
|
| 31 |
+
For HTTP URLs, they are assumed to be Streamable HTTP URLs unless they end in `/sse`.
|
| 32 |
+
|
| 33 |
+
For MCPConfig with multiple servers, a composite client is created where each server
|
| 34 |
+
is mounted with its name as prefix. This allows accessing tools and resources from multiple
|
| 35 |
+
servers through a single unified client interface, using naming patterns like
|
| 36 |
+
`servername_toolname` for tools and `protocol://servername/path` for resources.
|
| 37 |
+
If the MCPConfig contains only one server, a direct connection is established without prefixing.
|
| 38 |
+
|
| 39 |
+
Examples:
|
| 40 |
+
```python
|
| 41 |
+
# Connect to a local Python script
|
| 42 |
+
transport = infer_transport("my_script.py")
|
| 43 |
+
|
| 44 |
+
# Connect to a remote server via HTTP
|
| 45 |
+
transport = infer_transport("http://example.com/mcp")
|
| 46 |
+
|
| 47 |
+
# Connect to multiple servers using MCPConfig
|
| 48 |
+
config = {
|
| 49 |
+
"mcpServers": {
|
| 50 |
+
"weather": {"url": "http://weather.example.com/mcp"},
|
| 51 |
+
"calendar": {"url": "http://calendar.example.com/mcp"}
|
| 52 |
+
}
|
| 53 |
+
}
|
| 54 |
+
transport = infer_transport(config)
|
| 55 |
+
```
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
## Classes
|
| 59 |
+
|
| 60 |
+
### `SessionKwargs`
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
Keyword arguments for the MCP ClientSession constructor.
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
### `ClientTransport`
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
Abstract base class for different MCP client transport mechanisms.
|
| 70 |
+
|
| 71 |
+
A Transport is responsible for establishing and managing connections
|
| 72 |
+
to an MCP server, and providing a ClientSession within an async context.
|
| 73 |
+
|
| 74 |
+
|
| 75 |
+
### `WSTransport`
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
Transport implementation that connects to an MCP server via WebSockets.
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
### `SSETransport`
|
| 82 |
+
|
| 83 |
+
|
| 84 |
+
Transport implementation that connects to an MCP server via Server-Sent Events.
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
### `StreamableHttpTransport`
|
| 88 |
+
|
| 89 |
+
|
| 90 |
+
Transport implementation that connects to an MCP server via Streamable HTTP Requests.
|
| 91 |
+
|
| 92 |
+
|
| 93 |
+
### `StdioTransport`
|
| 94 |
+
|
| 95 |
+
|
| 96 |
+
Base transport for connecting to an MCP server via subprocess with stdio.
|
| 97 |
+
|
| 98 |
+
This is a base class that can be subclassed for specific command-based
|
| 99 |
+
transports like Python, Node, Uvx, etc.
|
| 100 |
+
|
| 101 |
+
|
| 102 |
+
### `PythonStdioTransport`
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
Transport for running Python scripts.
|
| 106 |
+
|
| 107 |
+
|
| 108 |
+
### `FastMCPStdioTransport`
|
| 109 |
+
|
| 110 |
+
|
| 111 |
+
Transport for running FastMCP servers using the FastMCP CLI.
|
| 112 |
+
|
| 113 |
+
|
| 114 |
+
### `NodeStdioTransport`
|
| 115 |
+
|
| 116 |
+
|
| 117 |
+
Transport for running Node.js scripts.
|
| 118 |
+
|
| 119 |
+
|
| 120 |
+
### `UvxStdioTransport`
|
| 121 |
+
|
| 122 |
+
|
| 123 |
+
Transport for running commands via the uvx tool.
|
| 124 |
+
|
| 125 |
+
|
| 126 |
+
### `NpxStdioTransport`
|
| 127 |
+
|
| 128 |
+
|
| 129 |
+
Transport for running commands via the npx tool.
|
| 130 |
+
|
| 131 |
+
|
| 132 |
+
### `FastMCPTransport`
|
| 133 |
+
|
| 134 |
+
|
| 135 |
+
In-memory transport for FastMCP servers.
|
| 136 |
+
|
| 137 |
+
This transport connects directly to a FastMCP server instance in the same
|
| 138 |
+
Python process. It works with both FastMCP 2.x servers and FastMCP 1.0
|
| 139 |
+
servers from the low-level MCP SDK. This is particularly useful for unit
|
| 140 |
+
tests or scenarios where client and server run in the same runtime.
|
| 141 |
+
|
| 142 |
+
|
| 143 |
+
### `MCPConfigTransport`
|
| 144 |
+
|
| 145 |
+
|
| 146 |
+
Transport for connecting to one or more MCP servers defined in an MCPConfig.
|
| 147 |
+
|
| 148 |
+
This transport provides a unified interface to multiple MCP servers defined in an MCPConfig
|
| 149 |
+
object or dictionary matching the MCPConfig schema. It supports two key scenarios:
|
| 150 |
+
|
| 151 |
+
1. If the MCPConfig contains exactly one server, it creates a direct transport to that server.
|
| 152 |
+
2. If the MCPConfig contains multiple servers, it creates a composite client by mounting
|
| 153 |
+
all servers on a single FastMCP instance, with each server's name used as its mounting prefix.
|
| 154 |
+
|
| 155 |
+
In the multi-server case, tools are accessible with the prefix pattern `{server_name}_{tool_name}`
|
| 156 |
+
and resources with the pattern `protocol://{server_name}/path/to/resource`.
|
| 157 |
+
|
| 158 |
+
This is particularly useful for creating clients that need to interact with multiple specialized
|
| 159 |
+
MCP servers through a single interface, simplifying client code.
|
| 160 |
+
|
| 161 |
+
Examples:
|
| 162 |
+
```python
|
| 163 |
+
from fastmcp import Client
|
| 164 |
+
from fastmcp.utilities.mcp_config import MCPConfig
|
| 165 |
+
|
| 166 |
+
# Create a config with multiple servers
|
| 167 |
+
config = {
|
| 168 |
+
"mcpServers": {
|
| 169 |
+
"weather": {
|
| 170 |
+
"url": "https://weather-api.example.com/mcp",
|
| 171 |
+
"transport": "streamable-http"
|
| 172 |
+
},
|
| 173 |
+
"calendar": {
|
| 174 |
+
"url": "https://calendar-api.example.com/mcp",
|
| 175 |
+
"transport": "streamable-http"
|
| 176 |
+
}
|
| 177 |
+
}
|
| 178 |
+
}
|
| 179 |
+
|
| 180 |
+
# Create a client with the config
|
| 181 |
+
client = Client(config)
|
| 182 |
+
|
| 183 |
+
async with client:
|
| 184 |
+
# Access tools with prefixes
|
| 185 |
+
weather = await client.call_tool("weather_get_forecast", {"city": "London"})
|
| 186 |
+
events = await client.call_tool("calendar_list_events", {"date": "2023-06-01"})
|
| 187 |
+
|
| 188 |
+
# Access resources with prefixed URIs
|
| 189 |
+
icons = await client.read_resource("weather://weather/icons/sunny")
|
| 190 |
+
```
|
| 191 |
+
|
docs/python-sdk/fastmcp-exceptions.mdx
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: exceptions
|
| 3 |
+
sidebarTitle: exceptions
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
# `fastmcp.exceptions`
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
Custom exceptions for FastMCP.
|
| 10 |
+
|
| 11 |
+
## Classes
|
| 12 |
+
|
| 13 |
+
### `FastMCPError`
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
Base error for FastMCP.
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
### `ValidationError`
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
Error in validating parameters or return values.
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
### `ResourceError`
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
Error in resource operations.
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
### `ToolError`
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
Error in tool operations.
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
### `PromptError`
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
Error in prompt operations.
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
### `InvalidSignature`
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
Invalid signature for use with FastMCP.
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
### `ClientError`
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
Error in client operations.
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
### `NotFoundError`
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
Object not found.
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
### `DisabledError`
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
Object is disabled.
|
| 65 |
+
|
docs/python-sdk/fastmcp-prompts-__init__.mdx
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: __init__
|
| 3 |
+
sidebarTitle: __init__
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
# `fastmcp.prompts`
|
| 7 |
+
|
| 8 |
+
*This module is empty or contains only private/internal implementations.*
|
docs/python-sdk/fastmcp-prompts-prompt.mdx
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: prompt
|
| 3 |
+
sidebarTitle: prompt
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
# `fastmcp.prompts.prompt`
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
Base classes for FastMCP prompts.
|
| 10 |
+
|
| 11 |
+
## Functions
|
| 12 |
+
|
| 13 |
+
### `Message`
|
| 14 |
+
|
| 15 |
+
```python
|
| 16 |
+
Message(content: str | MCPContent, role: Role | None = None, **kwargs: Any) -> PromptMessage
|
| 17 |
+
```
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
A user-friendly constructor for PromptMessage.
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
## Classes
|
| 24 |
+
|
| 25 |
+
### `PromptArgument`
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
An argument that can be passed to a prompt.
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
### `Prompt`
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
A prompt template that can be rendered with parameters.
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
**Methods:**
|
| 38 |
+
|
| 39 |
+
#### `to_mcp_prompt`
|
| 40 |
+
|
| 41 |
+
```python
|
| 42 |
+
to_mcp_prompt(self, **overrides: Any) -> MCPPrompt
|
| 43 |
+
```
|
| 44 |
+
|
| 45 |
+
Convert the prompt to an MCP prompt.
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
#### `from_function`
|
| 49 |
+
|
| 50 |
+
```python
|
| 51 |
+
from_function(fn: Callable[..., PromptResult | Awaitable[PromptResult]], name: str | None = None, description: str | None = None, tags: set[str] | None = None, enabled: bool | None = None) -> FunctionPrompt
|
| 52 |
+
```
|
| 53 |
+
|
| 54 |
+
Create a Prompt from a function.
|
| 55 |
+
|
| 56 |
+
The function can return:
|
| 57 |
+
- A string (converted to a message)
|
| 58 |
+
- A Message object
|
| 59 |
+
- A dict (converted to a message)
|
| 60 |
+
- A sequence of any of the above
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
### `FunctionPrompt`
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
A prompt that is a function.
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
**Methods:**
|
| 70 |
+
|
| 71 |
+
#### `from_function`
|
| 72 |
+
|
| 73 |
+
```python
|
| 74 |
+
from_function(cls, fn: Callable[..., PromptResult | Awaitable[PromptResult]], name: str | None = None, description: str | None = None, tags: set[str] | None = None, enabled: bool | None = None) -> FunctionPrompt
|
| 75 |
+
```
|
| 76 |
+
|
| 77 |
+
Create a Prompt from a function.
|
| 78 |
+
|
| 79 |
+
The function can return:
|
| 80 |
+
- A string (converted to a message)
|
| 81 |
+
- A Message object
|
| 82 |
+
- A dict (converted to a message)
|
| 83 |
+
- A sequence of any of the above
|
| 84 |
+
|
docs/python-sdk/fastmcp-prompts-prompt_manager.mdx
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: prompt_manager
|
| 3 |
+
sidebarTitle: prompt_manager
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
# `fastmcp.prompts.prompt_manager`
|
| 7 |
+
|
| 8 |
+
## Classes
|
| 9 |
+
|
| 10 |
+
### `PromptManager`
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
Manages FastMCP prompts.
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
**Methods:**
|
| 17 |
+
|
| 18 |
+
#### `mount`
|
| 19 |
+
|
| 20 |
+
```python
|
| 21 |
+
mount(self, server: MountedServer) -> None
|
| 22 |
+
```
|
| 23 |
+
|
| 24 |
+
Adds a mounted server as a source for prompts.
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
#### `add_prompt_from_fn`
|
| 28 |
+
|
| 29 |
+
```python
|
| 30 |
+
add_prompt_from_fn(self, fn: Callable[..., PromptResult | Awaitable[PromptResult]], name: str | None = None, description: str | None = None, tags: set[str] | None = None) -> FunctionPrompt
|
| 31 |
+
```
|
| 32 |
+
|
| 33 |
+
Create a prompt from a function.
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
#### `add_prompt`
|
| 37 |
+
|
| 38 |
+
```python
|
| 39 |
+
add_prompt(self, prompt: Prompt) -> Prompt
|
| 40 |
+
```
|
| 41 |
+
|
| 42 |
+
Add a prompt to the manager.
|
| 43 |
+
|
docs/python-sdk/fastmcp-resources-__init__.mdx
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: __init__
|
| 3 |
+
sidebarTitle: __init__
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
# `fastmcp.resources`
|
| 7 |
+
|
| 8 |
+
*This module is empty or contains only private/internal implementations.*
|
docs/python-sdk/fastmcp-resources-resource.mdx
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: resource
|
| 3 |
+
sidebarTitle: resource
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
# `fastmcp.resources.resource`
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
Base classes and interfaces for FastMCP resources.
|
| 10 |
+
|
| 11 |
+
## Classes
|
| 12 |
+
|
| 13 |
+
### `Resource`
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
Base class for all resources.
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
**Methods:**
|
| 20 |
+
|
| 21 |
+
#### `from_function`
|
| 22 |
+
|
| 23 |
+
```python
|
| 24 |
+
from_function(fn: Callable[[], Any], uri: str | AnyUrl, name: str | None = None, description: str | None = None, mime_type: str | None = None, tags: set[str] | None = None, enabled: bool | None = None) -> FunctionResource
|
| 25 |
+
```
|
| 26 |
+
|
| 27 |
+
#### `set_default_mime_type`
|
| 28 |
+
|
| 29 |
+
```python
|
| 30 |
+
set_default_mime_type(cls, mime_type: str | None) -> str
|
| 31 |
+
```
|
| 32 |
+
|
| 33 |
+
Set default MIME type if not provided.
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
#### `set_default_name`
|
| 37 |
+
|
| 38 |
+
```python
|
| 39 |
+
set_default_name(self) -> Self
|
| 40 |
+
```
|
| 41 |
+
|
| 42 |
+
Set default name from URI if not provided.
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
#### `to_mcp_resource`
|
| 46 |
+
|
| 47 |
+
```python
|
| 48 |
+
to_mcp_resource(self, **overrides: Any) -> MCPResource
|
| 49 |
+
```
|
| 50 |
+
|
| 51 |
+
Convert the resource to an MCPResource.
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
#### `key`
|
| 55 |
+
|
| 56 |
+
```python
|
| 57 |
+
key(self) -> str
|
| 58 |
+
```
|
| 59 |
+
|
| 60 |
+
The key of the component. This is used for internal bookkeeping
|
| 61 |
+
and may reflect e.g. prefixes or other identifiers. You should not depend on
|
| 62 |
+
keys having a certain value, as the same tool loaded from different
|
| 63 |
+
hierarchies of servers may have different keys.
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
### `FunctionResource`
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
A resource that defers data loading by wrapping a function.
|
| 70 |
+
|
| 71 |
+
The function is only called when the resource is read, allowing for lazy loading
|
| 72 |
+
of potentially expensive data. This is particularly useful when listing resources,
|
| 73 |
+
as the function won't be called until the resource is actually accessed.
|
| 74 |
+
|
| 75 |
+
The function can return:
|
| 76 |
+
- str for text content (default)
|
| 77 |
+
- bytes for binary content
|
| 78 |
+
- other types will be converted to JSON
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
**Methods:**
|
| 82 |
+
|
| 83 |
+
#### `from_function`
|
| 84 |
+
|
| 85 |
+
```python
|
| 86 |
+
from_function(cls, fn: Callable[[], Any], uri: str | AnyUrl, name: str | None = None, description: str | None = None, mime_type: str | None = None, tags: set[str] | None = None, enabled: bool | None = None) -> FunctionResource
|
| 87 |
+
```
|
| 88 |
+
|
| 89 |
+
Create a FunctionResource from a function.
|
| 90 |
+
|
docs/python-sdk/fastmcp-resources-resource_manager.mdx
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: resource_manager
|
| 3 |
+
sidebarTitle: resource_manager
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
# `fastmcp.resources.resource_manager`
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
Resource manager functionality.
|
| 10 |
+
|
| 11 |
+
## Classes
|
| 12 |
+
|
| 13 |
+
### `ResourceManager`
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
Manages FastMCP resources.
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
**Methods:**
|
| 20 |
+
|
| 21 |
+
#### `mount`
|
| 22 |
+
|
| 23 |
+
```python
|
| 24 |
+
mount(self, server: MountedServer) -> None
|
| 25 |
+
```
|
| 26 |
+
|
| 27 |
+
Adds a mounted server as a source for resources and templates.
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
#### `add_resource_or_template_from_fn`
|
| 31 |
+
|
| 32 |
+
```python
|
| 33 |
+
add_resource_or_template_from_fn(self, fn: Callable[..., Any], uri: str, name: str | None = None, description: str | None = None, mime_type: str | None = None, tags: set[str] | None = None) -> Resource | ResourceTemplate
|
| 34 |
+
```
|
| 35 |
+
|
| 36 |
+
Add a resource or template to the manager from a function.
|
| 37 |
+
|
| 38 |
+
**Args:**
|
| 39 |
+
- `fn`: The function to register as a resource or template
|
| 40 |
+
- `uri`: The URI for the resource or template
|
| 41 |
+
- `name`: Optional name for the resource or template
|
| 42 |
+
- `description`: Optional description of the resource or template
|
| 43 |
+
- `mime_type`: Optional MIME type for the resource or template
|
| 44 |
+
- `tags`: Optional set of tags for categorizing the resource or template
|
| 45 |
+
|
| 46 |
+
**Returns:**
|
| 47 |
+
- The added resource or template. If a resource or template with the same URI already exists,
|
| 48 |
+
- returns the existing resource or template.
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
#### `add_resource_from_fn`
|
| 52 |
+
|
| 53 |
+
```python
|
| 54 |
+
add_resource_from_fn(self, fn: Callable[..., Any], uri: str, name: str | None = None, description: str | None = None, mime_type: str | None = None, tags: set[str] | None = None) -> Resource
|
| 55 |
+
```
|
| 56 |
+
|
| 57 |
+
Add a resource to the manager from a function.
|
| 58 |
+
|
| 59 |
+
**Args:**
|
| 60 |
+
- `fn`: The function to register as a resource
|
| 61 |
+
- `uri`: The URI for the resource
|
| 62 |
+
- `name`: Optional name for the resource
|
| 63 |
+
- `description`: Optional description of the resource
|
| 64 |
+
- `mime_type`: Optional MIME type for the resource
|
| 65 |
+
- `tags`: Optional set of tags for categorizing the resource
|
| 66 |
+
|
| 67 |
+
**Returns:**
|
| 68 |
+
- The added resource. If a resource with the same URI already exists,
|
| 69 |
+
- returns the existing resource.
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
#### `add_resource`
|
| 73 |
+
|
| 74 |
+
```python
|
| 75 |
+
add_resource(self, resource: Resource) -> Resource
|
| 76 |
+
```
|
| 77 |
+
|
| 78 |
+
Add a resource to the manager.
|
| 79 |
+
|
| 80 |
+
**Args:**
|
| 81 |
+
- `resource`: A Resource instance to add. The resource's .key attribute
|
| 82 |
+
will be used as the storage key. To overwrite it, call
|
| 83 |
+
Resource.with_key() before calling this method.
|
| 84 |
+
|
| 85 |
+
|
| 86 |
+
#### `add_template_from_fn`
|
| 87 |
+
|
| 88 |
+
```python
|
| 89 |
+
add_template_from_fn(self, fn: Callable[..., Any], uri_template: str, name: str | None = None, description: str | None = None, mime_type: str | None = None, tags: set[str] | None = None) -> ResourceTemplate
|
| 90 |
+
```
|
| 91 |
+
|
| 92 |
+
Create a template from a function.
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
#### `add_template`
|
| 96 |
+
|
| 97 |
+
```python
|
| 98 |
+
add_template(self, template: ResourceTemplate) -> ResourceTemplate
|
| 99 |
+
```
|
| 100 |
+
|
| 101 |
+
Add a template to the manager.
|
| 102 |
+
|
| 103 |
+
**Args:**
|
| 104 |
+
- `template`: A ResourceTemplate instance to add. The template's .key attribute
|
| 105 |
+
will be used as the storage key. To overwrite it, call
|
| 106 |
+
ResourceTemplate.with_key() before calling this method.
|
| 107 |
+
|
| 108 |
+
**Returns:**
|
| 109 |
+
- The added template. If a template with the same URI already exists,
|
| 110 |
+
- returns the existing template.
|
| 111 |
+
|
docs/python-sdk/fastmcp-resources-template.mdx
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: template
|
| 3 |
+
sidebarTitle: template
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
# `fastmcp.resources.template`
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
Resource template functionality.
|
| 10 |
+
|
| 11 |
+
## Functions
|
| 12 |
+
|
| 13 |
+
### `build_regex`
|
| 14 |
+
|
| 15 |
+
```python
|
| 16 |
+
build_regex(template: str) -> re.Pattern
|
| 17 |
+
```
|
| 18 |
+
|
| 19 |
+
### `match_uri_template`
|
| 20 |
+
|
| 21 |
+
```python
|
| 22 |
+
match_uri_template(uri: str, uri_template: str) -> dict[str, str] | None
|
| 23 |
+
```
|
| 24 |
+
|
| 25 |
+
## Classes
|
| 26 |
+
|
| 27 |
+
### `ResourceTemplate`
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
A template for dynamically creating resources.
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
**Methods:**
|
| 34 |
+
|
| 35 |
+
#### `from_function`
|
| 36 |
+
|
| 37 |
+
```python
|
| 38 |
+
from_function(fn: Callable[..., Any], uri_template: str, name: str | None = None, description: str | None = None, mime_type: str | None = None, tags: set[str] | None = None, enabled: bool | None = None) -> FunctionResourceTemplate
|
| 39 |
+
```
|
| 40 |
+
|
| 41 |
+
#### `set_default_mime_type`
|
| 42 |
+
|
| 43 |
+
```python
|
| 44 |
+
set_default_mime_type(cls, mime_type: str | None) -> str
|
| 45 |
+
```
|
| 46 |
+
|
| 47 |
+
Set default MIME type if not provided.
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
#### `matches`
|
| 51 |
+
|
| 52 |
+
```python
|
| 53 |
+
matches(self, uri: str) -> dict[str, Any] | None
|
| 54 |
+
```
|
| 55 |
+
|
| 56 |
+
Check if URI matches template and extract parameters.
|
| 57 |
+
|
| 58 |
+
|
| 59 |
+
#### `to_mcp_template`
|
| 60 |
+
|
| 61 |
+
```python
|
| 62 |
+
to_mcp_template(self, **overrides: Any) -> MCPResourceTemplate
|
| 63 |
+
```
|
| 64 |
+
|
| 65 |
+
Convert the resource template to an MCPResourceTemplate.
|
| 66 |
+
|
| 67 |
+
|
| 68 |
+
#### `from_mcp_template`
|
| 69 |
+
|
| 70 |
+
```python
|
| 71 |
+
from_mcp_template(cls, mcp_template: MCPResourceTemplate) -> ResourceTemplate
|
| 72 |
+
```
|
| 73 |
+
|
| 74 |
+
Creates a FastMCP ResourceTemplate from a raw MCP ResourceTemplate object.
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
#### `key`
|
| 78 |
+
|
| 79 |
+
```python
|
| 80 |
+
key(self) -> str
|
| 81 |
+
```
|
| 82 |
+
|
| 83 |
+
The key of the component. This is used for internal bookkeeping
|
| 84 |
+
and may reflect e.g. prefixes or other identifiers. You should not depend on
|
| 85 |
+
keys having a certain value, as the same tool loaded from different
|
| 86 |
+
hierarchies of servers may have different keys.
|
| 87 |
+
|
| 88 |
+
|
| 89 |
+
### `FunctionResourceTemplate`
|
| 90 |
+
|
| 91 |
+
|
| 92 |
+
A template for dynamically creating resources.
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
**Methods:**
|
| 96 |
+
|
| 97 |
+
#### `from_function`
|
| 98 |
+
|
| 99 |
+
```python
|
| 100 |
+
from_function(cls, fn: Callable[..., Any], uri_template: str, name: str | None = None, description: str | None = None, mime_type: str | None = None, tags: set[str] | None = None, enabled: bool | None = None) -> FunctionResourceTemplate
|
| 101 |
+
```
|
| 102 |
+
|
| 103 |
+
Create a template from a function.
|
| 104 |
+
|
docs/python-sdk/fastmcp-resources-types.mdx
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: types
|
| 3 |
+
sidebarTitle: types
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
# `fastmcp.resources.types`
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
Concrete resource implementations.
|
| 10 |
+
|
| 11 |
+
## Classes
|
| 12 |
+
|
| 13 |
+
### `TextResource`
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
A resource that reads from a string.
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
### `BinaryResource`
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
A resource that reads from bytes.
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
### `FileResource`
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
A resource that reads from a file.
|
| 29 |
+
|
| 30 |
+
Set is_binary=True to read file as binary data instead of text.
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
**Methods:**
|
| 34 |
+
|
| 35 |
+
#### `validate_absolute_path`
|
| 36 |
+
|
| 37 |
+
```python
|
| 38 |
+
validate_absolute_path(cls, path: Path) -> Path
|
| 39 |
+
```
|
| 40 |
+
|
| 41 |
+
Ensure path is absolute.
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
#### `set_binary_from_mime_type`
|
| 45 |
+
|
| 46 |
+
```python
|
| 47 |
+
set_binary_from_mime_type(cls, is_binary: bool, info: ValidationInfo) -> bool
|
| 48 |
+
```
|
| 49 |
+
|
| 50 |
+
Set is_binary based on mime_type if not explicitly set.
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
### `HttpResource`
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
A resource that reads from an HTTP endpoint.
|
| 57 |
+
|
| 58 |
+
|
| 59 |
+
### `DirectoryResource`
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
A resource that lists files in a directory.
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
**Methods:**
|
| 66 |
+
|
| 67 |
+
#### `validate_absolute_path`
|
| 68 |
+
|
| 69 |
+
```python
|
| 70 |
+
validate_absolute_path(cls, path: Path) -> Path
|
| 71 |
+
```
|
| 72 |
+
|
| 73 |
+
Ensure path is absolute.
|
| 74 |
+
|
| 75 |
+
|
| 76 |
+
#### `list_files`
|
| 77 |
+
|
| 78 |
+
```python
|
| 79 |
+
list_files(self) -> list[Path]
|
| 80 |
+
```
|
| 81 |
+
|
| 82 |
+
List files in the directory.
|
| 83 |
+
|
docs/python-sdk/fastmcp-server-__init__.mdx
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: __init__
|
| 3 |
+
sidebarTitle: __init__
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
# `fastmcp.server`
|
| 7 |
+
|
| 8 |
+
*This module is empty or contains only private/internal implementations.*
|
docs/python-sdk/fastmcp-server-auth-__init__.mdx
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: __init__
|
| 3 |
+
sidebarTitle: __init__
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
# `fastmcp.server.auth`
|
| 7 |
+
|
| 8 |
+
*This module is empty or contains only private/internal implementations.*
|
docs/python-sdk/fastmcp-server-auth-auth.mdx
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: auth
|
| 3 |
+
sidebarTitle: auth
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
# `fastmcp.server.auth.auth`
|
| 7 |
+
|
| 8 |
+
## Classes
|
| 9 |
+
|
| 10 |
+
### `OAuthProvider`
|
docs/python-sdk/fastmcp-server-auth-providers-__init__.mdx
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: __init__
|
| 3 |
+
sidebarTitle: __init__
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
# `fastmcp.server.auth.providers`
|
| 7 |
+
|
| 8 |
+
*This module is empty or contains only private/internal implementations.*
|
docs/python-sdk/fastmcp-server-auth-providers-bearer.mdx
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: bearer
|
| 3 |
+
sidebarTitle: bearer
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
# `fastmcp.server.auth.providers.bearer`
|
| 7 |
+
|
| 8 |
+
## Classes
|
| 9 |
+
|
| 10 |
+
### `JWKData`
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
JSON Web Key data structure.
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
### `JWKSData`
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
JSON Web Key Set data structure.
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
### `RSAKeyPair`
|
| 23 |
+
|
| 24 |
+
**Methods:**
|
| 25 |
+
|
| 26 |
+
#### `generate`
|
| 27 |
+
|
| 28 |
+
```python
|
| 29 |
+
generate(cls) -> 'RSAKeyPair'
|
| 30 |
+
```
|
| 31 |
+
|
| 32 |
+
Generate an RSA key pair for testing.
|
| 33 |
+
|
| 34 |
+
**Returns:**
|
| 35 |
+
- (private_key_pem, public_key_pem)
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
#### `create_token`
|
| 39 |
+
|
| 40 |
+
```python
|
| 41 |
+
create_token(self, subject: str = 'fastmcp-user', issuer: str = 'https://fastmcp.example.com', audience: str | list[str] | None = None, scopes: list[str] | None = None, expires_in_seconds: int = 3600, additional_claims: dict[str, Any] | None = None, kid: str | None = None) -> str
|
| 42 |
+
```
|
| 43 |
+
|
| 44 |
+
Generate a test JWT token for testing purposes.
|
| 45 |
+
|
| 46 |
+
**Args:**
|
| 47 |
+
- `private_key_pem`: RSA private key in PEM format
|
| 48 |
+
- `subject`: Subject claim (usually user ID)
|
| 49 |
+
- `issuer`: Issuer claim
|
| 50 |
+
- `audience`: Audience claim - can be a string or list of strings (optional)
|
| 51 |
+
- `scopes`: List of scopes to include
|
| 52 |
+
- `expires_in_seconds`: Token expiration time in seconds
|
| 53 |
+
- `additional_claims`: Any additional claims to include
|
| 54 |
+
- `kid`: Key ID for JWKS lookup (optional)
|
| 55 |
+
|
| 56 |
+
**Returns:**
|
| 57 |
+
- Signed JWT token string
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
### `BearerAuthProvider`
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
Simple JWT Bearer Token validator for hosted MCP servers.
|
| 64 |
+
Uses RS256 asymmetric encryption. Supports either static public key
|
| 65 |
+
or JWKS URI for key rotation.
|
| 66 |
+
|
| 67 |
+
Note that this provider DOES NOT permit client registration or revocation, or any OAuth flows.
|
| 68 |
+
It is intended to be used with a control plane that manages clients and tokens.
|
| 69 |
+
|