fastmcp 2.10.1__tar.gz → 2.10.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 (375) hide show
  1. {fastmcp-2.10.1 → fastmcp-2.10.2}/PKG-INFO +1 -1
  2. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/clients/client.mdx +1 -1
  3. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/integrations/chatgpt.mdx +2 -1
  4. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/patterns/cli.mdx +1 -0
  5. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/patterns/testing.mdx +12 -2
  6. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/servers/composition.mdx +1 -1
  7. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/servers/proxy.mdx +6 -0
  8. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/tutorials/rest-api.mdx +1 -1
  9. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/cli/cli.py +16 -1
  10. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/cli/run.py +4 -0
  11. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/client/elicitation.py +5 -0
  12. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/client/transports.py +2 -4
  13. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/server/auth/providers/bearer.py +15 -6
  14. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/server/proxy.py +116 -0
  15. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/server/server.py +71 -18
  16. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/settings.py +19 -1
  17. fastmcp-2.10.2/src/fastmcp/utilities/cli.py +102 -0
  18. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/utilities/logging.py +3 -0
  19. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/utilities/mcp_config.py +12 -2
  20. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/utilities/tests.py +13 -0
  21. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/utilities/types.py +4 -3
  22. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/auth/providers/test_bearer.py +53 -0
  23. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/cli/test_cli.py +3 -2
  24. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/client/test_elicitation.py +36 -3
  25. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/client/test_openapi.py +1 -2
  26. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/client/test_streamable_http.py +15 -4
  27. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/deprecated/test_settings.py +6 -3
  28. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/prompts/test_prompt_manager.py +8 -2
  29. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/resources/test_resource_manager.py +7 -2
  30. fastmcp-2.10.2/tests/server/openapi/conftest.py +135 -0
  31. fastmcp-2.10.2/tests/server/openapi/test_advanced_behavior.py +312 -0
  32. fastmcp-2.10.2/tests/server/openapi/test_basic_functionality.py +344 -0
  33. fastmcp-2.10.2/tests/server/openapi/test_configuration.py +930 -0
  34. fastmcp-2.10.2/tests/server/openapi/test_description_propagation.py +795 -0
  35. fastmcp-2.10.2/tests/server/openapi/test_openapi_compatibility.py +661 -0
  36. fastmcp-2.10.2/tests/server/proxy/test_proxy_client.py +257 -0
  37. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/server/test_import_server.py +4 -4
  38. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/server/test_mount.py +28 -34
  39. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/server/test_proxy.py +3 -3
  40. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/tools/test_tool.py +2 -2
  41. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/tools/test_tool_manager.py +5 -2
  42. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/tools/test_tool_transform.py +1 -1
  43. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/utilities/test_mcp_config.py +89 -0
  44. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/utilities/test_types.py +54 -0
  45. fastmcp-2.10.1/tests/server/openapi/test_openapi.py +0 -2840
  46. {fastmcp-2.10.1 → fastmcp-2.10.2}/.ccignore +0 -0
  47. {fastmcp-2.10.1 → fastmcp-2.10.2}/.cursor/rules/core-mcp-objects.mdc +0 -0
  48. {fastmcp-2.10.1 → fastmcp-2.10.2}/.github/ISSUE_TEMPLATE/bug.yml +0 -0
  49. {fastmcp-2.10.1 → fastmcp-2.10.2}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  50. {fastmcp-2.10.1 → fastmcp-2.10.2}/.github/ISSUE_TEMPLATE/enhancement.yml +0 -0
  51. {fastmcp-2.10.1 → fastmcp-2.10.2}/.github/dependabot.yml +0 -0
  52. {fastmcp-2.10.1 → fastmcp-2.10.2}/.github/labeler.yml +0 -0
  53. {fastmcp-2.10.1 → fastmcp-2.10.2}/.github/release.yml +0 -0
  54. {fastmcp-2.10.1 → fastmcp-2.10.2}/.github/workflows/labeler.yml +0 -0
  55. {fastmcp-2.10.1 → fastmcp-2.10.2}/.github/workflows/publish.yml +0 -0
  56. {fastmcp-2.10.1 → fastmcp-2.10.2}/.github/workflows/run-static.yml +0 -0
  57. {fastmcp-2.10.1 → fastmcp-2.10.2}/.github/workflows/run-tests.yml +0 -0
  58. {fastmcp-2.10.1 → fastmcp-2.10.2}/.gitignore +0 -0
  59. {fastmcp-2.10.1 → fastmcp-2.10.2}/.pre-commit-config.yaml +0 -0
  60. {fastmcp-2.10.1 → fastmcp-2.10.2}/AGENTS.md +0 -0
  61. {fastmcp-2.10.1 → fastmcp-2.10.2}/CLAUDE.md +0 -0
  62. {fastmcp-2.10.1 → fastmcp-2.10.2}/LICENSE +0 -0
  63. {fastmcp-2.10.1 → fastmcp-2.10.2}/README.md +0 -0
  64. {fastmcp-2.10.1 → fastmcp-2.10.2}/Windows_Notes.md +0 -0
  65. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/.cursor/rules/mintlify.mdc +0 -0
  66. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/assets/demo-inspector.png +0 -0
  67. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/assets/favicon.ico +0 -0
  68. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/assets/images/tutorial-rest-api-result.png +0 -0
  69. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/assets/logo.png +0 -0
  70. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/assets/updates/release-2-7.png +0 -0
  71. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/changelog.mdx +0 -0
  72. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/clients/auth/bearer.mdx +0 -0
  73. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/clients/auth/oauth.mdx +0 -0
  74. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/clients/elicitation.mdx +0 -0
  75. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/clients/logging.mdx +0 -0
  76. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/clients/messages.mdx +0 -0
  77. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/clients/progress.mdx +0 -0
  78. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/clients/prompts.mdx +0 -0
  79. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/clients/resources.mdx +0 -0
  80. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/clients/roots.mdx +0 -0
  81. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/clients/sampling.mdx +0 -0
  82. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/clients/tools.mdx +0 -0
  83. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/clients/transports.mdx +0 -0
  84. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/community/README.md +0 -0
  85. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/community/showcase.mdx +0 -0
  86. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/css/banner.css +0 -0
  87. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/css/python-sdk.css +0 -0
  88. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/css/style.css +0 -0
  89. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/css/version-badge.css +0 -0
  90. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/deployment/asgi.mdx +0 -0
  91. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/deployment/running-server.mdx +0 -0
  92. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/docs.json +0 -0
  93. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/getting-started/installation.mdx +0 -0
  94. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/getting-started/quickstart.mdx +0 -0
  95. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/getting-started/welcome.mdx +0 -0
  96. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/integrations/anthropic.mdx +0 -0
  97. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/integrations/claude-code.mdx +0 -0
  98. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/integrations/claude-desktop.mdx +0 -0
  99. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/integrations/contrib.mdx +0 -0
  100. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/integrations/eunomia-authorization.mdx +0 -0
  101. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/integrations/gemini.mdx +0 -0
  102. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/integrations/openai.mdx +0 -0
  103. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/patterns/decorating-methods.mdx +0 -0
  104. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/patterns/http-requests.mdx +0 -0
  105. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/patterns/tool-transformation.mdx +0 -0
  106. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-cli-__init__.mdx +0 -0
  107. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-cli-claude.mdx +0 -0
  108. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-cli-cli.mdx +0 -0
  109. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-cli-run.mdx +0 -0
  110. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-client-__init__.mdx +0 -0
  111. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-client-auth-__init__.mdx +0 -0
  112. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-client-auth-bearer.mdx +0 -0
  113. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-client-auth-oauth.mdx +0 -0
  114. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-client-client.mdx +0 -0
  115. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-client-logging.mdx +0 -0
  116. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-client-oauth_callback.mdx +0 -0
  117. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-client-progress.mdx +0 -0
  118. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-client-roots.mdx +0 -0
  119. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-client-sampling.mdx +0 -0
  120. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-client-transports.mdx +0 -0
  121. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-exceptions.mdx +0 -0
  122. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-prompts-__init__.mdx +0 -0
  123. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-prompts-prompt.mdx +0 -0
  124. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-prompts-prompt_manager.mdx +0 -0
  125. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-resources-__init__.mdx +0 -0
  126. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-resources-resource.mdx +0 -0
  127. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-resources-resource_manager.mdx +0 -0
  128. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-resources-template.mdx +0 -0
  129. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-resources-types.mdx +0 -0
  130. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-server-__init__.mdx +0 -0
  131. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-server-auth-__init__.mdx +0 -0
  132. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-server-auth-auth.mdx +0 -0
  133. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-server-auth-providers-__init__.mdx +0 -0
  134. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-server-auth-providers-bearer.mdx +0 -0
  135. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-server-auth-providers-bearer_env.mdx +0 -0
  136. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-server-auth-providers-in_memory.mdx +0 -0
  137. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-server-context.mdx +0 -0
  138. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-server-dependencies.mdx +0 -0
  139. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-server-http.mdx +0 -0
  140. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-server-middleware-__init__.mdx +0 -0
  141. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-server-middleware-error_handling.mdx +0 -0
  142. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-server-middleware-logging.mdx +0 -0
  143. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-server-middleware-middleware.mdx +0 -0
  144. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-server-middleware-rate_limiting.mdx +0 -0
  145. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-server-middleware-timing.mdx +0 -0
  146. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-server-middleware.mdx +0 -0
  147. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-server-openapi.mdx +0 -0
  148. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-server-proxy.mdx +0 -0
  149. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-server-server.mdx +0 -0
  150. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-settings.mdx +0 -0
  151. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-tools-__init__.mdx +0 -0
  152. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-tools-tool.mdx +0 -0
  153. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-tools-tool_manager.mdx +0 -0
  154. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-tools-tool_transform.mdx +0 -0
  155. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-utilities-__init__.mdx +0 -0
  156. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-utilities-cache.mdx +0 -0
  157. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-utilities-components.mdx +0 -0
  158. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-utilities-exceptions.mdx +0 -0
  159. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-utilities-http.mdx +0 -0
  160. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-utilities-inspect.mdx +0 -0
  161. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-utilities-json_schema.mdx +0 -0
  162. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-utilities-logging.mdx +0 -0
  163. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-utilities-mcp_config.mdx +0 -0
  164. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-utilities-openapi.mdx +0 -0
  165. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-utilities-tests.mdx +0 -0
  166. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/python-sdk/fastmcp-utilities-types.mdx +0 -0
  167. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/servers/auth/bearer.mdx +0 -0
  168. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/servers/context.mdx +0 -0
  169. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/servers/elicitation.mdx +0 -0
  170. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/servers/logging.mdx +0 -0
  171. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/servers/middleware.mdx +0 -0
  172. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/servers/openapi.mdx +0 -0
  173. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/servers/progress.mdx +0 -0
  174. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/servers/prompts.mdx +0 -0
  175. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/servers/resources.mdx +0 -0
  176. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/servers/sampling.mdx +0 -0
  177. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/servers/server.mdx +0 -0
  178. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/servers/tools.mdx +0 -0
  179. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/snippets/version-badge.mdx +0 -0
  180. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/snippets/youtube-embed.mdx +0 -0
  181. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/tutorials/create-mcp-server.mdx +0 -0
  182. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/tutorials/mcp.mdx +0 -0
  183. {fastmcp-2.10.1 → fastmcp-2.10.2}/docs/updates.mdx +0 -0
  184. {fastmcp-2.10.1 → fastmcp-2.10.2}/examples/atproto_mcp/README.md +0 -0
  185. {fastmcp-2.10.1 → fastmcp-2.10.2}/examples/atproto_mcp/demo.py +0 -0
  186. {fastmcp-2.10.1 → fastmcp-2.10.2}/examples/atproto_mcp/pyproject.toml +0 -0
  187. {fastmcp-2.10.1 → fastmcp-2.10.2}/examples/atproto_mcp/src/atproto_mcp/__init__.py +0 -0
  188. {fastmcp-2.10.1 → fastmcp-2.10.2}/examples/atproto_mcp/src/atproto_mcp/__main__.py +0 -0
  189. {fastmcp-2.10.1 → fastmcp-2.10.2}/examples/atproto_mcp/src/atproto_mcp/_atproto/__init__.py +0 -0
  190. {fastmcp-2.10.1 → fastmcp-2.10.2}/examples/atproto_mcp/src/atproto_mcp/_atproto/_client.py +0 -0
  191. {fastmcp-2.10.1 → fastmcp-2.10.2}/examples/atproto_mcp/src/atproto_mcp/_atproto/_posts.py +0 -0
  192. {fastmcp-2.10.1 → fastmcp-2.10.2}/examples/atproto_mcp/src/atproto_mcp/_atproto/_profile.py +0 -0
  193. {fastmcp-2.10.1 → fastmcp-2.10.2}/examples/atproto_mcp/src/atproto_mcp/_atproto/_read.py +0 -0
  194. {fastmcp-2.10.1 → fastmcp-2.10.2}/examples/atproto_mcp/src/atproto_mcp/_atproto/_social.py +0 -0
  195. {fastmcp-2.10.1 → fastmcp-2.10.2}/examples/atproto_mcp/src/atproto_mcp/py.typed +0 -0
  196. {fastmcp-2.10.1 → fastmcp-2.10.2}/examples/atproto_mcp/src/atproto_mcp/server.py +0 -0
  197. {fastmcp-2.10.1 → fastmcp-2.10.2}/examples/atproto_mcp/src/atproto_mcp/settings.py +0 -0
  198. {fastmcp-2.10.1 → fastmcp-2.10.2}/examples/atproto_mcp/src/atproto_mcp/types.py +0 -0
  199. {fastmcp-2.10.1 → fastmcp-2.10.2}/examples/complex_inputs.py +0 -0
  200. {fastmcp-2.10.1 → fastmcp-2.10.2}/examples/config_server.py +0 -0
  201. {fastmcp-2.10.1 → fastmcp-2.10.2}/examples/desktop.py +0 -0
  202. {fastmcp-2.10.1 → fastmcp-2.10.2}/examples/echo.py +0 -0
  203. {fastmcp-2.10.1 → fastmcp-2.10.2}/examples/get_file.py +0 -0
  204. {fastmcp-2.10.1 → fastmcp-2.10.2}/examples/in_memory_proxy_example.py +0 -0
  205. {fastmcp-2.10.1 → fastmcp-2.10.2}/examples/memory.py +0 -0
  206. {fastmcp-2.10.1 → fastmcp-2.10.2}/examples/mount_example.py +0 -0
  207. {fastmcp-2.10.1 → fastmcp-2.10.2}/examples/sampling.py +0 -0
  208. {fastmcp-2.10.1 → fastmcp-2.10.2}/examples/screenshot.py +0 -0
  209. {fastmcp-2.10.1 → fastmcp-2.10.2}/examples/serializer.py +0 -0
  210. {fastmcp-2.10.1 → fastmcp-2.10.2}/examples/simple_echo.py +0 -0
  211. {fastmcp-2.10.1 → fastmcp-2.10.2}/examples/smart_home/README.md +0 -0
  212. {fastmcp-2.10.1 → fastmcp-2.10.2}/examples/smart_home/pyproject.toml +0 -0
  213. {fastmcp-2.10.1 → fastmcp-2.10.2}/examples/smart_home/src/smart_home/__init__.py +0 -0
  214. {fastmcp-2.10.1 → fastmcp-2.10.2}/examples/smart_home/src/smart_home/__main__.py +0 -0
  215. {fastmcp-2.10.1 → fastmcp-2.10.2}/examples/smart_home/src/smart_home/hub.py +0 -0
  216. {fastmcp-2.10.1 → fastmcp-2.10.2}/examples/smart_home/src/smart_home/lights/__init__.py +0 -0
  217. {fastmcp-2.10.1 → fastmcp-2.10.2}/examples/smart_home/src/smart_home/lights/hue_utils.py +0 -0
  218. {fastmcp-2.10.1 → fastmcp-2.10.2}/examples/smart_home/src/smart_home/lights/server.py +0 -0
  219. {fastmcp-2.10.1 → fastmcp-2.10.2}/examples/smart_home/src/smart_home/py.typed +0 -0
  220. {fastmcp-2.10.1 → fastmcp-2.10.2}/examples/smart_home/src/smart_home/settings.py +0 -0
  221. {fastmcp-2.10.1 → fastmcp-2.10.2}/examples/smart_home/uv.lock +0 -0
  222. {fastmcp-2.10.1 → fastmcp-2.10.2}/examples/tags_example.py +0 -0
  223. {fastmcp-2.10.1 → fastmcp-2.10.2}/examples/text_me.py +0 -0
  224. {fastmcp-2.10.1 → fastmcp-2.10.2}/justfile +0 -0
  225. {fastmcp-2.10.1 → fastmcp-2.10.2}/pyproject.toml +0 -0
  226. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/__init__.py +0 -0
  227. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/cli/__init__.py +0 -0
  228. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/cli/claude.py +0 -0
  229. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/client/__init__.py +0 -0
  230. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/client/auth/__init__.py +0 -0
  231. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/client/auth/bearer.py +0 -0
  232. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/client/auth/oauth.py +0 -0
  233. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/client/client.py +0 -0
  234. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/client/logging.py +0 -0
  235. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/client/messages.py +0 -0
  236. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/client/oauth_callback.py +0 -0
  237. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/client/progress.py +0 -0
  238. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/client/roots.py +0 -0
  239. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/client/sampling.py +0 -0
  240. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/contrib/README.md +0 -0
  241. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/contrib/bulk_tool_caller/README.md +0 -0
  242. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/contrib/bulk_tool_caller/__init__.py +0 -0
  243. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/contrib/bulk_tool_caller/bulk_tool_caller.py +0 -0
  244. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/contrib/bulk_tool_caller/example.py +0 -0
  245. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/contrib/component_manager/README.md +0 -0
  246. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/contrib/component_manager/__init__.py +0 -0
  247. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/contrib/component_manager/component_manager.py +0 -0
  248. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/contrib/component_manager/component_service.py +0 -0
  249. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/contrib/component_manager/example.py +0 -0
  250. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/contrib/mcp_mixin/README.md +0 -0
  251. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/contrib/mcp_mixin/__init__.py +0 -0
  252. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/contrib/mcp_mixin/example.py +0 -0
  253. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/contrib/mcp_mixin/mcp_mixin.py +0 -0
  254. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/exceptions.py +0 -0
  255. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/prompts/__init__.py +0 -0
  256. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/prompts/prompt.py +0 -0
  257. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/prompts/prompt_manager.py +0 -0
  258. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/py.typed +0 -0
  259. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/resources/__init__.py +0 -0
  260. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/resources/resource.py +0 -0
  261. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/resources/resource_manager.py +0 -0
  262. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/resources/template.py +0 -0
  263. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/resources/types.py +0 -0
  264. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/server/__init__.py +0 -0
  265. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/server/auth/__init__.py +0 -0
  266. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/server/auth/auth.py +0 -0
  267. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/server/auth/providers/__init__.py +0 -0
  268. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/server/auth/providers/bearer_env.py +0 -0
  269. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/server/auth/providers/in_memory.py +0 -0
  270. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/server/context.py +0 -0
  271. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/server/dependencies.py +0 -0
  272. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/server/elicitation.py +0 -0
  273. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/server/http.py +0 -0
  274. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/server/low_level.py +0 -0
  275. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/server/middleware/__init__.py +0 -0
  276. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/server/middleware/error_handling.py +0 -0
  277. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/server/middleware/logging.py +0 -0
  278. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/server/middleware/middleware.py +0 -0
  279. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/server/middleware/rate_limiting.py +0 -0
  280. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/server/middleware/timing.py +0 -0
  281. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/server/openapi.py +0 -0
  282. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/tools/__init__.py +0 -0
  283. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/tools/tool.py +0 -0
  284. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/tools/tool_manager.py +0 -0
  285. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/tools/tool_transform.py +0 -0
  286. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/utilities/__init__.py +0 -0
  287. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/utilities/cache.py +0 -0
  288. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/utilities/components.py +0 -0
  289. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/utilities/exceptions.py +0 -0
  290. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/utilities/http.py +0 -0
  291. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/utilities/inspect.py +0 -0
  292. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/utilities/json_schema.py +0 -0
  293. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/utilities/json_schema_type.py +0 -0
  294. {fastmcp-2.10.1 → fastmcp-2.10.2}/src/fastmcp/utilities/openapi.py +0 -0
  295. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/__init__.py +0 -0
  296. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/auth/__init__.py +0 -0
  297. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/auth/providers/test_bearer_env.py +0 -0
  298. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/auth/providers/test_token_verifier.py +0 -0
  299. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/auth/test_oauth_client.py +0 -0
  300. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/cli/__init__.py +0 -0
  301. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/cli/test_run.py +0 -0
  302. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/client/__init__.py +0 -0
  303. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/client/test_client.py +0 -0
  304. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/client/test_logs.py +0 -0
  305. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/client/test_notifications.py +0 -0
  306. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/client/test_progress.py +0 -0
  307. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/client/test_roots.py +0 -0
  308. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/client/test_sampling.py +0 -0
  309. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/client/test_sse.py +0 -0
  310. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/client/test_stdio.py +0 -0
  311. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/conftest.py +0 -0
  312. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/contrib/__init__.py +0 -0
  313. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/contrib/test_bulk_tool_caller.py +0 -0
  314. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/contrib/test_component_manager.py +0 -0
  315. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/contrib/test_mcp_mixin.py +0 -0
  316. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/deprecated/__init__.py +0 -0
  317. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/deprecated/test_deprecated.py +0 -0
  318. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/deprecated/test_mount_import_arg_order.py +0 -0
  319. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/deprecated/test_mount_separators.py +0 -0
  320. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/deprecated/test_resource_prefixes.py +0 -0
  321. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/deprecated/test_route_type_ignore.py +0 -0
  322. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/prompts/__init__.py +0 -0
  323. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/prompts/test_prompt.py +0 -0
  324. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/resources/__init__.py +0 -0
  325. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/resources/test_file_resources.py +0 -0
  326. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/resources/test_function_resources.py +0 -0
  327. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/resources/test_resource_template.py +0 -0
  328. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/resources/test_resources.py +0 -0
  329. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/server/__init__.py +0 -0
  330. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/server/http/__init__.py +0 -0
  331. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/server/http/test_auth_setup.py +0 -0
  332. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/server/http/test_bearer_auth_backend.py +0 -0
  333. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/server/http/test_custom_routes.py +0 -0
  334. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/server/http/test_http_dependencies.py +0 -0
  335. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/server/http/test_http_middleware.py +0 -0
  336. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/server/middleware/__init__.py +0 -0
  337. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/server/middleware/test_error_handling.py +0 -0
  338. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/server/middleware/test_logging.py +0 -0
  339. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/server/middleware/test_middleware.py +0 -0
  340. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/server/middleware/test_rate_limiting.py +0 -0
  341. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/server/middleware/test_timing.py +0 -0
  342. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/server/openapi/__init__.py +0 -0
  343. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/server/openapi/test_explode_integration.py +0 -0
  344. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/server/openapi/test_openapi_path_parameters.py +0 -0
  345. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/server/openapi/test_route_map_fn.py +0 -0
  346. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/server/test_app_state.py +0 -0
  347. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/server/test_auth_integration.py +0 -0
  348. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/server/test_context.py +0 -0
  349. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/server/test_file_server.py +0 -0
  350. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/server/test_logging.py +0 -0
  351. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/server/test_resource_prefix_formats.py +0 -0
  352. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/server/test_run_server.py +0 -0
  353. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/server/test_server.py +0 -0
  354. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/server/test_server_interactions.py +0 -0
  355. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/server/test_tool_annotations.py +0 -0
  356. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/server/test_tool_exclude_args.py +0 -0
  357. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/test_examples.py +0 -0
  358. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/test_servers/fastmcp_server.py +0 -0
  359. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/test_servers/sse.py +0 -0
  360. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/test_servers/stdio.py +0 -0
  361. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/tools/__init__.py +0 -0
  362. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/utilities/__init__.py +0 -0
  363. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/utilities/openapi/__init__.py +0 -0
  364. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/utilities/openapi/conftest.py +0 -0
  365. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/utilities/openapi/test_openapi.py +0 -0
  366. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/utilities/openapi/test_openapi_advanced.py +0 -0
  367. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/utilities/openapi/test_openapi_fastapi.py +0 -0
  368. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/utilities/test_cache.py +0 -0
  369. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/utilities/test_inspect.py +0 -0
  370. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/utilities/test_json_schema.py +0 -0
  371. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/utilities/test_json_schema_type.py +0 -0
  372. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/utilities/test_logging.py +0 -0
  373. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/utilities/test_tests.py +0 -0
  374. {fastmcp-2.10.1 → fastmcp-2.10.2}/tests/utilities/test_typeadapter.py +0 -0
  375. {fastmcp-2.10.1 → fastmcp-2.10.2}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastmcp
3
- Version: 2.10.1
3
+ Version: 2.10.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
@@ -176,7 +176,7 @@ async with client:
176
176
 
177
177
  # Execute a tool
178
178
  result = await client.call_tool("multiply", {"a": 5, "b": 3})
179
- print(result[0].text) # "15"
179
+ print(result.data) # 15
180
180
  ```
181
181
 
182
182
  See [Tools](/clients/tools) for detailed documentation.
@@ -135,7 +135,8 @@ Replace `https://your-server-url.com` with the actual URL of your server (such a
135
135
  2. Click **Add custom connector**
136
136
  3. Enter your server details:
137
137
  - **Name**: Library Catalog
138
- - **URL**: Your server URL (e.g., `https://abc123.ngrok.io`)
138
+ - **URL**: Your server URL, including the path.
139
+ - **Note**: Ensure your URL includes the correct path for the transport you’re using. The defaults are /sse/ for SSE (e.g., https://abc123.ngrok.io/sse/) and /mcp/ for HTTP (e.g., https://abc123.ngrok.io/mcp/).
139
140
  - **Description**: A library catalog for searching and retrieving books
140
141
 
141
142
  #### Test the Connection
@@ -46,6 +46,7 @@ This command runs the server directly in your current Python environment. You ar
46
46
  | Host | `--host` | Host to bind to when using http transport (default: 127.0.0.1) |
47
47
  | Port | `--port`, `-p` | Port to bind to when using http transport (default: 8000) |
48
48
  | Log Level | `--log-level`, `-l` | Log level (DEBUG, INFO, WARNING, ERROR, CRITICAL) |
49
+ | No Banner | `--no-banner` | Disable the startup banner display |
49
50
 
50
51
 
51
52
  #### Server Specification
@@ -22,7 +22,7 @@ from fastmcp import FastMCP, Client
22
22
  def mcp_server():
23
23
  server = FastMCP("TestServer")
24
24
 
25
- @server.tool
25
+ @server.tool
26
26
  def greet(name: str) -> str:
27
27
  return f"Hello, {name}!"
28
28
 
@@ -32,7 +32,17 @@ async def test_tool_functionality(mcp_server):
32
32
  # Pass the server directly to the Client constructor
33
33
  async with Client(mcp_server) as client:
34
34
  result = await client.call_tool("greet", {"name": "World"})
35
- assert result[0].text == "Hello, World!"
35
+ assert result.data == "Hello, World!"
36
36
  ```
37
37
 
38
38
  This pattern creates a direct connection between the client and server, allowing you to test your server's functionality efficiently.
39
+
40
+ <Tip>
41
+ If you're using pytest for async tests, as shown above, you may need to configure appropriate markers or set `asyncio_mode = "auto"` in your pytest configuration in order to handle async test functions automatically.
42
+ </Tip>
43
+
44
+
45
+ ## Mocking
46
+
47
+ FastMCP servers are designed to work seamlessly with standard Python testing tools and patterns. There's nothing special about testing FastMCP servers - you can use all the familiar Python mocking, patching, and testing techniques you already know.
48
+
@@ -180,7 +180,7 @@ async def test_dynamic_mount():
180
180
 
181
181
  async with Client(main_mcp) as client:
182
182
  result = await client.call_tool("dynamic_added_later")
183
- print("Result:", result[0].text)
183
+ print("Result:", result.data)
184
184
  # Shows: "Tool Added Dynamically!"
185
185
 
186
186
  if __name__ == "__main__":
@@ -162,6 +162,12 @@ composite_proxy = FastMCP.as_proxy(config, name="Composite Proxy")
162
162
  # - weather://weather/icons/sunny, calendar://calendar/events/today
163
163
  ```
164
164
 
165
+ ## Forwarding Interactions
166
+
167
+ `ProxyClient` is a subclass of `Client` that implements a set of default handlers to forward advanced interactions between the backend server and the client connected to the proxy. These handlers receive requests or notifications from the backend server and forward them to the client through the related request context, relaying the response back to the backend server if needed. This setup enables the proxy to support advanced MCP features, including roots, sampling, elicitation, logging, and progress.
168
+
169
+ To prevent the forwarding of any interaction, pass `None` to the corresponding handler when creating the `ProxyClient`. Typically, you should use `ProxyClient` to establish a proxy unless there is a specific reason not to. If the `transport` parameter is not an instance of `Client`, `FastMCP.as_proxy()` will automatically instantiate a `ProxyClient`.
170
+
165
171
  ## `FastMCPProxy` Class
166
172
 
167
173
  Internally, `FastMCP.as_proxy()` uses the `FastMCPProxy` class. You generally don't need to interact with this class directly, but it's available if needed.
@@ -114,7 +114,7 @@ async def main():
114
114
  # Call one of the generated tools
115
115
  print("\n\nCalling tool 'get_user_by_id'...")
116
116
  user = await client.call_tool("get_user_by_id", {"id": 1})
117
- print(f"Result:\n{user[0].text}")
117
+ print(f"Result:\n{user.data}")
118
118
 
119
119
  if __name__ == "__main__":
120
120
  asyncio.run(main())
@@ -64,6 +64,7 @@ def _build_uv_command(
64
64
  server_spec: str,
65
65
  with_editable: Path | None = None,
66
66
  with_packages: list[str] | None = None,
67
+ no_banner: bool = False,
67
68
  ) -> list[str]:
68
69
  """Build the uv run command that runs a MCP server through mcp run."""
69
70
  cmd = ["uv"]
@@ -80,6 +81,10 @@ def _build_uv_command(
80
81
 
81
82
  # Add mcp run command
82
83
  cmd.extend(["fastmcp", "run", server_spec])
84
+
85
+ if no_banner:
86
+ cmd.append("--no-banner")
87
+
83
88
  return cmd
84
89
 
85
90
 
@@ -192,7 +197,9 @@ def dev(
192
197
  if inspector_version:
193
198
  inspector_cmd += f"@{inspector_version}"
194
199
 
195
- uv_cmd = _build_uv_command(server_spec, with_editable, with_packages)
200
+ uv_cmd = _build_uv_command(
201
+ server_spec, with_editable, with_packages, no_banner=True
202
+ )
196
203
 
197
204
  # Run the MCP Inspector command with shell=True on Windows
198
205
  shell = sys.platform == "win32"
@@ -261,6 +268,13 @@ def run(
261
268
  help="Log level (DEBUG, INFO, WARNING, ERROR, CRITICAL)",
262
269
  ),
263
270
  ] = None,
271
+ no_banner: Annotated[
272
+ bool,
273
+ typer.Option(
274
+ "--no-banner",
275
+ help="Don't show the server banner",
276
+ ),
277
+ ] = False,
264
278
  ) -> None:
265
279
  """Run a MCP server or connect to a remote one.
266
280
 
@@ -297,6 +311,7 @@ def run(
297
311
  port=port,
298
312
  log_level=log_level,
299
313
  server_args=server_args,
314
+ show_banner=not no_banner,
300
315
  )
301
316
  except Exception as e:
302
317
  logger.error(
@@ -169,6 +169,7 @@ def run_command(
169
169
  port: int | None = None,
170
170
  log_level: str | None = None,
171
171
  server_args: list[str] | None = None,
172
+ show_banner: bool = True,
172
173
  ) -> None:
173
174
  """Run a MCP server or connect to a remote one.
174
175
 
@@ -201,6 +202,9 @@ def run_command(
201
202
  if log_level:
202
203
  kwargs["log_level"] = log_level
203
204
 
205
+ if not show_banner:
206
+ kwargs["show_banner"] = False
207
+
204
208
  try:
205
209
  server.run(**kwargs)
206
210
  except Exception as e:
@@ -53,6 +53,11 @@ def create_elicitation_callback(
53
53
  if not isinstance(result, ElicitResult):
54
54
  result = ElicitResult(action="accept", content=result)
55
55
  content = to_jsonable_python(result.content)
56
+ if not isinstance(content, dict | None):
57
+ raise ValueError(
58
+ "Elicitation responses must be serializable as a JSON object (dict). Received: "
59
+ f"{result.content!r}"
60
+ )
56
61
  return MCPElicitResult(**result.model_dump() | {"content": content})
57
62
  except Exception as e:
58
63
  return mcp.types.ErrorData(
@@ -773,8 +773,6 @@ class MCPConfigTransport(ClientTransport):
773
773
  """
774
774
 
775
775
  def __init__(self, config: MCPConfig | dict):
776
- from fastmcp.client.client import Client
777
-
778
776
  if isinstance(config, dict):
779
777
  config = MCPConfig.from_dict(config)
780
778
  self.config = config
@@ -792,9 +790,9 @@ class MCPConfigTransport(ClientTransport):
792
790
  composite_server = FastMCP()
793
791
 
794
792
  for name, server in self.config.mcpServers.items():
795
- server_client = Client(transport=server.to_transport())
796
793
  composite_server.mount(
797
- prefix=name, server=FastMCP.as_proxy(server_client)
794
+ prefix=name,
795
+ server=FastMCP.as_proxy(backend=server.to_transport()),
798
796
  )
799
797
 
800
798
  self.transport = FastMCPTransport(mcp=composite_server)
@@ -399,12 +399,21 @@ class BearerAuthProvider(OAuthProvider):
399
399
  return None
400
400
 
401
401
  def _extract_scopes(self, claims: dict[str, Any]) -> list[str]:
402
- """Extract scopes from JWT claims."""
403
- scope_claim = claims.get("scope", "")
404
- if isinstance(scope_claim, str):
405
- return scope_claim.split()
406
- elif isinstance(scope_claim, list):
407
- return scope_claim
402
+ """
403
+ Extract scopes from JWT claims. Supports both 'scope' and 'scp'
404
+ claims.
405
+
406
+ Checks the `scope` claim first (standard OAuth2 claim), then the `scp`
407
+ claim (used by some Identity Providers).
408
+ """
409
+
410
+ for claim in ["scope", "scp"]:
411
+ if claim in claims:
412
+ if isinstance(claims[claim], str):
413
+ return claims[claim].split()
414
+ elif isinstance(claims[claim], list):
415
+ return claims[claim]
416
+
408
417
  return []
409
418
 
410
419
  async def verify_token(self, token: str) -> AccessToken | None:
@@ -1,9 +1,12 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from pathlib import Path
3
4
  from typing import TYPE_CHECKING, Any, cast
4
5
  from urllib.parse import quote
5
6
 
6
7
  import mcp.types
8
+ from mcp.client.session import ClientSession
9
+ from mcp.shared.context import LifespanContextT, RequestContext
7
10
  from mcp.shared.exceptions import McpError
8
11
  from mcp.types import (
9
12
  METHOD_NOT_FOUND,
@@ -14,6 +17,10 @@ from mcp.types import (
14
17
  from pydantic.networks import AnyUrl
15
18
 
16
19
  from fastmcp.client import Client
20
+ from fastmcp.client.elicitation import ElicitResult
21
+ from fastmcp.client.logging import LogMessage
22
+ from fastmcp.client.roots import RootsList
23
+ from fastmcp.client.transports import ClientTransportT
17
24
  from fastmcp.exceptions import NotFoundError, ResourceError, ToolError
18
25
  from fastmcp.prompts import Prompt, PromptMessage
19
26
  from fastmcp.prompts.prompt import PromptArgument
@@ -21,10 +28,12 @@ from fastmcp.prompts.prompt_manager import PromptManager
21
28
  from fastmcp.resources import Resource, ResourceTemplate
22
29
  from fastmcp.resources.resource_manager import ResourceManager
23
30
  from fastmcp.server.context import Context
31
+ from fastmcp.server.dependencies import get_context
24
32
  from fastmcp.server.server import FastMCP
25
33
  from fastmcp.tools.tool import Tool, ToolResult
26
34
  from fastmcp.tools.tool_manager import ToolManager
27
35
  from fastmcp.utilities.logging import get_logger
36
+ from fastmcp.utilities.mcp_config import MCPConfig
28
37
 
29
38
  if TYPE_CHECKING:
30
39
  from fastmcp.server import Context
@@ -406,3 +415,110 @@ class FastMCPProxy(FastMCP):
406
415
  self._tool_manager = ProxyToolManager(client=self.client)
407
416
  self._resource_manager = ProxyResourceManager(client=self.client)
408
417
  self._prompt_manager = ProxyPromptManager(client=self.client)
418
+
419
+
420
+ async def default_proxy_roots_handler(
421
+ context: RequestContext[ClientSession, LifespanContextT],
422
+ ) -> RootsList:
423
+ """
424
+ A handler that forwards the list roots request from the remote server to the proxy's connected clients and relays the response back to the remote server.
425
+ """
426
+ ctx = get_context()
427
+ return await ctx.list_roots()
428
+
429
+
430
+ class ProxyClient(Client[ClientTransportT]):
431
+ """
432
+ A proxy client that forwards advanced interactions between a remote MCP server and the proxy's connected clients.
433
+ Supports forwarding roots, sampling, elicitation, logging, and progress.
434
+ """
435
+
436
+ def __init__(
437
+ self,
438
+ transport: (
439
+ ClientTransportT
440
+ | FastMCP
441
+ | AnyUrl
442
+ | Path
443
+ | MCPConfig
444
+ | dict[str, Any]
445
+ | str
446
+ ),
447
+ **kwargs,
448
+ ):
449
+ if "roots" not in kwargs:
450
+ kwargs["roots"] = default_proxy_roots_handler
451
+ if "sampling_handler" not in kwargs:
452
+ kwargs["sampling_handler"] = ProxyClient.default_sampling_handler
453
+ if "elicitation_handler" not in kwargs:
454
+ kwargs["elicitation_handler"] = ProxyClient.default_elicitation_handler
455
+ if "log_handler" not in kwargs:
456
+ kwargs["log_handler"] = ProxyClient.default_log_handler
457
+ if "progress_handler" not in kwargs:
458
+ kwargs["progress_handler"] = ProxyClient.default_progress_handler
459
+ super().__init__(transport, **kwargs)
460
+
461
+ @classmethod
462
+ async def default_sampling_handler(
463
+ cls,
464
+ messages: list[mcp.types.SamplingMessage],
465
+ params: mcp.types.CreateMessageRequestParams,
466
+ context: RequestContext[ClientSession, LifespanContextT],
467
+ ) -> mcp.types.CreateMessageResult:
468
+ """
469
+ A handler that forwards the sampling request from the remote server to the proxy's connected clients and relays the response back to the remote server.
470
+ """
471
+ ctx = get_context()
472
+ content = await ctx.sample(
473
+ [msg for msg in messages],
474
+ system_prompt=params.systemPrompt,
475
+ temperature=params.temperature,
476
+ max_tokens=params.maxTokens,
477
+ model_preferences=params.modelPreferences,
478
+ )
479
+ if isinstance(content, mcp.types.ResourceLink | mcp.types.EmbeddedResource):
480
+ raise RuntimeError("Content is not supported")
481
+ return mcp.types.CreateMessageResult(
482
+ role="assistant",
483
+ model="fastmcp-client",
484
+ content=content,
485
+ )
486
+
487
+ @classmethod
488
+ async def default_elicitation_handler(
489
+ cls,
490
+ message: str,
491
+ response_type: type,
492
+ params: mcp.types.ElicitRequestParams,
493
+ context: RequestContext[ClientSession, LifespanContextT],
494
+ ) -> ElicitResult:
495
+ """
496
+ A handler that forwards the elicitation request from the remote server to the proxy's connected clients and relays the response back to the remote server.
497
+ """
498
+ ctx = get_context()
499
+ result = await ctx.elicit(message, response_type)
500
+ if result.action == "accept":
501
+ return result.data
502
+ else:
503
+ return ElicitResult(action=result.action)
504
+
505
+ @classmethod
506
+ async def default_log_handler(cls, message: LogMessage) -> None:
507
+ """
508
+ A handler that forwards the log notification from the remote server to the proxy's connected clients.
509
+ """
510
+ ctx = get_context()
511
+ await ctx.log(message.data, level=message.level, logger_name=message.logger)
512
+
513
+ @classmethod
514
+ async def default_progress_handler(
515
+ cls,
516
+ progress: float,
517
+ total: float | None,
518
+ message: str | None,
519
+ ) -> None:
520
+ """
521
+ A handler that forwards the progress notification from the remote server to the proxy's connected clients.
522
+ """
523
+ ctx = get_context()
524
+ await ctx.report_progress(progress, total, message)
@@ -60,6 +60,7 @@ from fastmcp.settings import Settings
60
60
  from fastmcp.tools import ToolManager
61
61
  from fastmcp.tools.tool import FunctionTool, Tool, ToolResult
62
62
  from fastmcp.utilities.cache import TimedCache
63
+ from fastmcp.utilities.cli import log_server_banner
63
64
  from fastmcp.utilities.components import FastMCPComponent
64
65
  from fastmcp.utilities.logging import get_logger
65
66
  from fastmcp.utilities.mcp_config import MCPConfig
@@ -285,6 +286,7 @@ class FastMCP(Generic[LifespanResultT]):
285
286
  async def run_async(
286
287
  self,
287
288
  transport: Transport | None = None,
289
+ show_banner: bool = True,
288
290
  **transport_kwargs: Any,
289
291
  ) -> None:
290
292
  """Run the FastMCP server asynchronously.
@@ -298,15 +300,23 @@ class FastMCP(Generic[LifespanResultT]):
298
300
  raise ValueError(f"Unknown transport: {transport}")
299
301
 
300
302
  if transport == "stdio":
301
- await self.run_stdio_async(**transport_kwargs)
303
+ await self.run_stdio_async(
304
+ show_banner=show_banner,
305
+ **transport_kwargs,
306
+ )
302
307
  elif transport in {"http", "sse", "streamable-http"}:
303
- await self.run_http_async(transport=transport, **transport_kwargs)
308
+ await self.run_http_async(
309
+ transport=transport,
310
+ show_banner=show_banner,
311
+ **transport_kwargs,
312
+ )
304
313
  else:
305
314
  raise ValueError(f"Unknown transport: {transport}")
306
315
 
307
316
  def run(
308
317
  self,
309
318
  transport: Transport | None = None,
319
+ show_banner: bool = True,
310
320
  **transport_kwargs: Any,
311
321
  ) -> None:
312
322
  """Run the FastMCP server. Note this is a synchronous function.
@@ -315,7 +325,14 @@ class FastMCP(Generic[LifespanResultT]):
315
325
  transport: Transport protocol to use ("stdio", "sse", or "streamable-http")
316
326
  """
317
327
 
318
- anyio.run(partial(self.run_async, transport, **transport_kwargs))
328
+ anyio.run(
329
+ partial(
330
+ self.run_async,
331
+ transport,
332
+ show_banner=show_banner,
333
+ **transport_kwargs,
334
+ )
335
+ )
319
336
 
320
337
  def _setup_handlers(self) -> None:
321
338
  """Set up core MCP protocol handlers."""
@@ -1321,8 +1338,16 @@ class FastMCP(Generic[LifespanResultT]):
1321
1338
  enabled=enabled,
1322
1339
  )
1323
1340
 
1324
- async def run_stdio_async(self) -> None:
1341
+ async def run_stdio_async(self, show_banner: bool = True) -> None:
1325
1342
  """Run the server using stdio transport."""
1343
+
1344
+ # Display server banner
1345
+ if show_banner:
1346
+ log_server_banner(
1347
+ server=self,
1348
+ transport="stdio",
1349
+ )
1350
+
1326
1351
  async with stdio_server() as (read_stream, write_stream):
1327
1352
  logger.info(f"Starting MCP server {self.name!r} with transport 'stdio'")
1328
1353
  await self._mcp_server.run(
@@ -1335,6 +1360,7 @@ class FastMCP(Generic[LifespanResultT]):
1335
1360
 
1336
1361
  async def run_http_async(
1337
1362
  self,
1363
+ show_banner: bool = True,
1338
1364
  transport: Literal["http", "streamable-http", "sse"] = "http",
1339
1365
  host: str | None = None,
1340
1366
  port: int | None = None,
@@ -1342,6 +1368,7 @@ class FastMCP(Generic[LifespanResultT]):
1342
1368
  path: str | None = None,
1343
1369
  uvicorn_config: dict[str, Any] | None = None,
1344
1370
  middleware: list[ASGIMiddleware] | None = None,
1371
+ stateless_http: bool | None = None,
1345
1372
  ) -> None:
1346
1373
  """Run the server using HTTP transport.
1347
1374
 
@@ -1352,15 +1379,39 @@ class FastMCP(Generic[LifespanResultT]):
1352
1379
  log_level: Log level for the server (defaults to settings.log_level)
1353
1380
  path: Path for the endpoint (defaults to settings.streamable_http_path or settings.sse_path)
1354
1381
  uvicorn_config: Additional configuration for the Uvicorn server
1382
+ middleware: A list of middleware to apply to the app
1383
+ stateless_http: Whether to use stateless HTTP (defaults to settings.stateless_http)
1355
1384
  """
1385
+
1356
1386
  host = host or self._deprecated_settings.host
1357
1387
  port = port or self._deprecated_settings.port
1358
1388
  default_log_level_to_use = (
1359
1389
  log_level or self._deprecated_settings.log_level
1360
1390
  ).lower()
1361
1391
 
1362
- app = self.http_app(path=path, transport=transport, middleware=middleware)
1392
+ app = self.http_app(
1393
+ path=path,
1394
+ transport=transport,
1395
+ middleware=middleware,
1396
+ stateless_http=stateless_http,
1397
+ )
1398
+
1399
+ # Get the path for the server URL
1400
+ server_path = (
1401
+ app.state.path.lstrip("/")
1402
+ if hasattr(app, "state") and hasattr(app.state, "path")
1403
+ else path or ""
1404
+ )
1363
1405
 
1406
+ # Display server banner
1407
+ if show_banner:
1408
+ log_server_banner(
1409
+ server=self,
1410
+ transport=transport,
1411
+ host=host,
1412
+ port=port,
1413
+ path=server_path,
1414
+ )
1364
1415
  _uvicorn_config_from_user = uvicorn_config or {}
1365
1416
 
1366
1417
  config_kwargs: dict[str, Any] = {
@@ -1378,6 +1429,7 @@ class FastMCP(Generic[LifespanResultT]):
1378
1429
  logger.info(
1379
1430
  f"Starting MCP server {self.name!r} with transport {transport!r} on http://{host}:{port}/{path}"
1380
1431
  )
1432
+
1381
1433
  await server.serve()
1382
1434
 
1383
1435
  async def run_sse_async(
@@ -1591,9 +1643,8 @@ class FastMCP(Generic[LifespanResultT]):
1591
1643
  resource_separator: Deprecated. Separator character for resource URIs.
1592
1644
  prompt_separator: Deprecated. Separator character for prompt names.
1593
1645
  """
1594
- from fastmcp import Client
1595
1646
  from fastmcp.client.transports import FastMCPTransport
1596
- from fastmcp.server.proxy import FastMCPProxy
1647
+ from fastmcp.server.proxy import FastMCPProxy, ProxyClient
1597
1648
 
1598
1649
  # Deprecated since 2.9.0
1599
1650
  # Prior to 2.9.0, the first positional argument was the prefix and the
@@ -1645,7 +1696,7 @@ class FastMCP(Generic[LifespanResultT]):
1645
1696
  as_proxy = server._has_lifespan
1646
1697
 
1647
1698
  if as_proxy and not isinstance(server, FastMCPProxy):
1648
- server = FastMCPProxy(Client(transport=FastMCPTransport(server)))
1699
+ server = FastMCPProxy(ProxyClient(transport=FastMCPTransport(server)))
1649
1700
 
1650
1701
  # Delegate mounting to all three managers
1651
1702
  mounted_server = MountedServer(
@@ -1856,14 +1907,16 @@ class FastMCP(Generic[LifespanResultT]):
1856
1907
  @classmethod
1857
1908
  def as_proxy(
1858
1909
  cls,
1859
- backend: Client[ClientTransportT]
1860
- | ClientTransport
1861
- | FastMCP[Any]
1862
- | AnyUrl
1863
- | Path
1864
- | MCPConfig
1865
- | dict[str, Any]
1866
- | str,
1910
+ backend: (
1911
+ Client[ClientTransportT]
1912
+ | ClientTransport
1913
+ | FastMCP[Any]
1914
+ | AnyUrl
1915
+ | Path
1916
+ | MCPConfig
1917
+ | dict[str, Any]
1918
+ | str
1919
+ ),
1867
1920
  **settings: Any,
1868
1921
  ) -> FastMCPProxy:
1869
1922
  """Create a FastMCP proxy server for the given backend.
@@ -1874,12 +1927,12 @@ class FastMCP(Generic[LifespanResultT]):
1874
1927
  `fastmcp.client.Client` constructor.
1875
1928
  """
1876
1929
  from fastmcp.client.client import Client
1877
- from fastmcp.server.proxy import FastMCPProxy
1930
+ from fastmcp.server.proxy import FastMCPProxy, ProxyClient
1878
1931
 
1879
1932
  if isinstance(backend, Client):
1880
1933
  client = backend
1881
1934
  else:
1882
- client = Client(backend)
1935
+ client = ProxyClient(backend)
1883
1936
 
1884
1937
  return FastMCPProxy(client=client, **settings)
1885
1938
 
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations as _annotations
2
2
 
3
3
  import inspect
4
+ import warnings
4
5
  from pathlib import Path
5
6
  from typing import Annotated, Any, Literal
6
7
 
@@ -258,4 +259,21 @@ class Settings(BaseSettings):
258
259
  ] = None
259
260
 
260
261
 
261
- settings = Settings()
262
+ def __getattr__(name: str):
263
+ """
264
+ Used to deprecate the module-level Image class; can be removed once it is no longer imported to root.
265
+ """
266
+ if name == "settings":
267
+ import fastmcp
268
+
269
+ settings = fastmcp.settings
270
+ # Deprecated in 2.10.2
271
+ if settings.deprecation_warnings:
272
+ warnings.warn(
273
+ "`from fastmcp.settings import settings` is deprecated. use `fasmtpc.settings` instead.",
274
+ DeprecationWarning,
275
+ stacklevel=2,
276
+ )
277
+ return settings
278
+
279
+ raise AttributeError(f"module '{__name__}' has no attribute '{name}'")