fastmcp 2.2.6__tar.gz → 2.2.7__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {fastmcp-2.2.6 → fastmcp-2.2.7}/.github/workflows/run-tests.yml +1 -1
- {fastmcp-2.2.6 → fastmcp-2.2.7}/PKG-INFO +3 -3
- {fastmcp-2.2.6 → fastmcp-2.2.7}/README.md +1 -1
- {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/clients/client.mdx +29 -1
- {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/patterns/composition.mdx +48 -7
- {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/servers/context.mdx +28 -2
- {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/servers/fastmcp.mdx +40 -1
- {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/servers/tools.mdx +41 -1
- fastmcp-2.2.7/examples/serializer.py +32 -0
- fastmcp-2.2.7/examples/smart_home/README.md +15 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/justfile +1 -1
- {fastmcp-2.2.6 → fastmcp-2.2.7}/pyproject.toml +1 -1
- fastmcp-2.2.7/src/fastmcp/client/client.py +426 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/contrib/bulk_tool_caller/bulk_tool_caller.py +1 -3
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/prompts/prompt.py +8 -4
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/resources/template.py +5 -2
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/resources/types.py +4 -7
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/server/context.py +12 -1
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/server/openapi.py +28 -5
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/server/proxy.py +3 -2
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/server/server.py +243 -18
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/settings.py +7 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/tools/tool.py +24 -22
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/tools/tool_manager.py +16 -3
- fastmcp-2.2.7/src/fastmcp/utilities/http.py +44 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/utilities/openapi.py +147 -36
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/utilities/types.py +29 -1
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/client/test_client.py +106 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/prompts/test_prompt_manager.py +99 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/resources/test_function_resources.py +1 -1
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/resources/test_resource_template.py +114 -1
- fastmcp-2.2.7/tests/server/test_auth_integration.py +1263 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/server/test_mount.py +110 -1
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/server/test_openapi.py +737 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/server/test_server_interactions.py +7 -6
- fastmcp-2.2.7/tests/server/test_tool_annotations.py +219 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/tools/test_tool_manager.py +65 -13
- fastmcp-2.2.7/tests/utilities/test_types.py +145 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/uv.lock +526 -516
- fastmcp-2.2.6/examples/smart_home/README.md +0 -0
- fastmcp-2.2.6/src/fastmcp/client/client.py +0 -224
- {fastmcp-2.2.6 → fastmcp-2.2.7}/.cursor/rules/core-mcp-objects.mdc +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/.github/ISSUE_TEMPLATE/bug.yml +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/.github/ISSUE_TEMPLATE/enhancement.yml +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/.github/release.yml +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/.github/workflows/publish.yml +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/.github/workflows/run-static.yml +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/.gitignore +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/.pre-commit-config.yaml +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/LICENSE +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/Windows_Notes.md +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/assets/demo-inspector.png +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/clients/transports.mdx +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/docs.json +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/getting-started/installation.mdx +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/getting-started/quickstart.mdx +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/getting-started/welcome.mdx +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/patterns/contrib.mdx +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/patterns/decorating-methods.mdx +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/patterns/fastapi.mdx +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/patterns/openapi.mdx +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/patterns/proxy.mdx +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/patterns/testing.mdx +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/servers/prompts.mdx +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/servers/resources.mdx +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/snippets/version-badge.mdx +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/style.css +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/examples/complex_inputs.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/examples/desktop.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/examples/echo.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/examples/memory.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/examples/mount_example.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/examples/readme-quickstart.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/examples/sampling.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/examples/screenshot.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/examples/simple_echo.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/examples/smart_home/pyproject.toml +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/examples/smart_home/src/smart_home/__init__.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/examples/smart_home/src/smart_home/__main__.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/examples/smart_home/src/smart_home/hub.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/examples/smart_home/src/smart_home/lights/__init__.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/examples/smart_home/src/smart_home/lights/hue_utils.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/examples/smart_home/src/smart_home/lights/server.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/examples/smart_home/src/smart_home/py.typed +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/examples/smart_home/src/smart_home/settings.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/examples/smart_home/uv.lock +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/examples/text_me.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/__init__.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/cli/__init__.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/cli/claude.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/cli/cli.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/client/__init__.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/client/base.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/client/logging.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/client/roots.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/client/sampling.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/client/transports.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/contrib/README.md +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/contrib/bulk_tool_caller/README.md +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/contrib/bulk_tool_caller/__init__.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/contrib/bulk_tool_caller/example.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/contrib/mcp_mixin/README.md +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/contrib/mcp_mixin/__init__.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/contrib/mcp_mixin/example.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/contrib/mcp_mixin/mcp_mixin.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/exceptions.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/prompts/__init__.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/prompts/prompt_manager.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/py.typed +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/resources/__init__.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/resources/resource.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/resources/resource_manager.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/server/__init__.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/tools/__init__.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/utilities/__init__.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/utilities/decorators.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/utilities/func_metadata.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/utilities/logging.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/__init__.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/cli/test_run.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/client/__init__.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/client/test_logs.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/client/test_roots.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/client/test_sampling.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/conftest.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/contrib/__init__.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/contrib/test_bulk_tool_caller.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/contrib/test_mcp_mixin.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/prompts/__init__.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/prompts/test_base.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/resources/__init__.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/resources/test_file_resources.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/resources/test_resource_manager.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/resources/test_resources.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/server/__init__.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/server/test_file_server.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/server/test_import_server.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/server/test_lifespan.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/server/test_proxy.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/server/test_run_server.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/server/test_server.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/test_servers/fastmcp_server.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/test_servers/sse.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/test_servers/stdio.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/tools/__init__.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/utilities/__init__.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/utilities/openapi/__init__.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/utilities/openapi/conftest.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/utilities/openapi/test_openapi.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/utilities/openapi/test_openapi_advanced.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/utilities/openapi/test_openapi_fastapi.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/utilities/test_decorated_function.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/utilities/test_func_metadata.py +0 -0
- {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/utilities/test_logging.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fastmcp
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.7
|
|
4
4
|
Summary: The fast, Pythonic way to build MCP servers.
|
|
5
5
|
Project-URL: Homepage, https://gofastmcp.com
|
|
6
6
|
Project-URL: Repository, https://github.com/jlowin/fastmcp
|
|
@@ -19,7 +19,7 @@ Classifier: Typing :: Typed
|
|
|
19
19
|
Requires-Python: >=3.10
|
|
20
20
|
Requires-Dist: exceptiongroup>=1.2.2
|
|
21
21
|
Requires-Dist: httpx>=0.28.1
|
|
22
|
-
Requires-Dist: mcp<2.0.0,>=1.
|
|
22
|
+
Requires-Dist: mcp<2.0.0,>=1.7.1
|
|
23
23
|
Requires-Dist: openapi-pydantic>=0.5.1
|
|
24
24
|
Requires-Dist: python-dotenv>=1.1.0
|
|
25
25
|
Requires-Dist: rich>=13.9.4
|
|
@@ -789,7 +789,7 @@ Contributions make the open-source community vibrant! We welcome improvements an
|
|
|
789
789
|
|
|
790
790
|
Run the test suite:
|
|
791
791
|
```bash
|
|
792
|
-
uv run pytest -vv
|
|
792
|
+
uv run --frozen pytest -vv
|
|
793
793
|
```
|
|
794
794
|
|
|
795
795
|
#### Formatting & Linting
|
|
@@ -149,6 +149,34 @@ The `Client` provides methods corresponding to standard MCP requests:
|
|
|
149
149
|
* **`list_prompts()`**: Retrieves available prompt templates.
|
|
150
150
|
* **`get_prompt(name: str, arguments: dict[str, Any] | None = None)`**: Retrieves a rendered prompt message list.
|
|
151
151
|
|
|
152
|
+
### Raw MCP Protocol Objects
|
|
153
|
+
|
|
154
|
+
The FastMCP client attempts to provide a "friendly" interface to the MCP protocol, but sometimes you may need access to the raw MCP protocol objects. Each of the main client methods that returns data has a corresponding `*_mcp` method that returns the raw MCP protocol objects directly.
|
|
155
|
+
|
|
156
|
+
```python
|
|
157
|
+
# Standard method - returns just the list of tools
|
|
158
|
+
tools = await client.list_tools()
|
|
159
|
+
# tools -> list[mcp.types.Tool]
|
|
160
|
+
|
|
161
|
+
# Raw MCP method - returns the full protocol object
|
|
162
|
+
result = await client.list_tools_mcp()
|
|
163
|
+
# result -> mcp.types.ListToolsResult
|
|
164
|
+
tools = result.tools
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Available raw MCP methods:
|
|
168
|
+
|
|
169
|
+
* **`list_tools_mcp()`**: Returns `mcp.types.ListToolsResult`
|
|
170
|
+
* **`call_tool_mcp(name, arguments)`**: Returns `mcp.types.CallToolResult`
|
|
171
|
+
* **`list_resources_mcp()`**: Returns `mcp.types.ListResourcesResult`
|
|
172
|
+
* **`list_resource_templates_mcp()`**: Returns `mcp.types.ListResourceTemplatesResult`
|
|
173
|
+
* **`read_resource_mcp(uri)`**: Returns `mcp.types.ReadResourceResult`
|
|
174
|
+
* **`list_prompts_mcp()`**: Returns `mcp.types.ListPromptsResult`
|
|
175
|
+
* **`get_prompt_mcp(name, arguments)`**: Returns `mcp.types.GetPromptResult`
|
|
176
|
+
* **`complete_mcp(ref, argument)`**: Returns `mcp.types.CompleteResult`
|
|
177
|
+
|
|
178
|
+
These methods are especially useful for debugging or when you need to access metadata or fields that aren't exposed by the simplified methods.
|
|
179
|
+
|
|
152
180
|
### Advanced Features
|
|
153
181
|
|
|
154
182
|
MCP allows servers to interact with clients in order to provide additional capabilities. The `Client` constructor accepts additional configuration to handle these server requests.
|
|
@@ -268,5 +296,5 @@ async def safe_call_tool():
|
|
|
268
296
|
Other errors, like connection failures, will raise standard Python exceptions (e.g., `ConnectionError`, `TimeoutError`).
|
|
269
297
|
|
|
270
298
|
<Tip>
|
|
271
|
-
The client transport often has its own error-handling mechanisms, so you can not always trap errors like those raised by `call_tool` outside of the `async with` block. Instead, you can
|
|
299
|
+
The client transport often has its own error-handling mechanisms, so you can not always trap errors like those raised by `call_tool` outside of the `async with` block. Instead, you can use `call_tool_mcp()` to get the raw `mcp.types.CallToolResult` object and handle errors yourself by checking its `isError` attribute.
|
|
272
300
|
</Tip>
|
|
@@ -30,8 +30,6 @@ The choice of importing or mounting depends on your use case and requirements. I
|
|
|
30
30
|
| **Method** | `FastMCP.import_server()` | `FastMCP.mount()` |
|
|
31
31
|
| **Composition Type** | One-time copy (static) | Live link (dynamic) |
|
|
32
32
|
| **Updates** | Changes to subserver NOT reflected | Changes to subserver immediately reflected |
|
|
33
|
-
| **Lifespan** | Not managed | Automatically managed |
|
|
34
|
-
| **Synchronicity** | Async (must be awaited) | Sync |
|
|
35
33
|
| **Best For** | Bundling finalized components | Modular runtime composition |
|
|
36
34
|
|
|
37
35
|
### Proxy Servers
|
|
@@ -184,12 +182,12 @@ if __name__ == "__main__":
|
|
|
184
182
|
|
|
185
183
|
### How Mounting Works
|
|
186
184
|
|
|
187
|
-
|
|
185
|
+
Mounting creates a relationship between two servers where one server (the parent) delegates certain operations to another (the mounted server) based on prefixes. When mounting is configured:
|
|
188
186
|
|
|
189
|
-
1. **Live Link**:
|
|
190
|
-
2. **Dynamic Updates**: Changes made to the
|
|
191
|
-
3. **
|
|
192
|
-
4. **Delegation**: Requests for components matching the prefix are delegated to the
|
|
187
|
+
1. **Live Link**: The parent server establishes a connection to the mounted server.
|
|
188
|
+
2. **Dynamic Updates**: Changes made to the mounted server (e.g., adding new tools) are immediately reflected when accessed through the parent server.
|
|
189
|
+
3. **Prefixed Access**: The parent server uses prefixes to route requests to the mounted server.
|
|
190
|
+
4. **Delegation**: Requests for components matching the prefix are delegated to the mounted server at runtime.
|
|
193
191
|
|
|
194
192
|
The same prefixing rules apply as with `import_server` for naming tools, resources, templates, and prompts.
|
|
195
193
|
|
|
@@ -207,6 +205,49 @@ main_mcp.mount(
|
|
|
207
205
|
)
|
|
208
206
|
```
|
|
209
207
|
|
|
208
|
+
### Direct vs. Proxy Mounting
|
|
209
|
+
|
|
210
|
+
FastMCP supports two modes for mounting servers:
|
|
211
|
+
|
|
212
|
+
1. **Direct Mounting** (default): The parent server directly accesses the mounted server's objects in memory for optimal performance and observability. In this mode:
|
|
213
|
+
- No client lifecycle events occur on the mounted server
|
|
214
|
+
- The mounted server's lifespan context is not executed
|
|
215
|
+
- Communication is handled through direct method calls
|
|
216
|
+
|
|
217
|
+
2. **Proxy Mounting**: The parent server treats the mounted server as a separate entity and communicates with it through a client interface. In this mode:
|
|
218
|
+
- Full client lifecycle events occur on the mounted server
|
|
219
|
+
- The mounted server's lifespan is executed when a client connects
|
|
220
|
+
- Communication happens via an in-memory Client transport
|
|
221
|
+
- This preserves all client-facing behaviors but is slightly less efficient
|
|
222
|
+
|
|
223
|
+
You can control which mode to use with the `as_proxy` parameter:
|
|
224
|
+
|
|
225
|
+
```python
|
|
226
|
+
# Direct mounting (default when no custom lifespan)
|
|
227
|
+
main_mcp.mount("api", api_server)
|
|
228
|
+
|
|
229
|
+
# Proxy mounting (preserves full client lifecycle)
|
|
230
|
+
main_mcp.mount("api", api_server, as_proxy=True)
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
FastMCP automatically uses proxy mounting when the mounted server has a custom lifespan, but you can override this behavior by explicitly setting `as_proxy=False` or `as_proxy=True`.
|
|
234
|
+
|
|
235
|
+
#### Interaction with Proxy Servers
|
|
236
|
+
|
|
237
|
+
When using `FastMCP.from_client()` to create a proxy server, mounting that server will always use proxy mounting since the proxy server is already designed to be accessed via a client interface.
|
|
238
|
+
|
|
239
|
+
```python
|
|
240
|
+
from fastmcp import FastMCP, Client
|
|
241
|
+
|
|
242
|
+
# Create a proxy for a remote server
|
|
243
|
+
remote_proxy = FastMCP.from_client(Client("http://example.com/mcp"))
|
|
244
|
+
|
|
245
|
+
# Mount the proxy - this will preserve full client lifecycle
|
|
246
|
+
main_server.mount("remote", remote_proxy)
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
This is particularly useful for incorporating remote servers into your local application architecture.
|
|
250
|
+
|
|
210
251
|
|
|
211
252
|
## Example: Modular Application
|
|
212
253
|
|
|
@@ -253,7 +253,9 @@ async def request_info(ctx: Context) -> dict:
|
|
|
253
253
|
|
|
254
254
|
### Advanced Access
|
|
255
255
|
|
|
256
|
-
For advanced use cases, you can access the underlying MCP session and
|
|
256
|
+
For advanced use cases, you can access the underlying MCP session, FastMCP server, and HTTP requests.
|
|
257
|
+
|
|
258
|
+
#### Accessing FastMCP and Sessions
|
|
257
259
|
|
|
258
260
|
```python
|
|
259
261
|
@mcp.tool()
|
|
@@ -269,11 +271,35 @@ async def advanced_tool(ctx: Context) -> str:
|
|
|
269
271
|
return f"Server: {server_name}"
|
|
270
272
|
```
|
|
271
273
|
|
|
272
|
-
|
|
274
|
+
#### Accessing HTTP Requests
|
|
275
|
+
|
|
276
|
+
<VersionBadge version="2.2.7" />
|
|
277
|
+
|
|
278
|
+
For web applications, you can access the underlying HTTP request:
|
|
279
|
+
|
|
280
|
+
```python
|
|
281
|
+
@mcp.tool()
|
|
282
|
+
async def handle_web_request(ctx: Context) -> dict:
|
|
283
|
+
"""Access HTTP request information from the Starlette request."""
|
|
284
|
+
request = ctx.get_http_request()
|
|
285
|
+
|
|
286
|
+
# Access HTTP headers, query parameters, etc.
|
|
287
|
+
user_agent = request.headers.get("user-agent", "Unknown")
|
|
288
|
+
client_ip = request.client.host if request.client else "Unknown"
|
|
289
|
+
|
|
290
|
+
return {
|
|
291
|
+
"user_agent": user_agent,
|
|
292
|
+
"client_ip": client_ip,
|
|
293
|
+
"path": request.url.path,
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
#### Advanced Properties Reference
|
|
273
298
|
|
|
274
299
|
- **`ctx.fastmcp -> FastMCP`**: Access the server instance the context belongs to
|
|
275
300
|
- **`ctx.session`**: Access the raw `mcp.server.session.ServerSession` object
|
|
276
301
|
- **`ctx.request_context`**: Access the raw `mcp.shared.context.RequestContext` object
|
|
302
|
+
- **`ctx.get_http_request() -> Request`**: Access the active Starlette request object (when running with a web server)
|
|
277
303
|
|
|
278
304
|
<Warning>
|
|
279
305
|
Direct use of `session` or `request_context` requires understanding the low-level MCP Python SDK and may be less stable than using the methods provided directly on the `Context` object.
|
|
@@ -245,6 +245,7 @@ sub = FastMCP(name="Sub")
|
|
|
245
245
|
def hello():
|
|
246
246
|
return "hi"
|
|
247
247
|
|
|
248
|
+
# Mount directly
|
|
248
249
|
main.mount("sub", sub)
|
|
249
250
|
```
|
|
250
251
|
|
|
@@ -292,4 +293,42 @@ print(mcp.settings.on_duplicate_tools) # Output: "error"
|
|
|
292
293
|
- **`on_duplicate_resources`**: How to handle duplicate resource registrations
|
|
293
294
|
- **`on_duplicate_prompts`**: How to handle duplicate prompt registrations
|
|
294
295
|
|
|
295
|
-
All of these can be configured directly as parameters when creating the `FastMCP` instance.
|
|
296
|
+
All of these can be configured directly as parameters when creating the `FastMCP` instance.
|
|
297
|
+
|
|
298
|
+
## Authentication
|
|
299
|
+
|
|
300
|
+
<VersionBadge version="2.2.7" />
|
|
301
|
+
|
|
302
|
+
FastMCP inherits support for OAuth 2.0 authentication from the MCP protocol, allowing servers to protect their tools and resources behind authentication.
|
|
303
|
+
|
|
304
|
+
### OAuth 2.0 Support
|
|
305
|
+
|
|
306
|
+
The `mcp.server.auth` module implements an OAuth 2.0 server interface that servers can use by providing an implementation of the `OAuthServerProvider` protocol.
|
|
307
|
+
|
|
308
|
+
```python
|
|
309
|
+
from fastmcp import FastMCP
|
|
310
|
+
from mcp.server.auth.settings import (
|
|
311
|
+
RevocationOptions,
|
|
312
|
+
ClientRegistrationOptions,
|
|
313
|
+
AuthSettings,
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
# Create a server with authentication
|
|
318
|
+
mcp = FastMCP(
|
|
319
|
+
name="SecureApp",
|
|
320
|
+
auth_provider=MyOAuthServerProvider(),
|
|
321
|
+
auth=AuthSettings(
|
|
322
|
+
issuer_url="https://myapp.com",
|
|
323
|
+
revocation_options=RevocationOptions(
|
|
324
|
+
enabled=True,
|
|
325
|
+
),
|
|
326
|
+
client_registration_options=ClientRegistrationOptions(
|
|
327
|
+
enabled=True,
|
|
328
|
+
valid_scopes=["myscope", "myotherscope"],
|
|
329
|
+
default_scopes=["myscope"],
|
|
330
|
+
),
|
|
331
|
+
required_scopes=["myscope"],
|
|
332
|
+
),
|
|
333
|
+
)
|
|
334
|
+
```
|
|
@@ -5,6 +5,8 @@ description: Expose functions as executable capabilities for your MCP client.
|
|
|
5
5
|
icon: wrench
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
+
import { VersionBadge } from '/snippets/version-badge.mdx'
|
|
9
|
+
|
|
8
10
|
Tools are the core building blocks that allow your LLM to interact with external systems, execute code, and access data that isn't in its training data. In FastMCP, tools are Python functions exposed to LLMs through the MCP protocol.
|
|
9
11
|
|
|
10
12
|
## What Are Tools?
|
|
@@ -263,8 +265,46 @@ FastMCP automatically catches exceptions raised within your tool function:
|
|
|
263
265
|
|
|
264
266
|
Using informative exceptions helps the LLM understand failures and react appropriately.
|
|
265
267
|
|
|
266
|
-
|
|
268
|
+
### Annotations
|
|
269
|
+
|
|
270
|
+
<VersionBadge version="2.2.7" />
|
|
271
|
+
|
|
272
|
+
FastMCP allows you to add specialized metadata to your tools through annotations. These annotations communicate how tools behave to client applications without consuming token context in LLM prompts.
|
|
273
|
+
|
|
274
|
+
Annotations serve several purposes in client applications:
|
|
275
|
+
- Adding user-friendly titles for display purposes
|
|
276
|
+
- Indicating whether tools modify data or systems
|
|
277
|
+
- Describing the safety profile of tools (destructive vs. non-destructive)
|
|
278
|
+
- Signaling if tools interact with external systems
|
|
267
279
|
|
|
280
|
+
You can add annotations to a tool using the `annotations` parameter in the `@mcp.tool()` decorator:
|
|
281
|
+
|
|
282
|
+
```python
|
|
283
|
+
@mcp.tool(
|
|
284
|
+
annotations={
|
|
285
|
+
"title": "Calculate Sum",
|
|
286
|
+
"readOnlyHint": True,
|
|
287
|
+
"openWorldHint": False
|
|
288
|
+
}
|
|
289
|
+
)
|
|
290
|
+
def calculate_sum(a: float, b: float) -> float:
|
|
291
|
+
"""Add two numbers together."""
|
|
292
|
+
return a + b
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
FastMCP supports these standard annotations:
|
|
296
|
+
|
|
297
|
+
| Annotation | Type | Default | Purpose |
|
|
298
|
+
| :--------- | :--- | :------ | :------ |
|
|
299
|
+
| `title` | string | - | Display name for user interfaces |
|
|
300
|
+
| `readOnlyHint` | boolean | false | Indicates if the tool only reads without making changes |
|
|
301
|
+
| `destructiveHint` | boolean | true | For non-readonly tools, signals if changes are destructive |
|
|
302
|
+
| `idempotentHint` | boolean | false | Indicates if repeated identical calls have the same effect as a single call |
|
|
303
|
+
| `openWorldHint` | boolean | true | Specifies if the tool interacts with external systems |
|
|
304
|
+
|
|
305
|
+
Remember that annotations help make better user experiences but should be treated as advisory hints. They help client applications present appropriate UI elements and safety controls, but won't enforce security boundaries on their own. Always focus on making your annotations accurately represent what your tool actually does.
|
|
306
|
+
|
|
307
|
+
## MCP Context
|
|
268
308
|
|
|
269
309
|
Tools can access MCP features like logging, reading resources, or reporting progress through the `Context` object. To use it, add a parameter to your tool function with the type hint `Context`.
|
|
270
310
|
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
import yaml
|
|
5
|
+
|
|
6
|
+
from fastmcp import FastMCP
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
# Define a simple custom serializer
|
|
10
|
+
def custom_dict_serializer(data: Any) -> str:
|
|
11
|
+
return yaml.dump(data, width=100, sort_keys=False)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
server = FastMCP(name="CustomSerializerExample", tool_serializer=custom_dict_serializer)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@server.tool()
|
|
18
|
+
def get_example_data() -> dict:
|
|
19
|
+
"""Returns some example data."""
|
|
20
|
+
return {"name": "Test", "value": 123, "status": True}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
async def example_usage():
|
|
24
|
+
result = await server._mcp_call_tool("get_example_data", {})
|
|
25
|
+
print("Tool Result:")
|
|
26
|
+
print(result)
|
|
27
|
+
print("This is an example of using a custom serializer with FastMCP.")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
if __name__ == "__main__":
|
|
31
|
+
asyncio.run(example_usage())
|
|
32
|
+
server.run()
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# smart home mcp server
|
|
2
|
+
|
|
3
|
+
```bash
|
|
4
|
+
cd examples/smart_home
|
|
5
|
+
mcp install src/smart_home/hub.py:hub_mcp -f .env
|
|
6
|
+
```
|
|
7
|
+
where `.env` contains the following:
|
|
8
|
+
```
|
|
9
|
+
HUE_BRIDGE_IP=<your hue bridge ip>
|
|
10
|
+
HUE_BRIDGE_USERNAME=<your hue bridge username>
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
open -a Claude
|
|
15
|
+
```
|