fastmcp 2.5.0__tar.gz → 2.5.2__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 (199) hide show
  1. {fastmcp-2.5.0 → fastmcp-2.5.2}/PKG-INFO +1 -1
  2. {fastmcp-2.5.0 → fastmcp-2.5.2}/docs/clients/client.mdx +24 -13
  3. {fastmcp-2.5.0 → fastmcp-2.5.2}/docs/clients/transports.mdx +58 -1
  4. {fastmcp-2.5.0 → fastmcp-2.5.2}/docs/deployment/cli.mdx +6 -3
  5. {fastmcp-2.5.0 → fastmcp-2.5.2}/docs/patterns/http-requests.mdx +25 -17
  6. {fastmcp-2.5.0 → fastmcp-2.5.2}/docs/servers/openapi.mdx +2 -8
  7. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/cli/cli.py +1 -3
  8. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/client/client.py +83 -15
  9. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/client/transports.py +183 -48
  10. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/resources/template.py +1 -1
  11. fastmcp-2.5.2/src/fastmcp/server/dependencies.py +78 -0
  12. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/server/openapi.py +3 -22
  13. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/server/server.py +43 -16
  14. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/settings.py +7 -0
  15. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/tools/tool.py +4 -2
  16. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/client/test_openapi.py +22 -5
  17. fastmcp-2.5.2/tests/client/test_stdio.py +127 -0
  18. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/server/test_mount.py +76 -1
  19. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/server/test_proxy.py +9 -0
  20. fastmcp-2.5.0/src/fastmcp/server/dependencies.py +0 -35
  21. {fastmcp-2.5.0 → fastmcp-2.5.2}/.cursor/rules/core-mcp-objects.mdc +0 -0
  22. {fastmcp-2.5.0 → fastmcp-2.5.2}/.github/ISSUE_TEMPLATE/bug.yml +0 -0
  23. {fastmcp-2.5.0 → fastmcp-2.5.2}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  24. {fastmcp-2.5.0 → fastmcp-2.5.2}/.github/ISSUE_TEMPLATE/enhancement.yml +0 -0
  25. {fastmcp-2.5.0 → fastmcp-2.5.2}/.github/labeler.yml +0 -0
  26. {fastmcp-2.5.0 → fastmcp-2.5.2}/.github/release.yml +0 -0
  27. {fastmcp-2.5.0 → fastmcp-2.5.2}/.github/workflows/labeler.yml +0 -0
  28. {fastmcp-2.5.0 → fastmcp-2.5.2}/.github/workflows/publish.yml +0 -0
  29. {fastmcp-2.5.0 → fastmcp-2.5.2}/.github/workflows/run-static.yml +0 -0
  30. {fastmcp-2.5.0 → fastmcp-2.5.2}/.github/workflows/run-tests.yml +0 -0
  31. {fastmcp-2.5.0 → fastmcp-2.5.2}/.gitignore +0 -0
  32. {fastmcp-2.5.0 → fastmcp-2.5.2}/.pre-commit-config.yaml +0 -0
  33. {fastmcp-2.5.0 → fastmcp-2.5.2}/AGENTS.md +0 -0
  34. {fastmcp-2.5.0 → fastmcp-2.5.2}/LICENSE +0 -0
  35. {fastmcp-2.5.0 → fastmcp-2.5.2}/README.md +0 -0
  36. {fastmcp-2.5.0 → fastmcp-2.5.2}/Windows_Notes.md +0 -0
  37. {fastmcp-2.5.0 → fastmcp-2.5.2}/docs/assets/demo-inspector.png +0 -0
  38. {fastmcp-2.5.0 → fastmcp-2.5.2}/docs/clients/advanced-features.mdx +0 -0
  39. {fastmcp-2.5.0 → fastmcp-2.5.2}/docs/deployment/asgi.mdx +0 -0
  40. {fastmcp-2.5.0 → fastmcp-2.5.2}/docs/deployment/authentication.mdx +0 -0
  41. {fastmcp-2.5.0 → fastmcp-2.5.2}/docs/deployment/running-server.mdx +0 -0
  42. {fastmcp-2.5.0 → fastmcp-2.5.2}/docs/docs.json +0 -0
  43. {fastmcp-2.5.0 → fastmcp-2.5.2}/docs/getting-started/installation.mdx +0 -0
  44. {fastmcp-2.5.0 → fastmcp-2.5.2}/docs/getting-started/quickstart.mdx +0 -0
  45. {fastmcp-2.5.0 → fastmcp-2.5.2}/docs/getting-started/welcome.mdx +0 -0
  46. {fastmcp-2.5.0 → fastmcp-2.5.2}/docs/patterns/contrib.mdx +0 -0
  47. {fastmcp-2.5.0 → fastmcp-2.5.2}/docs/patterns/decorating-methods.mdx +0 -0
  48. {fastmcp-2.5.0 → fastmcp-2.5.2}/docs/patterns/fastapi.mdx +0 -0
  49. {fastmcp-2.5.0 → fastmcp-2.5.2}/docs/patterns/testing.mdx +0 -0
  50. {fastmcp-2.5.0 → fastmcp-2.5.2}/docs/servers/composition.mdx +0 -0
  51. {fastmcp-2.5.0 → fastmcp-2.5.2}/docs/servers/context.mdx +0 -0
  52. {fastmcp-2.5.0 → fastmcp-2.5.2}/docs/servers/fastmcp.mdx +0 -0
  53. {fastmcp-2.5.0 → fastmcp-2.5.2}/docs/servers/prompts.mdx +0 -0
  54. {fastmcp-2.5.0 → fastmcp-2.5.2}/docs/servers/proxy.mdx +0 -0
  55. {fastmcp-2.5.0 → fastmcp-2.5.2}/docs/servers/resources.mdx +0 -0
  56. {fastmcp-2.5.0 → fastmcp-2.5.2}/docs/servers/tools.mdx +0 -0
  57. {fastmcp-2.5.0 → fastmcp-2.5.2}/docs/snippets/version-badge.mdx +0 -0
  58. {fastmcp-2.5.0 → fastmcp-2.5.2}/docs/style.css +0 -0
  59. {fastmcp-2.5.0 → fastmcp-2.5.2}/examples/complex_inputs.py +0 -0
  60. {fastmcp-2.5.0 → fastmcp-2.5.2}/examples/desktop.py +0 -0
  61. {fastmcp-2.5.0 → fastmcp-2.5.2}/examples/echo.py +0 -0
  62. {fastmcp-2.5.0 → fastmcp-2.5.2}/examples/in_memory_proxy_example.py +0 -0
  63. {fastmcp-2.5.0 → fastmcp-2.5.2}/examples/memory.py +0 -0
  64. {fastmcp-2.5.0 → fastmcp-2.5.2}/examples/mount_example.py +0 -0
  65. {fastmcp-2.5.0 → fastmcp-2.5.2}/examples/sampling.py +0 -0
  66. {fastmcp-2.5.0 → fastmcp-2.5.2}/examples/screenshot.py +0 -0
  67. {fastmcp-2.5.0 → fastmcp-2.5.2}/examples/serializer.py +0 -0
  68. {fastmcp-2.5.0 → fastmcp-2.5.2}/examples/simple_echo.py +0 -0
  69. {fastmcp-2.5.0 → fastmcp-2.5.2}/examples/smart_home/README.md +0 -0
  70. {fastmcp-2.5.0 → fastmcp-2.5.2}/examples/smart_home/pyproject.toml +0 -0
  71. {fastmcp-2.5.0 → fastmcp-2.5.2}/examples/smart_home/src/smart_home/__init__.py +0 -0
  72. {fastmcp-2.5.0 → fastmcp-2.5.2}/examples/smart_home/src/smart_home/__main__.py +0 -0
  73. {fastmcp-2.5.0 → fastmcp-2.5.2}/examples/smart_home/src/smart_home/hub.py +0 -0
  74. {fastmcp-2.5.0 → fastmcp-2.5.2}/examples/smart_home/src/smart_home/lights/__init__.py +0 -0
  75. {fastmcp-2.5.0 → fastmcp-2.5.2}/examples/smart_home/src/smart_home/lights/hue_utils.py +0 -0
  76. {fastmcp-2.5.0 → fastmcp-2.5.2}/examples/smart_home/src/smart_home/lights/server.py +0 -0
  77. {fastmcp-2.5.0 → fastmcp-2.5.2}/examples/smart_home/src/smart_home/py.typed +0 -0
  78. {fastmcp-2.5.0 → fastmcp-2.5.2}/examples/smart_home/src/smart_home/settings.py +0 -0
  79. {fastmcp-2.5.0 → fastmcp-2.5.2}/examples/smart_home/uv.lock +0 -0
  80. {fastmcp-2.5.0 → fastmcp-2.5.2}/examples/tags_example.py +0 -0
  81. {fastmcp-2.5.0 → fastmcp-2.5.2}/examples/text_me.py +0 -0
  82. {fastmcp-2.5.0 → fastmcp-2.5.2}/justfile +0 -0
  83. {fastmcp-2.5.0 → fastmcp-2.5.2}/pyproject.toml +0 -0
  84. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/__init__.py +0 -0
  85. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/cli/__init__.py +0 -0
  86. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/cli/claude.py +0 -0
  87. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/cli/run.py +0 -0
  88. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/client/__init__.py +0 -0
  89. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/client/base.py +0 -0
  90. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/client/logging.py +0 -0
  91. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/client/progress.py +0 -0
  92. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/client/roots.py +0 -0
  93. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/client/sampling.py +0 -0
  94. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/contrib/README.md +0 -0
  95. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/contrib/bulk_tool_caller/README.md +0 -0
  96. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/contrib/bulk_tool_caller/__init__.py +0 -0
  97. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/contrib/bulk_tool_caller/bulk_tool_caller.py +0 -0
  98. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/contrib/bulk_tool_caller/example.py +0 -0
  99. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/contrib/mcp_mixin/README.md +0 -0
  100. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/contrib/mcp_mixin/__init__.py +0 -0
  101. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/contrib/mcp_mixin/example.py +0 -0
  102. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/contrib/mcp_mixin/mcp_mixin.py +0 -0
  103. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/exceptions.py +0 -0
  104. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/low_level/README.md +0 -0
  105. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/low_level/__init__.py +0 -0
  106. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/prompts/__init__.py +0 -0
  107. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/prompts/prompt.py +0 -0
  108. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/prompts/prompt_manager.py +0 -0
  109. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/py.typed +0 -0
  110. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/resources/__init__.py +0 -0
  111. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/resources/resource.py +0 -0
  112. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/resources/resource_manager.py +0 -0
  113. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/resources/types.py +0 -0
  114. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/server/__init__.py +0 -0
  115. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/server/context.py +0 -0
  116. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/server/http.py +0 -0
  117. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/server/proxy.py +0 -0
  118. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/tools/__init__.py +0 -0
  119. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/tools/tool_manager.py +0 -0
  120. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/utilities/__init__.py +0 -0
  121. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/utilities/cache.py +0 -0
  122. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/utilities/decorators.py +0 -0
  123. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/utilities/exceptions.py +0 -0
  124. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/utilities/json_schema.py +0 -0
  125. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/utilities/logging.py +0 -0
  126. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/utilities/mcp_config.py +0 -0
  127. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/utilities/openapi.py +0 -0
  128. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/utilities/tests.py +0 -0
  129. {fastmcp-2.5.0 → fastmcp-2.5.2}/src/fastmcp/utilities/types.py +0 -0
  130. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/__init__.py +0 -0
  131. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/cli/test_cli.py +0 -0
  132. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/cli/test_run.py +0 -0
  133. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/client/__init__.py +0 -0
  134. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/client/test_client.py +0 -0
  135. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/client/test_logs.py +0 -0
  136. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/client/test_progress.py +0 -0
  137. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/client/test_roots.py +0 -0
  138. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/client/test_sampling.py +0 -0
  139. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/client/test_sse.py +0 -0
  140. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/client/test_streamable_http.py +0 -0
  141. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/conftest.py +0 -0
  142. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/contrib/__init__.py +0 -0
  143. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/contrib/test_bulk_tool_caller.py +0 -0
  144. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/contrib/test_mcp_mixin.py +0 -0
  145. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/deprecated/__init__.py +0 -0
  146. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/deprecated/test_deprecated.py +0 -0
  147. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/deprecated/test_mount_separators.py +0 -0
  148. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/deprecated/test_resource_prefixes.py +0 -0
  149. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/deprecated/test_route_type_ignore.py +0 -0
  150. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/prompts/__init__.py +0 -0
  151. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/prompts/test_prompt.py +0 -0
  152. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/prompts/test_prompt_manager.py +0 -0
  153. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/resources/__init__.py +0 -0
  154. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/resources/test_file_resources.py +0 -0
  155. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/resources/test_function_resources.py +0 -0
  156. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/resources/test_resource_manager.py +0 -0
  157. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/resources/test_resource_template.py +0 -0
  158. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/resources/test_resources.py +0 -0
  159. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/server/__init__.py +0 -0
  160. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/server/http/test_custom_routes.py +0 -0
  161. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/server/http/test_http_dependencies.py +0 -0
  162. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/server/http/test_http_middleware.py +0 -0
  163. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/server/openapi/test_openapi.py +0 -0
  164. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/server/openapi/test_openapi_path_parameters.py +0 -0
  165. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/server/openapi/test_route_map_fn.py +0 -0
  166. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/server/test_app_state.py +0 -0
  167. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/server/test_auth_integration.py +0 -0
  168. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/server/test_context.py +0 -0
  169. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/server/test_file_server.py +0 -0
  170. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/server/test_import_server.py +0 -0
  171. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/server/test_lifespan.py +0 -0
  172. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/server/test_logging.py +0 -0
  173. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/server/test_resource_prefix_formats.py +0 -0
  174. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/server/test_run_server.py +0 -0
  175. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/server/test_server.py +0 -0
  176. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/server/test_server_interactions.py +0 -0
  177. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/server/test_tool_annotations.py +0 -0
  178. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/test_examples.py +0 -0
  179. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/test_servers/fastmcp_server.py +0 -0
  180. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/test_servers/sse.py +0 -0
  181. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/test_servers/stdio.py +0 -0
  182. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/tools/__init__.py +0 -0
  183. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/tools/test_tool.py +0 -0
  184. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/tools/test_tool_manager.py +0 -0
  185. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/utilities/__init__.py +0 -0
  186. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/utilities/openapi/__init__.py +0 -0
  187. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/utilities/openapi/conftest.py +0 -0
  188. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/utilities/openapi/test_openapi.py +0 -0
  189. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/utilities/openapi/test_openapi_advanced.py +0 -0
  190. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/utilities/openapi/test_openapi_fastapi.py +0 -0
  191. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/utilities/test_cache.py +0 -0
  192. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/utilities/test_decorated_function.py +0 -0
  193. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/utilities/test_json_schema.py +0 -0
  194. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/utilities/test_logging.py +0 -0
  195. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/utilities/test_mcp_config.py +0 -0
  196. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/utilities/test_tests.py +0 -0
  197. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/utilities/test_typeadapter.py +0 -0
  198. {fastmcp-2.5.0 → fastmcp-2.5.2}/tests/utilities/test_types.py +0 -0
  199. {fastmcp-2.5.0 → fastmcp-2.5.2}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastmcp
3
- Version: 2.5.0
3
+ Version: 2.5.2
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
@@ -18,18 +18,6 @@ The FastMCP Client architecture separates the protocol logic (`Client`) from the
18
18
  - **`Client`**: Handles sending MCP requests (like `tools/call`, `resources/read`), receiving responses, and managing callbacks.
19
19
  - **`Transport`**: Responsible for establishing and maintaining the connection to the server (e.g., via WebSockets, SSE, Stdio, or in-memory).
20
20
 
21
- ```python
22
- from fastmcp import Client, FastMCP
23
- from fastmcp.client import (
24
- RootsHandler,
25
- RootsList,
26
- LogHandler,
27
- MessageHandler,
28
- SamplingHandler,
29
- ProgressHandler # For handling progress notifications
30
- )
31
- ```
32
-
33
21
  ### Transports
34
22
 
35
23
  Clients must be initialized with a `transport`. You can either provide an already instantiated transport object, or provide a transport source and let FastMCP attempt to infer the correct transport to use.
@@ -282,7 +270,7 @@ These methods are especially useful for debugging or when you need to access met
282
270
 
283
271
  ### Additional Features
284
272
 
285
- #### Pinging the server
273
+ #### Pinging the Server
286
274
 
287
275
  The client can be used to ping the server to verify connectivity.
288
276
 
@@ -292,6 +280,29 @@ async with client:
292
280
  print("Server is reachable")
293
281
  ```
294
282
 
283
+ #### Session Management
284
+
285
+ When using stdio transports, clients support a `keep_alive` feature (enabled by default) that maintains subprocess sessions between connection contexts. You can manually control this behavior using the client's `close()` method.
286
+
287
+ When `keep_alive=False`, the client will automatically close the session when the context manager exits.
288
+
289
+ ```python
290
+ from fastmcp import Client
291
+
292
+ client = Client("my_mcp_server.py") # keep_alive=True by default
293
+
294
+ async def example():
295
+ async with client:
296
+ await client.ping()
297
+
298
+ async with client:
299
+ await client.ping() # Same subprocess as above
300
+ ```
301
+
302
+ <Note>
303
+ For detailed examples and configuration options, see [Session Management in Transports](/clients/transports#session-management).
304
+ </Note>
305
+
295
306
  #### Timeouts
296
307
 
297
308
  <VersionBadge version="2.3.4" />
@@ -160,6 +160,63 @@ client = Client(transport)
160
160
 
161
161
  These transports manage an MCP server running as a subprocess, communicating with it via standard input (stdin) and standard output (stdout). This is the standard mechanism used by clients like Claude Desktop.
162
162
 
163
+ ### Session Management
164
+
165
+ All stdio transports support a `keep_alive` parameter (default: `True`) that controls session persistence across multiple client context managers:
166
+
167
+ - **`keep_alive=True` (default)**: The subprocess and session are maintained between client context exits and re-entries. This improves performance when making multiple separate connections to the same server.
168
+ - **`keep_alive=False`**: A new subprocess is started for each client context, ensuring complete isolation between sessions.
169
+
170
+ When `keep_alive=True`, you can manually close the session using `await client.close()` if needed. This will terminate the subprocess and require a new one to be started on the next connection.
171
+
172
+ <CodeGroup>
173
+ ```python keep_alive=True
174
+ from fastmcp import Client
175
+
176
+ # Client with keep_alive=True (default)
177
+ client = Client("my_mcp_server.py")
178
+
179
+ async def example():
180
+ # First session
181
+ async with client:
182
+ await client.ping()
183
+
184
+ # Second session - uses the same subprocess
185
+ async with client:
186
+ await client.ping()
187
+
188
+ # Manually close the session
189
+ await client.close()
190
+
191
+ # Third session - will start a new subprocess
192
+ async with client:
193
+ await client.ping()
194
+
195
+ asyncio.run(example())
196
+ ```
197
+ ```python keep_alive=False
198
+ from fastmcp import Client
199
+
200
+ # Client with keep_alive=False
201
+ client = Client("my_mcp_server.py", keep_alive=False)
202
+
203
+ async def example():
204
+ # First session
205
+ async with client:
206
+ await client.ping()
207
+
208
+ # Second session - will start a new subprocess
209
+ async with client:
210
+ await client.ping()
211
+
212
+ # Third session - will start a new subprocess
213
+ async with client:
214
+ await client.ping()
215
+
216
+ asyncio.run(example())
217
+ ```
218
+ </CodeGroup>
219
+
163
220
  ### Python Stdio
164
221
 
165
222
  - **Class:** `fastmcp.client.transports.PythonStdioTransport`
@@ -218,7 +275,7 @@ client = Client(node_server_script)
218
275
  # Option 2: Explicit transport
219
276
  transport = NodeStdioTransport(
220
277
  script_path=node_server_script,
221
- node_cmd="node" # Optional: specify path to Node executable
278
+ node_cmd="node", # Optional: specify path to Node executable
222
279
  )
223
280
  client = Client(transport)
224
281
 
@@ -148,9 +148,12 @@ Install a MCP server in the Claude desktop app.
148
148
  fastmcp install server.py
149
149
  ```
150
150
 
151
- <Tip>
152
- This command installs your server in an isolated environment. All dependencies must be explicitly specified using the `--with` and/or `--with-editable` options.
153
- </Tip>
151
+
152
+ Note that for security reasons, Claude runs every MCP server in a completely isolated environment. Therefore, all dependencies must be explicitly specified using the `--with` and/or `--with-editable` options (following `uv` conventions) or by attaching them to your server in code via the `dependencies` parameter.
153
+ <Warning>
154
+ - **`uv` must be installed and available in your system PATH**. Claude Desktop runs in its own isolated environment and needs `uv` to manage dependencies.
155
+ - **On macOS, it is recommended to install `uv` globally with Homebrew** so that Claude Desktop will detect it: `brew install uv`. Installing `uv` with other methods may not make it accessible to Claude Desktop.
156
+ </Warning>
154
157
 
155
158
  <Warning>
156
159
  The `install` command currently only sets up servers for STDIO transport. When installed in the Claude desktop app, your server will be run using STDIO regardless of any transport configuration in your code.
@@ -23,7 +23,7 @@ from fastmcp import FastMCP
23
23
  from fastmcp.server.dependencies import get_http_request
24
24
  from starlette.requests import Request
25
25
 
26
- mcp = FastMCP(name="HTTPRequestDemo")
26
+ mcp = FastMCP(name="HTTP Request Demo")
27
27
 
28
28
  @mcp.tool()
29
29
  async def user_agent_info() -> dict:
@@ -48,32 +48,40 @@ This approach works anywhere within a request's execution flow, not just within
48
48
  2. You're calling nested functions that need HTTP request data
49
49
  3. You're working with middleware or other request processing code
50
50
 
51
- ## Important Notes
52
-
53
- - HTTP requests are only available when FastMCP is running as part of a web application
54
- - Accessing the HTTP request outside of a web request context will raise a `RuntimeError`
55
- - The `get_http_request()` function returns a standard [Starlette Request](https://www.starlette.io/requests/) object
51
+ ## Accessing HTTP Headers Only
56
52
 
57
- ## Common Use Cases
53
+ If you only need request headers and want to avoid potential errors, you can use the `get_http_headers()` helper:
58
54
 
59
- ### Accessing Request Headers
55
+ ```python {2}
56
+ from fastmcp import FastMCP
57
+ from fastmcp.server.dependencies import get_http_headers
60
58
 
61
- ```python
62
- from fastmcp.server.dependencies import get_http_request
59
+ mcp = FastMCP(name="Headers Demo")
63
60
 
64
61
  @mcp.tool()
65
- async def get_auth_info() -> dict:
66
- """Get authentication information from request headers."""
67
- request = get_http_request()
62
+ async def safe_header_info() -> dict:
63
+ """Safely get header information without raising errors."""
64
+ # Get headers (returns empty dict if no request context)
65
+ headers = get_http_headers()
68
66
 
69
67
  # Get authorization header
70
- auth_header = request.headers.get("authorization", "")
71
-
72
- # Check for Bearer token
68
+ auth_header = headers.get("authorization", "")
73
69
  is_bearer = auth_header.startswith("Bearer ")
74
70
 
75
71
  return {
72
+ "user_agent": headers.get("user-agent", "Unknown"),
73
+ "content_type": headers.get("content-type", "Unknown"),
76
74
  "has_auth": bool(auth_header),
77
- "auth_type": "Bearer" if is_bearer else "Other" if auth_header else "None"
75
+ "auth_type": "Bearer" if is_bearer else "Other" if auth_header else "None",
76
+ "headers_count": len(headers)
78
77
  }
79
78
  ```
79
+
80
+ By default, `get_http_headers()` excludes problematic headers like `host` and `content-length`. To include all headers, use `get_http_headers(include_all=True)`.
81
+
82
+ ## Important Notes
83
+
84
+ - HTTP requests are only available when FastMCP is running as part of a web application
85
+ - Accessing the HTTP request with `get_http_request()` outside of a web request context will raise a `RuntimeError`
86
+ - The `get_http_headers()` function **never raises errors** - it returns an empty dict when no request context is available
87
+ - The `get_http_request()` function returns a standard [Starlette Request](https://www.starlette.io/requests/) object
@@ -51,13 +51,7 @@ FastMCP analyzes your API specification and automatically creates MCP components
51
51
  | `GET` without path params | `GET /stats` | **Resource** |
52
52
  | `POST`, `PUT`, `PATCH`, `DELETE`, etc. | `POST /users` | **Tool** |
53
53
 
54
-
55
-
56
- ### Custom Route Maps
57
-
58
- <VersionBadge version="2.5.0" />
59
-
60
- FastMCP uses an ordered list of `RouteMap` objects to determine how to map OpenAPI routes to various MCP component types.
54
+ Interally, FastMCP uses an ordered list of `RouteMap` objects to determine how to map OpenAPI routes to various MCP component types.
61
55
 
62
56
  Each `RouteMap` specifies a combination of methods, patterns, and tags, as well as a corresponding MCP component type. Each OpenAPI route is checked against each `RouteMap` in order, and the first one that matches every criteria is used to determine its converted MCP type. A special type, `EXCLUDE`, can be used to exclude routes from the MCP server entirely.
63
57
 
@@ -66,7 +60,7 @@ Each `RouteMap` specifies a combination of methods, patterns, and tags, as well
66
60
  - **Tags**: A set of OpenAPI tags that must all be present. An empty set (`{}`) means no tag filtering, so the route matches regardless of its tags.
67
61
  - **MCP type**: What MCP component type to create (`TOOL`, `RESOURCE`, `RESOURCE_TEMPLATE`, or `EXCLUDE`)
68
62
 
69
- To illustrate this in practice, here are FastMCP's default route mappings as a list of `RouteMap` objects:
63
+ To illustrate this in practice, here are FastMCP's default rules as a list of `RouteMap` objects:
70
64
 
71
65
  ```python
72
66
  from fastmcp.server.openapi import RouteMap, MCPType
@@ -50,9 +50,7 @@ def _get_npx_command():
50
50
  def _parse_env_var(env_var: str) -> tuple[str, str]:
51
51
  """Parse environment variable string in format KEY=VALUE."""
52
52
  if "=" not in env_var:
53
- logger.error(
54
- f"Invalid environment variable format: {env_var}. Must be KEY=VALUE"
55
- )
53
+ logger.error("Invalid environment variable format. Must be KEY=VALUE")
56
54
  sys.exit(1)
57
55
  key, value = env_var.split("=", 1)
58
56
  return key.strip(), value.strip()
@@ -1,7 +1,7 @@
1
1
  import datetime
2
2
  from contextlib import AsyncExitStack, asynccontextmanager
3
3
  from pathlib import Path
4
- from typing import Any, cast
4
+ from typing import Any, Generic, cast, overload
5
5
 
6
6
  import anyio
7
7
  import mcp.types
@@ -9,6 +9,7 @@ from exceptiongroup import catch
9
9
  from mcp import ClientSession
10
10
  from pydantic import AnyUrl
11
11
 
12
+ import fastmcp
12
13
  from fastmcp.client.logging import (
13
14
  LogHandler,
14
15
  MessageHandler,
@@ -27,7 +28,18 @@ from fastmcp.server import FastMCP
27
28
  from fastmcp.utilities.exceptions import get_catch_handlers
28
29
  from fastmcp.utilities.mcp_config import MCPConfig
29
30
 
30
- from .transports import ClientTransport, SessionKwargs, infer_transport
31
+ from .transports import (
32
+ ClientTransportT,
33
+ FastMCP1Server,
34
+ FastMCPTransport,
35
+ MCPConfigTransport,
36
+ NodeStdioTransport,
37
+ PythonStdioTransport,
38
+ SessionKwargs,
39
+ SSETransport,
40
+ StreamableHttpTransport,
41
+ infer_transport,
42
+ )
31
43
 
32
44
  __all__ = [
33
45
  "Client",
@@ -40,13 +52,13 @@ __all__ = [
40
52
  ]
41
53
 
42
54
 
43
- class Client:
55
+ class Client(Generic[ClientTransportT]):
44
56
  """
45
57
  MCP client that delegates connection management to a Transport instance.
46
58
 
47
59
  The Client class is responsible for MCP protocol logic, while the Transport
48
- handles connection establishment and management. Client provides methods
49
- for working with resources, prompts, tools and other MCP capabilities.
60
+ handles connection establishment and management. Client provides methods for
61
+ working with resources, prompts, tools and other MCP capabilities.
50
62
 
51
63
  Args:
52
64
  transport: Connection source specification, which can be:
@@ -62,24 +74,60 @@ class Client:
62
74
  message_handler: Optional handler for protocol messages
63
75
  progress_handler: Optional handler for progress notifications
64
76
  timeout: Optional timeout for requests (seconds or timedelta)
77
+ init_timeout: Optional timeout for initial connection (seconds or timedelta).
78
+ Set to 0 to disable. If None, uses the value in the FastMCP global settings.
65
79
 
66
80
  Examples:
67
- ```python
68
- # Connect to FastMCP server
69
- client = Client("http://localhost:8080")
81
+ ```python # Connect to FastMCP server client =
82
+ Client("http://localhost:8080")
70
83
 
71
84
  async with client:
72
- # List available resources
73
- resources = await client.list_resources()
85
+ # List available resources resources = await client.list_resources()
74
86
 
75
- # Call a tool
76
- result = await client.call_tool("my_tool", {"param": "value"})
87
+ # Call a tool result = await client.call_tool("my_tool", {"param":
88
+ "value"})
77
89
  ```
78
90
  """
79
91
 
92
+ @overload
93
+ def __new__(
94
+ cls,
95
+ transport: ClientTransportT,
96
+ **kwargs: Any,
97
+ ) -> "Client[ClientTransportT]": ...
98
+
99
+ @overload
100
+ def __new__(
101
+ cls, transport: AnyUrl, **kwargs
102
+ ) -> "Client[SSETransport|StreamableHttpTransport]": ...
103
+
104
+ @overload
105
+ def __new__(
106
+ cls, transport: FastMCP | FastMCP1Server, **kwargs
107
+ ) -> "Client[FastMCPTransport]": ...
108
+
109
+ @overload
110
+ def __new__(
111
+ cls, transport: Path, **kwargs
112
+ ) -> "Client[PythonStdioTransport|NodeStdioTransport]": ...
113
+
114
+ @overload
115
+ def __new__(
116
+ cls, transport: MCPConfig | dict[str, Any], **kwargs
117
+ ) -> "Client[MCPConfigTransport]": ...
118
+
119
+ @overload
120
+ def __new__(
121
+ cls, transport: str, **kwargs
122
+ ) -> "Client[PythonStdioTransport|NodeStdioTransport|SSETransport|StreamableHttpTransport]": ...
123
+
124
+ def __new__(cls, transport, **kwargs) -> "Client":
125
+ instance = super().__new__(cls)
126
+ return instance
127
+
80
128
  def __init__(
81
129
  self,
82
- transport: ClientTransport
130
+ transport: ClientTransportT
83
131
  | FastMCP
84
132
  | AnyUrl
85
133
  | Path
@@ -93,8 +141,9 @@ class Client:
93
141
  message_handler: MessageHandler | None = None,
94
142
  progress_handler: ProgressHandler | None = None,
95
143
  timeout: datetime.timedelta | float | int | None = None,
144
+ init_timeout: datetime.timedelta | float | int | None = None,
96
145
  ):
97
- self.transport = infer_transport(transport)
146
+ self.transport = cast(ClientTransportT, infer_transport(transport))
98
147
  self._session: ClientSession | None = None
99
148
  self._exit_stack: AsyncExitStack | None = None
100
149
  self._nesting_counter: int = 0
@@ -111,6 +160,17 @@ class Client:
111
160
  if isinstance(timeout, int | float):
112
161
  timeout = datetime.timedelta(seconds=timeout)
113
162
 
163
+ # handle init handshake timeout
164
+ if init_timeout is None:
165
+ init_timeout = fastmcp.settings.settings.client_init_timeout
166
+ if isinstance(init_timeout, datetime.timedelta):
167
+ init_timeout = init_timeout.total_seconds()
168
+ elif not init_timeout:
169
+ init_timeout = None
170
+ else:
171
+ init_timeout = float(init_timeout)
172
+ self._init_timeout = init_timeout
173
+
114
174
  self._session_kwargs: SessionKwargs = {
115
175
  "sampling_callback": None,
116
176
  "list_roots_callback": None,
@@ -134,6 +194,7 @@ class Client:
134
194
  raise RuntimeError(
135
195
  "Client is not connected. Use the 'async with client:' context manager first."
136
196
  )
197
+
137
198
  return self._session
138
199
 
139
200
  @property
@@ -168,9 +229,11 @@ class Client:
168
229
  self._session = session
169
230
  # Initialize the session
170
231
  try:
171
- with anyio.fail_after(1):
232
+ with anyio.fail_after(self._init_timeout):
172
233
  self._initialize_result = await self._session.initialize()
173
234
  yield
235
+ except anyio.ClosedResourceError:
236
+ raise RuntimeError("Server session was closed unexpectedly")
174
237
  except TimeoutError:
175
238
  raise RuntimeError("Failed to initialize server session")
176
239
  finally:
@@ -203,6 +266,11 @@ class Client:
203
266
  finally:
204
267
  self._exit_stack = None
205
268
 
269
+ async def close(self):
270
+ await self.transport.close()
271
+ self._session = None
272
+ self._initialize_result = None
273
+
206
274
  # --- MCP Client Methods ---
207
275
 
208
276
  async def ping(self) -> bool: