fastmcp 2.3.5__tar.gz → 2.5.0__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.3.5 → fastmcp-2.5.0}/.github/workflows/run-tests.yml +2 -2
- {fastmcp-2.3.5 → fastmcp-2.5.0}/PKG-INFO +27 -4
- {fastmcp-2.3.5 → fastmcp-2.5.0}/README.md +26 -3
- fastmcp-2.5.0/docs/clients/advanced-features.mdx +152 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/docs/clients/client.mdx +89 -157
- {fastmcp-2.3.5 → fastmcp-2.5.0}/docs/clients/transports.mdx +63 -3
- {fastmcp-2.3.5 → fastmcp-2.5.0}/docs/docs.json +3 -3
- {fastmcp-2.3.5 → fastmcp-2.5.0}/docs/getting-started/installation.mdx +14 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/docs/getting-started/welcome.mdx +4 -8
- fastmcp-2.5.0/docs/patterns/fastapi.mdx +47 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/docs/servers/composition.mdx +59 -32
- {fastmcp-2.3.5 → fastmcp-2.5.0}/docs/servers/context.mdx +4 -3
- fastmcp-2.5.0/docs/servers/openapi.mdx +469 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/docs/servers/proxy.mdx +60 -2
- {fastmcp-2.3.5 → fastmcp-2.5.0}/docs/servers/resources.mdx +15 -6
- {fastmcp-2.3.5 → fastmcp-2.5.0}/docs/servers/tools.mdx +20 -8
- fastmcp-2.5.0/examples/tags_example.py +141 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/pyproject.toml +6 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/client/client.py +44 -6
- fastmcp-2.5.0/src/fastmcp/client/logging.py +27 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/client/transports.py +202 -57
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/prompts/prompt.py +11 -4
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/prompts/prompt_manager.py +25 -5
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/resources/resource_manager.py +31 -5
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/resources/template.py +10 -5
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/server/context.py +46 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/server/http.py +25 -1
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/server/openapi.py +436 -73
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/server/server.py +412 -127
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/settings.py +46 -1
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/tools/tool.py +5 -1
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/tools/tool_manager.py +9 -2
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/utilities/logging.py +6 -1
- fastmcp-2.5.0/src/fastmcp/utilities/mcp_config.py +77 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/utilities/openapi.py +233 -602
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/utilities/tests.py +8 -4
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/client/test_client.py +133 -3
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/client/test_logs.py +2 -2
- fastmcp-2.5.0/tests/client/test_openapi.py +192 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/contrib/test_bulk_tool_caller.py +3 -9
- {fastmcp-2.3.5/tests → fastmcp-2.5.0/tests/deprecated}/test_deprecated.py +80 -2
- fastmcp-2.5.0/tests/deprecated/test_mount_separators.py +85 -0
- fastmcp-2.5.0/tests/deprecated/test_resource_prefixes.py +98 -0
- fastmcp-2.5.0/tests/deprecated/test_route_type_ignore.py +113 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/prompts/test_prompt.py +24 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/prompts/test_prompt_manager.py +46 -2
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/resources/test_resource_manager.py +38 -35
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/resources/test_resource_template.py +25 -0
- fastmcp-2.5.0/tests/server/http/test_custom_routes.py +105 -0
- fastmcp-2.5.0/tests/server/http/test_http_dependencies.py +168 -0
- {fastmcp-2.3.5/tests/server → fastmcp-2.5.0/tests/server/http}/test_http_middleware.py +0 -6
- {fastmcp-2.3.5/tests/server → fastmcp-2.5.0/tests/server/openapi}/test_openapi.py +606 -98
- fastmcp-2.5.0/tests/server/openapi/test_openapi_path_parameters.py +457 -0
- fastmcp-2.5.0/tests/server/openapi/test_route_map_fn.py +377 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/server/test_auth_integration.py +0 -29
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/server/test_context.py +29 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/server/test_import_server.py +19 -23
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/server/test_lifespan.py +163 -3
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/server/test_mount.py +37 -38
- fastmcp-2.5.0/tests/server/test_resource_prefix_formats.py +65 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/server/test_server.py +290 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/server/test_server_interactions.py +46 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/test_examples.py +0 -5
- fastmcp-2.5.0/tests/tools/__init__.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/tools/test_tool.py +31 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/tools/test_tool_manager.py +111 -5
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/utilities/openapi/test_openapi_fastapi.py +9 -9
- fastmcp-2.5.0/tests/utilities/test_mcp_config.py +142 -0
- fastmcp-2.5.0/tests/utilities/test_tests.py +10 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/uv.lock +17 -2
- fastmcp-2.3.5/docs/patterns/fastapi.mdx +0 -144
- fastmcp-2.3.5/docs/patterns/openapi.mdx +0 -226
- fastmcp-2.3.5/src/fastmcp/client/logging.py +0 -21
- fastmcp-2.3.5/tests/server/test_http_dependencies.py +0 -102
- fastmcp-2.3.5/tests/utilities/test_tests.py +0 -9
- {fastmcp-2.3.5 → fastmcp-2.5.0}/.cursor/rules/core-mcp-objects.mdc +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/.github/ISSUE_TEMPLATE/bug.yml +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/.github/ISSUE_TEMPLATE/enhancement.yml +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/.github/labeler.yml +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/.github/release.yml +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/.github/workflows/labeler.yml +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/.github/workflows/publish.yml +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/.github/workflows/run-static.yml +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/.gitignore +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/.pre-commit-config.yaml +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/AGENTS.md +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/LICENSE +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/Windows_Notes.md +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/docs/assets/demo-inspector.png +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/docs/deployment/asgi.mdx +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/docs/deployment/authentication.mdx +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/docs/deployment/cli.mdx +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/docs/deployment/running-server.mdx +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/docs/getting-started/quickstart.mdx +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/docs/patterns/contrib.mdx +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/docs/patterns/decorating-methods.mdx +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/docs/patterns/http-requests.mdx +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/docs/patterns/testing.mdx +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/docs/servers/fastmcp.mdx +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/docs/servers/prompts.mdx +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/docs/snippets/version-badge.mdx +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/docs/style.css +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/examples/complex_inputs.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/examples/desktop.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/examples/echo.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/examples/in_memory_proxy_example.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/examples/memory.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/examples/mount_example.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/examples/sampling.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/examples/screenshot.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/examples/serializer.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/examples/simple_echo.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/examples/smart_home/README.md +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/examples/smart_home/pyproject.toml +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/examples/smart_home/src/smart_home/__init__.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/examples/smart_home/src/smart_home/__main__.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/examples/smart_home/src/smart_home/hub.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/examples/smart_home/src/smart_home/lights/__init__.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/examples/smart_home/src/smart_home/lights/hue_utils.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/examples/smart_home/src/smart_home/lights/server.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/examples/smart_home/src/smart_home/py.typed +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/examples/smart_home/src/smart_home/settings.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/examples/smart_home/uv.lock +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/examples/text_me.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/justfile +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/__init__.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/cli/__init__.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/cli/claude.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/cli/cli.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/cli/run.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/client/__init__.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/client/base.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/client/progress.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/client/roots.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/client/sampling.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/contrib/README.md +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/contrib/bulk_tool_caller/README.md +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/contrib/bulk_tool_caller/__init__.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/contrib/bulk_tool_caller/bulk_tool_caller.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/contrib/bulk_tool_caller/example.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/contrib/mcp_mixin/README.md +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/contrib/mcp_mixin/__init__.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/contrib/mcp_mixin/example.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/contrib/mcp_mixin/mcp_mixin.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/exceptions.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/low_level/README.md +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/low_level/__init__.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/prompts/__init__.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/py.typed +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/resources/__init__.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/resources/resource.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/resources/types.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/server/__init__.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/server/dependencies.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/server/proxy.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/tools/__init__.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/utilities/__init__.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/utilities/cache.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/utilities/decorators.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/utilities/exceptions.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/utilities/json_schema.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/src/fastmcp/utilities/types.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/__init__.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/cli/test_cli.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/cli/test_run.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/client/__init__.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/client/test_progress.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/client/test_roots.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/client/test_sampling.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/client/test_sse.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/client/test_streamable_http.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/conftest.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/contrib/__init__.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/contrib/test_mcp_mixin.py +0 -0
- {fastmcp-2.3.5/tests/prompts → fastmcp-2.5.0/tests/deprecated}/__init__.py +0 -0
- {fastmcp-2.3.5/tests/resources → fastmcp-2.5.0/tests/prompts}/__init__.py +0 -0
- {fastmcp-2.3.5/tests/server → fastmcp-2.5.0/tests/resources}/__init__.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/resources/test_file_resources.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/resources/test_function_resources.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/resources/test_resources.py +0 -0
- {fastmcp-2.3.5/tests/tools → fastmcp-2.5.0/tests/server}/__init__.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/server/test_app_state.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/server/test_file_server.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/server/test_logging.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/server/test_proxy.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/server/test_run_server.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/server/test_tool_annotations.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/test_servers/fastmcp_server.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/test_servers/sse.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/test_servers/stdio.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/utilities/__init__.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/utilities/openapi/__init__.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/utilities/openapi/conftest.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/utilities/openapi/test_openapi.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/utilities/openapi/test_openapi_advanced.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/utilities/test_cache.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/utilities/test_decorated_function.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/utilities/test_json_schema.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/utilities/test_logging.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/utilities/test_typeadapter.py +0 -0
- {fastmcp-2.3.5 → fastmcp-2.5.0}/tests/utilities/test_types.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fastmcp
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.5.0
|
|
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
|
|
@@ -44,11 +44,11 @@ Description-Content-Type: text/markdown
|
|
|
44
44
|
> [!NOTE]
|
|
45
45
|
> #### FastMCP 2.0 & The Official MCP SDK
|
|
46
46
|
>
|
|
47
|
-
>
|
|
47
|
+
> FastMCP is the standard framework for building MCP servers and clients. FastMCP 1.0 was incorporated into the [official MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk).
|
|
48
48
|
>
|
|
49
|
-
> **
|
|
49
|
+
> **This is FastMCP 2.0,** the actively maintained version that significantly expands on 1.0's basic server-building capabilities by introducing full client support, server composition, OpenAPI/FastAPI integration, remote server proxying, built-in testing tools, and more.
|
|
50
50
|
>
|
|
51
|
-
> FastMCP 2.0 is the
|
|
51
|
+
> FastMCP 2.0 is the complete toolkit for modern AI applications. Ready to upgrade or get started? Follow the [installation instructions](https://gofastmcp.com/getting-started/installation), which include specific steps for upgrading from the official MCP SDK.
|
|
52
52
|
|
|
53
53
|
---
|
|
54
54
|
|
|
@@ -282,6 +282,29 @@ async def main():
|
|
|
282
282
|
# ... use the client
|
|
283
283
|
```
|
|
284
284
|
|
|
285
|
+
FastMCP also supports connecting to multiple servers through a single unified client using the standard MCP configuration format:
|
|
286
|
+
|
|
287
|
+
```python
|
|
288
|
+
from fastmcp import Client
|
|
289
|
+
|
|
290
|
+
# Standard MCP configuration with multiple servers
|
|
291
|
+
config = {
|
|
292
|
+
"mcpServers": {
|
|
293
|
+
"weather": {"url": "https://weather-api.example.com/mcp"},
|
|
294
|
+
"assistant": {"command": "python", "args": ["./assistant_server.py"]}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
# Create a client that connects to all servers
|
|
299
|
+
client = Client(config)
|
|
300
|
+
|
|
301
|
+
async def main():
|
|
302
|
+
async with client:
|
|
303
|
+
# Access tools and resources with server prefixes
|
|
304
|
+
forecast = await client.call_tool("weather_get_forecast", {"city": "London"})
|
|
305
|
+
answer = await client.call_tool("assistant_answer_question", {"query": "What is MCP?"})
|
|
306
|
+
```
|
|
307
|
+
|
|
285
308
|
Learn more in the [**Client Documentation**](https://gofastmcp.com/clients/client) and [**Transports Documentation**](https://gofastmcp.com/clients/transports).
|
|
286
309
|
|
|
287
310
|
## Advanced Features
|
|
@@ -15,11 +15,11 @@
|
|
|
15
15
|
> [!NOTE]
|
|
16
16
|
> #### FastMCP 2.0 & The Official MCP SDK
|
|
17
17
|
>
|
|
18
|
-
>
|
|
18
|
+
> FastMCP is the standard framework for building MCP servers and clients. FastMCP 1.0 was incorporated into the [official MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk).
|
|
19
19
|
>
|
|
20
|
-
> **
|
|
20
|
+
> **This is FastMCP 2.0,** the actively maintained version that significantly expands on 1.0's basic server-building capabilities by introducing full client support, server composition, OpenAPI/FastAPI integration, remote server proxying, built-in testing tools, and more.
|
|
21
21
|
>
|
|
22
|
-
> FastMCP 2.0 is the
|
|
22
|
+
> FastMCP 2.0 is the complete toolkit for modern AI applications. Ready to upgrade or get started? Follow the [installation instructions](https://gofastmcp.com/getting-started/installation), which include specific steps for upgrading from the official MCP SDK.
|
|
23
23
|
|
|
24
24
|
---
|
|
25
25
|
|
|
@@ -253,6 +253,29 @@ async def main():
|
|
|
253
253
|
# ... use the client
|
|
254
254
|
```
|
|
255
255
|
|
|
256
|
+
FastMCP also supports connecting to multiple servers through a single unified client using the standard MCP configuration format:
|
|
257
|
+
|
|
258
|
+
```python
|
|
259
|
+
from fastmcp import Client
|
|
260
|
+
|
|
261
|
+
# Standard MCP configuration with multiple servers
|
|
262
|
+
config = {
|
|
263
|
+
"mcpServers": {
|
|
264
|
+
"weather": {"url": "https://weather-api.example.com/mcp"},
|
|
265
|
+
"assistant": {"command": "python", "args": ["./assistant_server.py"]}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
# Create a client that connects to all servers
|
|
270
|
+
client = Client(config)
|
|
271
|
+
|
|
272
|
+
async def main():
|
|
273
|
+
async with client:
|
|
274
|
+
# Access tools and resources with server prefixes
|
|
275
|
+
forecast = await client.call_tool("weather_get_forecast", {"city": "London"})
|
|
276
|
+
answer = await client.call_tool("assistant_answer_question", {"query": "What is MCP?"})
|
|
277
|
+
```
|
|
278
|
+
|
|
256
279
|
Learn more in the [**Client Documentation**](https://gofastmcp.com/clients/client) and [**Transports Documentation**](https://gofastmcp.com/clients/transports).
|
|
257
280
|
|
|
258
281
|
## Advanced Features
|
|
@@ -0,0 +1,152 @@
|
|
|
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>
|
|
@@ -37,13 +37,14 @@ Clients must be initialized with a `transport`. You can either provide an alread
|
|
|
37
37
|
The following inference rules are used to determine the appropriate `ClientTransport` based on the input type:
|
|
38
38
|
|
|
39
39
|
1. **`ClientTransport` Instance**: If you provide an already instantiated transport object, it's used directly.
|
|
40
|
-
2. **`FastMCP` Instance**: Creates a `FastMCPTransport` for efficient in-memory communication (ideal for testing).
|
|
40
|
+
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`.
|
|
41
41
|
3. **`Path` or `str` pointing to an existing file**:
|
|
42
42
|
* If it ends with `.py`: Creates a `PythonStdioTransport` to run the script using `python`.
|
|
43
43
|
* If it ends with `.js`: Creates a `NodeStdioTransport` to run the script using `node`.
|
|
44
44
|
4. **`AnyUrl` or `str` pointing to a URL that begins with `http://` or `https://`**:
|
|
45
45
|
* Creates a `StreamableHttpTransport`
|
|
46
|
-
5.
|
|
46
|
+
5. **`MCPConfig` or dictionary matching MCPConfig schema**: Creates a client that connects to one or more MCP servers specified in the config.
|
|
47
|
+
6. **Other**: Raises a `ValueError` if the type cannot be inferred.
|
|
47
48
|
|
|
48
49
|
```python
|
|
49
50
|
import asyncio
|
|
@@ -52,30 +53,100 @@ from fastmcp import Client, FastMCP
|
|
|
52
53
|
# Example transports (more details in Transports page)
|
|
53
54
|
server_instance = FastMCP(name="TestServer") # In-memory server
|
|
54
55
|
http_url = "https://example.com/mcp" # HTTP server URL
|
|
55
|
-
ws_url = "ws://localhost:9000" # WebSocket server URL
|
|
56
56
|
server_script = "my_mcp_server.py" # Path to a Python server file
|
|
57
57
|
|
|
58
58
|
# Client automatically infers the transport type
|
|
59
59
|
client_in_memory = Client(server_instance)
|
|
60
60
|
client_http = Client(http_url)
|
|
61
|
-
|
|
61
|
+
|
|
62
62
|
client_stdio = Client(server_script)
|
|
63
63
|
|
|
64
64
|
print(client_in_memory.transport)
|
|
65
65
|
print(client_http.transport)
|
|
66
|
-
print(client_ws.transport)
|
|
67
66
|
print(client_stdio.transport)
|
|
68
67
|
|
|
69
68
|
# Expected Output (types may vary slightly based on environment):
|
|
70
69
|
# <FastMCP(server='TestServer')>
|
|
71
70
|
# <StreamableHttp(url='https://example.com/mcp')>
|
|
72
|
-
# <WebSocket(url='ws://localhost:9000')>
|
|
73
71
|
# <PythonStdioTransport(command='python', args=['/path/to/your/my_mcp_server.py'])>
|
|
74
72
|
```
|
|
73
|
+
|
|
74
|
+
You can also initialize a client from an MCP configuration dictionary or `MCPConfig` file:
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
from fastmcp import Client
|
|
78
|
+
|
|
79
|
+
config = {
|
|
80
|
+
"mcpServers": {
|
|
81
|
+
"local": {"command": "python", "args": ["local_server.py"]},
|
|
82
|
+
"remote": {"url": "https://example.com/mcp"},
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
client_config = Client(config)
|
|
87
|
+
```
|
|
75
88
|
<Tip>
|
|
76
89
|
For more control over connection details (like headers for SSE, environment variables for Stdio), you can instantiate the specific `ClientTransport` class yourself and pass it to the `Client`. See the [Transports](/clients/transports) page for details.
|
|
77
90
|
</Tip>
|
|
78
91
|
|
|
92
|
+
### Multi-Server Clients
|
|
93
|
+
|
|
94
|
+
<VersionBadge version="2.4.0" />
|
|
95
|
+
|
|
96
|
+
FastMCP supports creating clients that connect to multiple MCP servers through a single client interface using a standard MCP configuration format (`MCPConfig`). This configuration approach makes it easy to connect to multiple specialized servers or create composable systems with a simple, declarative syntax.
|
|
97
|
+
|
|
98
|
+
<Note>
|
|
99
|
+
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.
|
|
100
|
+
</Note>
|
|
101
|
+
|
|
102
|
+
When you create a client with an `MCPConfig` containing multiple servers:
|
|
103
|
+
|
|
104
|
+
1. FastMCP creates a composite client that internally mounts all servers using their config names as prefixes
|
|
105
|
+
2. Tools and resources from each server are accessible with appropriate prefixes in the format `servername_toolname` and `protocol://servername/resource/path`
|
|
106
|
+
3. You interact with this as a single unified client, with requests automatically routed to the appropriate server
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
from fastmcp import Client
|
|
110
|
+
|
|
111
|
+
# Create a standard MCP configuration with multiple servers
|
|
112
|
+
config = {
|
|
113
|
+
"mcpServers": {
|
|
114
|
+
# A remote HTTP server
|
|
115
|
+
"weather": {
|
|
116
|
+
"url": "https://weather-api.example.com/mcp",
|
|
117
|
+
"transport": "streamable-http"
|
|
118
|
+
},
|
|
119
|
+
# A local server running via stdio
|
|
120
|
+
"assistant": {
|
|
121
|
+
"command": "python",
|
|
122
|
+
"args": ["./my_assistant_server.py"],
|
|
123
|
+
"env": {"DEBUG": "true"}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
# Create a client that connects to both servers
|
|
129
|
+
client = Client(config)
|
|
130
|
+
|
|
131
|
+
async def main():
|
|
132
|
+
async with client:
|
|
133
|
+
# Access tools from different servers with prefixes
|
|
134
|
+
weather_data = await client.call_tool("weather_get_forecast", {"city": "London"})
|
|
135
|
+
response = await client.call_tool("assistant_answer_question", {"question": "What's the capital of France?"})
|
|
136
|
+
|
|
137
|
+
# Access resources with prefixed URIs
|
|
138
|
+
weather_icons = await client.read_resource("weather://weather/icons/sunny")
|
|
139
|
+
templates = await client.read_resource("resource://assistant/templates/list")
|
|
140
|
+
|
|
141
|
+
print(f"Weather: {weather_data}")
|
|
142
|
+
print(f"Assistant: {response}")
|
|
143
|
+
|
|
144
|
+
if __name__ == "__main__":
|
|
145
|
+
asyncio.run(main())
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
If your configuration has only a single server, FastMCP will create a direct client to that server without any prefixing.
|
|
149
|
+
|
|
79
150
|
## Client Usage
|
|
80
151
|
|
|
81
152
|
### Connection Lifecycle
|
|
@@ -209,11 +280,19 @@ Available raw MCP methods:
|
|
|
209
280
|
|
|
210
281
|
These methods are especially useful for debugging or when you need to access metadata or fields that aren't exposed by the simplified methods.
|
|
211
282
|
|
|
212
|
-
###
|
|
283
|
+
### Additional Features
|
|
284
|
+
|
|
285
|
+
#### Pinging the server
|
|
213
286
|
|
|
214
|
-
|
|
287
|
+
The client can be used to ping the server to verify connectivity.
|
|
288
|
+
|
|
289
|
+
```python
|
|
290
|
+
async with client:
|
|
291
|
+
await client.ping()
|
|
292
|
+
print("Server is reachable")
|
|
293
|
+
```
|
|
215
294
|
|
|
216
|
-
####
|
|
295
|
+
#### Timeouts
|
|
217
296
|
|
|
218
297
|
<VersionBadge version="2.3.4" />
|
|
219
298
|
|
|
@@ -253,154 +332,7 @@ Timeout behavior varies between transport types:
|
|
|
253
332
|
For consistent behavior across all transports, we recommend explicitly setting timeouts at the individual tool call level when needed, rather than relying on client-level timeouts.
|
|
254
333
|
</Warning>
|
|
255
334
|
|
|
256
|
-
####
|
|
257
|
-
|
|
258
|
-
<VersionBadge version="2.3.5" />
|
|
259
|
-
|
|
260
|
-
MCP servers can report progress during long-running operations. The client can set a progress handler to receive and process these updates.
|
|
261
|
-
|
|
262
|
-
```python
|
|
263
|
-
from fastmcp import Client
|
|
264
|
-
from fastmcp.client.progress import ProgressHandler
|
|
265
|
-
|
|
266
|
-
# A simple progress handler that prints progress updates
|
|
267
|
-
async def my_progress_handler(
|
|
268
|
-
progress: float,
|
|
269
|
-
total: float | None,
|
|
270
|
-
message: str | None
|
|
271
|
-
) -> None:
|
|
272
|
-
"""Handle progress updates from the server."""
|
|
273
|
-
if total is not None:
|
|
274
|
-
percent = (progress / total) * 100
|
|
275
|
-
print(f"Progress: {percent:.1f}% ({progress}/{total})")
|
|
276
|
-
else:
|
|
277
|
-
print(f"Progress: {progress}")
|
|
278
|
-
|
|
279
|
-
if message:
|
|
280
|
-
print(f"Message: {message}")
|
|
281
|
-
|
|
282
|
-
# Set the progress handler at client level
|
|
283
|
-
client = Client(
|
|
284
|
-
my_mcp_server,
|
|
285
|
-
progress_handler=my_progress_handler
|
|
286
|
-
)
|
|
287
|
-
```
|
|
288
|
-
|
|
289
|
-
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.
|
|
290
|
-
|
|
291
|
-
You can override the progress handler for specific tool calls:
|
|
292
|
-
|
|
293
|
-
```python
|
|
294
|
-
# Client uses the default debug logger for progress
|
|
295
|
-
client = Client(my_mcp_server)
|
|
296
|
-
|
|
297
|
-
async with client:
|
|
298
|
-
# Use default progress handler (debug logging)
|
|
299
|
-
result1 = await client.call_tool("long_task", {"param": "value"})
|
|
300
|
-
|
|
301
|
-
# Override with custom progress handler just for this call
|
|
302
|
-
result2 = await client.call_tool(
|
|
303
|
-
"another_task",
|
|
304
|
-
{"param": "value"},
|
|
305
|
-
progress_handler=my_progress_handler
|
|
306
|
-
)
|
|
307
|
-
```
|
|
308
|
-
|
|
309
|
-
A typical progress update includes:
|
|
310
|
-
- Current progress value (e.g., 2 of 5 steps completed)
|
|
311
|
-
- Total expected value (may be None)
|
|
312
|
-
- Status message (may be None)
|
|
313
|
-
|
|
314
|
-
#### LLM Sampling
|
|
315
|
-
|
|
316
|
-
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.
|
|
317
|
-
|
|
318
|
-
The following example uses the `marvin` library to generate a completion:
|
|
319
|
-
|
|
320
|
-
```python {8-17, 21}
|
|
321
|
-
import marvin
|
|
322
|
-
from fastmcp import Client
|
|
323
|
-
from fastmcp.client.sampling import (
|
|
324
|
-
SamplingMessage,
|
|
325
|
-
SamplingParams,
|
|
326
|
-
RequestContext,
|
|
327
|
-
)
|
|
328
|
-
|
|
329
|
-
async def sampling_handler(
|
|
330
|
-
messages: list[SamplingMessage],
|
|
331
|
-
params: SamplingParams,
|
|
332
|
-
context: RequestContext
|
|
333
|
-
) -> str:
|
|
334
|
-
return await marvin.say_async(
|
|
335
|
-
message=[m.content.text for m in messages],
|
|
336
|
-
instructions=params.systemPrompt,
|
|
337
|
-
)
|
|
338
|
-
|
|
339
|
-
client = Client(
|
|
340
|
-
...,
|
|
341
|
-
sampling_handler=sampling_handler,
|
|
342
|
-
)
|
|
343
|
-
```
|
|
344
|
-
|
|
345
|
-
#### Logging
|
|
346
|
-
|
|
347
|
-
MCP servers can emit logs to clients. The client can set a logging callback to receive these logs.
|
|
348
|
-
|
|
349
|
-
```python {4-5, 9}
|
|
350
|
-
from fastmcp import Client
|
|
351
|
-
from fastmcp.client.logging import LogHandler, LogMessage
|
|
352
|
-
|
|
353
|
-
async def my_log_handler(params: LogMessage):
|
|
354
|
-
print(f"[Server Log - {params.level.upper()}] {params.logger or 'default'}: {params.data}")
|
|
355
|
-
|
|
356
|
-
client_with_logging = Client(
|
|
357
|
-
...,
|
|
358
|
-
log_handler=my_log_handler,
|
|
359
|
-
)
|
|
360
|
-
```
|
|
361
|
-
|
|
362
|
-
#### Roots
|
|
363
|
-
|
|
364
|
-
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.
|
|
365
|
-
|
|
366
|
-
Servers can request roots from clients, and clients can notify servers when their roots change.
|
|
367
|
-
|
|
368
|
-
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.
|
|
369
|
-
|
|
370
|
-
<CodeGroup>
|
|
371
|
-
```python Static Roots {5}
|
|
372
|
-
from fastmcp import Client
|
|
373
|
-
|
|
374
|
-
client = Client(
|
|
375
|
-
...,
|
|
376
|
-
roots=["/path/to/root1", "/path/to/root2"],
|
|
377
|
-
)
|
|
378
|
-
```
|
|
379
|
-
```python Dynamic Roots Callback {4-6, 10}
|
|
380
|
-
from fastmcp import Client
|
|
381
|
-
from fastmcp.client.roots import RequestContext
|
|
382
|
-
|
|
383
|
-
async def roots_callback(context: RequestContext) -> list[str]:
|
|
384
|
-
print(f"Server requested roots (Request ID: {context.request_id})")
|
|
385
|
-
return ["/path/to/root1", "/path/to/root2"]
|
|
386
|
-
|
|
387
|
-
client = Client(
|
|
388
|
-
...,
|
|
389
|
-
roots=roots_callback,
|
|
390
|
-
)
|
|
391
|
-
```
|
|
392
|
-
</CodeGroup>
|
|
393
|
-
### Utility Methods
|
|
394
|
-
|
|
395
|
-
* **`ping()`**: Sends a ping request to the server to verify connectivity.
|
|
396
|
-
```python
|
|
397
|
-
async def check_connection():
|
|
398
|
-
async with client:
|
|
399
|
-
await client.ping()
|
|
400
|
-
print("Server is reachable")
|
|
401
|
-
```
|
|
402
|
-
|
|
403
|
-
### Error Handling
|
|
335
|
+
#### Error Handling
|
|
404
336
|
|
|
405
337
|
When a `call_tool` request results in an error on the server (e.g., the tool function raised an exception), the `client.call_tool()` method will raise a `fastmcp.client.ClientError`.
|
|
406
338
|
|
|
@@ -290,8 +290,8 @@ asyncio.run(main())
|
|
|
290
290
|
### FastMCP Transport
|
|
291
291
|
|
|
292
292
|
- **Class:** `fastmcp.client.transports.FastMCPTransport`
|
|
293
|
-
- **Inferred From:** An instance of `fastmcp.server.FastMCP`
|
|
294
|
-
- **Use Case:** Connecting directly to a
|
|
293
|
+
- **Inferred From:** An instance of `fastmcp.server.FastMCP` or a **FastMCP 1.0 server** (`mcp.server.fastmcp.FastMCP`)
|
|
294
|
+
- **Use Case:** Connecting directly to a FastMCP server instance in the same Python process
|
|
295
295
|
|
|
296
296
|
This is extremely useful for testing your FastMCP servers.
|
|
297
297
|
|
|
@@ -317,4 +317,64 @@ async def main():
|
|
|
317
317
|
asyncio.run(main())
|
|
318
318
|
```
|
|
319
319
|
|
|
320
|
-
Communication happens through efficient in-memory queues, making it very fast and ideal for unit testing.
|
|
320
|
+
Communication happens through efficient in-memory queues, making it very fast and ideal for unit testing.
|
|
321
|
+
|
|
322
|
+
## Configuration-Based Transports
|
|
323
|
+
|
|
324
|
+
### MCPConfig Transport
|
|
325
|
+
|
|
326
|
+
<VersionBadge version="2.4.0" />
|
|
327
|
+
|
|
328
|
+
- **Class:** `fastmcp.client.transports.MCPConfigTransport`
|
|
329
|
+
- **Inferred From:** An instance of `MCPConfig` or a dictionary matching the MCPConfig schema
|
|
330
|
+
- **Use Case:** Connecting to one or more MCP servers defined in a configuration object
|
|
331
|
+
|
|
332
|
+
MCPConfig follows an emerging standard for MCP server configuration but is subject to change as the specification evolves. The standard supports both local servers (running via stdio) and remote servers (accessed via HTTP).
|
|
333
|
+
|
|
334
|
+
```python
|
|
335
|
+
from fastmcp import Client
|
|
336
|
+
|
|
337
|
+
# Configuration for multiple MCP servers (both local and remote)
|
|
338
|
+
config = {
|
|
339
|
+
"mcpServers": {
|
|
340
|
+
# Remote HTTP server
|
|
341
|
+
"weather": {
|
|
342
|
+
"url": "https://weather-api.example.com/mcp",
|
|
343
|
+
"transport": "streamable-http"
|
|
344
|
+
},
|
|
345
|
+
# Local stdio server
|
|
346
|
+
"assistant": {
|
|
347
|
+
"command": "python",
|
|
348
|
+
"args": ["./assistant_server.py"],
|
|
349
|
+
"env": {"DEBUG": "true"}
|
|
350
|
+
},
|
|
351
|
+
# Another remote server
|
|
352
|
+
"calendar": {
|
|
353
|
+
"url": "https://calendar-api.example.com/mcp",
|
|
354
|
+
"transport": "streamable-http"
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
# Create a transport from the config (happens automatically with Client)
|
|
360
|
+
client = Client(config)
|
|
361
|
+
|
|
362
|
+
async def main():
|
|
363
|
+
async with client:
|
|
364
|
+
# Tools are accessible with server name prefixes
|
|
365
|
+
weather = await client.call_tool("weather_get_forecast", {"city": "London"})
|
|
366
|
+
answer = await client.call_tool("assistant_answer_question", {"query": "What is MCP?"})
|
|
367
|
+
events = await client.call_tool("calendar_list_events", {"date": "2023-06-01"})
|
|
368
|
+
|
|
369
|
+
# Resources use prefixed URI paths
|
|
370
|
+
icons = await client.read_resource("weather://weather/icons/sunny")
|
|
371
|
+
docs = await client.read_resource("resource://assistant/docs/mcp")
|
|
372
|
+
|
|
373
|
+
asyncio.run(main())
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
If your configuration has only a single server, the client will connect directly to that server without any prefixing. This makes it convenient to switch between single and multi-server configurations without changing your client code.
|
|
377
|
+
|
|
378
|
+
<Note>
|
|
379
|
+
The MCPConfig format is an emerging standard for MCP server configuration and may change as the MCP ecosystem evolves. While FastMCP aims to maintain compatibility with future versions, be aware that field names or structure might change.
|
|
380
|
+
</Note>
|
|
@@ -50,6 +50,7 @@
|
|
|
50
50
|
"servers/resources",
|
|
51
51
|
"servers/prompts",
|
|
52
52
|
"servers/context",
|
|
53
|
+
"servers/openapi",
|
|
53
54
|
"servers/proxy",
|
|
54
55
|
"servers/composition"
|
|
55
56
|
]
|
|
@@ -67,7 +68,8 @@
|
|
|
67
68
|
"group": "Clients",
|
|
68
69
|
"pages": [
|
|
69
70
|
"clients/client",
|
|
70
|
-
"clients/transports"
|
|
71
|
+
"clients/transports",
|
|
72
|
+
"clients/advanced-features"
|
|
71
73
|
]
|
|
72
74
|
},
|
|
73
75
|
{
|
|
@@ -75,8 +77,6 @@
|
|
|
75
77
|
"pages": [
|
|
76
78
|
"patterns/decorating-methods",
|
|
77
79
|
"patterns/http-requests",
|
|
78
|
-
"patterns/openapi",
|
|
79
|
-
"patterns/fastapi",
|
|
80
80
|
"patterns/contrib",
|
|
81
81
|
"patterns/testing"
|
|
82
82
|
]
|