fastmcp 2.7.0__tar.gz → 2.7.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {fastmcp-2.7.0 → fastmcp-2.7.1}/PKG-INFO +1 -1
- {fastmcp-2.7.0 → fastmcp-2.7.1}/docs/integrations/contrib.mdx +1 -1
- {fastmcp-2.7.0 → fastmcp-2.7.1}/docs/integrations/gemini.mdx +1 -1
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/cli/cli.py +1 -1
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/client/transports.py +8 -9
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/prompts/prompt.py +3 -3
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/resources/resource.py +2 -2
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/server/dependencies.py +1 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/server/http.py +2 -1
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/server/server.py +9 -8
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/settings.py +1 -1
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/tools/tool.py +3 -3
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/utilities/mcp_config.py +11 -3
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/client/test_client.py +72 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/server/test_mount.py +13 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/server/test_proxy.py +3 -2
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/utilities/test_mcp_config.py +59 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/utilities/test_typeadapter.py +2 -2
- {fastmcp-2.7.0 → fastmcp-2.7.1}/.cursor/rules/core-mcp-objects.mdc +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/.github/ISSUE_TEMPLATE/bug.yml +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/.github/ISSUE_TEMPLATE/enhancement.yml +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/.github/labeler.yml +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/.github/release.yml +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/.github/workflows/labeler.yml +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/.github/workflows/publish.yml +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/.github/workflows/run-static.yml +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/.github/workflows/run-tests.yml +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/.gitignore +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/.pre-commit-config.yaml +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/AGENTS.md +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/LICENSE +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/README.md +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/Windows_Notes.md +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/docs/assets/demo-inspector.png +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/docs/assets/favicon.ico +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/docs/assets/logo.png +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/docs/clients/advanced-features.mdx +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/docs/clients/auth/bearer.mdx +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/docs/clients/auth/oauth.mdx +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/docs/clients/client.mdx +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/docs/clients/transports.mdx +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/docs/deployment/asgi.mdx +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/docs/deployment/running-server.mdx +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/docs/docs.json +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/docs/getting-started/installation.mdx +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/docs/getting-started/quickstart.mdx +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/docs/getting-started/welcome.mdx +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/docs/integrations/anthropic.mdx +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/docs/integrations/claude-desktop.mdx +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/docs/integrations/openai.mdx +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/docs/patterns/cli.mdx +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/docs/patterns/decorating-methods.mdx +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/docs/patterns/http-requests.mdx +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/docs/patterns/testing.mdx +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/docs/servers/auth/bearer.mdx +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/docs/servers/composition.mdx +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/docs/servers/context.mdx +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/docs/servers/fastmcp.mdx +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/docs/servers/openapi.mdx +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/docs/servers/prompts.mdx +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/docs/servers/proxy.mdx +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/docs/servers/resources.mdx +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/docs/servers/tools.mdx +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/docs/snippets/version-badge.mdx +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/docs/style.css +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/docs/updates.mdx +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/examples/complex_inputs.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/examples/config_server.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/examples/desktop.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/examples/echo.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/examples/in_memory_proxy_example.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/examples/memory.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/examples/mount_example.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/examples/sampling.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/examples/screenshot.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/examples/serializer.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/examples/simple_echo.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/examples/smart_home/README.md +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/examples/smart_home/pyproject.toml +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/examples/smart_home/src/smart_home/__init__.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/examples/smart_home/src/smart_home/__main__.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/examples/smart_home/src/smart_home/hub.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/examples/smart_home/src/smart_home/lights/__init__.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/examples/smart_home/src/smart_home/lights/hue_utils.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/examples/smart_home/src/smart_home/lights/server.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/examples/smart_home/src/smart_home/py.typed +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/examples/smart_home/src/smart_home/settings.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/examples/smart_home/uv.lock +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/examples/tags_example.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/examples/text_me.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/justfile +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/pyproject.toml +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/__init__.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/cli/__init__.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/cli/claude.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/cli/run.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/client/__init__.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/client/auth/__init__.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/client/auth/bearer.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/client/auth/oauth.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/client/client.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/client/logging.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/client/oauth_callback.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/client/progress.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/client/roots.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/client/sampling.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/contrib/README.md +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/contrib/bulk_tool_caller/README.md +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/contrib/bulk_tool_caller/__init__.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/contrib/bulk_tool_caller/bulk_tool_caller.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/contrib/bulk_tool_caller/example.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/contrib/mcp_mixin/README.md +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/contrib/mcp_mixin/__init__.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/contrib/mcp_mixin/example.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/contrib/mcp_mixin/mcp_mixin.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/exceptions.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/prompts/__init__.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/prompts/prompt_manager.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/py.typed +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/resources/__init__.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/resources/resource_manager.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/resources/template.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/resources/types.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/server/__init__.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/server/auth/__init__.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/server/auth/auth.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/server/auth/providers/__init__.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/server/auth/providers/bearer.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/server/auth/providers/bearer_env.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/server/auth/providers/in_memory.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/server/context.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/server/openapi.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/server/proxy.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/tools/__init__.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/tools/tool_manager.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/utilities/__init__.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/utilities/cache.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/utilities/exceptions.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/utilities/http.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/utilities/json_schema.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/utilities/logging.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/utilities/openapi.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/utilities/tests.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/src/fastmcp/utilities/types.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/__init__.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/auth/__init__.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/auth/providers/test_bearer.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/auth/providers/test_bearer_env.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/auth/test_oauth_client.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/cli/__init__.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/cli/test_cli.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/cli/test_run.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/client/__init__.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/client/test_logs.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/client/test_openapi.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/client/test_progress.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/client/test_roots.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/client/test_sampling.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/client/test_sse.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/client/test_stdio.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/client/test_streamable_http.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/conftest.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/contrib/__init__.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/contrib/test_bulk_tool_caller.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/contrib/test_mcp_mixin.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/deprecated/__init__.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/deprecated/test_deprecated.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/deprecated/test_mount_separators.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/deprecated/test_resource_prefixes.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/deprecated/test_route_type_ignore.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/prompts/__init__.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/prompts/test_prompt.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/prompts/test_prompt_manager.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/resources/__init__.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/resources/test_file_resources.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/resources/test_function_resources.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/resources/test_resource_manager.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/resources/test_resource_template.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/resources/test_resources.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/server/__init__.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/server/http/__init__.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/server/http/test_custom_routes.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/server/http/test_http_dependencies.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/server/http/test_http_middleware.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/server/openapi/__init__.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/server/openapi/test_openapi.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/server/openapi/test_openapi_path_parameters.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/server/openapi/test_route_map_fn.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/server/test_app_state.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/server/test_auth_integration.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/server/test_context.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/server/test_file_server.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/server/test_import_server.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/server/test_logging.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/server/test_resource_prefix_formats.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/server/test_run_server.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/server/test_server.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/server/test_server_interactions.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/server/test_tool_annotations.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/server/test_tool_exclude_args.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/test_examples.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/test_servers/fastmcp_server.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/test_servers/sse.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/test_servers/stdio.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/tools/__init__.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/tools/test_tool.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/tools/test_tool_manager.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/utilities/__init__.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/utilities/openapi/__init__.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/utilities/openapi/conftest.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/utilities/openapi/test_openapi.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/utilities/openapi/test_openapi_advanced.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/utilities/openapi/test_openapi_fastapi.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/utilities/test_cache.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/utilities/test_json_schema.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/utilities/test_logging.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/utilities/test_tests.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/tests/utilities/test_types.py +0 -0
- {fastmcp-2.7.0 → fastmcp-2.7.1}/uv.lock +0 -0
|
@@ -12,7 +12,7 @@ FastMCP includes a `contrib` package that holds community-contributed modules. T
|
|
|
12
12
|
|
|
13
13
|
Contrib modules provide additional features, integrations, or patterns that complement the core FastMCP library. They offer a way for the community to share useful extensions while keeping the core library focused and maintainable.
|
|
14
14
|
|
|
15
|
-
The available modules can be viewed in the [contrib directory](https://github.com/jlowin/fastmcp/tree/main/src/contrib).
|
|
15
|
+
The available modules can be viewed in the [contrib directory](https://github.com/jlowin/fastmcp/tree/main/src/fastmcp/contrib).
|
|
16
16
|
|
|
17
17
|
## Usage
|
|
18
18
|
|
|
@@ -32,6 +32,7 @@ from mcp.shared.memory import create_connected_server_and_client_session
|
|
|
32
32
|
from pydantic import AnyUrl
|
|
33
33
|
from typing_extensions import Unpack
|
|
34
34
|
|
|
35
|
+
from fastmcp.client.auth.bearer import BearerAuth
|
|
35
36
|
from fastmcp.client.auth.oauth import OAuth
|
|
36
37
|
from fastmcp.server.dependencies import get_http_headers
|
|
37
38
|
from fastmcp.server.server import FastMCP
|
|
@@ -152,7 +153,7 @@ class WSTransport(ClientTransport):
|
|
|
152
153
|
yield session
|
|
153
154
|
|
|
154
155
|
def __repr__(self) -> str:
|
|
155
|
-
return f"<
|
|
156
|
+
return f"<WebSocketTransport(url='{self.url}')>"
|
|
156
157
|
|
|
157
158
|
|
|
158
159
|
class SSETransport(ClientTransport):
|
|
@@ -183,8 +184,7 @@ class SSETransport(ClientTransport):
|
|
|
183
184
|
if auth == "oauth":
|
|
184
185
|
auth = OAuth(self.url)
|
|
185
186
|
elif isinstance(auth, str):
|
|
186
|
-
|
|
187
|
-
auth = None
|
|
187
|
+
auth = BearerAuth(auth)
|
|
188
188
|
self.auth = auth
|
|
189
189
|
|
|
190
190
|
@contextlib.asynccontextmanager
|
|
@@ -221,7 +221,7 @@ class SSETransport(ClientTransport):
|
|
|
221
221
|
yield session
|
|
222
222
|
|
|
223
223
|
def __repr__(self) -> str:
|
|
224
|
-
return f"<
|
|
224
|
+
return f"<SSETransport(url='{self.url}')>"
|
|
225
225
|
|
|
226
226
|
|
|
227
227
|
class StreamableHttpTransport(ClientTransport):
|
|
@@ -252,8 +252,7 @@ class StreamableHttpTransport(ClientTransport):
|
|
|
252
252
|
if auth == "oauth":
|
|
253
253
|
auth = OAuth(self.url)
|
|
254
254
|
elif isinstance(auth, str):
|
|
255
|
-
|
|
256
|
-
auth = None
|
|
255
|
+
auth = BearerAuth(auth)
|
|
257
256
|
self.auth = auth
|
|
258
257
|
|
|
259
258
|
@contextlib.asynccontextmanager
|
|
@@ -291,7 +290,7 @@ class StreamableHttpTransport(ClientTransport):
|
|
|
291
290
|
yield session
|
|
292
291
|
|
|
293
292
|
def __repr__(self) -> str:
|
|
294
|
-
return f"<
|
|
293
|
+
return f"<StreamableHttpTransport(url='{self.url}')>"
|
|
295
294
|
|
|
296
295
|
|
|
297
296
|
class StdioTransport(ClientTransport):
|
|
@@ -683,7 +682,7 @@ class FastMCPTransport(ClientTransport):
|
|
|
683
682
|
yield session
|
|
684
683
|
|
|
685
684
|
def __repr__(self) -> str:
|
|
686
|
-
return f"<
|
|
685
|
+
return f"<FastMCPTransport(server='{self.server.name}')>"
|
|
687
686
|
|
|
688
687
|
|
|
689
688
|
class MCPConfigTransport(ClientTransport):
|
|
@@ -769,7 +768,7 @@ class MCPConfigTransport(ClientTransport):
|
|
|
769
768
|
yield session
|
|
770
769
|
|
|
771
770
|
def __repr__(self) -> str:
|
|
772
|
-
return f"<
|
|
771
|
+
return f"<MCPConfigTransport(config='{self.config}')>"
|
|
773
772
|
|
|
774
773
|
|
|
775
774
|
@overload
|
|
@@ -59,7 +59,7 @@ class PromptArgument(FastMCPBaseModel):
|
|
|
59
59
|
|
|
60
60
|
name: str = Field(description="Name of the argument")
|
|
61
61
|
description: str | None = Field(
|
|
62
|
-
None, description="Description of what the argument does"
|
|
62
|
+
default=None, description="Description of what the argument does"
|
|
63
63
|
)
|
|
64
64
|
required: bool = Field(
|
|
65
65
|
default=False, description="Whether the argument is required"
|
|
@@ -71,13 +71,13 @@ class Prompt(FastMCPBaseModel, ABC):
|
|
|
71
71
|
|
|
72
72
|
name: str = Field(description="Name of the prompt")
|
|
73
73
|
description: str | None = Field(
|
|
74
|
-
None, description="Description of what the prompt does"
|
|
74
|
+
default=None, description="Description of what the prompt does"
|
|
75
75
|
)
|
|
76
76
|
tags: Annotated[set[str], BeforeValidator(_convert_set_defaults)] = Field(
|
|
77
77
|
default_factory=set, description="Tags for the prompt"
|
|
78
78
|
)
|
|
79
79
|
arguments: list[PromptArgument] | None = Field(
|
|
80
|
-
None, description="Arguments that can be passed to the prompt"
|
|
80
|
+
default=None, description="Arguments that can be passed to the prompt"
|
|
81
81
|
)
|
|
82
82
|
|
|
83
83
|
def __eq__(self, other: object) -> bool:
|
|
@@ -38,9 +38,9 @@ class Resource(FastMCPBaseModel, abc.ABC):
|
|
|
38
38
|
uri: Annotated[AnyUrl, UrlConstraints(host_required=False)] = Field(
|
|
39
39
|
default=..., description="URI of the resource"
|
|
40
40
|
)
|
|
41
|
-
name: str | None = Field(description="Name of the resource"
|
|
41
|
+
name: str | None = Field(default=None, description="Name of the resource")
|
|
42
42
|
description: str | None = Field(
|
|
43
|
-
description="Description of the resource"
|
|
43
|
+
default=None, description="Description of the resource"
|
|
44
44
|
)
|
|
45
45
|
tags: Annotated[set[str], BeforeValidator(_convert_set_defaults)] = Field(
|
|
46
46
|
default_factory=set, description="Tags for the resource"
|
|
@@ -13,6 +13,7 @@ from mcp.server.auth.middleware.bearer_auth import (
|
|
|
13
13
|
from mcp.server.auth.routes import create_auth_routes
|
|
14
14
|
from mcp.server.lowlevel.server import LifespanResultT
|
|
15
15
|
from mcp.server.sse import SseServerTransport
|
|
16
|
+
from mcp.server.streamable_http import EventStore
|
|
16
17
|
from mcp.server.streamable_http_manager import StreamableHTTPSessionManager
|
|
17
18
|
from starlette.applications import Starlette
|
|
18
19
|
from starlette.middleware import Middleware
|
|
@@ -241,7 +242,7 @@ def create_sse_app(
|
|
|
241
242
|
def create_streamable_http_app(
|
|
242
243
|
server: FastMCP[LifespanResultT],
|
|
243
244
|
streamable_http_path: str,
|
|
244
|
-
event_store: None = None,
|
|
245
|
+
event_store: EventStore | None = None,
|
|
245
246
|
auth: OAuthProvider | None = None,
|
|
246
247
|
json_response: bool = False,
|
|
247
248
|
stateless_http: bool = False,
|
|
@@ -41,6 +41,7 @@ from starlette.requests import Request
|
|
|
41
41
|
from starlette.responses import Response
|
|
42
42
|
from starlette.routing import BaseRoute, Route
|
|
43
43
|
|
|
44
|
+
import fastmcp
|
|
44
45
|
import fastmcp.server
|
|
45
46
|
import fastmcp.settings
|
|
46
47
|
from fastmcp.exceptions import NotFoundError
|
|
@@ -131,6 +132,8 @@ class FastMCP(Generic[LifespanResultT]):
|
|
|
131
132
|
tools: list[Tool | Callable[..., Any]] | None = None,
|
|
132
133
|
**settings: Any,
|
|
133
134
|
):
|
|
135
|
+
if cache_expiration_seconds is not None:
|
|
136
|
+
settings["cache_expiration_seconds"] = cache_expiration_seconds
|
|
134
137
|
self.settings = fastmcp.settings.ServerSettings(**settings)
|
|
135
138
|
|
|
136
139
|
# If mask_error_details is provided, override the settings value
|
|
@@ -148,7 +151,9 @@ class FastMCP(Generic[LifespanResultT]):
|
|
|
148
151
|
self.tags: set[str] = tags or set()
|
|
149
152
|
self.dependencies = dependencies
|
|
150
153
|
self._cache = TimedCache(
|
|
151
|
-
expiration=datetime.timedelta(
|
|
154
|
+
expiration=datetime.timedelta(
|
|
155
|
+
seconds=self.settings.cache_expiration_seconds
|
|
156
|
+
)
|
|
152
157
|
)
|
|
153
158
|
self._mounted_servers: dict[str, MountedServer] = {}
|
|
154
159
|
self._additional_http_routes: list[BaseRoute] = []
|
|
@@ -490,11 +495,7 @@ class FastMCP(Generic[LifespanResultT]):
|
|
|
490
495
|
with the Context type annotation. See the @tool decorator for examples.
|
|
491
496
|
|
|
492
497
|
Args:
|
|
493
|
-
|
|
494
|
-
name: Optional name for the tool (defaults to function name)
|
|
495
|
-
description: Optional description of what the tool does
|
|
496
|
-
tags: Optional set of tags for categorizing the tool
|
|
497
|
-
annotations: Optional annotations about the tool's behavior
|
|
498
|
+
tool: The Tool instance to register
|
|
498
499
|
"""
|
|
499
500
|
self._tool_manager.add_tool(tool)
|
|
500
501
|
self._cache.clear()
|
|
@@ -864,7 +865,7 @@ class FastMCP(Generic[LifespanResultT]):
|
|
|
864
865
|
|
|
865
866
|
This decorator supports multiple calling patterns:
|
|
866
867
|
- @server.prompt (without parentheses)
|
|
867
|
-
- @server.prompt (with empty parentheses)
|
|
868
|
+
- @server.prompt() (with empty parentheses)
|
|
868
869
|
- @server.prompt("custom_name") (with name as first argument)
|
|
869
870
|
- @server.prompt(name="custom_name") (with name as keyword argument)
|
|
870
871
|
- server.prompt(function, name="custom_name") (direct function call)
|
|
@@ -886,7 +887,7 @@ class FastMCP(Generic[LifespanResultT]):
|
|
|
886
887
|
}
|
|
887
888
|
]
|
|
888
889
|
|
|
889
|
-
@server.prompt
|
|
890
|
+
@server.prompt()
|
|
890
891
|
def analyze_with_context(table_name: str, ctx: Context) -> list[Message]:
|
|
891
892
|
ctx.info(f"Analyzing table {table_name}")
|
|
892
893
|
schema = read_table_schema(table_name)
|
|
@@ -170,7 +170,7 @@ class ServerSettings(BaseSettings):
|
|
|
170
170
|
),
|
|
171
171
|
] = []
|
|
172
172
|
|
|
173
|
-
# cache settings (for
|
|
173
|
+
# cache settings (for getting attributes from servers, used to avoid repeated calls)
|
|
174
174
|
cache_expiration_seconds: float = 0
|
|
175
175
|
|
|
176
176
|
# StreamableHTTP settings
|
|
@@ -45,14 +45,14 @@ class Tool(FastMCPBaseModel, ABC):
|
|
|
45
45
|
default_factory=set, description="Tags for the tool"
|
|
46
46
|
)
|
|
47
47
|
annotations: ToolAnnotations | None = Field(
|
|
48
|
-
None, description="Additional annotations about the tool"
|
|
48
|
+
default=None, description="Additional annotations about the tool"
|
|
49
49
|
)
|
|
50
50
|
exclude_args: list[str] | None = Field(
|
|
51
|
-
None,
|
|
51
|
+
default=None,
|
|
52
52
|
description="Arguments to exclude from the tool schema, such as State, Memory, or Credential",
|
|
53
53
|
)
|
|
54
54
|
serializer: Callable[[Any], str] | None = Field(
|
|
55
|
-
None, description="Optional custom serializer for tool results"
|
|
55
|
+
default=None, description="Optional custom serializer for tool results"
|
|
56
56
|
)
|
|
57
57
|
|
|
58
58
|
def to_mcp_tool(self, **overrides: Any) -> MCPTool:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import TYPE_CHECKING, Any, Literal
|
|
3
|
+
from typing import TYPE_CHECKING, Annotated, Any, Literal
|
|
4
4
|
from urllib.parse import urlparse
|
|
5
5
|
|
|
6
6
|
from pydantic import AnyUrl, Field
|
|
@@ -56,6 +56,12 @@ class RemoteMCPServer(FastMCPBaseModel):
|
|
|
56
56
|
url: str
|
|
57
57
|
headers: dict[str, str] = Field(default_factory=dict)
|
|
58
58
|
transport: Literal["streamable-http", "sse", "http"] | None = None
|
|
59
|
+
auth: Annotated[
|
|
60
|
+
str | Literal["oauth"] | None,
|
|
61
|
+
Field(
|
|
62
|
+
description='Either a string representing a Bearer token or the literal "oauth" to use OAuth authentication.'
|
|
63
|
+
),
|
|
64
|
+
] = None
|
|
59
65
|
|
|
60
66
|
def to_transport(self) -> StreamableHttpTransport | SSETransport:
|
|
61
67
|
from fastmcp.client.transports import SSETransport, StreamableHttpTransport
|
|
@@ -66,9 +72,11 @@ class RemoteMCPServer(FastMCPBaseModel):
|
|
|
66
72
|
transport = self.transport
|
|
67
73
|
|
|
68
74
|
if transport == "sse":
|
|
69
|
-
return SSETransport(self.url, headers=self.headers)
|
|
75
|
+
return SSETransport(self.url, headers=self.headers, auth=self.auth)
|
|
70
76
|
else:
|
|
71
|
-
return StreamableHttpTransport(
|
|
77
|
+
return StreamableHttpTransport(
|
|
78
|
+
self.url, headers=self.headers, auth=self.auth
|
|
79
|
+
)
|
|
72
80
|
|
|
73
81
|
|
|
74
82
|
class MCPConfig(FastMCPBaseModel):
|
|
@@ -4,9 +4,11 @@ from typing import cast
|
|
|
4
4
|
|
|
5
5
|
import pytest
|
|
6
6
|
from mcp import McpError
|
|
7
|
+
from mcp.client.auth import OAuthClientProvider
|
|
7
8
|
from pydantic import AnyUrl
|
|
8
9
|
|
|
9
10
|
from fastmcp.client import Client
|
|
11
|
+
from fastmcp.client.auth.bearer import BearerAuth
|
|
10
12
|
from fastmcp.client.transports import (
|
|
11
13
|
FastMCPTransport,
|
|
12
14
|
MCPConfigTransport,
|
|
@@ -810,3 +812,73 @@ class TestInferTransport:
|
|
|
810
812
|
server = FastMCP1()
|
|
811
813
|
transport = infer_transport(server)
|
|
812
814
|
assert isinstance(transport, FastMCPTransport)
|
|
815
|
+
|
|
816
|
+
|
|
817
|
+
class TestAuth:
|
|
818
|
+
def test_default_auth_is_none(self):
|
|
819
|
+
client = Client(transport=StreamableHttpTransport("http://localhost:8000"))
|
|
820
|
+
assert client.transport.auth is None
|
|
821
|
+
|
|
822
|
+
def test_stdio_doesnt_support_auth(self):
|
|
823
|
+
with pytest.raises(ValueError, match="This transport does not support auth"):
|
|
824
|
+
Client(transport=StdioTransport("echo", ["hello"]), auth="oauth")
|
|
825
|
+
|
|
826
|
+
def test_oauth_literal_sets_up_oauth_shttp(self):
|
|
827
|
+
client = Client(
|
|
828
|
+
transport=StreamableHttpTransport("http://localhost:8000"), auth="oauth"
|
|
829
|
+
)
|
|
830
|
+
assert isinstance(client.transport, StreamableHttpTransport)
|
|
831
|
+
assert isinstance(client.transport.auth, OAuthClientProvider)
|
|
832
|
+
|
|
833
|
+
def test_oauth_literal_pass_direct_to_transport(self):
|
|
834
|
+
client = Client(
|
|
835
|
+
transport=StreamableHttpTransport("http://localhost:8000", auth="oauth"),
|
|
836
|
+
)
|
|
837
|
+
assert isinstance(client.transport, StreamableHttpTransport)
|
|
838
|
+
assert isinstance(client.transport.auth, OAuthClientProvider)
|
|
839
|
+
|
|
840
|
+
def test_oauth_literal_sets_up_oauth_sse(self):
|
|
841
|
+
client = Client(transport=SSETransport("http://localhost:8000"), auth="oauth")
|
|
842
|
+
assert isinstance(client.transport, SSETransport)
|
|
843
|
+
assert isinstance(client.transport.auth, OAuthClientProvider)
|
|
844
|
+
|
|
845
|
+
def test_oauth_literal_pass_direct_to_transport_sse(self):
|
|
846
|
+
client = Client(transport=SSETransport("http://localhost:8000", auth="oauth"))
|
|
847
|
+
assert isinstance(client.transport, SSETransport)
|
|
848
|
+
assert isinstance(client.transport.auth, OAuthClientProvider)
|
|
849
|
+
|
|
850
|
+
def test_auth_string_sets_up_bearer_auth_shttp(self):
|
|
851
|
+
client = Client(
|
|
852
|
+
transport=StreamableHttpTransport("http://localhost:8000"),
|
|
853
|
+
auth="test_token",
|
|
854
|
+
)
|
|
855
|
+
assert isinstance(client.transport, StreamableHttpTransport)
|
|
856
|
+
assert isinstance(client.transport.auth, BearerAuth)
|
|
857
|
+
assert client.transport.auth.token.get_secret_value() == "test_token"
|
|
858
|
+
|
|
859
|
+
def test_auth_string_pass_direct_to_transport_shttp(self):
|
|
860
|
+
client = Client(
|
|
861
|
+
transport=StreamableHttpTransport(
|
|
862
|
+
"http://localhost:8000", auth="test_token"
|
|
863
|
+
),
|
|
864
|
+
)
|
|
865
|
+
assert isinstance(client.transport, StreamableHttpTransport)
|
|
866
|
+
assert isinstance(client.transport.auth, BearerAuth)
|
|
867
|
+
assert client.transport.auth.token.get_secret_value() == "test_token"
|
|
868
|
+
|
|
869
|
+
def test_auth_string_sets_up_bearer_auth_sse(self):
|
|
870
|
+
client = Client(
|
|
871
|
+
transport=SSETransport("http://localhost:8000"),
|
|
872
|
+
auth="test_token",
|
|
873
|
+
)
|
|
874
|
+
assert isinstance(client.transport, SSETransport)
|
|
875
|
+
assert isinstance(client.transport.auth, BearerAuth)
|
|
876
|
+
assert client.transport.auth.token.get_secret_value() == "test_token"
|
|
877
|
+
|
|
878
|
+
def test_auth_string_pass_direct_to_transport_sse(self):
|
|
879
|
+
client = Client(
|
|
880
|
+
transport=SSETransport("http://localhost:8000", auth="test_token"),
|
|
881
|
+
)
|
|
882
|
+
assert isinstance(client.transport, SSETransport)
|
|
883
|
+
assert isinstance(client.transport.auth, BearerAuth)
|
|
884
|
+
assert client.transport.auth.token.get_secret_value() == "test_token"
|
|
@@ -304,6 +304,19 @@ class TestDynamicChanges:
|
|
|
304
304
|
tools = await main_app.get_tools()
|
|
305
305
|
assert "sub_temp_tool" not in tools
|
|
306
306
|
|
|
307
|
+
async def test_cache_expiration(self):
|
|
308
|
+
main_app = FastMCP("MainApp", cache_expiration_seconds=2)
|
|
309
|
+
sub_app = FastMCP("SubApp")
|
|
310
|
+
tools = await main_app.get_tools()
|
|
311
|
+
assert len(tools) == 0
|
|
312
|
+
|
|
313
|
+
@sub_app.tool
|
|
314
|
+
def sub_tool():
|
|
315
|
+
return "sub_tool"
|
|
316
|
+
|
|
317
|
+
tools = await main_app.get_tools()
|
|
318
|
+
assert len(tools) == 0
|
|
319
|
+
|
|
307
320
|
|
|
308
321
|
class TestResourcesAndTemplates:
|
|
309
322
|
"""Test mounting with resources and resource templates."""
|
|
@@ -9,7 +9,7 @@ from pydantic import AnyUrl
|
|
|
9
9
|
|
|
10
10
|
from fastmcp import FastMCP
|
|
11
11
|
from fastmcp.client import Client
|
|
12
|
-
from fastmcp.client.transports import FastMCPTransport
|
|
12
|
+
from fastmcp.client.transports import FastMCPTransport, StreamableHttpTransport
|
|
13
13
|
from fastmcp.exceptions import ToolError
|
|
14
14
|
from fastmcp.server.proxy import FastMCPProxy
|
|
15
15
|
|
|
@@ -104,7 +104,8 @@ def test_as_proxy_with_url():
|
|
|
104
104
|
"""FastMCP.as_proxy should accept a URL without connecting."""
|
|
105
105
|
proxy = FastMCP.as_proxy("http://example.com/mcp")
|
|
106
106
|
assert isinstance(proxy, FastMCPProxy)
|
|
107
|
-
assert
|
|
107
|
+
assert isinstance(proxy.client.transport, StreamableHttpTransport)
|
|
108
|
+
assert proxy.client.transport.url == "http://example.com/mcp"
|
|
108
109
|
|
|
109
110
|
|
|
110
111
|
class TestTools:
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import inspect
|
|
2
2
|
from pathlib import Path
|
|
3
3
|
|
|
4
|
+
from fastmcp.client.auth.bearer import BearerAuth
|
|
5
|
+
from fastmcp.client.auth.oauth import OAuthClientProvider
|
|
4
6
|
from fastmcp.client.client import Client
|
|
5
7
|
from fastmcp.client.transports import (
|
|
6
8
|
SSETransport,
|
|
@@ -136,3 +138,60 @@ async def test_multi_client(tmp_path: Path):
|
|
|
136
138
|
result_2 = await client.call_tool("test_2_add", {"a": 1, "b": 2})
|
|
137
139
|
assert result_1[0].text == "3" # type: ignore[attr-dict]
|
|
138
140
|
assert result_2[0].text == "3" # type: ignore[attr-dict]
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
async def test_remote_config_default_no_auth():
|
|
144
|
+
config = {
|
|
145
|
+
"mcpServers": {
|
|
146
|
+
"test_server": {
|
|
147
|
+
"url": "http://localhost:8000",
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
client = Client(config)
|
|
152
|
+
assert isinstance(client.transport.transport, StreamableHttpTransport)
|
|
153
|
+
assert client.transport.transport.auth is None
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
async def test_remote_config_with_auth_token():
|
|
157
|
+
config = {
|
|
158
|
+
"mcpServers": {
|
|
159
|
+
"test_server": {
|
|
160
|
+
"url": "http://localhost:8000",
|
|
161
|
+
"auth": "test_token",
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
client = Client(config)
|
|
166
|
+
assert isinstance(client.transport.transport, StreamableHttpTransport)
|
|
167
|
+
assert isinstance(client.transport.transport.auth, BearerAuth)
|
|
168
|
+
assert client.transport.transport.auth.token.get_secret_value() == "test_token"
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
async def test_remote_config_sse_with_auth_token():
|
|
172
|
+
config = {
|
|
173
|
+
"mcpServers": {
|
|
174
|
+
"test_server": {
|
|
175
|
+
"url": "http://localhost:8000/sse",
|
|
176
|
+
"auth": "test_token",
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
client = Client(config)
|
|
181
|
+
assert isinstance(client.transport.transport, SSETransport)
|
|
182
|
+
assert isinstance(client.transport.transport.auth, BearerAuth)
|
|
183
|
+
assert client.transport.transport.auth.token.get_secret_value() == "test_token"
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
async def test_remote_config_with_oauth_literal():
|
|
187
|
+
config = {
|
|
188
|
+
"mcpServers": {
|
|
189
|
+
"test_server": {
|
|
190
|
+
"url": "http://localhost:8000",
|
|
191
|
+
"auth": "oauth",
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
client = Client(config)
|
|
196
|
+
assert isinstance(client.transport.transport, StreamableHttpTransport)
|
|
197
|
+
assert isinstance(client.transport.transport.auth, OAuthClientProvider)
|
|
@@ -60,7 +60,7 @@ def complex_arguments_fn(
|
|
|
60
60
|
456,
|
|
61
61
|
],
|
|
62
62
|
field_with_default_via_field_annotation_before_nondefault_arg: Annotated[
|
|
63
|
-
int, Field(1)
|
|
63
|
+
int, Field(default=1)
|
|
64
64
|
],
|
|
65
65
|
unannotated,
|
|
66
66
|
my_model_a: SomeInputModelA,
|
|
@@ -68,7 +68,7 @@ def complex_arguments_fn(
|
|
|
68
68
|
my_model_b: SomeInputModelB,
|
|
69
69
|
an_int_annotated_with_field_default: Annotated[
|
|
70
70
|
int,
|
|
71
|
-
Field(1, description="An int with a field"),
|
|
71
|
+
Field(default=1, description="An int with a field"),
|
|
72
72
|
],
|
|
73
73
|
unannotated_with_default=5,
|
|
74
74
|
my_model_a_with_default: SomeInputModelA = SomeInputModelA(), # noqa: B008
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|