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.
Files changed (155) hide show
  1. {fastmcp-2.2.6 → fastmcp-2.2.7}/.github/workflows/run-tests.yml +1 -1
  2. {fastmcp-2.2.6 → fastmcp-2.2.7}/PKG-INFO +3 -3
  3. {fastmcp-2.2.6 → fastmcp-2.2.7}/README.md +1 -1
  4. {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/clients/client.mdx +29 -1
  5. {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/patterns/composition.mdx +48 -7
  6. {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/servers/context.mdx +28 -2
  7. {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/servers/fastmcp.mdx +40 -1
  8. {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/servers/tools.mdx +41 -1
  9. fastmcp-2.2.7/examples/serializer.py +32 -0
  10. fastmcp-2.2.7/examples/smart_home/README.md +15 -0
  11. {fastmcp-2.2.6 → fastmcp-2.2.7}/justfile +1 -1
  12. {fastmcp-2.2.6 → fastmcp-2.2.7}/pyproject.toml +1 -1
  13. fastmcp-2.2.7/src/fastmcp/client/client.py +426 -0
  14. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/contrib/bulk_tool_caller/bulk_tool_caller.py +1 -3
  15. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/prompts/prompt.py +8 -4
  16. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/resources/template.py +5 -2
  17. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/resources/types.py +4 -7
  18. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/server/context.py +12 -1
  19. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/server/openapi.py +28 -5
  20. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/server/proxy.py +3 -2
  21. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/server/server.py +243 -18
  22. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/settings.py +7 -0
  23. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/tools/tool.py +24 -22
  24. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/tools/tool_manager.py +16 -3
  25. fastmcp-2.2.7/src/fastmcp/utilities/http.py +44 -0
  26. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/utilities/openapi.py +147 -36
  27. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/utilities/types.py +29 -1
  28. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/client/test_client.py +106 -0
  29. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/prompts/test_prompt_manager.py +99 -0
  30. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/resources/test_function_resources.py +1 -1
  31. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/resources/test_resource_template.py +114 -1
  32. fastmcp-2.2.7/tests/server/test_auth_integration.py +1263 -0
  33. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/server/test_mount.py +110 -1
  34. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/server/test_openapi.py +737 -0
  35. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/server/test_server_interactions.py +7 -6
  36. fastmcp-2.2.7/tests/server/test_tool_annotations.py +219 -0
  37. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/tools/test_tool_manager.py +65 -13
  38. fastmcp-2.2.7/tests/utilities/test_types.py +145 -0
  39. {fastmcp-2.2.6 → fastmcp-2.2.7}/uv.lock +526 -516
  40. fastmcp-2.2.6/examples/smart_home/README.md +0 -0
  41. fastmcp-2.2.6/src/fastmcp/client/client.py +0 -224
  42. {fastmcp-2.2.6 → fastmcp-2.2.7}/.cursor/rules/core-mcp-objects.mdc +0 -0
  43. {fastmcp-2.2.6 → fastmcp-2.2.7}/.github/ISSUE_TEMPLATE/bug.yml +0 -0
  44. {fastmcp-2.2.6 → fastmcp-2.2.7}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  45. {fastmcp-2.2.6 → fastmcp-2.2.7}/.github/ISSUE_TEMPLATE/enhancement.yml +0 -0
  46. {fastmcp-2.2.6 → fastmcp-2.2.7}/.github/release.yml +0 -0
  47. {fastmcp-2.2.6 → fastmcp-2.2.7}/.github/workflows/publish.yml +0 -0
  48. {fastmcp-2.2.6 → fastmcp-2.2.7}/.github/workflows/run-static.yml +0 -0
  49. {fastmcp-2.2.6 → fastmcp-2.2.7}/.gitignore +0 -0
  50. {fastmcp-2.2.6 → fastmcp-2.2.7}/.pre-commit-config.yaml +0 -0
  51. {fastmcp-2.2.6 → fastmcp-2.2.7}/LICENSE +0 -0
  52. {fastmcp-2.2.6 → fastmcp-2.2.7}/Windows_Notes.md +0 -0
  53. {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/assets/demo-inspector.png +0 -0
  54. {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/clients/transports.mdx +0 -0
  55. {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/docs.json +0 -0
  56. {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/getting-started/installation.mdx +0 -0
  57. {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/getting-started/quickstart.mdx +0 -0
  58. {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/getting-started/welcome.mdx +0 -0
  59. {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/patterns/contrib.mdx +0 -0
  60. {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/patterns/decorating-methods.mdx +0 -0
  61. {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/patterns/fastapi.mdx +0 -0
  62. {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/patterns/openapi.mdx +0 -0
  63. {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/patterns/proxy.mdx +0 -0
  64. {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/patterns/testing.mdx +0 -0
  65. {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/servers/prompts.mdx +0 -0
  66. {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/servers/resources.mdx +0 -0
  67. {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/snippets/version-badge.mdx +0 -0
  68. {fastmcp-2.2.6 → fastmcp-2.2.7}/docs/style.css +0 -0
  69. {fastmcp-2.2.6 → fastmcp-2.2.7}/examples/complex_inputs.py +0 -0
  70. {fastmcp-2.2.6 → fastmcp-2.2.7}/examples/desktop.py +0 -0
  71. {fastmcp-2.2.6 → fastmcp-2.2.7}/examples/echo.py +0 -0
  72. {fastmcp-2.2.6 → fastmcp-2.2.7}/examples/memory.py +0 -0
  73. {fastmcp-2.2.6 → fastmcp-2.2.7}/examples/mount_example.py +0 -0
  74. {fastmcp-2.2.6 → fastmcp-2.2.7}/examples/readme-quickstart.py +0 -0
  75. {fastmcp-2.2.6 → fastmcp-2.2.7}/examples/sampling.py +0 -0
  76. {fastmcp-2.2.6 → fastmcp-2.2.7}/examples/screenshot.py +0 -0
  77. {fastmcp-2.2.6 → fastmcp-2.2.7}/examples/simple_echo.py +0 -0
  78. {fastmcp-2.2.6 → fastmcp-2.2.7}/examples/smart_home/pyproject.toml +0 -0
  79. {fastmcp-2.2.6 → fastmcp-2.2.7}/examples/smart_home/src/smart_home/__init__.py +0 -0
  80. {fastmcp-2.2.6 → fastmcp-2.2.7}/examples/smart_home/src/smart_home/__main__.py +0 -0
  81. {fastmcp-2.2.6 → fastmcp-2.2.7}/examples/smart_home/src/smart_home/hub.py +0 -0
  82. {fastmcp-2.2.6 → fastmcp-2.2.7}/examples/smart_home/src/smart_home/lights/__init__.py +0 -0
  83. {fastmcp-2.2.6 → fastmcp-2.2.7}/examples/smart_home/src/smart_home/lights/hue_utils.py +0 -0
  84. {fastmcp-2.2.6 → fastmcp-2.2.7}/examples/smart_home/src/smart_home/lights/server.py +0 -0
  85. {fastmcp-2.2.6 → fastmcp-2.2.7}/examples/smart_home/src/smart_home/py.typed +0 -0
  86. {fastmcp-2.2.6 → fastmcp-2.2.7}/examples/smart_home/src/smart_home/settings.py +0 -0
  87. {fastmcp-2.2.6 → fastmcp-2.2.7}/examples/smart_home/uv.lock +0 -0
  88. {fastmcp-2.2.6 → fastmcp-2.2.7}/examples/text_me.py +0 -0
  89. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/__init__.py +0 -0
  90. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/cli/__init__.py +0 -0
  91. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/cli/claude.py +0 -0
  92. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/cli/cli.py +0 -0
  93. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/client/__init__.py +0 -0
  94. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/client/base.py +0 -0
  95. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/client/logging.py +0 -0
  96. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/client/roots.py +0 -0
  97. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/client/sampling.py +0 -0
  98. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/client/transports.py +0 -0
  99. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/contrib/README.md +0 -0
  100. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/contrib/bulk_tool_caller/README.md +0 -0
  101. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/contrib/bulk_tool_caller/__init__.py +0 -0
  102. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/contrib/bulk_tool_caller/example.py +0 -0
  103. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/contrib/mcp_mixin/README.md +0 -0
  104. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/contrib/mcp_mixin/__init__.py +0 -0
  105. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/contrib/mcp_mixin/example.py +0 -0
  106. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/contrib/mcp_mixin/mcp_mixin.py +0 -0
  107. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/exceptions.py +0 -0
  108. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/prompts/__init__.py +0 -0
  109. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/prompts/prompt_manager.py +0 -0
  110. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/py.typed +0 -0
  111. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/resources/__init__.py +0 -0
  112. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/resources/resource.py +0 -0
  113. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/resources/resource_manager.py +0 -0
  114. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/server/__init__.py +0 -0
  115. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/tools/__init__.py +0 -0
  116. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/utilities/__init__.py +0 -0
  117. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/utilities/decorators.py +0 -0
  118. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/utilities/func_metadata.py +0 -0
  119. {fastmcp-2.2.6 → fastmcp-2.2.7}/src/fastmcp/utilities/logging.py +0 -0
  120. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/__init__.py +0 -0
  121. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/cli/test_run.py +0 -0
  122. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/client/__init__.py +0 -0
  123. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/client/test_logs.py +0 -0
  124. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/client/test_roots.py +0 -0
  125. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/client/test_sampling.py +0 -0
  126. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/conftest.py +0 -0
  127. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/contrib/__init__.py +0 -0
  128. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/contrib/test_bulk_tool_caller.py +0 -0
  129. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/contrib/test_mcp_mixin.py +0 -0
  130. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/prompts/__init__.py +0 -0
  131. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/prompts/test_base.py +0 -0
  132. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/resources/__init__.py +0 -0
  133. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/resources/test_file_resources.py +0 -0
  134. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/resources/test_resource_manager.py +0 -0
  135. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/resources/test_resources.py +0 -0
  136. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/server/__init__.py +0 -0
  137. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/server/test_file_server.py +0 -0
  138. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/server/test_import_server.py +0 -0
  139. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/server/test_lifespan.py +0 -0
  140. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/server/test_proxy.py +0 -0
  141. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/server/test_run_server.py +0 -0
  142. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/server/test_server.py +0 -0
  143. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/test_servers/fastmcp_server.py +0 -0
  144. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/test_servers/sse.py +0 -0
  145. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/test_servers/stdio.py +0 -0
  146. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/tools/__init__.py +0 -0
  147. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/utilities/__init__.py +0 -0
  148. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/utilities/openapi/__init__.py +0 -0
  149. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/utilities/openapi/conftest.py +0 -0
  150. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/utilities/openapi/test_openapi.py +0 -0
  151. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/utilities/openapi/test_openapi_advanced.py +0 -0
  152. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/utilities/openapi/test_openapi_fastapi.py +0 -0
  153. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/utilities/test_decorated_function.py +0 -0
  154. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/utilities/test_func_metadata.py +0 -0
  155. {fastmcp-2.2.6 → fastmcp-2.2.7}/tests/utilities/test_logging.py +0 -0
@@ -59,4 +59,4 @@ jobs:
59
59
  uv pip install pyreadline3
60
60
 
61
61
  - name: Run tests
62
- run: uv run pytest -vv
62
+ run: uv run --frozen pytest -vv
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastmcp
3
- Version: 2.2.6
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.6.0
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
@@ -760,7 +760,7 @@ Contributions make the open-source community vibrant! We welcome improvements an
760
760
 
761
761
  Run the test suite:
762
762
  ```bash
763
- uv run pytest -vv
763
+ uv run --frozen pytest -vv
764
764
  ```
765
765
 
766
766
  #### 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 call `call_tool(..., _return_raw_result=True)` to get the raw `mcp.types.CallToolResult` object and handle errors yourself by checking its `isError` attribute.
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
- When you call `main_mcp.mount(prefix, server)`:
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**: A live connection is established between `main_mcp` and the `subserver`.
190
- 2. **Dynamic Updates**: Changes made to the `subserver` (e.g., adding new tools) **will be reflected** immediately when accessing components through `main_mcp`.
191
- 3. **Lifespan Management**: The `subserver`'s `lifespan` context **is automatically managed** and executed within the `main_mcp`'s lifespan.
192
- 4. **Delegation**: Requests for components matching the prefix are delegated to the subserver at runtime.
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 FastMCP server.
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
- **Advanced Properties:**
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
- ## MCP Context
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
+ ```
@@ -6,4 +6,4 @@ test: build
6
6
 
7
7
  # Run pyright on all files
8
8
  typecheck:
9
- uv run pyright
9
+ uv run --frozen pyright
@@ -7,7 +7,7 @@ dependencies = [
7
7
  "python-dotenv>=1.1.0",
8
8
  "exceptiongroup>=1.2.2",
9
9
  "httpx>=0.28.1",
10
- "mcp>=1.6.0,<2.0.0",
10
+ "mcp>=1.7.1,<2.0.0",
11
11
  "openapi-pydantic>=0.5.1",
12
12
  "rich>=13.9.4",
13
13
  "typer>=0.15.2",