Copy disabled (too large)
Download .txt
Showing preview only (10,070K chars total). Download the full file to get everything.
Repository: PrefectHQ/fastmcp
Branch: main
Commit: f01c8fd7f467
Files: 1240
Total size: 9.4 MB
Directory structure:
gitextract_xwrq15g3/
├── .ccignore
├── .claude/
│ ├── hooks/
│ │ └── session-init.sh
│ ├── settings.json
│ └── skills/
│ ├── code-review/
│ │ └── SKILL.md
│ ├── python-tests/
│ │ └── SKILL.md
│ └── review-pr/
│ └── SKILL.md
├── .coderabbit.yaml
├── .cursor/
│ └── rules/
│ └── core-mcp-objects.mdc
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug.yml
│ │ ├── config.yml
│ │ └── enhancement.yml
│ ├── actions/
│ │ ├── run-claude/
│ │ │ └── action.yml
│ │ ├── run-pytest/
│ │ │ └── action.yml
│ │ └── setup-uv/
│ │ └── action.yml
│ ├── dependabot.yml
│ ├── pull_request_template.md
│ ├── release.yml
│ ├── scripts/
│ │ ├── mention/
│ │ │ ├── gh-get-review-threads.sh
│ │ │ └── gh-resolve-review-thread.sh
│ │ └── pr-review/
│ │ ├── pr-comment.sh
│ │ ├── pr-diff.sh
│ │ ├── pr-existing-comments.sh
│ │ ├── pr-remove-comment.sh
│ │ └── pr-review.sh
│ └── workflows/
│ ├── auto-close-duplicates.yml
│ ├── auto-close-needs-mre.yml
│ ├── martian-test-failure.yml
│ ├── martian-triage-issue.yml
│ ├── marvin-comment-on-issue.yml
│ ├── marvin-comment-on-pr.yml
│ ├── marvin-dedupe-issues.yml
│ ├── marvin-label-triage.yml
│ ├── minimize-resolved-reviews.yml
│ ├── publish.yml
│ ├── run-static.yml
│ ├── run-tests.yml
│ ├── run-upgrade-checks.yml
│ ├── update-config-schema.yml
│ └── update-sdk-docs.yml
├── .gitignore
├── .pre-commit-config.yaml
├── CLAUDE.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── SECURITY.md
├── docs/
│ ├── .ccignore
│ ├── .cursor/
│ │ └── rules/
│ │ └── mintlify.mdc
│ ├── apps/
│ │ ├── development.mdx
│ │ ├── low-level.mdx
│ │ ├── overview.mdx
│ │ ├── patterns.mdx
│ │ └── prefab.mdx
│ ├── assets/
│ │ └── schemas/
│ │ └── mcp_server_config/
│ │ ├── latest.json
│ │ └── v1.json
│ ├── changelog.mdx
│ ├── cli/
│ │ ├── auth.mdx
│ │ ├── client.mdx
│ │ ├── generate-cli.mdx
│ │ ├── inspecting.mdx
│ │ ├── install-mcp.mdx
│ │ ├── overview.mdx
│ │ └── running.mdx
│ ├── clients/
│ │ ├── auth/
│ │ │ ├── bearer.mdx
│ │ │ ├── cimd.mdx
│ │ │ └── oauth.mdx
│ │ ├── cli.mdx
│ │ ├── client.mdx
│ │ ├── elicitation.mdx
│ │ ├── generate-cli.mdx
│ │ ├── logging.mdx
│ │ ├── notifications.mdx
│ │ ├── progress.mdx
│ │ ├── prompts.mdx
│ │ ├── resources.mdx
│ │ ├── roots.mdx
│ │ ├── sampling.mdx
│ │ ├── tasks.mdx
│ │ ├── tools.mdx
│ │ └── transports.mdx
│ ├── community/
│ │ ├── README.md
│ │ └── showcase.mdx
│ ├── css/
│ │ ├── banner.css
│ │ ├── python-sdk.css
│ │ ├── style.css
│ │ └── version-badge.css
│ ├── deployment/
│ │ ├── http.mdx
│ │ ├── prefect-horizon.mdx
│ │ ├── running-server.mdx
│ │ └── server-configuration.mdx
│ ├── development/
│ │ ├── contributing.mdx
│ │ ├── releases.mdx
│ │ ├── tests.mdx
│ │ └── v3-notes/
│ │ ├── auth-provider-env-vars.mdx
│ │ └── v3-features.mdx
│ ├── docs.json
│ ├── getting-started/
│ │ ├── installation.mdx
│ │ ├── quickstart.mdx
│ │ ├── upgrading/
│ │ │ ├── from-fastmcp-2.mdx
│ │ │ ├── from-low-level-sdk.mdx
│ │ │ └── from-mcp-sdk.mdx
│ │ └── welcome.mdx
│ ├── integrations/
│ │ ├── anthropic.mdx
│ │ ├── auth0.mdx
│ │ ├── authkit.mdx
│ │ ├── aws-cognito.mdx
│ │ ├── azure.mdx
│ │ ├── chatgpt.mdx
│ │ ├── claude-code.mdx
│ │ ├── claude-desktop.mdx
│ │ ├── cursor.mdx
│ │ ├── descope.mdx
│ │ ├── discord.mdx
│ │ ├── eunomia-authorization.mdx
│ │ ├── fastapi.mdx
│ │ ├── gemini-cli.mdx
│ │ ├── gemini.mdx
│ │ ├── github.mdx
│ │ ├── google.mdx
│ │ ├── goose.mdx
│ │ ├── mcp-json-configuration.mdx
│ │ ├── oci.mdx
│ │ ├── openai.mdx
│ │ ├── openapi.mdx
│ │ ├── permit.mdx
│ │ ├── propelauth.mdx
│ │ ├── scalekit.mdx
│ │ ├── supabase.mdx
│ │ └── workos.mdx
│ ├── more/
│ │ └── settings.mdx
│ ├── patterns/
│ │ ├── cli.mdx
│ │ ├── contrib.mdx
│ │ └── testing.mdx
│ ├── public/
│ │ └── schemas/
│ │ └── fastmcp.json/
│ │ ├── latest.json
│ │ └── v1.json
│ ├── python-sdk/
│ │ ├── fastmcp-cli-__init__.mdx
│ │ ├── fastmcp-cli-apps_dev.mdx
│ │ ├── fastmcp-cli-auth.mdx
│ │ ├── fastmcp-cli-cimd.mdx
│ │ ├── fastmcp-cli-cli.mdx
│ │ ├── fastmcp-cli-client.mdx
│ │ ├── fastmcp-cli-discovery.mdx
│ │ ├── fastmcp-cli-generate.mdx
│ │ ├── fastmcp-cli-install-__init__.mdx
│ │ ├── fastmcp-cli-install-claude_code.mdx
│ │ ├── fastmcp-cli-install-claude_desktop.mdx
│ │ ├── fastmcp-cli-install-cursor.mdx
│ │ ├── fastmcp-cli-install-gemini_cli.mdx
│ │ ├── fastmcp-cli-install-goose.mdx
│ │ ├── fastmcp-cli-install-mcp_json.mdx
│ │ ├── fastmcp-cli-install-shared.mdx
│ │ ├── fastmcp-cli-install-stdio.mdx
│ │ ├── fastmcp-cli-run.mdx
│ │ ├── fastmcp-cli-tasks.mdx
│ │ ├── fastmcp-client-__init__.mdx
│ │ ├── fastmcp-client-auth-__init__.mdx
│ │ ├── fastmcp-client-auth-bearer.mdx
│ │ ├── fastmcp-client-auth-oauth.mdx
│ │ ├── fastmcp-client-client.mdx
│ │ ├── fastmcp-client-elicitation.mdx
│ │ ├── fastmcp-client-logging.mdx
│ │ ├── fastmcp-client-messages.mdx
│ │ ├── fastmcp-client-mixins-__init__.mdx
│ │ ├── fastmcp-client-mixins-prompts.mdx
│ │ ├── fastmcp-client-mixins-resources.mdx
│ │ ├── fastmcp-client-mixins-task_management.mdx
│ │ ├── fastmcp-client-mixins-tools.mdx
│ │ ├── fastmcp-client-oauth_callback.mdx
│ │ ├── fastmcp-client-progress.mdx
│ │ ├── fastmcp-client-roots.mdx
│ │ ├── fastmcp-client-sampling-__init__.mdx
│ │ ├── fastmcp-client-sampling-handlers-__init__.mdx
│ │ ├── fastmcp-client-sampling-handlers-anthropic.mdx
│ │ ├── fastmcp-client-sampling-handlers-google_genai.mdx
│ │ ├── fastmcp-client-sampling-handlers-openai.mdx
│ │ ├── fastmcp-client-tasks.mdx
│ │ ├── fastmcp-client-telemetry.mdx
│ │ ├── fastmcp-client-transports-__init__.mdx
│ │ ├── fastmcp-client-transports-base.mdx
│ │ ├── fastmcp-client-transports-config.mdx
│ │ ├── fastmcp-client-transports-http.mdx
│ │ ├── fastmcp-client-transports-inference.mdx
│ │ ├── fastmcp-client-transports-memory.mdx
│ │ ├── fastmcp-client-transports-sse.mdx
│ │ ├── fastmcp-client-transports-stdio.mdx
│ │ ├── fastmcp-decorators.mdx
│ │ ├── fastmcp-dependencies.mdx
│ │ ├── fastmcp-exceptions.mdx
│ │ ├── fastmcp-experimental-__init__.mdx
│ │ ├── fastmcp-experimental-sampling-__init__.mdx
│ │ ├── fastmcp-experimental-sampling-handlers.mdx
│ │ ├── fastmcp-experimental-transforms-__init__.mdx
│ │ ├── fastmcp-experimental-transforms-code_mode.mdx
│ │ ├── fastmcp-mcp_config.mdx
│ │ ├── fastmcp-prompts-__init__.mdx
│ │ ├── fastmcp-prompts-base.mdx
│ │ ├── fastmcp-prompts-function_prompt.mdx
│ │ ├── fastmcp-resources-__init__.mdx
│ │ ├── fastmcp-resources-base.mdx
│ │ ├── fastmcp-resources-function_resource.mdx
│ │ ├── fastmcp-resources-template.mdx
│ │ ├── fastmcp-resources-types.mdx
│ │ ├── fastmcp-server-__init__.mdx
│ │ ├── fastmcp-server-app.mdx
│ │ ├── fastmcp-server-apps.mdx
│ │ ├── fastmcp-server-auth-__init__.mdx
│ │ ├── fastmcp-server-auth-auth.mdx
│ │ ├── fastmcp-server-auth-authorization.mdx
│ │ ├── fastmcp-server-auth-cimd.mdx
│ │ ├── fastmcp-server-auth-jwt_issuer.mdx
│ │ ├── fastmcp-server-auth-middleware.mdx
│ │ ├── fastmcp-server-auth-oauth_proxy-__init__.mdx
│ │ ├── fastmcp-server-auth-oauth_proxy-consent.mdx
│ │ ├── fastmcp-server-auth-oauth_proxy-models.mdx
│ │ ├── fastmcp-server-auth-oauth_proxy-proxy.mdx
│ │ ├── fastmcp-server-auth-oauth_proxy-ui.mdx
│ │ ├── fastmcp-server-auth-oidc_proxy.mdx
│ │ ├── fastmcp-server-auth-providers-__init__.mdx
│ │ ├── fastmcp-server-auth-providers-auth0.mdx
│ │ ├── fastmcp-server-auth-providers-aws.mdx
│ │ ├── fastmcp-server-auth-providers-azure.mdx
│ │ ├── fastmcp-server-auth-providers-debug.mdx
│ │ ├── fastmcp-server-auth-providers-descope.mdx
│ │ ├── fastmcp-server-auth-providers-discord.mdx
│ │ ├── fastmcp-server-auth-providers-github.mdx
│ │ ├── fastmcp-server-auth-providers-google.mdx
│ │ ├── fastmcp-server-auth-providers-in_memory.mdx
│ │ ├── fastmcp-server-auth-providers-introspection.mdx
│ │ ├── fastmcp-server-auth-providers-jwt.mdx
│ │ ├── fastmcp-server-auth-providers-oci.mdx
│ │ ├── fastmcp-server-auth-providers-propelauth.mdx
│ │ ├── fastmcp-server-auth-providers-scalekit.mdx
│ │ ├── fastmcp-server-auth-providers-supabase.mdx
│ │ ├── fastmcp-server-auth-providers-workos.mdx
│ │ ├── fastmcp-server-auth-redirect_validation.mdx
│ │ ├── fastmcp-server-auth-ssrf.mdx
│ │ ├── fastmcp-server-context.mdx
│ │ ├── fastmcp-server-dependencies.mdx
│ │ ├── fastmcp-server-elicitation.mdx
│ │ ├── fastmcp-server-event_store.mdx
│ │ ├── fastmcp-server-http.mdx
│ │ ├── fastmcp-server-lifespan.mdx
│ │ ├── fastmcp-server-low_level.mdx
│ │ ├── fastmcp-server-middleware-__init__.mdx
│ │ ├── fastmcp-server-middleware-authorization.mdx
│ │ ├── fastmcp-server-middleware-caching.mdx
│ │ ├── fastmcp-server-middleware-dereference.mdx
│ │ ├── fastmcp-server-middleware-error_handling.mdx
│ │ ├── fastmcp-server-middleware-logging.mdx
│ │ ├── fastmcp-server-middleware-middleware.mdx
│ │ ├── fastmcp-server-middleware-ping.mdx
│ │ ├── fastmcp-server-middleware-rate_limiting.mdx
│ │ ├── fastmcp-server-middleware-response_limiting.mdx
│ │ ├── fastmcp-server-middleware-timing.mdx
│ │ ├── fastmcp-server-middleware-tool_injection.mdx
│ │ ├── fastmcp-server-mixins-__init__.mdx
│ │ ├── fastmcp-server-mixins-lifespan.mdx
│ │ ├── fastmcp-server-mixins-mcp_operations.mdx
│ │ ├── fastmcp-server-mixins-transport.mdx
│ │ ├── fastmcp-server-openapi-__init__.mdx
│ │ ├── fastmcp-server-openapi-components.mdx
│ │ ├── fastmcp-server-openapi-routing.mdx
│ │ ├── fastmcp-server-openapi-server.mdx
│ │ ├── fastmcp-server-providers-__init__.mdx
│ │ ├── fastmcp-server-providers-aggregate.mdx
│ │ ├── fastmcp-server-providers-base.mdx
│ │ ├── fastmcp-server-providers-fastmcp_provider.mdx
│ │ ├── fastmcp-server-providers-filesystem.mdx
│ │ ├── fastmcp-server-providers-filesystem_discovery.mdx
│ │ ├── fastmcp-server-providers-local_provider-__init__.mdx
│ │ ├── fastmcp-server-providers-local_provider-decorators-__init__.mdx
│ │ ├── fastmcp-server-providers-local_provider-decorators-prompts.mdx
│ │ ├── fastmcp-server-providers-local_provider-decorators-resources.mdx
│ │ ├── fastmcp-server-providers-local_provider-decorators-tools.mdx
│ │ ├── fastmcp-server-providers-local_provider-local_provider.mdx
│ │ ├── fastmcp-server-providers-openapi-__init__.mdx
│ │ ├── fastmcp-server-providers-openapi-components.mdx
│ │ ├── fastmcp-server-providers-openapi-provider.mdx
│ │ ├── fastmcp-server-providers-openapi-routing.mdx
│ │ ├── fastmcp-server-providers-proxy.mdx
│ │ ├── fastmcp-server-providers-skills-__init__.mdx
│ │ ├── fastmcp-server-providers-skills-claude_provider.mdx
│ │ ├── fastmcp-server-providers-skills-directory_provider.mdx
│ │ ├── fastmcp-server-providers-skills-skill_provider.mdx
│ │ ├── fastmcp-server-providers-skills-vendor_providers.mdx
│ │ ├── fastmcp-server-providers-wrapped_provider.mdx
│ │ ├── fastmcp-server-proxy.mdx
│ │ ├── fastmcp-server-sampling-__init__.mdx
│ │ ├── fastmcp-server-sampling-run.mdx
│ │ ├── fastmcp-server-sampling-sampling_tool.mdx
│ │ ├── fastmcp-server-server.mdx
│ │ ├── fastmcp-server-tasks-__init__.mdx
│ │ ├── fastmcp-server-tasks-capabilities.mdx
│ │ ├── fastmcp-server-tasks-config.mdx
│ │ ├── fastmcp-server-tasks-elicitation.mdx
│ │ ├── fastmcp-server-tasks-handlers.mdx
│ │ ├── fastmcp-server-tasks-keys.mdx
│ │ ├── fastmcp-server-tasks-notifications.mdx
│ │ ├── fastmcp-server-tasks-requests.mdx
│ │ ├── fastmcp-server-tasks-routing.mdx
│ │ ├── fastmcp-server-tasks-subscriptions.mdx
│ │ ├── fastmcp-server-telemetry.mdx
│ │ ├── fastmcp-server-transforms-__init__.mdx
│ │ ├── fastmcp-server-transforms-catalog.mdx
│ │ ├── fastmcp-server-transforms-namespace.mdx
│ │ ├── fastmcp-server-transforms-prompts_as_tools.mdx
│ │ ├── fastmcp-server-transforms-resources_as_tools.mdx
│ │ ├── fastmcp-server-transforms-search-__init__.mdx
│ │ ├── fastmcp-server-transforms-search-base.mdx
│ │ ├── fastmcp-server-transforms-search-bm25.mdx
│ │ ├── fastmcp-server-transforms-search-regex.mdx
│ │ ├── fastmcp-server-transforms-tool_transform.mdx
│ │ ├── fastmcp-server-transforms-version_filter.mdx
│ │ ├── fastmcp-server-transforms-visibility.mdx
│ │ ├── fastmcp-settings.mdx
│ │ ├── fastmcp-telemetry.mdx
│ │ ├── fastmcp-tools-__init__.mdx
│ │ ├── fastmcp-tools-base.mdx
│ │ ├── fastmcp-tools-function_parsing.mdx
│ │ ├── fastmcp-tools-function_tool.mdx
│ │ ├── fastmcp-tools-tool_transform.mdx
│ │ ├── fastmcp-utilities-__init__.mdx
│ │ ├── fastmcp-utilities-async_utils.mdx
│ │ ├── fastmcp-utilities-auth.mdx
│ │ ├── fastmcp-utilities-cli.mdx
│ │ ├── fastmcp-utilities-components.mdx
│ │ ├── fastmcp-utilities-exceptions.mdx
│ │ ├── fastmcp-utilities-http.mdx
│ │ ├── fastmcp-utilities-inspect.mdx
│ │ ├── fastmcp-utilities-json_schema.mdx
│ │ ├── fastmcp-utilities-json_schema_type.mdx
│ │ ├── fastmcp-utilities-lifespan.mdx
│ │ ├── fastmcp-utilities-logging.mdx
│ │ ├── fastmcp-utilities-mcp_server_config-__init__.mdx
│ │ ├── fastmcp-utilities-mcp_server_config-v1-__init__.mdx
│ │ ├── fastmcp-utilities-mcp_server_config-v1-environments-__init__.mdx
│ │ ├── fastmcp-utilities-mcp_server_config-v1-environments-base.mdx
│ │ ├── fastmcp-utilities-mcp_server_config-v1-environments-uv.mdx
│ │ ├── fastmcp-utilities-mcp_server_config-v1-mcp_server_config.mdx
│ │ ├── fastmcp-utilities-mcp_server_config-v1-sources-__init__.mdx
│ │ ├── fastmcp-utilities-mcp_server_config-v1-sources-base.mdx
│ │ ├── fastmcp-utilities-mcp_server_config-v1-sources-filesystem.mdx
│ │ ├── fastmcp-utilities-openapi-__init__.mdx
│ │ ├── fastmcp-utilities-openapi-director.mdx
│ │ ├── fastmcp-utilities-openapi-formatters.mdx
│ │ ├── fastmcp-utilities-openapi-json_schema_converter.mdx
│ │ ├── fastmcp-utilities-openapi-models.mdx
│ │ ├── fastmcp-utilities-openapi-parser.mdx
│ │ ├── fastmcp-utilities-openapi-schemas.mdx
│ │ ├── fastmcp-utilities-pagination.mdx
│ │ ├── fastmcp-utilities-skills.mdx
│ │ ├── fastmcp-utilities-tests.mdx
│ │ ├── fastmcp-utilities-timeout.mdx
│ │ ├── fastmcp-utilities-token_cache.mdx
│ │ ├── fastmcp-utilities-types.mdx
│ │ ├── fastmcp-utilities-ui.mdx
│ │ ├── fastmcp-utilities-version_check.mdx
│ │ └── fastmcp-utilities-versions.mdx
│ ├── servers/
│ │ ├── auth/
│ │ │ ├── authentication.mdx
│ │ │ ├── full-oauth-server.mdx
│ │ │ ├── multi-auth.mdx
│ │ │ ├── oauth-proxy.mdx
│ │ │ ├── oidc-proxy.mdx
│ │ │ ├── remote-oauth.mdx
│ │ │ └── token-verification.mdx
│ │ ├── authorization.mdx
│ │ ├── composition.mdx
│ │ ├── context.mdx
│ │ ├── dependency-injection.mdx
│ │ ├── elicitation.mdx
│ │ ├── icons.mdx
│ │ ├── lifespan.mdx
│ │ ├── logging.mdx
│ │ ├── middleware.mdx
│ │ ├── pagination.mdx
│ │ ├── progress.mdx
│ │ ├── prompts.mdx
│ │ ├── providers/
│ │ │ ├── custom.mdx
│ │ │ ├── filesystem.mdx
│ │ │ ├── local.mdx
│ │ │ ├── overview.mdx
│ │ │ ├── proxy.mdx
│ │ │ └── skills.mdx
│ │ ├── resources.mdx
│ │ ├── sampling.mdx
│ │ ├── server.mdx
│ │ ├── storage-backends.mdx
│ │ ├── tasks.mdx
│ │ ├── telemetry.mdx
│ │ ├── testing.mdx
│ │ ├── tools.mdx
│ │ ├── transforms/
│ │ │ ├── code-mode.mdx
│ │ │ ├── namespace.mdx
│ │ │ ├── namespacing.mdx
│ │ │ ├── prompts-as-tools.mdx
│ │ │ ├── resources-as-tools.mdx
│ │ │ ├── tool-search.mdx
│ │ │ ├── tool-transformation.mdx
│ │ │ └── transforms.mdx
│ │ ├── versioning.mdx
│ │ └── visibility.mdx
│ ├── snippets/
│ │ ├── local-focus.mdx
│ │ ├── version-badge.mdx
│ │ └── youtube-embed.mdx
│ ├── tutorials/
│ │ ├── create-mcp-server.mdx
│ │ ├── mcp.mdx
│ │ └── rest-api.mdx
│ ├── unify-intent.js
│ ├── updates.mdx
│ ├── v2/
│ │ ├── changelog.mdx
│ │ ├── clients/
│ │ │ ├── auth/
│ │ │ │ ├── bearer.mdx
│ │ │ │ └── oauth.mdx
│ │ │ ├── client.mdx
│ │ │ ├── elicitation.mdx
│ │ │ ├── logging.mdx
│ │ │ ├── messages.mdx
│ │ │ ├── progress.mdx
│ │ │ ├── prompts.mdx
│ │ │ ├── resources.mdx
│ │ │ ├── roots.mdx
│ │ │ ├── sampling.mdx
│ │ │ ├── tasks.mdx
│ │ │ ├── tools.mdx
│ │ │ └── transports.mdx
│ │ ├── community/
│ │ │ └── showcase.mdx
│ │ ├── deployment/
│ │ │ ├── http.mdx
│ │ │ ├── running-server.mdx
│ │ │ └── server-configuration.mdx
│ │ ├── development/
│ │ │ ├── contributing.mdx
│ │ │ ├── releases.mdx
│ │ │ ├── tests.mdx
│ │ │ └── upgrade-guide.mdx
│ │ ├── getting-started/
│ │ │ ├── installation.mdx
│ │ │ ├── quickstart.mdx
│ │ │ └── welcome.mdx
│ │ ├── integrations/
│ │ │ ├── anthropic.mdx
│ │ │ ├── auth0.mdx
│ │ │ ├── authkit.mdx
│ │ │ ├── aws-cognito.mdx
│ │ │ ├── azure.mdx
│ │ │ ├── chatgpt.mdx
│ │ │ ├── claude-code.mdx
│ │ │ ├── claude-desktop.mdx
│ │ │ ├── cursor.mdx
│ │ │ ├── descope.mdx
│ │ │ ├── discord.mdx
│ │ │ ├── eunomia-authorization.mdx
│ │ │ ├── fastapi.mdx
│ │ │ ├── gemini-cli.mdx
│ │ │ ├── gemini.mdx
│ │ │ ├── github.mdx
│ │ │ ├── google.mdx
│ │ │ ├── mcp-json-configuration.mdx
│ │ │ ├── oci.mdx
│ │ │ ├── openai.mdx
│ │ │ ├── openapi.mdx
│ │ │ ├── permit.mdx
│ │ │ ├── scalekit.mdx
│ │ │ ├── supabase.mdx
│ │ │ └── workos.mdx
│ │ ├── patterns/
│ │ │ ├── cli.mdx
│ │ │ ├── contrib.mdx
│ │ │ ├── decorating-methods.mdx
│ │ │ ├── testing.mdx
│ │ │ └── tool-transformation.mdx
│ │ ├── servers/
│ │ │ ├── auth/
│ │ │ │ ├── authentication.mdx
│ │ │ │ ├── full-oauth-server.mdx
│ │ │ │ ├── oauth-proxy.mdx
│ │ │ │ ├── oidc-proxy.mdx
│ │ │ │ ├── remote-oauth.mdx
│ │ │ │ └── token-verification.mdx
│ │ │ ├── composition.mdx
│ │ │ ├── context.mdx
│ │ │ ├── elicitation.mdx
│ │ │ ├── icons.mdx
│ │ │ ├── logging.mdx
│ │ │ ├── middleware.mdx
│ │ │ ├── progress.mdx
│ │ │ ├── prompts.mdx
│ │ │ ├── proxy.mdx
│ │ │ ├── resources.mdx
│ │ │ ├── sampling.mdx
│ │ │ ├── server.mdx
│ │ │ ├── storage-backends.mdx
│ │ │ ├── tasks.mdx
│ │ │ └── tools.mdx
│ │ ├── tutorials/
│ │ │ ├── create-mcp-server.mdx
│ │ │ ├── mcp.mdx
│ │ │ └── rest-api.mdx
│ │ └── updates.mdx
│ └── v2-banner.js
├── examples/
│ ├── apps/
│ │ ├── chart_server.py
│ │ ├── contacts/
│ │ │ └── contacts_server.py
│ │ ├── datatable_server.py
│ │ ├── greet_server.py
│ │ ├── patterns_server.py
│ │ └── qr_server/
│ │ ├── README.md
│ │ ├── fastmcp.json
│ │ ├── pyproject.toml
│ │ └── qr_server.py
│ ├── atproto_mcp/
│ │ ├── README.md
│ │ ├── demo.py
│ │ ├── fastmcp.json
│ │ ├── pyproject.toml
│ │ └── src/
│ │ └── atproto_mcp/
│ │ ├── __init__.py
│ │ ├── __main__.py
│ │ ├── _atproto/
│ │ │ ├── __init__.py
│ │ │ ├── _client.py
│ │ │ ├── _posts.py
│ │ │ ├── _profile.py
│ │ │ ├── _read.py
│ │ │ └── _social.py
│ │ ├── py.typed
│ │ ├── server.py
│ │ ├── settings.py
│ │ └── types.py
│ ├── auth/
│ │ ├── authkit_dcr/
│ │ │ ├── README.md
│ │ │ ├── client.py
│ │ │ └── server.py
│ │ ├── aws_oauth/
│ │ │ ├── README.md
│ │ │ ├── client.py
│ │ │ ├── requirements.txt
│ │ │ └── server.py
│ │ ├── azure_oauth/
│ │ │ ├── README.md
│ │ │ ├── client.py
│ │ │ └── server.py
│ │ ├── discord_oauth/
│ │ │ ├── README.md
│ │ │ ├── client.py
│ │ │ └── server.py
│ │ ├── github_oauth/
│ │ │ ├── README.md
│ │ │ ├── client.py
│ │ │ └── server.py
│ │ ├── google_oauth/
│ │ │ ├── README.md
│ │ │ ├── client.py
│ │ │ └── server.py
│ │ ├── mounted/
│ │ │ ├── README.md
│ │ │ ├── client.py
│ │ │ └── server.py
│ │ ├── propelauth_oauth/
│ │ │ ├── README.md
│ │ │ ├── client.py
│ │ │ └── server.py
│ │ ├── scalekit_oauth/
│ │ │ ├── README.md
│ │ │ ├── client.py
│ │ │ └── server.py
│ │ └── workos_oauth/
│ │ ├── README.md
│ │ ├── client.py
│ │ └── server.py
│ ├── code_mode/
│ │ ├── README.md
│ │ ├── client.py
│ │ └── server.py
│ ├── complex_inputs.py
│ ├── config_server.py
│ ├── custom_tool_serializer_decorator.py
│ ├── desktop.py
│ ├── diagnostics/
│ │ ├── client_with_tracing.py
│ │ └── server.py
│ ├── echo.py
│ ├── elicitation.py
│ ├── fastmcp_config/
│ │ ├── env_interpolation_example.json
│ │ ├── fastmcp.json
│ │ ├── full_example.fastmcp.json
│ │ ├── server.py
│ │ └── simple.fastmcp.json
│ ├── fastmcp_config_demo/
│ │ ├── README.md
│ │ ├── fastmcp.json
│ │ └── server.py
│ ├── filesystem-provider/
│ │ ├── mcp/
│ │ │ ├── prompts/
│ │ │ │ └── assistant.py
│ │ │ ├── resources/
│ │ │ │ └── config.py
│ │ │ └── tools/
│ │ │ ├── calculator.py
│ │ │ └── greeting.py
│ │ └── server.py
│ ├── get_file.py
│ ├── in_memory_proxy_example.py
│ ├── memory.fastmcp.json
│ ├── memory.py
│ ├── mount_example.fastmcp.json
│ ├── mount_example.py
│ ├── namespace_activation/
│ │ ├── README.md
│ │ ├── client.py
│ │ └── server.py
│ ├── persistent_state/
│ │ ├── README.md
│ │ ├── client.py
│ │ ├── client_stdio.py
│ │ └── server.py
│ ├── prompts_as_tools/
│ │ ├── client.py
│ │ └── server.py
│ ├── providers/
│ │ └── sqlite/
│ │ ├── README.md
│ │ ├── server.py
│ │ └── setup_db.py
│ ├── resources_as_tools/
│ │ ├── client.py
│ │ └── server.py
│ ├── run_with_tracing.py
│ ├── sampling/
│ │ ├── README.md
│ │ ├── server_fallback.py
│ │ ├── structured_output.py
│ │ ├── text.py
│ │ └── tool_use.py
│ ├── screenshot.fastmcp.json
│ ├── screenshot.py
│ ├── search/
│ │ ├── README.md
│ │ ├── client_bm25.py
│ │ ├── client_regex.py
│ │ ├── server_bm25.py
│ │ └── server_regex.py
│ ├── simple_echo.py
│ ├── skills/
│ │ ├── README.md
│ │ ├── client.py
│ │ ├── download_skills.py
│ │ ├── sample_skills/
│ │ │ ├── code-review/
│ │ │ │ └── SKILL.md
│ │ │ └── pdf-processing/
│ │ │ ├── SKILL.md
│ │ │ └── reference.md
│ │ └── server.py
│ ├── smart_home/
│ │ ├── README.md
│ │ ├── hub.fastmcp.json
│ │ ├── lights.fastmcp.json
│ │ ├── pyproject.toml
│ │ └── src/
│ │ └── smart_home/
│ │ ├── __init__.py
│ │ ├── __main__.py
│ │ ├── hub.py
│ │ ├── lights/
│ │ │ ├── __init__.py
│ │ │ ├── hue_utils.py
│ │ │ └── server.py
│ │ ├── py.typed
│ │ └── settings.py
│ ├── tags_example.py
│ ├── task_elicitation.py
│ ├── tasks/
│ │ ├── README.md
│ │ ├── client.py
│ │ ├── docker-compose.yml
│ │ └── server.py
│ ├── testing_demo/
│ │ ├── README.md
│ │ ├── pyproject.toml
│ │ ├── server.py
│ │ └── tests/
│ │ └── test_server.py
│ ├── text_me.py
│ ├── tool_result_echo.py
│ └── versioning/
│ ├── client_version_selection.py
│ ├── version_filters.py
│ └── versioned_components.py
├── justfile
├── logo.py
├── loq.toml
├── pyproject.toml
├── scripts/
│ ├── auto_close_duplicates.py
│ ├── auto_close_needs_mre.py
│ └── benchmark_imports.py
├── skills/
│ └── fastmcp-client-cli/
│ └── SKILL.md
├── src/
│ └── fastmcp/
│ ├── __init__.py
│ ├── cli/
│ │ ├── __init__.py
│ │ ├── __main__.py
│ │ ├── apps_dev.py
│ │ ├── auth.py
│ │ ├── cimd.py
│ │ ├── cli.py
│ │ ├── client.py
│ │ ├── discovery.py
│ │ ├── generate.py
│ │ ├── install/
│ │ │ ├── __init__.py
│ │ │ ├── claude_code.py
│ │ │ ├── claude_desktop.py
│ │ │ ├── cursor.py
│ │ │ ├── gemini_cli.py
│ │ │ ├── goose.py
│ │ │ ├── mcp_json.py
│ │ │ ├── shared.py
│ │ │ └── stdio.py
│ │ ├── run.py
│ │ └── tasks.py
│ ├── client/
│ │ ├── __init__.py
│ │ ├── auth/
│ │ │ ├── __init__.py
│ │ │ ├── bearer.py
│ │ │ └── oauth.py
│ │ ├── client.py
│ │ ├── elicitation.py
│ │ ├── logging.py
│ │ ├── messages.py
│ │ ├── mixins/
│ │ │ ├── __init__.py
│ │ │ ├── prompts.py
│ │ │ ├── resources.py
│ │ │ ├── task_management.py
│ │ │ └── tools.py
│ │ ├── oauth_callback.py
│ │ ├── progress.py
│ │ ├── roots.py
│ │ ├── sampling/
│ │ │ ├── __init__.py
│ │ │ └── handlers/
│ │ │ ├── __init__.py
│ │ │ ├── anthropic.py
│ │ │ ├── google_genai.py
│ │ │ └── openai.py
│ │ ├── tasks.py
│ │ ├── telemetry.py
│ │ └── transports/
│ │ ├── __init__.py
│ │ ├── base.py
│ │ ├── config.py
│ │ ├── http.py
│ │ ├── inference.py
│ │ ├── memory.py
│ │ ├── sse.py
│ │ └── stdio.py
│ ├── contrib/
│ │ ├── README.md
│ │ ├── bulk_tool_caller/
│ │ │ ├── README.md
│ │ │ ├── __init__.py
│ │ │ ├── bulk_tool_caller.py
│ │ │ └── example.py
│ │ ├── component_manager/
│ │ │ ├── README.md
│ │ │ ├── __init__.py
│ │ │ ├── component_manager.py
│ │ │ └── example.py
│ │ └── mcp_mixin/
│ │ ├── README.md
│ │ ├── __init__.py
│ │ ├── example.py
│ │ └── mcp_mixin.py
│ ├── decorators.py
│ ├── dependencies.py
│ ├── exceptions.py
│ ├── experimental/
│ │ ├── __init__.py
│ │ ├── sampling/
│ │ │ ├── __init__.py
│ │ │ └── handlers/
│ │ │ ├── __init__.py
│ │ │ └── openai.py
│ │ ├── server/
│ │ │ └── openapi/
│ │ │ └── __init__.py
│ │ ├── transforms/
│ │ │ ├── __init__.py
│ │ │ └── code_mode.py
│ │ └── utilities/
│ │ └── openapi/
│ │ └── __init__.py
│ ├── mcp_config.py
│ ├── prompts/
│ │ ├── __init__.py
│ │ ├── base.py
│ │ └── function_prompt.py
│ ├── py.typed
│ ├── resources/
│ │ ├── __init__.py
│ │ ├── base.py
│ │ ├── function_resource.py
│ │ ├── template.py
│ │ └── types.py
│ ├── server/
│ │ ├── __init__.py
│ │ ├── app.py
│ │ ├── apps.py
│ │ ├── auth/
│ │ │ ├── __init__.py
│ │ │ ├── auth.py
│ │ │ ├── authorization.py
│ │ │ ├── cimd.py
│ │ │ ├── handlers/
│ │ │ │ └── authorize.py
│ │ │ ├── jwt_issuer.py
│ │ │ ├── middleware.py
│ │ │ ├── oauth_proxy/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── consent.py
│ │ │ │ ├── models.py
│ │ │ │ ├── proxy.py
│ │ │ │ └── ui.py
│ │ │ ├── oidc_proxy.py
│ │ │ ├── providers/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── auth0.py
│ │ │ │ ├── aws.py
│ │ │ │ ├── azure.py
│ │ │ │ ├── debug.py
│ │ │ │ ├── descope.py
│ │ │ │ ├── discord.py
│ │ │ │ ├── github.py
│ │ │ │ ├── google.py
│ │ │ │ ├── in_memory.py
│ │ │ │ ├── introspection.py
│ │ │ │ ├── jwt.py
│ │ │ │ ├── oci.py
│ │ │ │ ├── propelauth.py
│ │ │ │ ├── scalekit.py
│ │ │ │ ├── supabase.py
│ │ │ │ └── workos.py
│ │ │ ├── redirect_validation.py
│ │ │ └── ssrf.py
│ │ ├── context.py
│ │ ├── dependencies.py
│ │ ├── elicitation.py
│ │ ├── event_store.py
│ │ ├── http.py
│ │ ├── lifespan.py
│ │ ├── low_level.py
│ │ ├── middleware/
│ │ │ ├── __init__.py
│ │ │ ├── authorization.py
│ │ │ ├── caching.py
│ │ │ ├── dereference.py
│ │ │ ├── error_handling.py
│ │ │ ├── logging.py
│ │ │ ├── middleware.py
│ │ │ ├── ping.py
│ │ │ ├── rate_limiting.py
│ │ │ ├── response_limiting.py
│ │ │ ├── timing.py
│ │ │ └── tool_injection.py
│ │ ├── mixins/
│ │ │ ├── __init__.py
│ │ │ ├── lifespan.py
│ │ │ ├── mcp_operations.py
│ │ │ └── transport.py
│ │ ├── openapi/
│ │ │ ├── __init__.py
│ │ │ ├── components.py
│ │ │ ├── routing.py
│ │ │ └── server.py
│ │ ├── providers/
│ │ │ ├── __init__.py
│ │ │ ├── aggregate.py
│ │ │ ├── base.py
│ │ │ ├── fastmcp_provider.py
│ │ │ ├── filesystem.py
│ │ │ ├── filesystem_discovery.py
│ │ │ ├── local_provider/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── decorators/
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── prompts.py
│ │ │ │ │ ├── resources.py
│ │ │ │ │ └── tools.py
│ │ │ │ └── local_provider.py
│ │ │ ├── openapi/
│ │ │ │ ├── README.md
│ │ │ │ ├── __init__.py
│ │ │ │ ├── components.py
│ │ │ │ ├── provider.py
│ │ │ │ └── routing.py
│ │ │ ├── proxy.py
│ │ │ ├── skills/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── _common.py
│ │ │ │ ├── claude_provider.py
│ │ │ │ ├── directory_provider.py
│ │ │ │ ├── skill_provider.py
│ │ │ │ └── vendor_providers.py
│ │ │ └── wrapped_provider.py
│ │ ├── proxy.py
│ │ ├── sampling/
│ │ │ ├── __init__.py
│ │ │ ├── run.py
│ │ │ └── sampling_tool.py
│ │ ├── server.py
│ │ ├── tasks/
│ │ │ ├── __init__.py
│ │ │ ├── capabilities.py
│ │ │ ├── config.py
│ │ │ ├── elicitation.py
│ │ │ ├── handlers.py
│ │ │ ├── keys.py
│ │ │ ├── notifications.py
│ │ │ ├── requests.py
│ │ │ ├── routing.py
│ │ │ └── subscriptions.py
│ │ ├── telemetry.py
│ │ └── transforms/
│ │ ├── __init__.py
│ │ ├── catalog.py
│ │ ├── namespace.py
│ │ ├── prompts_as_tools.py
│ │ ├── resources_as_tools.py
│ │ ├── search/
│ │ │ ├── __init__.py
│ │ │ ├── base.py
│ │ │ ├── bm25.py
│ │ │ └── regex.py
│ │ ├── tool_transform.py
│ │ ├── version_filter.py
│ │ └── visibility.py
│ ├── settings.py
│ ├── telemetry.py
│ ├── tools/
│ │ ├── __init__.py
│ │ ├── base.py
│ │ ├── function_parsing.py
│ │ ├── function_tool.py
│ │ └── tool_transform.py
│ └── utilities/
│ ├── __init__.py
│ ├── async_utils.py
│ ├── auth.py
│ ├── cli.py
│ ├── components.py
│ ├── exceptions.py
│ ├── http.py
│ ├── inspect.py
│ ├── json_schema.py
│ ├── json_schema_type.py
│ ├── lifespan.py
│ ├── logging.py
│ ├── mcp_server_config/
│ │ ├── __init__.py
│ │ └── v1/
│ │ ├── __init__.py
│ │ ├── environments/
│ │ │ ├── __init__.py
│ │ │ ├── base.py
│ │ │ └── uv.py
│ │ ├── mcp_server_config.py
│ │ ├── schema.json
│ │ └── sources/
│ │ ├── __init__.py
│ │ ├── base.py
│ │ └── filesystem.py
│ ├── openapi/
│ │ ├── README.md
│ │ ├── __init__.py
│ │ ├── director.py
│ │ ├── formatters.py
│ │ ├── json_schema_converter.py
│ │ ├── models.py
│ │ ├── parser.py
│ │ └── schemas.py
│ ├── pagination.py
│ ├── skills.py
│ ├── tests.py
│ ├── timeout.py
│ ├── token_cache.py
│ ├── types.py
│ ├── ui.py
│ ├── version_check.py
│ └── versions.py
├── tests/
│ ├── __init__.py
│ ├── cli/
│ │ ├── __init__.py
│ │ ├── test_cimd_cli.py
│ │ ├── test_cli.py
│ │ ├── test_client_commands.py
│ │ ├── test_config.py
│ │ ├── test_cursor.py
│ │ ├── test_discovery.py
│ │ ├── test_generate_cli.py
│ │ ├── test_goose.py
│ │ ├── test_install.py
│ │ ├── test_mcp_server_config_integration.py
│ │ ├── test_mcp_server_config_schema.py
│ │ ├── test_project_prepare.py
│ │ ├── test_run.py
│ │ ├── test_run_config.py
│ │ ├── test_server_args.py
│ │ ├── test_shared.py
│ │ ├── test_tasks.py
│ │ └── test_with_argv.py
│ ├── client/
│ │ ├── __init__.py
│ │ ├── auth/
│ │ │ ├── __init__.py
│ │ │ ├── test_oauth_cimd.py
│ │ │ ├── test_oauth_client.py
│ │ │ └── test_oauth_static_client.py
│ │ ├── client/
│ │ │ ├── __init__.py
│ │ │ ├── test_auth.py
│ │ │ ├── test_client.py
│ │ │ ├── test_error_handling.py
│ │ │ ├── test_initialize.py
│ │ │ ├── test_session.py
│ │ │ ├── test_timeout.py
│ │ │ └── test_transport.py
│ │ ├── sampling/
│ │ │ ├── __init__.py
│ │ │ └── handlers/
│ │ │ ├── __init__.py
│ │ │ ├── test_anthropic_handler.py
│ │ │ ├── test_google_genai_handler.py
│ │ │ └── test_openai_handler.py
│ │ ├── tasks/
│ │ │ ├── conftest.py
│ │ │ ├── test_client_prompt_tasks.py
│ │ │ ├── test_client_resource_tasks.py
│ │ │ ├── test_client_task_notifications.py
│ │ │ ├── test_client_task_protocol.py
│ │ │ ├── test_client_tool_tasks.py
│ │ │ ├── test_task_context_validation.py
│ │ │ └── test_task_result_caching.py
│ │ ├── telemetry/
│ │ │ ├── __init__.py
│ │ │ └── test_client_tracing.py
│ │ ├── test_elicitation.py
│ │ ├── test_elicitation_enums.py
│ │ ├── test_logs.py
│ │ ├── test_notifications.py
│ │ ├── test_oauth_callback_race.py
│ │ ├── test_oauth_callback_xss.py
│ │ ├── test_openapi.py
│ │ ├── test_progress.py
│ │ ├── test_roots.py
│ │ ├── test_sampling.py
│ │ ├── test_sampling_result_types.py
│ │ ├── test_sampling_tool_loop.py
│ │ ├── test_sse.py
│ │ ├── test_stdio.py
│ │ ├── test_streamable_http.py
│ │ └── transports/
│ │ ├── __init__.py
│ │ ├── test_memory_transport.py
│ │ ├── test_no_redirect.py
│ │ ├── test_transports.py
│ │ └── test_uv_transport.py
│ ├── conftest.py
│ ├── contrib/
│ │ ├── __init__.py
│ │ ├── test_bulk_tool_caller.py
│ │ ├── test_component_manager.py
│ │ └── test_mcp_mixin.py
│ ├── deprecated/
│ │ ├── __init__.py
│ │ ├── conftest.py
│ │ ├── openapi/
│ │ │ └── test_openapi.py
│ │ ├── server/
│ │ │ ├── __init__.py
│ │ │ └── test_include_exclude_tags.py
│ │ ├── test_add_tool_transformation.py
│ │ ├── test_deprecated.py
│ │ ├── test_exclude_args.py
│ │ ├── test_function_component_imports.py
│ │ ├── test_import_server.py
│ │ ├── test_openapi_deprecations.py
│ │ ├── test_settings.py
│ │ ├── test_tool_injection_middleware.py
│ │ └── test_tool_serializer.py
│ ├── experimental/
│ │ ├── README.md
│ │ ├── __init__.py
│ │ └── transforms/
│ │ ├── test_code_mode.py
│ │ ├── test_code_mode_discovery.py
│ │ └── test_code_mode_serialization.py
│ ├── fs/
│ │ ├── test_discovery.py
│ │ └── test_provider.py
│ ├── integration_tests/
│ │ ├── __init__.py
│ │ ├── auth/
│ │ │ ├── __init__.py
│ │ │ └── test_github_provider_integration.py
│ │ ├── conftest.py
│ │ ├── test_github_mcp_remote.py
│ │ └── test_timeout_fix.py
│ ├── prompts/
│ │ ├── __init__.py
│ │ ├── test_prompt.py
│ │ └── test_standalone_decorator.py
│ ├── resources/
│ │ ├── __init__.py
│ │ ├── test_file_resources.py
│ │ ├── test_function_resources.py
│ │ ├── test_resource_template.py
│ │ ├── test_resource_template_meta.py
│ │ ├── test_resource_template_query_params.py
│ │ ├── test_resources.py
│ │ └── test_standalone_decorator.py
│ ├── server/
│ │ ├── __init__.py
│ │ ├── auth/
│ │ │ ├── __init__.py
│ │ │ ├── oauth_proxy/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── conftest.py
│ │ │ │ ├── test_authorization.py
│ │ │ │ ├── test_client_registration.py
│ │ │ │ ├── test_config.py
│ │ │ │ ├── test_e2e.py
│ │ │ │ ├── test_oauth_proxy.py
│ │ │ │ ├── test_tokens.py
│ │ │ │ └── test_ui.py
│ │ │ ├── providers/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── test_auth0.py
│ │ │ │ ├── test_aws.py
│ │ │ │ ├── test_azure.py
│ │ │ │ ├── test_azure_scopes.py
│ │ │ │ ├── test_descope.py
│ │ │ │ ├── test_discord.py
│ │ │ │ ├── test_github.py
│ │ │ │ ├── test_google.py
│ │ │ │ ├── test_http_client.py
│ │ │ │ ├── test_introspection.py
│ │ │ │ ├── test_propelauth.py
│ │ │ │ ├── test_scalekit.py
│ │ │ │ ├── test_supabase.py
│ │ │ │ └── test_workos.py
│ │ │ ├── test_auth_provider.py
│ │ │ ├── test_authorization.py
│ │ │ ├── test_cimd.py
│ │ │ ├── test_cimd_validators.py
│ │ │ ├── test_debug_verifier.py
│ │ │ ├── test_enhanced_error_responses.py
│ │ │ ├── test_jwt_issuer.py
│ │ │ ├── test_jwt_provider.py
│ │ │ ├── test_jwt_provider_bearer.py
│ │ │ ├── test_multi_auth.py
│ │ │ ├── test_oauth_consent_flow.py
│ │ │ ├── test_oauth_consent_page.py
│ │ │ ├── test_oauth_mounting.py
│ │ │ ├── test_oauth_proxy_redirect_validation.py
│ │ │ ├── test_oauth_proxy_storage.py
│ │ │ ├── test_oidc_proxy.py
│ │ │ ├── test_oidc_proxy_token.py
│ │ │ ├── test_redirect_validation.py
│ │ │ ├── test_remote_auth_provider.py
│ │ │ ├── test_ssrf_protection.py
│ │ │ └── test_static_token_verifier.py
│ │ ├── http/
│ │ │ ├── __init__.py
│ │ │ ├── test_bearer_auth_backend.py
│ │ │ ├── test_custom_routes.py
│ │ │ ├── test_http_auth_middleware.py
│ │ │ ├── test_http_dependencies.py
│ │ │ ├── test_http_middleware.py
│ │ │ └── test_stale_access_token.py
│ │ ├── middleware/
│ │ │ ├── __init__.py
│ │ │ ├── test_caching.py
│ │ │ ├── test_dereference.py
│ │ │ ├── test_error_handling.py
│ │ │ ├── test_initialization_middleware.py
│ │ │ ├── test_logging.py
│ │ │ ├── test_middleware.py
│ │ │ ├── test_middleware_nested.py
│ │ │ ├── test_ping.py
│ │ │ ├── test_rate_limiting.py
│ │ │ ├── test_response_limiting.py
│ │ │ ├── test_timing.py
│ │ │ └── test_tool_injection.py
│ │ ├── mount/
│ │ │ ├── __init__.py
│ │ │ ├── test_advanced.py
│ │ │ ├── test_filtering.py
│ │ │ ├── test_mount.py
│ │ │ ├── test_prompts.py
│ │ │ ├── test_proxy.py
│ │ │ └── test_resources.py
│ │ ├── providers/
│ │ │ ├── __init__.py
│ │ │ ├── local_provider_tools/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── test_context.py
│ │ │ │ ├── test_decorator.py
│ │ │ │ ├── test_enabled.py
│ │ │ │ ├── test_local_provider_tools.py
│ │ │ │ ├── test_output_schema.py
│ │ │ │ ├── test_parameters.py
│ │ │ │ └── test_tags.py
│ │ │ ├── openapi/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── test_comprehensive.py
│ │ │ │ ├── test_deepobject_style.py
│ │ │ │ ├── test_end_to_end_compatibility.py
│ │ │ │ ├── test_openapi_features.py
│ │ │ │ ├── test_openapi_performance.py
│ │ │ │ ├── test_parameter_collisions.py
│ │ │ │ ├── test_performance_comparison.py
│ │ │ │ └── test_server.py
│ │ │ ├── proxy/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── test_proxy_client.py
│ │ │ │ ├── test_proxy_server.py
│ │ │ │ └── test_stateful_proxy_client.py
│ │ │ ├── test_base_provider.py
│ │ │ ├── test_fastmcp_provider.py
│ │ │ ├── test_local_provider.py
│ │ │ ├── test_local_provider_prompts.py
│ │ │ ├── test_local_provider_resources.py
│ │ │ ├── test_skills_provider.py
│ │ │ ├── test_skills_vendor_providers.py
│ │ │ └── test_transforming_provider.py
│ │ ├── sampling/
│ │ │ ├── __init__.py
│ │ │ ├── test_prepare_tools.py
│ │ │ └── test_sampling_tool.py
│ │ ├── tasks/
│ │ │ ├── __init__.py
│ │ │ ├── conftest.py
│ │ │ ├── test_context_background_task.py
│ │ │ ├── test_custom_subclass_tasks.py
│ │ │ ├── test_notifications.py
│ │ │ ├── test_progress_dependency.py
│ │ │ ├── test_resource_task_meta_parameter.py
│ │ │ ├── test_server_tasks_parameter.py
│ │ │ ├── test_sync_function_task_disabled.py
│ │ │ ├── test_task_capabilities.py
│ │ │ ├── test_task_config.py
│ │ │ ├── test_task_dependencies.py
│ │ │ ├── test_task_elicitation_relay.py
│ │ │ ├── test_task_meta_parameter.py
│ │ │ ├── test_task_metadata.py
│ │ │ ├── test_task_methods.py
│ │ │ ├── test_task_mount.py
│ │ │ ├── test_task_prompts.py
│ │ │ ├── test_task_protocol.py
│ │ │ ├── test_task_proxy.py
│ │ │ ├── test_task_resources.py
│ │ │ ├── test_task_return_types.py
│ │ │ ├── test_task_security.py
│ │ │ ├── test_task_status_notifications.py
│ │ │ ├── test_task_tools.py
│ │ │ └── test_task_ttl.py
│ │ ├── telemetry/
│ │ │ ├── __init__.py
│ │ │ ├── test_provider_tracing.py
│ │ │ └── test_server_tracing.py
│ │ ├── test_app_state.py
│ │ ├── test_auth_integration.py
│ │ ├── test_auth_integration_errors.py
│ │ ├── test_context.py
│ │ ├── test_dependencies.py
│ │ ├── test_dependencies_advanced.py
│ │ ├── test_event_store.py
│ │ ├── test_file_server.py
│ │ ├── test_icons.py
│ │ ├── test_input_validation.py
│ │ ├── test_log_level.py
│ │ ├── test_logging.py
│ │ ├── test_pagination.py
│ │ ├── test_providers.py
│ │ ├── test_run_server.py
│ │ ├── test_server.py
│ │ ├── test_server_docket.py
│ │ ├── test_server_lifespan.py
│ │ ├── test_session_visibility.py
│ │ ├── test_streamable_http_no_redirect.py
│ │ ├── test_tool_annotations.py
│ │ ├── test_tool_transformation.py
│ │ ├── transforms/
│ │ │ ├── test_catalog.py
│ │ │ ├── test_prompts_as_tools.py
│ │ │ ├── test_resources_as_tools.py
│ │ │ ├── test_search.py
│ │ │ └── test_visibility.py
│ │ └── versioning/
│ │ ├── __init__.py
│ │ ├── test_calls.py
│ │ ├── test_filtering.py
│ │ ├── test_mounting.py
│ │ ├── test_versioning.py
│ │ └── test_visibility_version_fallback.py
│ ├── telemetry/
│ │ ├── __init__.py
│ │ └── test_module.py
│ ├── test_apps.py
│ ├── test_apps_prefab.py
│ ├── test_fastmcp_app.py
│ ├── test_json_schema_generation.py
│ ├── test_mcp_config.py
│ ├── tools/
│ │ ├── __init__.py
│ │ ├── test_standalone_decorator.py
│ │ ├── test_tool_future_annotations.py
│ │ ├── test_tool_timeout.py
│ │ ├── tool/
│ │ │ ├── __init__.py
│ │ │ ├── test_callable.py
│ │ │ ├── test_content.py
│ │ │ ├── test_output_schema.py
│ │ │ ├── test_results.py
│ │ │ ├── test_title.py
│ │ │ └── test_tool.py
│ │ └── tool_transform/
│ │ ├── __init__.py
│ │ ├── test_args.py
│ │ ├── test_metadata.py
│ │ ├── test_schemas.py
│ │ └── test_tool_transform.py
│ └── utilities/
│ ├── __init__.py
│ ├── json_schema_type/
│ │ ├── __init__.py
│ │ ├── test_advanced.py
│ │ ├── test_constraints.py
│ │ ├── test_containers.py
│ │ ├── test_formats.py
│ │ ├── test_json_schema_type.py
│ │ └── test_unions.py
│ ├── openapi/
│ │ ├── __init__.py
│ │ ├── conftest.py
│ │ ├── test_allof_requestbody.py
│ │ ├── test_circular_references.py
│ │ ├── test_direct_array_schemas.py
│ │ ├── test_director.py
│ │ ├── test_legacy_compatibility.py
│ │ ├── test_models.py
│ │ ├── test_nullable_fields.py
│ │ ├── test_parser.py
│ │ ├── test_propertynames_ref_rewrite.py
│ │ ├── test_schemas.py
│ │ └── test_transitive_references.py
│ ├── test_async_utils.py
│ ├── test_auth.py
│ ├── test_cli.py
│ ├── test_components.py
│ ├── test_inspect.py
│ ├── test_inspect_icons.py
│ ├── test_json_schema.py
│ ├── test_logging.py
│ ├── test_skills.py
│ ├── test_tests.py
│ ├── test_token_cache.py
│ ├── test_typeadapter.py
│ ├── test_types.py
│ └── test_version_check.py
└── v3-notes/
├── get-methods-consolidation.md
├── prompt-internal-types.md
├── provider-architecture.md
├── provider-test-pattern.md
├── resource-internal-types.md
├── task-meta-parameter.md
└── visibility.md
================================================
FILE CONTENTS
================================================
================================================
FILE: .ccignore
================================================
.pre-commit-config.yaml
.github/
docs/changelog.mdx
docs/python-sdk/
examples/
src/fastmcp/contrib/
tests/contrib/
================================================
FILE: .claude/hooks/session-init.sh
================================================
#!/bin/bash
set -e
# Only run in remote/cloud environments
if [ "$CLAUDE_CODE_REMOTE" != "true" ]; then
exit 0
fi
command -v gh &> /dev/null && exit 0
LOCAL_BIN="$HOME/.local/bin"
mkdir -p "$LOCAL_BIN"
ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')
VERSION=$(curl -fsSL https://api.github.com/repos/cli/cli/releases/latest | grep '"tag_name"' | cut -d'"' -f4)
TARBALL="gh_${VERSION#v}_linux_${ARCH}.tar.gz"
echo "Installing gh ${VERSION}..."
TEMP=$(mktemp -d)
trap 'rm -rf "$TEMP"' EXIT
curl -fsSL "https://github.com/cli/cli/releases/download/${VERSION}/${TARBALL}" | tar -xz -C "$TEMP"
cp "$TEMP"/gh_*/bin/gh "$LOCAL_BIN/gh"
chmod 755 "$LOCAL_BIN/gh"
[ -n "$CLAUDE_ENV_FILE" ] && echo "export PATH=\"$LOCAL_BIN:\$PATH\"" >> "$CLAUDE_ENV_FILE"
echo "gh installed: $("$LOCAL_BIN/gh" --version | head -1)"
================================================
FILE: .claude/settings.json
================================================
{
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "bash \"$CLAUDE_PROJECT_DIR\"/.claude/hooks/session-init.sh",
"timeout": 120
}
]
}
]
}
}
================================================
FILE: .claude/skills/code-review/SKILL.md
================================================
---
name: reviewing-code
description: Review code for quality, maintainability, and correctness. Use when reviewing pull requests, evaluating code changes, or providing feedback on implementations. Focuses on API design, patterns, and actionable feedback.
---
# Code Review
## Philosophy
Code review maintains a healthy codebase while helping contributors succeed. The burden of proof is on the PR to demonstrate it adds value. Your job is to help it get there through actionable feedback.
**Critical**: A perfectly written PR that adds unwanted functionality must still be rejected. The code must advance the codebase in the intended direction. When rejecting, provide clear guidance on how to align with project goals.
Be friendly and welcoming while maintaining high standards. Call out what works well. When code needs improvement, be specific about why and how to fix it.
## What to Focus On
### Does this advance the codebase correctly?
Even perfect code for unwanted features should be rejected.
### Dependency version compatibility
When a PR adapts code to a new version of a dependency (e.g., removing a parameter that was dropped upstream, using a new API):
- **The version pin in `pyproject.toml` must match.** If the change breaks compatibility with the previously-pinned minimum version, the minimum version must be bumped. Otherwise users on the old version get a regression.
- **If backwards compatibility with the old version is desired**, the code must handle both versions (e.g., try/except, version check). Simply deleting the old API usage without bumping the pin is always wrong — it silently breaks users on the old version.
- **Lock file (`uv.lock`) changes should be scoped to the PR's purpose.** A PR fixing a ty compatibility issue should not also include unrelated dependency version bumps (anthropic, google-auth, etc.) from running `uv sync --upgrade`. These create noise and make the diff harder to review.
### API design and naming
Identify confusing patterns or non-idiomatic code:
- Parameter values that contradict defaults
- Mutable default arguments
- Unclear naming that will confuse future readers
- Inconsistent patterns with the rest of the codebase
### Specific improvements
Provide actionable feedback, not generic observations.
### User ergonomics
Think about the API from a user's perspective. Is it intuitive? What's the learning curve?
## For Agent Reviewers
1. **Read the full context**: Examine related files, tests, and documentation before reviewing
2. **Check against established patterns**: Look for consistency with codebase conventions
3. **Verify functionality claims**: Understand what the code actually does, not just what it claims
4. **Consider edge cases**: Think through error conditions and boundary scenarios
## What to Avoid
- Generic feedback without specifics
- Hypothetical problems unlikely to occur
- Nitpicking organizational choices without strong reason
- Summarizing what the PR already describes
- Star ratings or excessive emojis
- Bikeshedding style preferences when functionality is correct
- Requesting changes without suggesting solutions
- Focusing on personal coding style over project conventions
## Tone
- Acknowledge good decisions: "This API design is clean"
- Be direct but respectful
- Explain impact: "This will confuse users because..."
- Remember: Someone else maintains this code forever
## Decision Framework
Before approving, ask:
1. Does this PR achieve its stated purpose?
2. Is that purpose aligned with where the codebase should go?
3. Would I be comfortable maintaining this code?
4. Have I actually understood what it does, not just what it claims?
5. Does this change introduce technical debt?
If something needs work, your review should help it get there through specific, actionable feedback. If it's solving the wrong problem, say so clearly.
## Comment Examples
**Good comments:**
| Instead of | Write |
|------------|-------|
| "Add more tests" | "The `handle_timeout` method needs tests for the edge case where timeout=0" |
| "This API is confusing" | "The parameter name `data` is ambiguous - consider `message_content` to match the MCP specification" |
| "This could be better" | "This approach works but creates a circular dependency. Consider moving the validation to `utils/validators.py`" |
## Checklist
Before approving, verify:
- [ ] All required development workflow steps completed (uv sync, prek, pytest)
- [ ] Changes align with repository patterns and conventions
- [ ] API changes are documented and backwards-compatible where possible
- [ ] Error handling follows project patterns (specific exception types)
- [ ] Tests cover new functionality and edge cases
- [ ] The change advances the codebase in the intended direction
================================================
FILE: .claude/skills/python-tests/SKILL.md
================================================
---
name: testing-python
description: Write and evaluate effective Python tests using pytest. Use when writing tests, reviewing test code, debugging test failures, or improving test coverage. Covers test design, fixtures, parameterization, mocking, and async testing.
---
# Writing Effective Python Tests
## Core Principles
Every test should be **atomic**, **self-contained**, and test **single functionality**. A test that tests multiple things is harder to debug and maintain.
## Test Structure
### Atomic unit tests
Each test should verify a single behavior. The test name should tell you what's broken when it fails. Multiple assertions are fine when they all verify the same behavior.
```python
# Good: Name tells you what's broken
def test_user_creation_sets_defaults():
user = User(name="Alice")
assert user.role == "member"
assert user.id is not None
assert user.created_at is not None
# Bad: If this fails, what behavior is broken?
def test_user():
user = User(name="Alice")
assert user.role == "member"
user.promote()
assert user.role == "admin"
assert user.can_delete_others()
```
### Use parameterization for variations of the same concept
```python
import pytest
@pytest.mark.parametrize("input,expected", [
("hello", "HELLO"),
("World", "WORLD"),
("", ""),
("123", "123"),
])
def test_uppercase_conversion(input, expected):
assert input.upper() == expected
```
### Use separate tests for different functionality
Don't parameterize unrelated behaviors. If the test logic differs, write separate tests.
## Project-Specific Rules
### No async markers needed
This project uses `asyncio_mode = "auto"` globally. Write async tests without decorators:
```python
# Correct
async def test_async_operation():
result = await some_async_function()
assert result == expected
# Wrong - don't add this
@pytest.mark.asyncio
async def test_async_operation():
...
```
### Imports at module level
Put ALL imports at the top of the file:
```python
# Correct
import pytest
from fastmcp import FastMCP
from fastmcp.client import Client
async def test_something():
mcp = FastMCP("test")
...
# Wrong - no local imports
async def test_something():
from fastmcp import FastMCP # Don't do this
...
```
### Use in-memory transport for testing
Pass FastMCP servers directly to clients:
```python
from fastmcp import FastMCP
from fastmcp.client import Client
mcp = FastMCP("TestServer")
@mcp.tool
def greet(name: str) -> str:
return f"Hello, {name}!"
async def test_greet_tool():
async with Client(mcp) as client:
result = await client.call_tool("greet", {"name": "World"})
assert result[0].text == "Hello, World!"
```
Only use HTTP transport when explicitly testing network features.
### Inline snapshots for complex data
Use `inline-snapshot` for testing JSON schemas and complex structures:
```python
from inline_snapshot import snapshot
def test_schema_generation():
schema = generate_schema(MyModel)
assert schema == snapshot() # Will auto-populate on first run
```
Commands:
- `pytest --inline-snapshot=create` - populate empty snapshots
- `pytest --inline-snapshot=fix` - update after intentional changes
## Fixtures
### Prefer function-scoped fixtures
```python
@pytest.fixture
def client():
return Client()
async def test_with_client(client):
result = await client.ping()
assert result is not None
```
### Use `tmp_path` for file operations
```python
def test_file_writing(tmp_path):
file = tmp_path / "test.txt"
file.write_text("content")
assert file.read_text() == "content"
```
## Mocking
### Mock at the boundary
```python
from unittest.mock import patch, AsyncMock
async def test_external_api_call():
with patch("mymodule.external_client.fetch", new_callable=AsyncMock) as mock:
mock.return_value = {"data": "test"}
result = await my_function()
assert result == {"data": "test"}
```
### Don't mock what you own
Test your code with real implementations when possible. Mock external services, not internal classes.
## Test Naming
Use descriptive names that explain the scenario:
```python
# Good
def test_login_fails_with_invalid_password():
def test_user_can_update_own_profile():
def test_admin_can_delete_any_user():
# Bad
def test_login():
def test_update():
def test_delete():
```
## Error Testing
```python
import pytest
def test_raises_on_invalid_input():
with pytest.raises(ValueError, match="must be positive"):
calculate(-1)
async def test_async_raises():
with pytest.raises(ConnectionError):
await connect_to_invalid_host()
```
## Running Tests
```bash
uv run pytest -n auto # Run all tests in parallel
uv run pytest -n auto -x # Stop on first failure
uv run pytest path/to/test.py # Run specific file
uv run pytest -k "test_name" # Run tests matching pattern
uv run pytest -m "not integration" # Exclude integration tests
```
## Checklist
Before submitting tests:
- [ ] Each test tests one thing
- [ ] No `@pytest.mark.asyncio` decorators
- [ ] Imports at module level
- [ ] Descriptive test names
- [ ] Using in-memory transport (not HTTP) unless testing networking
- [ ] Parameterization for variations of same behavior
- [ ] Separate tests for different behaviors
================================================
FILE: .claude/skills/review-pr/SKILL.md
================================================
---
name: review-pr
description: Monitor and respond to automated PR reviews (Codex bot). Use when pushing a PR, checking review status, or responding to bot feedback. Handles the full cycle of push -> wait for review -> evaluate comments -> fix -> re-push.
---
# PR Review Workflow
This repo has `chatgpt-codex-connector[bot]` configured as an automated reviewer. After every push to a PR branch, Codex reviews the diff and either:
- Reacts with a thumbs-up on its review body (no suggestions — PR is clean)
- Posts inline comments with suggestions (each tagged with a priority badge)
## Checking review status
After pushing, check whether Codex has reviewed the latest commit:
```bash
# Get the latest commit SHA on the branch
LATEST=$(git rev-parse HEAD)
# Check if Codex has reviewed that specific commit
gh api repos/PrefectHQ/fastmcp/pulls/{PR_NUMBER}/reviews \
| jq "[.[] | select(.user.login == \"chatgpt-codex-connector[bot]\" and .commit_id == \"$LATEST\")] | length"
```
If the count is 0, Codex hasn't reviewed the latest push yet. Wait and check again.
If the count is > 0, check for inline comments on the latest review:
```bash
# Get the review body to check for thumbs-up
gh api repos/PrefectHQ/fastmcp/pulls/{PR_NUMBER}/reviews \
| jq '[.[] | select(.user.login == "chatgpt-codex-connector[bot]") | {state, body: .body[:300], commit_id: .commit_id}] | last'
```
A clean review from Codex looks like a review body that contains a thumbs-up reaction or says "no suggestions." If the body contains "Here are some automated review suggestions," there are inline comments to evaluate.
## Evaluating Codex comments
Fetch all inline comments from Codex:
```bash
gh api repos/PrefectHQ/fastmcp/pulls/{PR_NUMBER}/comments \
| jq '[.[] | select(.user.login == "chatgpt-codex-connector[bot]") | {body, path, line, created_at}]'
```
Codex comments include priority badges:
- `P0` (red) — Critical issue, likely a real bug
- `P1` (orange) — Important, worth fixing
- `P2` (yellow) — Moderate, evaluate on merit
**How to evaluate Codex comments:**
1. **Treat Codex as a competent but sometimes overzealous reviewer.** It catches real bugs (cache eviction ordering, silent data loss, missing validation) but also suggests scope expansions and hypothetical improvements.
2. **Fix real bugs** — issues in code you actually changed where behavior is incorrect or data is silently lost.
3. **Dismiss scope expansion** — if a comment points out a pre-existing limitation unrelated to your diff, note it as a potential follow-up but don't block the PR.
4. **Dismiss speculative concerns** — if a comment describes a scenario that requires very specific conditions and the existing behavior is acceptable, dismiss it.
5. **When fixing, be proactive** — if Codex found one instance of a pattern bug (e.g., missing role validation in one handler), check all similar code paths before pushing. Codex will find the next instance on the next review cycle, so get ahead of it.
## Responding to every comment
**Every Codex comment must get a visible response** — either a fix or a reply explaining why it was dismissed. The maintainer can't see your reasoning otherwise.
- **If fixing**: The fix itself is the response. No reply needed unless the fix is non-obvious.
- **If dismissing**: Reply to the comment thread with a brief explanation of why. Keep it to 1-2 sentences. Examples:
- "This is pre-existing behavior unrelated to this diff — the scope lookup fallback existed before caching was added. Worth a follow-up issue but not blocking this PR."
- "The AsyncExitStack handles cleanup when the session exits, so the subprocess isn't leaked — just kept alive slightly longer than necessary in this edge case."
- "Gemini supports a much wider range of media types than OpenAI/Anthropic, so a restrictive allowlist would be inaccurate here."
Use `gh api` to reply (note: use `in_reply_to`, not a `/replies` sub-path):
```bash
# Reply to a specific review comment
gh api repos/PrefectHQ/fastmcp/pulls/{PR_NUMBER}/comments \
-f body="Your reply here" \
-F in_reply_to={COMMENT_ID}
```
## The fix-push-review cycle
After evaluating comments:
1. Fix all real issues in one batch
2. Reply to all dismissed comments with reasoning
3. Think about what patterns Codex might flag next — check similar code paths proactively
4. Commit and push
5. Check that Codex reviews the new commit
6. Repeat until Codex gives a clean review (thumbs-up) or only has dismissible comments
## Responding to stale comments
Codex sometimes re-posts old comments that reference code you've already fixed (they appear on the old commit's diff). These are stale — verify the fix is in the latest commit and reply noting the fix is already in place.
## When a PR is ready
A PR is ready for human review when:
- All Codex comments are either fixed or replied to with dismissal reasoning
- CI checks pass
- The diff is clean and focused on the stated purpose
================================================
FILE: .coderabbit.yaml
================================================
reviews:
path_filters:
- "!docs/python-sdk/**"
================================================
FILE: .cursor/rules/core-mcp-objects.mdc
================================================
---
description:
globs:
alwaysApply: true
---
There are four major MCP object types:
- Tools (src/tools/)
- Resources (src/resources/)
- Resource Templates (src/resources/)
- Prompts (src/prompts)
While these have slightly different semantics and implementations, in general changes that affect interactions with any one (like adding tags, importing, etc.) will need to be adopted, applied, and tested on all others. Note that while resources and resource templates are different objects, they are both in `src/resources/`.
================================================
FILE: .github/ISSUE_TEMPLATE/bug.yml
================================================
name: 🐛 Bug Report
description: Report a bug or unexpected behavior in FastMCP
labels: [bug, pending]
body:
- type: markdown
attributes:
value: |
Thanks for reporting a bug!
A good bug report is one of the most valuable contributions you can make — see [CONTRIBUTING.md](../../CONTRIBUTING.md). If the fix is straightforward, a PR is also welcome.
### Before you submit
- Make sure you're testing on the **latest version** of FastMCP — many issues are already fixed in newer releases
- Check if someone else has **already reported this** or if it's been fixed on the main branch
- You **must** include a copy/pasteable, properly formatted MRE (minimal reproducible example) or your issue may be closed without response
- **The ideal issue is a clear problem description and an MRE — that's it.** If you've done genuine investigation and have a non-obvious insight into the root cause, include it. But please don't speculate or ask an LLM to generate a diagnosis. We have LLMs too, and an incorrect analysis is harder to work with than none at all.
- **Keep it short.** A clear description plus a concise MRE is ideal — aim to fit in a single screen. Issues that include unsolicited root cause analysis, proposed fixes, or multi-section diagnostic writeups will be labeled `too-long` and not triaged until condensed.
- **Using an LLM?** Great — but it must follow these guidelines. Generic LLM output that ignores our contributing conventions will be closed. See [CONTRIBUTING.md](../../CONTRIBUTING.md).
- type: textarea
id: description
attributes:
label: What happened?
description: |
Describe the bug in a few sentences. What did you do, what happened, and what did you expect instead?
Do NOT include root cause analysis, proposed fixes, or diagnostic writeups — just describe the problem.
validations:
required: true
- type: textarea
id: example
attributes:
label: Example Code
description: >
If applicable, please provide a self-contained,
[minimal, reproducible example](https://stackoverflow.com/help/minimal-reproducible-example)
demonstrating the bug. If possible, your example should be a single-file script.
placeholder: |
import asyncio
from fastmcp import FastMCP, Client
mcp = FastMCP()
async def demo():
async with Client(mcp) as client:
... # show the bug here
if __name__ == "__main__":
asyncio.run(demo())
render: Python
- type: textarea
id: version
attributes:
label: Version Information
description: |
Please tell us about your FastMCP version, MCP version, Python version, and OS, as well as any other relevant details about your environment.
To get the basic information, run the following command in your terminal and paste the output below:
```bash
fastmcp version --copy
```
render: Text
validations:
required: true
================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false
contact_links:
- name: FastMCP Documentation
url: https://gofastmcp.com
about: Please review the documentation before opening an issue.
- name: MCP Python SDK
url: https://github.com/modelcontextprotocol/python-sdk/issues
about: Issues related to the low-level MCP Python SDK, including the FastMCP 1.0 module that is included in the `mcp` package, should be filed on the official MCP repository.
================================================
FILE: .github/ISSUE_TEMPLATE/enhancement.yml
================================================
name: 💡 Enhancement Request
description: Suggest an idea or improvement for FastMCP
labels: [enhancement, pending]
body:
- type: markdown
attributes:
value: |
Thanks for suggesting an improvement to FastMCP!
Enhancement issues are the **primary way** features and improvements get into FastMCP. Maintainers use well-written issues to implement changes that fit the codebase's patterns and ship quickly. A clear issue here is more impactful than a PR — see [CONTRIBUTING.md](../../CONTRIBUTING.md) for why.
### Before you submit
- 🔍 **Check if this has already been requested** — search existing issues first
- 🎯 **Describe the problem you're trying to solve**, not the solution you want — we'll figure out the best implementation
- ✂️ **Keep it short.** A motivating description and a concrete use case is the ideal request — aim to fit in a single screen. Skip proposed implementations, API designs, or multi-option analyses — maintainers will figure out the approach. Requests that are difficult to parse will be labeled `too-long` and not triaged until condensed.
- 🤖 **Using an LLM?** Great — but it must follow these guidelines. Generic LLM output that ignores our contributing conventions will be closed. See [CONTRIBUTING.md](../../CONTRIBUTING.md).
- type: textarea
id: description
attributes:
label: Enhancement
description: |
What problem or use case does this solve? How does current behavior fall short?
Focus on the *what* and *why* — the motivating scenario. You don't need to propose an API or implementation.
validations:
required: true
================================================
FILE: .github/actions/run-claude/action.yml
================================================
# Composite Action for running Claude Code Action
#
# Wraps anthropics/claude-code-action with MCP server configuration.
# Template based on elastic/ai-github-actions base action.
#
# Usage:
# - uses: ./.github/actions/run-claude
# with:
# prompt: "Your prompt here"
# claude-oauth-token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
# github-token: ${{ steps.marvin-token.outputs.token }}
# allowed-tools: "Edit,Read,Write,Bash(*),mcp__github__add_issue_comment"
#
name: "Run Claude"
description: "Run Claude Code with MCP servers"
author: "FastMCP"
branding:
icon: "cpu"
color: "orange"
inputs:
prompt:
description: "Prompt to pass to Claude"
required: true
claude-oauth-token:
description: "Claude Code OAuth token for authentication"
required: true
github-token:
description: "GitHub token for Claude to operate with"
required: true
allowed-tools:
description: "Comma-separated list of allowed tools (e.g. Edit,Write,Bash(npm test))"
required: false
default: ""
model:
description: "Model to use for Claude"
required: false
default: "claude-opus-4-6"
allowed-bots:
description: "Allowed bot usernames, or '*' for all bots"
required: false
default: ""
track-progress:
description: "Whether Claude should track progress"
required: false
default: "true"
mcp-servers:
description: "MCP server configuration JSON"
required: false
default: '{"mcpServers":{"agents-md-generator":{"type":"http","url":"https://agents-md-generator.fastmcp.app/mcp"},"public-code-search":{"type":"http","url":"https://public-code-search.fastmcp.app/mcp"}}}'
trigger-phrase:
description: "Trigger phrase (for mention workflows)"
required: false
default: "/marvin"
outputs:
conclusion:
description: "The conclusion of the Claude Code run"
value: ${{ steps.claude.outputs.conclusion }}
runs:
using: "composite"
steps:
- name: Clean up stale Claude locks
shell: bash
run: rm -rf ~/.claude/.locks ~/.local/state/claude/locks || true
- name: Run Claude Code
id: claude
env:
GITHUB_TOKEN: ${{ inputs.github-token }}
uses: anthropics/claude-code-action@v1
with:
github_token: ${{ inputs.github-token }}
claude_code_oauth_token: ${{ inputs.claude-oauth-token }}
bot_name: "Marvin Context Protocol"
trigger_phrase: ${{ inputs.trigger-phrase }}
allowed_bots: ${{ inputs.allowed-bots }}
track_progress: ${{ inputs.track-progress }}
prompt: ${{ inputs.prompt }}
claude_args: |
${{ (inputs.allowed-tools != '' || inputs.extra-allowed-tools != '') && format('--allowedTools {0}{1}', inputs.allowed-tools, inputs.extra-allowed-tools != '' && format(',{0}', inputs.extra-allowed-tools) || '') || '' }}
${{ inputs.mcp-servers != '' && format('--mcp-config ''{0}''', inputs.mcp-servers) || '' }}
--model ${{ inputs.model }}
settings: |
{"model": "${{ inputs.model }}"}
================================================
FILE: .github/actions/run-pytest/action.yml
================================================
name: "Run Pytest"
description: "Run pytest with appropriate flags for the test type and platform"
inputs:
test-type:
description: "Type of tests to run: unit, integration, or client_process"
required: false
default: "unit"
runs:
using: "composite"
steps:
- name: Run pytest
shell: bash
run: |
if [ "${{ inputs.test-type }}" == "integration" ]; then
MARKER="integration"
TIMEOUT="30"
MAX_PROCS="2"
EXTRA_FLAGS=""
elif [ "${{ inputs.test-type }}" == "client_process" ]; then
MARKER="client_process"
TIMEOUT="5"
MAX_PROCS="0"
EXTRA_FLAGS="-x"
else
MARKER="not integration and not client_process"
TIMEOUT="5"
MAX_PROCS="4"
EXTRA_FLAGS=""
fi
PARALLEL_FLAGS=""
if [ "$MAX_PROCS" != "0" ] && [ "${{ runner.os }}" != "Windows" ]; then
PARALLEL_FLAGS="--numprocesses auto --maxprocesses $MAX_PROCS --dist worksteal"
fi
uv run --no-sync pytest \
--inline-snapshot=disable \
--timeout=$TIMEOUT \
--durations=50 \
-m "$MARKER" \
$PARALLEL_FLAGS \
$EXTRA_FLAGS \
tests
================================================
FILE: .github/actions/setup-uv/action.yml
================================================
name: "Setup UV Environment"
description: "Install uv and dependencies (requires checkout first)"
inputs:
python-version:
description: "Python version to use"
required: false
default: "3.10"
resolution:
description: "Dependency resolution: locked, upgrade, or lowest-direct"
required: false
default: "locked"
runs:
using: "composite"
steps:
- name: Install uv
uses: astral-sh/setup-uv@v7
with:
enable-cache: true
cache-dependency-glob: "uv.lock"
python-version: ${{ inputs.python-version }}
- name: Install dependencies
shell: bash
run: |
if [ "${{ inputs.resolution }}" == "locked" ]; then
uv sync --locked
elif [ "${{ inputs.resolution }}" == "upgrade" ]; then
uv sync --upgrade
else
uv sync --resolution ${{ inputs.resolution }}
fi
================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
- package-ecosystem: "pip"
directory: "/"
schedule:
interval: "daily"
labels:
- "dependencies"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
labels:
- "dependencies"
================================================
FILE: .github/pull_request_template.md
================================================
## Description
<!-- What does this PR do? Link to the issue it addresses. -->
Closes #
## Contribution type
<!-- Check the one that applies. If you're unsure whether your change is welcome, please open an issue first — see CONTRIBUTING.md. -->
- [ ] Bug fix (simple, well-scoped fix for a clearly broken behavior)
- [ ] Documentation improvement
- [ ] Enhancement (maintainers typically implement enhancements — see [CONTRIBUTING.md](../CONTRIBUTING.md))
## Checklist
- [ ] This PR addresses an existing issue (or fixes a self-evident bug)
- [ ] I have read [CONTRIBUTING.md](../CONTRIBUTING.md)
- [ ] I have added tests that cover my changes
- [ ] I have run `uv run prek run --all-files` and all checks pass
- [ ] I have self-reviewed my changes
- [ ] If I used an LLM, it followed the repo's contributing conventions (not generic output)
================================================
FILE: .github/release.yml
================================================
changelog:
exclude:
labels:
- ignore in release notes
categories:
- title: New Features 🎉
labels:
- feature
- title: Breaking Changes ⚠️
labels:
- breaking change
exclude:
labels:
- contrib
- security
- title: Enhancements ✨
labels:
- enhancement
exclude:
labels:
- breaking change
- security
- title: Security 🔒
labels:
- security
- title: Fixes 🐞
labels:
- bug
exclude:
labels:
- contrib
- security
- title: Docs 📚
labels:
- documentation
- title: Examples & Contrib 💡
labels:
- example
- contrib
- title: Dependencies 📦
labels:
- dependencies
exclude:
labels:
- security
- title: Other Changes 🦾
labels:
- "*"
================================================
FILE: .github/scripts/mention/gh-get-review-threads.sh
================================================
#!/usr/bin/env bash
set -euo pipefail
# Get PR review threads with comments via GitHub GraphQL API
#
# Usage:
# gh-get-review-threads.sh [FILTER]
#
# Arguments:
# FILTER - Optional: filter for unresolved threads from specific author
#
# Environment (set by composite action):
# MENTION_REPO - Repository (owner/repo format)
# MENTION_PR_NUMBER - Pull request number
# GITHUB_TOKEN - GitHub API token
#
# Output:
# JSON array of review threads with nested comments
# Parse OWNER and REPO from MENTION_REPO
REPO_FULL="${MENTION_REPO:?MENTION_REPO environment variable is required}"
OWNER="${REPO_FULL%/*}"
REPO="${REPO_FULL#*/}"
PR_NUMBER="${MENTION_PR_NUMBER:?MENTION_PR_NUMBER environment variable is required}"
FILTER="${1:-}"
gh api graphql -f query='
query($owner: String!, $repo: String!, $prNumber: Int!) {
repository(owner: $owner, name: $repo) {
pullRequest(number: $prNumber) {
reviewThreads(first: 100) {
nodes {
id
isResolved
isOutdated
path
line
comments(first: 50) {
nodes {
id
body
author { login }
createdAt
}
}
}
}
}
}
}' -F owner="$OWNER" \
-F repo="$REPO" \
-F prNumber="$PR_NUMBER" \
--jq '.data.repository.pullRequest.reviewThreads.nodes' | \
if [ -n "$FILTER" ]; then
jq --arg author "$FILTER" '
map(select(
.isResolved == false and
.comments.nodes | any(.author.login == $author)
))'
else
cat
fi
================================================
FILE: .github/scripts/mention/gh-resolve-review-thread.sh
================================================
#!/usr/bin/env bash
set -euo pipefail
# Resolve a GitHub PR review thread, optionally posting a comment first
#
# Usage:
# gh-resolve-review-thread.sh THREAD_ID [COMMENT]
#
# Arguments:
# THREAD_ID - The GraphQL node ID of the review thread to resolve
# COMMENT - Optional: Comment body to post before resolving
#
# Environment (set by composite action):
# MENTION_REPO - Repository (owner/repo format)
# MENTION_PR_NUMBER - Pull request number
# GITHUB_TOKEN - GitHub API token
#
# Behavior:
# 1. If COMMENT is provided, posts it as a reply to the thread
# 2. Resolves the thread
# Validate required environment variables
: "${MENTION_REPO:?MENTION_REPO environment variable is required}"
: "${MENTION_PR_NUMBER:?MENTION_PR_NUMBER environment variable is required}"
THREAD_ID="${1:?Thread ID required}"
COMMENT="${2:-}"
# Step 1: Post comment if provided
if [ -n "$COMMENT" ]; then
echo "Posting comment to thread..." >&2
COMMENT_RESULT=$(gh api graphql -f query='
mutation($threadId: ID!, $body: String!) {
addPullRequestReviewThreadReply(input: {
pullRequestReviewThreadId: $threadId,
body: $body
}) {
comment {
id
}
}
}' -f threadId="$THREAD_ID" -f body="$COMMENT")
if echo "$COMMENT_RESULT" | jq -e '.errors' > /dev/null 2>&1; then
echo "Error posting comment: $COMMENT_RESULT" >&2
exit 1
fi
fi
# Step 2: Resolve the thread
echo "Resolving thread..." >&2
RESOLVE_RESULT=$(gh api graphql -f query='
mutation($threadId: ID!) {
resolveReviewThread(input: {threadId: $threadId}) {
thread {
id
isResolved
}
}
}' -f threadId="$THREAD_ID" --jq '.data.resolveReviewThread.thread')
echo "$RESOLVE_RESULT"
echo "✓ Thread resolved" >&2
================================================
FILE: .github/scripts/pr-review/pr-comment.sh
================================================
#!/bin/bash
# pr-comment.sh - Queue a structured inline review comment for the PR review
#
# Usage:
# pr-comment.sh <file> <line> --severity <level> --title <description> --why <reason> [suggestion via stdin]
# pr-comment.sh <file> <line> --severity <level> --title <description> --why <reason> --no-suggestion
#
# Arguments:
# file File path (required)
# line Line number (required)
# --severity Severity level: critical, high, medium, low, nitpick (required)
# --title Brief description for comment heading (required)
# --why One sentence explaining the risk/impact (required)
# --no-suggestion Explicitly skip suggestion (use for architectural issues)
#
# The suggestion code is read from stdin (use heredoc). If no stdin and no --no-suggestion, errors.
#
# Examples:
# # With suggestion (preferred)
# pr-comment.sh src/main.go 42 --severity high --title "Missing error check" --why "Errors are silently ignored" <<'EOF'
# if err != nil {
# return fmt.Errorf("operation failed: %w", err)
# }
# EOF
#
# # Without suggestion (for issues requiring broader changes)
# pr-comment.sh src/main.go 42 --severity medium --title "Consider extracting to function" \
# --why "This logic is duplicated in 3 places" --no-suggestion
#
# Environment variables (set by the composite action):
# PR_REVIEW_REPO - Repository (owner/repo)
# PR_REVIEW_PR_NUMBER - Pull request number
# PR_REVIEW_COMMENTS_DIR - Directory to cache comments (default: /tmp/pr-review-comments)
set -e
# Configuration from environment
REPO="${PR_REVIEW_REPO:?PR_REVIEW_REPO environment variable is required}"
PR_NUMBER="${PR_REVIEW_PR_NUMBER:?PR_REVIEW_PR_NUMBER environment variable is required}"
COMMENTS_DIR="${PR_REVIEW_COMMENTS_DIR:-/tmp/pr-review-comments}"
# Severity emoji mapping
declare -A SEVERITY_EMOJI=(
[critical]="🔴 CRITICAL"
[high]="🟠 HIGH"
[medium]="🟡 MEDIUM"
[low]="⚪ LOW"
[nitpick]="💬 NITPICK"
)
# Parse arguments
FILE=""
LINE=""
SEVERITY=""
TITLE=""
WHY=""
NO_SUGGESTION=false
# First two positional args are file and line
if [ $# -lt 2 ]; then
echo "Error: file and line are required"
echo "Usage: pr-comment.sh <file> <line> --severity <level> --title <desc> --why <reason> [<<'EOF' ... EOF]"
exit 1
fi
FILE="$1"
LINE="$2"
shift 2
# Parse named arguments
while [ $# -gt 0 ]; do
case "$1" in
--severity)
SEVERITY="$2"
shift 2
;;
--title)
TITLE="$2"
shift 2
;;
--why)
WHY="$2"
shift 2
;;
--no-suggestion)
NO_SUGGESTION=true
shift
;;
*)
echo "Error: Unknown argument: $1"
exit 1
;;
esac
done
# Read suggestion from stdin if available
SUGGESTION=""
if [ ! -t 0 ]; then
SUGGESTION=$(cat)
fi
# Validate required arguments
if [ -z "$SEVERITY" ]; then
echo "Error: --severity is required (critical, high, medium, low, nitpick)"
exit 1
fi
if [ -z "$TITLE" ]; then
echo "Error: --title is required"
exit 1
fi
if [ -z "$WHY" ]; then
echo "Error: --why is required"
exit 1
fi
# Validate severity level
if [ -z "${SEVERITY_EMOJI[$SEVERITY]}" ]; then
echo "Error: Invalid severity '$SEVERITY'. Must be one of: critical, high, medium, low, nitpick"
exit 1
fi
# Require either suggestion or explicit --no-suggestion
if [ -z "$SUGGESTION" ] && [ "$NO_SUGGESTION" = false ]; then
echo "Error: Suggestion required. Provide code via stdin (heredoc) or use --no-suggestion"
echo ""
echo "Example with suggestion:"
echo " pr-comment.sh file.go 42 --severity high --title \"desc\" --why \"reason\" <<'EOF'"
echo " fixed code here"
echo " EOF"
echo ""
echo "Example without suggestion:"
echo " pr-comment.sh file.go 42 --severity medium --title \"desc\" --why \"reason\" --no-suggestion"
exit 1
fi
# Validate line is a positive integer (>= 1)
if ! [[ "$LINE" =~ ^[1-9][0-9]*$ ]]; then
echo "Error: Line number must be a positive integer (>= 1), got: $LINE"
exit 1
fi
# Get the diff for this file to validate the comment location
DIFF_DATA=$(gh api "repos/${REPO}/pulls/${PR_NUMBER}/files" --paginate | jq --arg f "$FILE" '.[] | select(.filename==$f)')
if [ -z "$DIFF_DATA" ]; then
echo "Error: File '${FILE}' not found in PR diff"
echo ""
echo "Files changed in this PR:"
gh api "repos/${REPO}/pulls/${PR_NUMBER}/files" --paginate --jq '.[].filename'
exit 1
fi
PATCH=$(echo "$DIFF_DATA" | jq -r '.patch // empty')
if [ -z "$PATCH" ]; then
echo "Error: No patch data for file '${FILE}' (file may be binary or too large)"
exit 1
fi
# Verify the line exists in the diff
LINE_IN_DIFF=$(echo "$PATCH" | awk -v target_line="$LINE" '
BEGIN { current_line = 0; found = 0 }
/^@@/ {
line = $0
gsub(/.*\+/, "", line)
gsub(/[^0-9].*/, "", line)
current_line = line - 1
next
}
{
if (substr($0, 1, 1) != "-") {
current_line++
if (current_line == target_line) {
found = 1
exit
}
}
}
END { if (found) print "1"; else print "0" }
')
if [ "$LINE_IN_DIFF" != "1" ]; then
echo "Error: Line ${LINE} not found in the diff for '${FILE}'"
echo ""
echo "Note: You can only comment on lines that appear in the diff (added, modified, or context lines)"
echo ""
echo "First 50 lines of diff for this file:"
echo "$PATCH" | head -50
exit 1
fi
# Create comments directory if it doesn't exist
mkdir -p "${COMMENTS_DIR}"
# Assemble the comment body
SEVERITY_LABEL="${SEVERITY_EMOJI[$SEVERITY]}"
BODY="**${SEVERITY_LABEL}** ${TITLE}
Why: ${WHY}"
# Add suggestion block if provided
if [ -n "$SUGGESTION" ]; then
BODY="${BODY}
\`\`\`suggestion
${SUGGESTION}
\`\`\`"
fi
# Append standard footer
FOOTER='
---
Marvin Context Protocol | Type `/marvin` to interact further
Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.'
BODY_WITH_FOOTER="${BODY}${FOOTER}"
# Generate unique comment ID
COMMENT_ID="comment-$(date +%s)-$(od -An -N4 -tu4 /dev/urandom | tr -d ' ')"
COMMENT_FILE="${COMMENTS_DIR}/${COMMENT_ID}.json"
# Create the comment JSON object
jq -n \
--arg path "$FILE" \
--argjson line "$LINE" \
--arg side "RIGHT" \
--arg body "$BODY_WITH_FOOTER" \
--arg id "$COMMENT_ID" \
'{
path: $path,
line: $line,
side: $side,
body: $body,
_meta: {
id: $id,
file: $path,
line: $line
}
}' > "${COMMENT_FILE}"
echo "✓ Queued review comment for ${FILE}:${LINE}"
echo " Severity: ${SEVERITY_LABEL}"
echo " Title: ${TITLE}"
echo " Comment ID: ${COMMENT_ID}"
echo " Comment will be submitted with pr-review.sh"
echo " Remove with: pr-remove-comment.sh ${FILE} ${LINE}"
================================================
FILE: .github/scripts/pr-review/pr-diff.sh
================================================
#!/bin/bash
# pr-diff.sh - Show changed files or diff for a specific file
#
# Usage:
# pr-diff.sh - List all changed files (shows full diff if small enough)
# pr-diff.sh <file> - Show diff for a specific file with line numbers
#
# Environment variables (set by the composite action):
# PR_REVIEW_REPO - Repository (owner/repo)
# PR_REVIEW_PR_NUMBER - Pull request number
set -e
# Configuration from environment
REPO="${PR_REVIEW_REPO:?PR_REVIEW_REPO environment variable is required}"
PR_NUMBER="${PR_REVIEW_PR_NUMBER:?PR_REVIEW_PR_NUMBER environment variable is required}"
EXPECTED_HEAD="${PR_REVIEW_HEAD_SHA:-}"
# Check if HEAD has changed since review started (race condition detection)
if [ -n "$EXPECTED_HEAD" ]; then
CURRENT_HEAD=$(gh api "repos/${REPO}/pulls/${PR_NUMBER}" --jq '.head.sha')
if [ "$CURRENT_HEAD" != "$EXPECTED_HEAD" ]; then
echo "⚠️ WARNING: PR head has changed since review started!"
echo " Review started at: ${EXPECTED_HEAD:0:7}"
echo " Current head: ${CURRENT_HEAD:0:7}"
echo " Line numbers below may not match the commit being reviewed."
echo ""
fi
fi
# Thresholds for "too big" - show file list only if exceeded
MAX_FILES=25
MAX_TOTAL_LINES=1500
FILE="$1"
# Function to add line numbers to a patch
# Format: [LINE] +added | [LINE] context | [----] -deleted
add_line_numbers() {
awk '
BEGIN { new_line = 0 }
/^@@/ {
# Parse hunk header: @@ -old_start,old_count +new_start,new_count @@
match($0, /\+([0-9]+)/)
new_line = substr($0, RSTART+1, RLENGTH-1) - 1
print ""
print $0
next
}
/^-/ {
# Deleted line - cannot comment on these
printf "[----] %s\n", $0
next
}
/^\+/ {
# Added line - can comment, show line number
new_line++
printf "[%4d] %s\n", new_line, $0
next
}
{
# Context line (space prefix) - can comment, show line number
new_line++
printf "[%4d] %s\n", new_line, $0
}
'
}
if [ -z "$FILE" ]; then
# Get file list with stats
FILES_DATA=$(gh api "repos/${REPO}/pulls/${PR_NUMBER}/files" --paginate)
FILE_COUNT=$(echo "$FILES_DATA" | jq 'length')
TOTAL_ADDITIONS=$(echo "$FILES_DATA" | jq '[.[].additions] | add // 0')
TOTAL_DELETIONS=$(echo "$FILES_DATA" | jq '[.[].deletions] | add // 0')
TOTAL_LINES=$((TOTAL_ADDITIONS + TOTAL_DELETIONS))
echo "PR #${PR_NUMBER} Summary: ${FILE_COUNT} files changed (+${TOTAL_ADDITIONS}/-${TOTAL_DELETIONS})"
echo ""
# Check if diff is too large
if [ "$FILE_COUNT" -gt "$MAX_FILES" ] || [ "$TOTAL_LINES" -gt "$MAX_TOTAL_LINES" ]; then
echo "⚠️ Large diff detected (>${MAX_FILES} files or >${MAX_TOTAL_LINES} lines changed)"
echo " Review files individually using: pr-diff.sh <filename>"
echo ""
echo "Files changed:"
echo "$FILES_DATA" | jq -r '.[] | " \(.filename) (+\(.additions)/-\(.deletions))"'
else
# Small enough - show all diffs with line numbers
echo "Files changed:"
echo "$FILES_DATA" | jq -r '.[] | " \(.filename) (+\(.additions)/-\(.deletions))"'
echo ""
echo "─────────────────────────────────────────────────────────────────────"
echo ""
# Show each file's diff by iterating over indices
for i in $(seq 0 $((FILE_COUNT - 1))); do
FNAME=$(echo "$FILES_DATA" | jq -r ".[$i].filename")
PATCH=$(echo "$FILES_DATA" | jq -r ".[$i].patch // empty")
if [ -n "$PATCH" ]; then
echo "## ${FNAME}"
echo "Use: pr-comment.sh ${FNAME} <LINE> --severity <level> --title \"desc\" --why \"reason\" <<'EOF' ... EOF"
echo "Format: [LINE] +added | [LINE] context | [----] -deleted (can't comment)"
echo "$PATCH" | add_line_numbers
echo ""
echo "─────────────────────────────────────────────────────────────────────"
echo ""
fi
done
fi
else
# Show specific file diff
PATCH=$(gh api "repos/${REPO}/pulls/${PR_NUMBER}/files" --paginate --jq --arg file "$FILE" '.[] | select(.filename==$file) | .patch')
if [ -z "$PATCH" ]; then
echo "Error: File '${FILE}' not found in PR diff"
echo ""
echo "Files changed in this PR:"
gh api "repos/${REPO}/pulls/${PR_NUMBER}/files" --paginate --jq '.[].filename'
exit 1
fi
echo "## ${FILE}"
echo "Use: pr-comment.sh ${FILE} <LINE> --severity <level> --title \"desc\" --why \"reason\" <<'EOF' ... EOF"
echo "Format: [LINE] +added | [LINE] context | [----] -deleted (can't comment)"
echo "$PATCH" | add_line_numbers
fi
================================================
FILE: .github/scripts/pr-review/pr-existing-comments.sh
================================================
#!/bin/bash
# pr-existing-comments.sh - Fetch existing review threads on a PR
#
# Usage:
# pr-existing-comments.sh - Show all review threads with full details
# pr-existing-comments.sh --summary - Show per-file summary only (for large PRs)
# pr-existing-comments.sh --unresolved - Show only unresolved threads
# pr-existing-comments.sh --file <path> - Show threads for a specific file
# pr-existing-comments.sh --full - Show full comment text (no truncation)
#
# Output: Formatted summary of existing review threads grouped by file,
# showing thread status, comments, and whether issues were addressed.
#
# For large PRs, use --summary first to see the overview, then --file <path>
# to get full thread details when reviewing each file.
#
# Environment variables (set by the composite action):
# PR_REVIEW_REPO - Repository (owner/repo)
# PR_REVIEW_PR_NUMBER - Pull request number
set -e
# Configuration from environment
REPO="${PR_REVIEW_REPO:?PR_REVIEW_REPO environment variable is required}"
PR_NUMBER="${PR_REVIEW_PR_NUMBER:?PR_REVIEW_PR_NUMBER environment variable is required}"
OWNER="${REPO%/*}"
REPO_NAME="${REPO#*/}"
# Parse arguments
FILTER_UNRESOLVED=false
FILTER_FILE=""
SUMMARY_ONLY=false
FULL_TEXT=false
while [ $# -gt 0 ]; do
case "$1" in
--unresolved)
FILTER_UNRESOLVED=true
shift
;;
--file)
FILTER_FILE="$2"
shift 2
;;
--summary)
SUMMARY_ONLY=true
shift
;;
--full)
FULL_TEXT=true
shift
;;
*)
echo "Usage: pr-existing-comments.sh [--summary] [--unresolved] [--file <path>] [--full]"
exit 1
;;
esac
done
# Fetch review threads via GraphQL
THREADS=$(gh api graphql -f query='
query($owner: String!, $repo: String!, $prNumber: Int!) {
repository(owner: $owner, name: $repo) {
pullRequest(number: $prNumber) {
reviewThreads(first: 100) {
nodes {
id
isResolved
isOutdated
path
line
originalLine
startLine
originalStartLine
diffSide
comments(first: 50) {
nodes {
id
body
author { login }
createdAt
originalCommit { abbreviatedOid }
}
}
}
}
}
}
}' -F owner="$OWNER" \
-F repo="$REPO_NAME" \
-F prNumber="$PR_NUMBER" \
--jq '.data.repository.pullRequest.reviewThreads.nodes')
if [ -z "$THREADS" ] || [ "$THREADS" = "null" ]; then
echo "No existing review threads found."
exit 0
fi
# Apply filters
FILTERED="$THREADS"
if [ "$FILTER_UNRESOLVED" = true ]; then
FILTERED=$(echo "$FILTERED" | jq '[.[] | select(.isResolved == false)]')
fi
if [ -n "$FILTER_FILE" ]; then
FILTERED=$(echo "$FILTERED" | jq --arg file "$FILTER_FILE" '[.[] | select(.path == $file)]')
fi
THREAD_COUNT=$(echo "$FILTERED" | jq 'length')
if [ "$THREAD_COUNT" -eq 0 ]; then
if [ "$FILTER_UNRESOLVED" = true ]; then
echo "No unresolved review threads found."
elif [ -n "$FILTER_FILE" ]; then
echo "No review threads found for ${FILTER_FILE}."
else
echo "No existing review threads found."
fi
exit 0
fi
# Count resolved vs unresolved
RESOLVED_COUNT=$(echo "$FILTERED" | jq '[.[] | select(.isResolved == true)] | length')
UNRESOLVED_COUNT=$(echo "$FILTERED" | jq '[.[] | select(.isResolved == false)] | length')
OUTDATED_COUNT=$(echo "$FILTERED" | jq '[.[] | select(.isOutdated == true)] | length')
echo "Existing review threads: ${THREAD_COUNT} total (${UNRESOLVED_COUNT} unresolved, ${RESOLVED_COUNT} resolved, ${OUTDATED_COUNT} outdated)"
echo ""
# Summary mode: show per-file counts only
if [ "$SUMMARY_ONLY" = true ]; then
echo "Threads by file:"
echo "$FILTERED" | jq -r '
group_by(.path) | .[] |
. as $threads |
($threads | length) as $total |
([$threads[] | select(.isResolved == false)] | length) as $unresolved |
([$threads[] | select(.isResolved == true)] | length) as $resolved |
([$threads[] | select(.isOutdated == true)] | length) as $outdated |
([$threads[] | select(.comments.nodes | length > 1)] | length) as $has_replies |
" " + $threads[0].path +
" — " + ($total | tostring) + " threads" +
" (" + ($unresolved | tostring) + " unresolved, " + ($resolved | tostring) + " resolved" +
(if $outdated > 0 then ", " + ($outdated | tostring) + " outdated" else "" end) +
")" +
(if $has_replies > 0 then " ⚠️ " + ($has_replies | tostring) + " with replies" else "" end)
'
echo ""
echo "Use: pr-existing-comments.sh --file <path> to see full thread details for a file"
exit 0
fi
# Full detail mode: output threads grouped by file
# Show full conversation for threads with replies
FIRST_LIMIT=200
REPLY_LIMIT=300
if [ "$FULL_TEXT" = true ]; then
FIRST_LIMIT=999999
REPLY_LIMIT=999999
fi
echo "$FILTERED" | jq -r --argjson first_limit "$FIRST_LIMIT" --argjson reply_limit "$REPLY_LIMIT" '
group_by(.path) | .[] |
"## " + .[0].path + " (" + (length | tostring) + " threads)\n" +
([.[] |
" " +
(if .isResolved then "✅ RESOLVED" elif .isOutdated then "⚠️ OUTDATED" else "🔴 UNRESOLVED" end) +
" (line " + (if .line then (.line | tostring) elif .startLine then (.startLine | tostring) elif .originalLine then ("~" + (.originalLine | tostring)) elif .originalStartLine then ("~" + (.originalStartLine | tostring)) else "?" end) + ")" +
# Show the commit the comment was originally made on
(if .comments.nodes[0].originalCommit.abbreviatedOid then " [" + .comments.nodes[0].originalCommit.abbreviatedOid + "]" else "" end) +
# Flag threads with replies — indicates a conversation happened
(if (.comments.nodes | length) > 1 then " ← has replies" else "" end) +
"\n" +
([.comments.nodes | to_entries[] |
.value as $comment |
.key as $idx |
($comment.body | gsub("\n"; " ")) as $flat |
if $idx == 0 then
" @" + ($comment.author.login // "unknown") + ": " + $flat[0:$first_limit] +
(if ($flat | length) > $first_limit then " [truncated]" else "" end)
else
" ↳ @" + ($comment.author.login // "unknown") + ": " + $flat[0:$reply_limit] +
(if ($flat | length) > $reply_limit then " [truncated]" else "" end)
end
] | join("\n")) +
"\n"
] | join("\n"))
'
================================================
FILE: .github/scripts/pr-review/pr-remove-comment.sh
================================================
#!/bin/bash
# pr-remove-comment.sh - Remove a queued review comment
#
# Usage:
# pr-remove-comment.sh <file> <line-number>
# pr-remove-comment.sh <comment-id>
#
# Examples:
# pr-remove-comment.sh src/main.go 42
# pr-remove-comment.sh comment-1234567890-1234567890
#
# This script removes a previously queued comment before it's submitted.
# Useful if the agent realizes it made a mistake or wants to update a comment.
#
# Environment variables (set by the composite action):
# PR_REVIEW_COMMENTS_DIR - Directory containing comment files (default: /tmp/pr-review-comments)
set -e
COMMENTS_DIR="${PR_REVIEW_COMMENTS_DIR:-/tmp/pr-review-comments}"
if [ ! -d "${COMMENTS_DIR}" ]; then
echo "No comments directory found: ${COMMENTS_DIR}"
exit 0
fi
# Check if first argument looks like a comment ID
if [[ "$1" =~ ^comment- ]]; then
COMMENT_ID="$1"
COMMENT_FILE="${COMMENTS_DIR}/${COMMENT_ID}.json"
if [ -f "${COMMENT_FILE}" ]; then
FILE=$(jq -r '._meta.file // .path' "${COMMENT_FILE}")
LINE=$(jq -r '._meta.line // .line' "${COMMENT_FILE}")
rm -f "${COMMENT_FILE}"
echo "✓ Removed comment ${COMMENT_ID} for ${FILE}:${LINE}"
else
echo "Comment not found: ${COMMENT_ID}"
exit 1
fi
else
# Treat as file and line number
FILE="$1"
LINE="$2"
if [ -z "$FILE" ] || [ -z "$LINE" ]; then
echo "Usage:"
echo " pr-remove-comment.sh <file> <line-number>"
echo " pr-remove-comment.sh <comment-id>"
echo ""
echo "Examples:"
echo " pr-remove-comment.sh src/main.go 42"
echo " pr-remove-comment.sh comment-1234567890-1234567890"
exit 1
fi
# Validate line is a positive integer (>= 1)
if ! [[ "$LINE" =~ ^[1-9][0-9]*$ ]]; then
echo "Error: Line number must be a positive integer (>= 1), got: $LINE"
exit 1
fi
# Find and remove matching comment files
# Use nullglob to handle case where no files match
shopt -s nullglob
REMOVED=0
for COMMENT_FILE in "${COMMENTS_DIR}"/comment-*.json; do
COMMENT_FILE_PATH=$(jq -r '._meta.file // .path' "${COMMENT_FILE}")
COMMENT_LINE=$(jq -r '._meta.line // .line' "${COMMENT_FILE}")
if [ "$COMMENT_FILE_PATH" = "$FILE" ] && [ "$COMMENT_LINE" = "$LINE" ]; then
COMMENT_ID=$(basename "${COMMENT_FILE}" .json)
rm -f "${COMMENT_FILE}"
echo "✓ Removed comment ${COMMENT_ID} for ${FILE}:${LINE}"
REMOVED=$((REMOVED + 1))
fi
done
if [ "$REMOVED" -eq 0 ]; then
echo "No comment found for ${FILE}:${LINE}"
exit 1
fi
fi
================================================
FILE: .github/scripts/pr-review/pr-review.sh
================================================
#!/bin/bash
# pr-review.sh - Submit a PR review (approve, request changes, or comment)
#
# Usage: pr-review.sh <APPROVE|REQUEST_CHANGES|COMMENT> [review-body]
# Example: pr-review.sh REQUEST_CHANGES "Please fix the issues noted above"
#
# This script creates and submits a review with any queued inline comments.
# Comments are read from individual files in PR_REVIEW_COMMENTS_DIR (created by pr-comment.sh).
#
# The review body can contain special characters (backticks, dollar signs, etc.)
# and will be safely passed to the GitHub API without shell interpretation.
#
# Environment variables (set by the composite action):
# PR_REVIEW_REPO - Repository (owner/repo)
# PR_REVIEW_PR_NUMBER - Pull request number
# PR_REVIEW_HEAD_SHA - HEAD commit SHA
# PR_REVIEW_COMMENTS_DIR - Directory containing queued comment files (default: /tmp/pr-review-comments)
set -e
# Configuration from environment
REPO="${PR_REVIEW_REPO:?PR_REVIEW_REPO environment variable is required}"
PR_NUMBER="${PR_REVIEW_PR_NUMBER:?PR_REVIEW_PR_NUMBER environment variable is required}"
HEAD_SHA="${PR_REVIEW_HEAD_SHA:?PR_REVIEW_HEAD_SHA environment variable is required}"
COMMENTS_DIR="${PR_REVIEW_COMMENTS_DIR:-/tmp/pr-review-comments}"
# Arguments
EVENT="$1"
shift 2>/dev/null || true
# Read body from remaining arguments
# Join all remaining arguments with spaces, preserving the string as-is
BODY="$*"
if [ -z "$EVENT" ]; then
echo "Usage: pr-review.sh <APPROVE|REQUEST_CHANGES|COMMENT> [review-body]"
echo "Example: pr-review.sh REQUEST_CHANGES 'Please fix the issues noted in the inline comments'"
exit 1
fi
# Validate event type
case "$EVENT" in
APPROVE|REQUEST_CHANGES|COMMENT)
;;
*)
echo "Error: Invalid event type '${EVENT}'"
echo "Must be one of: APPROVE, REQUEST_CHANGES, COMMENT"
exit 1
;;
esac
# Read queued comments from individual files
COMMENTS="[]"
COMMENT_COUNT=0
if [ -d "${COMMENTS_DIR}" ]; then
# Collect all comment files and merge into a single JSON array
# Remove _meta fields before submitting (they're only for internal use)
COMMENT_FILES=("${COMMENTS_DIR}"/comment-*.json)
if [ -f "${COMMENT_FILES[0]}" ]; then
# Use jq to read all comment files, extract the comment data (without _meta), and combine
COMMENTS=$(jq -s '[.[] | del(._meta)]' "${COMMENTS_DIR}"/comment-*.json)
COMMENT_COUNT=$(echo "$COMMENTS" | jq 'length')
if [ "$COMMENT_COUNT" -gt 0 ]; then
echo "Found ${COMMENT_COUNT} queued inline comment(s)"
fi
fi
fi
# Append standard footer to the review body (if body is provided)
FOOTER='
---
Marvin Context Protocol | Type `/marvin` to interact further
Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.'
if [ -n "$BODY" ]; then
BODY_WITH_FOOTER="${BODY}${FOOTER}"
else
BODY_WITH_FOOTER=""
fi
# Build the review request JSON
# Use jq to safely construct the JSON with all special characters handled
REVIEW_JSON=$(jq -n \
--arg commit_id "$HEAD_SHA" \
--arg event "$EVENT" \
--arg body "$BODY_WITH_FOOTER" \
--argjson comments "$COMMENTS" \
'{
commit_id: $commit_id,
event: $event,
comments: $comments
} + (if $body != "" then {body: $body} else {} end)')
# Check if HEAD has changed since review started (race condition detection)
CURRENT_HEAD=$(gh api "repos/${REPO}/pulls/${PR_NUMBER}" --jq '.head.sha')
if [ "$CURRENT_HEAD" != "$HEAD_SHA" ]; then
echo "⚠️ WARNING: PR head has changed since review started!"
echo " Review started at: ${HEAD_SHA:0:7}"
echo " Current head: ${CURRENT_HEAD:0:7}"
echo ""
echo " New commits may have shifted line numbers. Review will be submitted"
echo " against the original commit (${HEAD_SHA:0:7}) but comments may be outdated."
echo ""
fi
echo "Submitting ${EVENT} review for commit ${HEAD_SHA:0:7}..."
# Create and submit the review in one API call
# Use a temp file to safely pass the JSON body
TEMP_JSON=$(mktemp)
trap "rm -f ${TEMP_JSON}" EXIT
echo "$REVIEW_JSON" > "${TEMP_JSON}"
RESPONSE=$(gh api "repos/${REPO}/pulls/${PR_NUMBER}/reviews" \
-X POST \
--input "${TEMP_JSON}" 2>&1) || {
echo "Error submitting review:"
echo "$RESPONSE"
exit 1
}
# Clean up the comments directory after successful submission
if [ -d "${COMMENTS_DIR}" ] && [ "$COMMENT_COUNT" -gt 0 ]; then
rm -f "${COMMENTS_DIR}"/comment-*.json
# Remove directory if empty
rmdir "${COMMENTS_DIR}" 2>/dev/null || true
fi
REVIEW_URL=$(echo "$RESPONSE" | jq -r '.html_url // empty')
REVIEW_STATE=$(echo "$RESPONSE" | jq -r '.state // empty')
if [ -n "$REVIEW_URL" ]; then
echo "✓ Review submitted (${REVIEW_STATE}): ${REVIEW_URL}"
if [ "$COMMENT_COUNT" -gt 0 ]; then
echo " Included ${COMMENT_COUNT} inline comment(s)"
fi
else
echo "✓ Review submitted successfully"
fi
================================================
FILE: .github/workflows/auto-close-duplicates.yml
================================================
name: Auto-close duplicate issues
description: Auto-closes issues that are duplicates of existing issues
on:
schedule:
- cron: "0 9 * * *" # Run daily at 9 AM UTC
workflow_dispatch:
jobs:
auto-close-duplicates:
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
issues: write
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Generate Marvin App token
id: marvin-token
uses: actions/create-github-app-token@v3
with:
app-id: ${{ secrets.MARVIN_APP_ID }}
private-key: ${{ secrets.MARVIN_APP_PRIVATE_KEY }}
- name: Install uv
uses: astral-sh/setup-uv@v7
- name: Auto-close duplicate issues
run: uv run scripts/auto_close_duplicates.py
env:
GITHUB_TOKEN: ${{ steps.marvin-token.outputs.token }}
GITHUB_REPOSITORY_OWNER: ${{ github.repository_owner }}
GITHUB_REPOSITORY_NAME: ${{ github.event.repository.name }}
================================================
FILE: .github/workflows/auto-close-needs-mre.yml
================================================
name: Auto-close needs MRE issues
description: Auto-closes issues that need minimal reproducible examples after 7 days of author inactivity
on:
schedule:
- cron: "0 9 * * *" # Run daily at 9 AM UTC
workflow_dispatch:
jobs:
auto-close-needs-mre:
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
issues: write
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Generate Marvin App token
id: marvin-token
uses: actions/create-github-app-token@v3
with:
app-id: ${{ secrets.MARVIN_APP_ID }}
private-key: ${{ secrets.MARVIN_APP_PRIVATE_KEY }}
- name: Install uv
uses: astral-sh/setup-uv@v7
- name: Auto-close needs MRE issues
run: uv run scripts/auto_close_needs_mre.py
env:
GITHUB_TOKEN: ${{ steps.marvin-token.outputs.token }}
GITHUB_REPOSITORY_OWNER: ${{ github.repository_owner }}
GITHUB_REPOSITORY_NAME: ${{ github.event.repository.name }}
================================================
FILE: .github/workflows/martian-test-failure.yml
================================================
name: Marvin Test Failure Analysis
on:
workflow_run:
workflows: ["Tests", "Run static analysis"]
types:
- completed
concurrency:
group: marvin-test-failure-${{ github.event.workflow_run.head_branch }}
cancel-in-progress: true
jobs:
martian-test-failure:
# Only run if the test workflow failed
if: ${{ github.event.workflow_run.conclusion == 'failure' }}
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
issues: read
id-token: write
actions: read # Required for Claude to read CI results
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
fetch-depth: 1
- name: Generate Marvin App token
id: marvin-token
uses: actions/create-github-app-token@v3
with:
app-id: ${{ secrets.MARVIN_APP_ID }}
private-key: ${{ secrets.MARVIN_APP_PRIVATE_KEY }}
- name: Set up Python 3.10
uses: actions/setup-python@v6
with:
python-version: "3.10"
# Install UV package manager
- name: Install UV
uses: astral-sh/setup-uv@v7
# Install dependencies
- name: Install dependencies
run: uv sync --all-packages --group dev
- name: Set analysis prompt
id: analysis-prompt
run: |
cat >> $GITHUB_OUTPUT << 'EOF'
PROMPT<<PROMPT_END
You're a test failure analysis assistant for FastMCP, a Python framework for building Model Context Protocol servers and clients.
# Your Task
A GitHub Actions workflow has failed. Your job is to:
1. Analyze the test failure(s) to understand what went wrong
2. Identify the root cause of the failure(s)
3. Suggest a clear, actionable solution to fix the failure(s)
# Getting Started
1. Call the generate_agents_md tool to get a high-level summary of the project
2. Get the pull request associated with this workflow run from the GitHub repository: ${{ github.repository }}
- The workflow run ID is: ${{ github.event.workflow_run.id }}
- The workflow run was triggered by: ${{ github.event.workflow_run.event }}
- Use GitHub MCP tools to get PR details and workflow run information
3. Use the GitHub MCP tools to fetch job logs and failure information:
- Use get_workflow_run to get details about the failed workflow
- Use list_workflow_jobs to see which jobs failed
- Use get_job_logs with failed_only=true to get logs for failed jobs
- Use summarize_run_log_failures to get an AI summary of what failed
4. Analyze the failures to understand the root cause
5. Search the codebase for relevant files, tests, and implementations
# Your Response
Post a comment on the pull request with your analysis. Your comment should include:
## Test Failure Analysis
**Summary**: A brief 1-2 sentence summary of what failed.
**Root Cause**: A clear explanation of why the tests failed, based on your analysis of the logs and code.
**Suggested Solution**: Specific, actionable steps to fix the failure(s). Include:
- Which files need to be modified
- What changes are needed
- Why these changes will fix the issue
<details>
<summary>Detailed Analysis</summary>
Include here:
- Relevant log excerpts showing the failure
- Code snippets that are causing the issue
- Any related issues or PRs that might be relevant
</details>
<details>
<summary>Related Files</summary>
List files that are relevant to the failure with brief explanations of their relevance.
</details>
# Important Guidelines
- Be concise and actionable - developers want to quickly understand and fix the issue. Provide
additional context, references, etc in collapsible details blocks to ensure that the comment you're adding
is short and easy to read but additional information is a click away.
- Focus on facts from the logs and code, not speculation
- If you can't determine the root cause, say so clearly
- If your only suggestion is a bad suggestion (disable the test, change the timeout, etc), indicate that you've run out of ideas and
that they probably don't want to do that.
- Provide specific file names, line numbers, and code references when possible
- You can run make commands (e.g., `make lint`, `make typecheck`, `make sync`) to build, test, or lint the code
- You can also run git commands (e.g., `git status`, `git log`, `git diff`) to inspect the repository
- You can use WebSearch and WebFetch to research errors, stack traces, or related issues
- For bash commands, you are limited to make and git commands only
# CRITICAL: ANGRY USERS
**IMPORTANT**: If the user is angry with you, the triage bot, don't respond. Just exit immediately without further action.
If at any point in the conversation the user has asked you to stop replying to the thread, just exit immediately.
If you are posting the same suggestion as you have previously made, do not post the suggestion again.
# IMPORTANT: EDIT YOUR COMMENT
Do not post a new comment every time you triage a failing workflow. If a previous comment has been posted by you (marvin)
in a previous triage, edit that comment do not add a new comment for each failure. Be sure to include a note that you've edited
your comment to reflect the latest analysis. Don't worry about keeping the old content around, there's comment history for
that.
# Problems Encountered
If you encounter any problems during your analysis (e.g., unable to fetch logs, tools not working), document them clearly so the team knows what limitations you faced.
PROMPT_END
EOF
- name: Setup GitHub MCP Server
run: |
mkdir -p /tmp/mcp-config
cat > /tmp/mcp-config/mcp-servers.json << 'EOF'
{
"mcpServers": {
"repository-summary": {
"type": "http",
"url": "https://agents-md-generator.fastmcp.app/mcp"
},
"code-search": {
"type": "http",
"url": "https://public-code-search.fastmcp.app/mcp"
},
"github-research": {
"type": "stdio",
"command": "uvx",
"args": [
"github-research-mcp"
],
"env": {
"DISABLE_SUMMARIES": "true",
"GITHUB_PERSONAL_ACCESS_TOKEN": "${{ secrets.GITHUB_TOKEN }}"
}
}
}
}
EOF
- name: Clean up stale Claude locks
run: rm -rf ~/.claude/.locks ~/.local/state/claude/locks || true
- name: Run Claude Code
id: claude
uses: anthropics/claude-code-action@v1
with:
github_token: ${{ steps.marvin-token.outputs.token }}
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY_FOR_CI }}
bot_name: "Marvin Context Protocol"
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
additional_permissions: |
actions: read
prompt: ${{ steps.analysis-prompt.outputs.PROMPT }}
claude_args: |
--allowed-tools mcp__repository-summary,mcp__code-search,mcp__github-research,WebSearch,WebFetch,Bash(make:*,git:*)
--mcp-config /tmp/mcp-config/mcp-servers.json
================================================
FILE: .github/workflows/martian-triage-issue.yml
================================================
# Triage new issues: investigate, recommend, apply labels
# Calls run-claude directly with triage prompt (elastic issue-triage style)
name: Triage Issue
on:
issues:
types: [opened]
jobs:
triage:
if: |
github.event.issue.user.login == 'strawgate' ||
(github.event.issue.user.login == 'jlowin' && contains(toJSON(github.event.issue.labels.*.name), 'bug'))
concurrency:
group: triage-issue-${{ github.event.issue.number }}
cancel-in-progress: true
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
issues: write
pull-requests: read
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
repository: ${{ github.repository }}
ref: ${{ github.event.repository.default_branch }}
- name: Generate Marvin App token
id: marvin-token
uses: actions/create-github-app-token@v3
with:
app-id: ${{ secrets.MARVIN_APP_ID }}
private-key: ${{ secrets.MARVIN_APP_PRIVATE_KEY }}
- name: React to issue with eyes
env:
GH_TOKEN: ${{ steps.marvin-token.outputs.token }}
run: |
gh api "repos/${{ github.repository }}/issues/${{ github.event.issue.number }}/reactions" -f content=eyes 2>/dev/null || true
- name: Run Claude for Triage
uses: ./.github/actions/run-claude
with:
claude-oauth-token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
github-token: ${{ steps.marvin-token.outputs.token }}
allowed-tools: "Edit,MultiEdit,Glob,Grep,LS,Read,Write,WebSearch,WebFetch,mcp__github_comment__update_claude_comment,mcp__github_ci__get_ci_status,mcp__github_ci__get_workflow_run_details,mcp__github_ci__download_job_log,Bash(*),mcp__agents-md-generator__generate_agents_md,mcp__public-code-search__search_code"
prompt: |
<context>
Repository: ${{ github.repository }}
Issue Number: #${{ github.event.issue.number }}
Issue Title: ${{ github.event.issue.title }}
Issue Author: ${{ github.event.issue.user.login }}
</context>
<issue_body>
${{ github.event.issue.body }}
</issue_body>
<task>
Triage this new GitHub issue and provide a helpful, actionable response. You can write files and execute commands to test, verify, or investigate the issue.
</task>
<constraints>
This workflow is for investigation, testing, and planning.
You CANNOT: Create branches, checkout branches, commit code to the repository
Do not push changes to the repository.
You CAN: Read/analyze code, search repository, review git history, search for similar issues, write files, verify behavior, provide analysis and recommendations
</constraints>
<allowed_tools>
You have access to the following tools (comma-separated list):
Edit,MultiEdit,Glob,Grep,LS,Read,Write,WebSearch,WebFetch,mcp__github_comment__update_claude_comment,mcp__github_ci__get_ci_status,mcp__github_ci__get_workflow_run_details,mcp__github_ci__download_job_log,Bash(*),mcp__agents-md-generator__generate_agents_md,mcp__public-code-search__search_code
You can only use tools that are explicitly listed above. For Bash commands, the pattern `Bash(command:*)` means you can run that command with any arguments. If a command is not listed, it is not available.
</allowed_tools>
<getting_started>
Use `mcp__agents-md-generator__generate_agents_md` to get repository context before triaging.
</getting_started>
<investigation_tools>
- `mcp__public-code-search__search_code`: Search code in OTHER repositories (use `Grep`/`Read` for this repo)
- `WebSearch`: Search the web for documentation, best practices, or solutions
- `WebFetch`: Fetch and read content from URLs
- Git commands: You have access to git commands, but write commands (commit, push, checkout, branch creation) are blocked
- Write: You can write files (e.g., test files, temporary files for verification)
- Execution: See `<allowed_tools>` section above for exact list of available execution commands
</investigation_tools>
<execution_guidelines>
If execution commands are available (check `<allowed_tools>` section), you can:
- Run tests to verify reported bugs or test proposed solutions
- Execute scripts to understand behavior
- Run linters or static analysis tools
- Verify environment setup or dependencies
- Test specific code paths or scenarios
- Write test files to confirm behavior
When executing commands:
- Explain what you're testing and why
- Include command output in your response when relevant
- Use execution to validate your findings and recommendations
- Only use commands that are explicitly listed in `<allowed_tools>`
</execution_guidelines>
<response_goals>
Your number one priority is to provide a great response to the issue. A great response is a response that is clear, concise, accurate, and actionable. You will avoid long paragraphs, flowery language, and overly verbose responses. Your readers have limited time and attention, so you will be concise and to the point.
In priority order your goal is to:
1. Provide context about the request or issue (related issues, pull requests, files, etc.)
2. Layout a single high-quality and actionable recommendation for how to address the issue based on your knowledge of the project, codebase, and issue
3. Provide a high quality and detailed plan that a junior developer could follow to implement the recommendation
4. Use execution to verify findings when appropriate (check `<allowed_tools>` section for available commands)
</response_goals>
<response_sections>
Populate the following sections in your response:
Recommendation (or "No recommendation" with reason)
Findings
Verification (if you executed tests or commands - check `<allowed_tools>` section)
Detailed Action Plan
Related Items
Related Files
Related Webpages
You may not be able to do all of these things, sometimes you may find that all you can do is provide in-depth context of the issue and related items. That's perfectly acceptable and expected. Your performance is judged by how accurate your findings are, do the investigation required to have high confidence in your findings and recommendations. "I don't know" or "I'm unable to recommend a course of action" is better than a bad or wrong answer.
When formulating your response, you will never "bury the lede", you will always provide a clear and concise tl;dr as the first thing in your response. As your response grows in length you can organize the more detailed parts of your response collapsible sections using <details> and <summary> tags. You shouldn't put everything in collapsible sections, especially if the response is short. Use your discretion to determine when to use collapsible sections to avoid overwhelming the reader with too much detail -- think of them like an appendix that can be expanded if the reader is interested.
</response_sections>
<response_examples>
# Example output for "Recommendation" part of the response
PR #654 already implements the requested feature but is incomplete. The Pull Request is not in a mergeable state yet, the remaining work should be completed: 1) update the Calculator.divide method to utilize the new DivisionByZeroError or the safe_divide function, and 2) update the tests to ensure that the Calculator.divide method raises the new DivisionByZeroError when the divisor is 0.
<details>
<summary>Findings</summary>
...details from the code analysis that are relevant to the issue and the recommendation...
</details>
<details>
<summary>Verification</summary>
I ran the existing tests (if execution commands are available in `<allowed_tools>`) and confirmed the current behavior:
```bash
$ pytest test_calculator.py::test_divide_by_zero
FAILED - raises ValueError instead of DivisionByZeroError
```
This confirms the issue report is accurate.
</details>
<details>
<summary>Detailed Action Plan</summary>
...a detailed plan that a junior developer could follow to implement the recommendation...
</details>
# Example Output for "Related Items" part of the response
<details>
<summary>Related Issues and Pull Requests</summary>
| Repository | Issue or PR | Relevance |
| --- | --- | --- |
| PrefectHQ/fastmcp | [Add matrix operations support](https://github.com/PrefectHQ/fastmcp/pull/680) | This pull request directly addresses the feature request for adding matrix operations to the calculator. |
| PrefectHQ/fastmcp | [Add matrix operations support](https://github.com/PrefectHQ/fastmcp/issues/681) | This issue directly addresses the feature request for adding matrix operations to the calculator. |
</details>
<details>
<summary>Related Files</summary>
| Repository | File | Relevance | Sections |
| --- | --- | --- | --- |
| modelcontextprotocol/python-sdk | [test_calculator.py](https://github.com/modelcontextprotocol/python-sdk/blob/main/test_calculator.py) | This file contains the test cases for the Calculator class, including a test that specifically asserts a ValueError is raised for division by zero, confirming the current intended behavior. | [25-27](https://github.com/modelcontextprotocol/python-sdk/blob/main/test_calculator.py#L25-L27) |
| modelcontextprotocol/python-sdk | [calculator.py](https://github.com/modelcontextprotocol/python-sdk/blob/main/calculator.py) | This file contains the implementation of the Calculator class, specifically the `divide` method which raises the ValueError when dividing by zero, matching the bug report. | [29-32](https://github.com/modelcontextprotocol/python-sdk/blob/main/calculator.py#L29-L32) |
</details>
<details>
<summary>Related Webpages</summary>
| Name | URL | Relevance |
| --- | --- | --- |
| Handling Division by Zero Best Practices | https://my-blog-about-division-by-zero.com/handling+division+by+zero+in+calculator | This webpage provides general best practices for handling division by zero in calculator applications and in Python, which is directly relevant to the issue and potential solutions. |
</details>
</response_examples>
<response_footer>
Always end your comment with a new line, three dashes, and the footer message:
<exact_content>
---
Marvin Context Protocol | Type `/marvin` to interact further
Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.
</exact_content>
</response_footer>
<github_formatting>
When writing GitHub comments, wrap branch names, tags, or other @-references in backticks (e.g., `@main`, `@v1.0`) to avoid accidentally pinging users. Do not add backticks around terms that are already inside backticks or code blocks.
</github_formatting>
================================================
FILE: .github/workflows/marvin-comment-on-issue.yml
================================================
# Respond to /marvin mentions in issue comments (elastic mention-in-issue style)
# Calls run-claude directly
name: Comment on Issue
on:
issue_comment:
types: [created]
permissions:
actions: read
contents: write
issues: write
pull-requests: write
id-token: write
jobs:
comment:
if: |
!github.event.issue.pull_request &&
contains(github.event.comment.body, '/marvin') &&
contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association)
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Install UV
uses: astral-sh/setup-uv@v7
with:
enable-cache: true
cache-dependency-glob: "uv.lock"
- name: Install dependencies
run: uv sync --python 3.12
- name: Generate Marvin App token
id: marvin-token
uses: actions/create-github-app-token@v3
with:
app-id: ${{ secrets.MARVIN_APP_ID }}
private-key: ${{ secrets.MARVIN_APP_PRIVATE_KEY }}
- name: React to comment with eyes
env:
GH_TOKEN: ${{ steps.marvin-token.outputs.token }}
run: |
gh api "repos/${{ github.repository }}/issues/comments/${{ github.event.comment.id }}/reactions" -f content=eyes 2>/dev/null || true
- name: Run Claude for Issue Comment
uses: ./.github/actions/run-claude
with:
claude-oauth-token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
github-token: ${{ steps.marvin-token.outputs.token }}
trigger-phrase: "/marvin"
allowed-bots: "*"
allowed-tools: "Edit,MultiEdit,Glob,Grep,LS,Read,Write,WebSearch,WebFetch,mcp__github_comment__update_claude_comment,mcp__github_ci__get_ci_status,mcp__github_ci__get_workflow_run_details,mcp__github_ci__download_job_log,Bash(*),mcp__agents-md-generator__generate_agents_md,mcp__public-code-search__search_code"
prompt: |
<context>
Repository: ${{ github.repository }}
Issue Number: #${{ github.event.issue.number }}
Issue Title: ${{ github.event.issue.title }}
Issue Author: ${{ github.event.issue.user.login }}
Comment Author: ${{ github.event.comment.user.login }}
</context>
<user_request>
${{ github.event.comment.body }}
</user_request>
<task>
You have been mentioned in a GitHub issue comment. Understand the request, gather context, complete the task, and respond with results.
</task>
<constraints>
You CAN: Read/analyze code, modify files, write code, run tests, execute commands
You CAN: Commit code, push changes, create branches, create pull requests
</constraints>
<allowed_tools>
You have access to the following tools (comma-separated list):
Edit,MultiEdit,Glob,Grep,LS,Read,Write,WebSearch,WebFetch,mcp__github_comment__update_claude_comment,mcp__github_ci__get_ci_status,mcp__github_ci__get_workflow_run_details,mcp__github_ci__download_job_log,Bash(*),mcp__agents-md-generator__generate_agents_md,mcp__public-code-search__search_code
You can only use tools that are explicitly listed above. For Bash commands, the pattern `Bash(command:*)` means you can run that command with any arguments. If a command is not listed, it is not available.
</allowed_tools>
<getting_started>
Use `mcp__agents-md-generator__generate_agents_md` to get repository context before responding.
</getting_started>
<investigation_approach>
Be thorough in your investigations:
- Understand the full context of the repository
- Review related code, issues, and PRs
- Consider edge cases and implications
- Gather all relevant information before responding
Available tools:
- `mcp__public-code-search__search_code`: Search code in OTHER repositories (use `Grep`/`Read` for this repo)
- `WebSearch`: Search the web for documentation, best practices, or solutions
- `WebFetch`: Fetch and read content from URLs
</investigation_approach>
<common_tasks>
- Answer questions about the codebase
- Help debug reported problems (make changes locally to test, cannot push)
- Suggest solutions or workarounds
- Provide code examples
- Help clarify requirements
- Link to relevant documentation or code
</common_tasks>
<response_guidelines>
- Be concise and actionable
- If the request is unclear, ask clarifying questions
- If the request requires actions you cannot perform (like pushing changes), explain what you can and cannot do
- When making code changes, explain that they are local only and cannot be pushed
</response_guidelines>
<response_footer>
Always end your comment with a new line, three dashes, and the footer message:
<exact_content>
---
Marvin Context Protocol | Type `/marvin` to interact further
Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.
</exact_content>
</response_footer>
<github_formatting>
When writing GitHub comments, wrap branch names, tags, or other @-references in backticks (e.g., `@main`, `@v1.0`) to avoid accidentally pinging users. Do not add backticks around terms that are already inside backticks or code blocks.
</github_formatting>
================================================
FILE: .github/workflows/marvin-comment-on-pr.yml
================================================
# Respond to /marvin mentions in PR review comments and issue comments on PRs
# Calls run-claude directly
name: Comment on PR
on:
issue_comment:
types: [created]
permissions:
contents: write
pull-requests: write
issues: read
id-token: write
jobs:
comment:
if: |
github.event.issue.pull_request &&
contains(github.event.comment.body, '/marvin') &&
contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association)
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout PR head branch
uses: actions/checkout@v6
with:
# do not set to pull_request.head.ref, claude will pull the branch if needed
fetch-depth: 0
- name: Install UV
uses: astral-sh/setup-uv@v7
with:
enable-cache: true
cache-dependency-glob: "uv.lock"
- name: Install dependencies
run: uv sync --python 3.12
- name: Generate Marvin App token
id: marvin-token
uses: actions/create-github-app-token@v3
with:
app-id: ${{ secrets.MARVIN_APP_ID }}
private-key: ${{ secrets.MARVIN_APP_PRIVATE_KEY }}
- name: React to comment with eyes
env:
GH_TOKEN: ${{ steps.marvin-token.outputs.token }}
run: |
gh api "repos/${{ github.repository }}/issues/comments/${{ github.event.comment.id }}/reactions" -f content=eyes 2>/dev/null || true
- name: Get PR HEAD SHA
id: pr-info
env:
GH_TOKEN: ${{ steps.marvin-token.outputs.token }}
run: |
PR_NUMBER="${{ github.event.issue.number }}"
HEAD_SHA=$(gh api "repos/${{ github.repository }}/pulls/${PR_NUMBER}" --jq '.head.sha')
echo "head_sha=${HEAD_SHA}" >> "$GITHUB_OUTPUT"
echo "pr_number=${PR_NUMBER}" >> "$GITHUB_OUTPUT"
- name: Run Claude for PR Comment
uses: ./.github/actions/run-claude
env:
MENTION_REPO: ${{ github.repository }}
MENTION_PR_NUMBER: ${{ steps.pr-info.outputs.pr_number }}
MENTION_SCRIPTS: ${{ github.workspace }}/.github/scripts/mention
PR_REVIEW_REPO: ${{ github.repository }}
PR_REVIEW_PR_NUMBER: ${{ steps.pr-info.outputs.pr_number }}
PR_REVIEW_HEAD_SHA: ${{ steps.pr-info.outputs.head_sha }}
PR_REVIEW_COMMENTS_DIR: /tmp/pr-review-comments
PR_REVIEW_HELPERS_DIR: ${{ github.workspace }}/.github/scripts/pr-review
with:
claude-oauth-token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
github-token: ${{ steps.marvin-token.outputs.token }}
trigger-phrase: "/marvin"
allowed-bots: "*"
allowed-tools: "Edit,MultiEdit,Glob,Grep,LS,Read,Write,WebSearch,WebFetch,mcp__github_comment__update_claude_comment,mcp__github_ci__get_ci_status,mcp__github_ci__get_workflow_run_details,mcp__github_ci__download_job_log,Bash(*),mcp__agents-md-generator__generate_agents_md,mcp__public-code-search__search_code"
prompt: |
<context>
Repository: ${{ github.repository }}
PR Number: #${{ steps.pr-info.outputs.pr_number }}
PR Title: ${{ github.event.issue.title }}
PR Author: ${{ github.event.issue.user.login }}
Comment Author: ${{ github.event.comment.user.login }}
**Note**: The PR head branch has already been checked out. The workspace is ready - you can immediately start working on the PR code.
</context>
<user_request>
${{ github.event.comment.body }}
</user_request>
<task>
You have been mentioned in a Pull Request comment. Understand the request, gather context, complete the task, and respond with results.
</task>
<constraints>
This workflow allows read, write, and execute capabilities but cannot push changes.
You CAN: Read/analyze code, modify files, write code, run tests, execute commands, resolve review threads
You CANNOT: Commit code, push changes, create branches, checkout branches, create pull requests
**Important**: You cannot push changes to the repository - you can only make changes locally and provide feedback or recommendations.
</constraints>
<allowed_tools>
You have access to the following tools (comma-separated list):
Edit,MultiEdit,Glob,Grep,LS,Read,Write,WebSearch,WebFetch,mcp__github_comment__update_claude_comment,mcp__github_ci__get_ci_status,mcp__github_ci__get_workflow_run_details,mcp__github_ci__download_job_log,Bash(*),mcp__agents-md-generator__generate_agents_md,mcp__public-code-search__search_code
You can only use tools that are explicitly listed above. For Bash commands, the pattern `Bash(command:*)` means you can run that command with any arguments. If a command is not listed, it is not available.
</allowed_tools>
<getting_started>
Use `mcp__agents-md-generator__generate_agents_md` to get repository context before responding.
</getting_started>
<investigation_approach>
Be thorough in your investigations:
- Understand the full context of the repository
- Review related code, issues, and PRs
- Consider edge cases and implications
- Gather all relevant information before responding
Available tools:
- `mcp__public-code-search__search_code`: Search code in OTHER repositories (use `Grep`/`Read` for this repo)
- `WebSearch`: Search the web for documentation, best practices, or solutions
- `WebFetch`: Fetch and read content from URLs
</investigation_approach>
<common_tasks>
- Address review feedback and fix issues (make changes locally, cannot push)
- Answer questions about the changes
- Make additional code changes (local only)
- Resolve review threads after addressing feedback (if changes are made separately)
- Perform PR reviews when asked (use the PR review process below)
</common_tasks>
<pr_review_guidance>
When asked to review this PR, follow this structured review process.
The `$PR_REVIEW_HELPERS_DIR` environment variable is pre-configured for all scripts below.
<review_process>
Follow these steps in order:
**Step 1: Gather context**
- Use `mcp__agents-md-generator__generate_agents_md` to get repository context
(if this fails, explore the repository to understand the codebase — read key files like README, CONTRIBUTING, etc.)
- Run `$PR_REVIEW_HELPERS_DIR/pr-existing-comments.sh --summary` to see existing review threads per file
- Run `$PR_REVIEW_HELPERS_DIR/pr-diff.sh` to see changed files with line-numbered diffs
(for large PRs, this lists files only — review each with `pr-diff.sh <filename>`)
**Step 2: Review each file**
For each changed file:
a. If the summary showed existing threads for this file, first run:
`$PR_REVIEW_HELPERS_DIR/pr-existing-comments.sh --file <path>`
Read the full thread details. The output uses these conventions:
- `← has replies` — a conversation happened; read carefully before commenting
- `[truncated]` — comment was cut short; add `--full` if you need the complete text to understand the comment
- `[abc1234]` — commit the comment was made on; use `git show abc1234` if needed
- `~42` — approximate line from an older revision (exact line no longer maps to current diff)
b. Review the diff. Use `Read` to see full file contents when you need more context.
Identify issues matching review_criteria. Do NOT flag:
- Issues in unchanged code (only review the diff)
- Style preferences handled by linters
- Pre-existing issues not introduced by this PR
- Issues already covered by existing threads (see below)
**Existing thread rules** (check BEFORE leaving any comment):
- Resolved with reviewer reply → reviewer's decision is final. Do NOT re-flag.
Examples: "It should remain as X", "This is intentional", "No need to do this change"
- Resolved without reply → author likely fixed it. Do NOT re-raise unless the fix introduced a new problem.
- Unresolved → already flagged. Do NOT re-comment. Mention in review body if you have more to add.
- Outdated → code changed. Only re-flag if the issue still applies to the current diff.
When in doubt, do not duplicate. Redundant comments erode trust in the review process.
**Step 3: Leave comments for NEW issues only**
For each genuinely new issue not covered by existing threads:
```bash
$PR_REVIEW_HELPERS_DIR/pr-comment.sh <file> <line> \
--severity <critical|high|medium|low|nitpick> \
--title "Brief description" \
--why "Risk or impact" <<'EOF'
corrected code here
EOF
```
Always provide suggestion code. Use `--no-suggestion` only when the fix requires
changes across multiple locations. Broader architectural concerns belong in the
review body, not inline comments.
To remove a queued comment: `$PR_REVIEW_HELPERS_DIR/pr-remove-comment.sh <file> <line>`
**Step 4: Submit the review**
```bash
$PR_REVIEW_HELPERS_DIR/pr-review.sh <APPROVE|REQUEST_CHANGES|COMMENT> "<review body>"
```
- REQUEST_CHANGES: Any 🔴 CRITICAL or 🟠 HIGH issues found
- COMMENT: 🟡 MEDIUM issues found (but no critical/high)
- APPROVE: No issues, or only ⚪ LOW / 💬 NITPICK suggestions
The review body should include broader architectural concerns not suited for inline comments.
Avoid summarizing the PR or offering praise. If approving with no issues, omit the review body.
A standard footer is automatically appended to all comments and reviews.
</review_process>
<severity_classification>
🔴 CRITICAL - Must fix before merge (security vulnerabilities, data corruption, production-breaking bugs)
🟠 HIGH - Should fix before merge (logic errors, missing validation, significant performance issues)
🟡 MEDIUM - Address soon, non-blocking (error handling gaps, suboptimal patterns, missing edge cases)
⚪ LOW - Author discretion, non-blocking (minor improvements, documentation, style not covered by linters)
💬 NITPICK - Truly optional (stylistic preferences, alternative approaches — safe to ignore)
</severity_classification>
<review_criteria>
Focus on these categories, in priority order:
1. Security vulnerabilities (injection, XSS, auth bypass, secrets exposure)
2. Logic bugs that could cause runtime failures or incorrect behavior
3. Data integrity issues (race conditions, missing transactions, corruption risk)
4. Performance bottlenecks (N+1 queries, memory leaks, blocking operations)
5. Error handling gaps (unhandled exceptions, missing validation)
6. Breaking changes to public APIs without migration path
7. Missing or incorrect test coverage for critical paths
</review_criteria>
</pr_review_guidance>
<review_thread_tools>
View unresolved review threads:
```bash
$MENTION_SCRIPTS/gh-get-review-threads.sh
```
Filter for unresolved threads from a specific reviewer:
```bash
$MENTION_SCRIPTS/gh-get-review-threads.sh "reviewer-username"
```
Resolve a review thread after addressing feedback:
```bash
$MENTION_SCRIPTS/gh-resolve-review-thread.sh "THREAD_ID" "Fixed by updating the error handling"
```
- `THREAD_ID` is the GraphQL node ID from the review threads output (e.g., `PRRT_kwDOABC123`)
- The comment is optional - use it to explain what you did
Note: Since you cannot push changes, you can resolve threads to acknowledge feedback, but actual fixes would need to be applied separately.
</review_thread_tools>
<response_guidelines>
- Be concise and actionable
- If the request is unclear, ask clarifying questions
- If the request requires actions you cannot perform (like pushing changes), explain what you can and cannot do
- When making code changes, explain that they are local only and cannot be pushed
**When performing a PR review**: Your substantive feedback belongs in the PR review submission
(via pr-review.sh), not in the comment response. The comment should only report:
- That you've submitted the review (with the outcome: approved, requested changes, etc.)
- Any issues encountered during the review process
- Brief status updates
Do NOT duplicate the review content in your comment - the review itself contains all the details.
Keep the comment short, e.g., "I've submitted my review requesting changes. See the review for details."
</response_guidelines>
<response_footer>
Always end your comment with a new line, three dashes, and the footer message:
<exact_content>
---
Marvin Context Protocol | Type `/marvin` to interact further
Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.
</exact_content>
</response_footer>
<github_formatting>
When writing GitHub comments, wrap branch names, tags, or other @-references in backticks (e.g., `@main`, `@v1.0`) to avoid accidentally pinging users. Do not add backticks around terms that are already inside backticks or code blocks.
</github_formatting>
================================================
FILE: .github/workflows/marvin-dedupe-issues.yml
================================================
name: Marvin Issue Dedupe
# description: Automatically dedupe GitHub issues using Marvin
on:
issues:
types: [opened]
workflow_dispatch:
inputs:
issue_number:
description: "Issue number to process for duplicate detection"
required: true
type: string
jobs:
marvin-dedupe-issues:
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
issues: write
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Generate Marvin App token
id: marvin-token
uses: actions/create-github-app-token@v3
with:
app-id: ${{ secrets.MARVIN_APP_ID }}
private-key: ${{ secrets.MARVIN_APP_PRIVATE_KEY }}
- name: Set dedupe prompt
id: dedupe-prompt
run: |
cat >> $GITHUB_OUTPUT << 'EOF'
PROMPT<<PROMPT_END
Find up to 3 likely duplicate issues for GitHub issue ${{ github.repository }}/issues/${{ github.event.issue.number || inputs.issue_number }}.
Follow these steps precisely:
1. Check if the GitHub issue (a) is closed, (b) does not need to be deduped (eg. because it is broad product feedback without a specific solution, or positive feedback), or (c) already has a duplicates comment that you made earlier. If so, do not proceed.
2. View the GitHub issue and produce a summary of the issue
3. Then, launch 3 parallel agents using the Task tool to search GitHub for duplicates of this issue, using diverse keywords and search approaches, using the summary from step 2
4. Next, consider the results from steps 2 and 3 and filter out false positives that are likely not actually duplicates of the original issue. Be conservative — only flag issues that describe the same underlying problem, not issues that merely share keywords or involve the same subsystem. If there are no duplicates remaining, do not proceed.
5. Finally, comment back on the issue with a list of up to three duplicate issues (or zero, if there are no likely duplicates). If there are no duplicates, DO NOT COMMENT. Just exit. Do NOT add any labels — labeling is handled by a later workflow step.
Notes for your agents:
- Use `gh` to interact with GitHub, rather than web fetch
- Do not use other tools, beyond `gh` and Task (eg. don't use other MCP servers, file edit, etc.)
- Make a todo list first
- Never include this issue as a duplicate of itself
For your comment, follow this format precisely (example with 3 suspected duplicates):
---
Found 3 possible duplicate issues:
1. #123: Issue title here
2. #456: Another issue title
3. #789: Third issue title
This issue will be automatically closed as a duplicate in 3 days.
- If your issue is a duplicate, please close it and 👍 the existing issue instead
- To prevent auto-closure, add a comment or 👎 this comment
---
PROMPT_END
EOF
- name: Clean up stale Claude locks
run: rm -rf ~/.claude/.locks ~/.local/state/claude/locks || true
- name: Run Marvin dedupe command
uses: anthropics/claude-code-action@v1
with:
github_token: ${{ steps.marvin-token.outputs.token }}
bot_name: "Marvin Context Protocol"
prompt: ${{ steps.dedupe-prompt.outputs.PROMPT }}
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY_FOR_CI }}
allowed_non_write_users: "*"
claude_args: |
--allowedTools Bash(gh issue view:*),Bash(gh search:*),Bash(gh issue list:*),Bash(gh api:*),Bash(gh issue comment:*),Task
settings: |
{
"model": "claude-sonnet-4-6",
"env": {
"GH_TOKEN": "${{ steps.marvin-token.outputs.token }}"
}
}
- name: Add potential-duplicate label if bot commented in this run
env:
GH_TOKEN: ${{ steps.marvin-token.outputs.token }}
run: |
ISSUE=${{ github.event.issue.number || inputs.issue_number }}
# Only match bot comments created in the last 10 minutes (this run)
CUTOFF=$(date -u -d '10 minutes ago' '+%Y-%m-%dT%H:%M:%SZ' 2>/dev/null \
|| date -u -v-10M '+%Y-%m-%dT%H:%M:%SZ')
HAS_RECENT=$(gh api "repos/${{ github.repository }}/issues/${ISSUE}/comments?sort=created&direction=desc&per_page=10" \
--jq "[.[] | select(
.user.type == \"Bot\" and
(.body | test(\"possible duplicate issues\"; \"i\")) and
.created_at >= \"${CUTOFF}\"
)] | length")
if [ "$HAS_RECENT" -gt 0 ]; then
gh issue edit "$ISSUE" --add-label "potential-duplicate" -R "${{ github.repository }}"
echo "Added potential-duplicate label to #${ISSUE}"
else
echo "No recent duplicate comment found, skipping label"
fi
================================================
FILE: .github/workflows/marvin-label-triage.yml
================================================
name: Marvin Label Triage
# Automatically triage GitHub issues and PRs using Marvin
on:
issues:
types: [opened]
pull_request_target:
types: [opened]
workflow_dispatch:
inputs:
issue_number:
description: "Issue or PR number to triage"
required: true
type: string
concurrency:
group: triage-${{ github.event.issue.number || github.event.pull_request.number || inputs.issue_number }}
cancel-in-progress: false
jobs:
label-issue-or-pr:
if: github.actor != 'dependabot[bot]'
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
issues: write
pull-requests: write
steps:
- name: Checkout base repository
uses: actions/checkout@v6
with:
repository: ${{ github.repository }}
ref: ${{ github.event.repository.default_branch }}
- name: Generate Marvin App token
id: marvin-token
uses: actions/create-github-app-token@v3
with:
app-id: ${{ secrets.MARVIN_APP_ID }}
private-key: ${{ secrets.MARVIN_APP_PRIVATE_KEY }}
owner: PrefectHQ
- name: Set triage prompt
id: triage-prompt
run: |
cat >> $GITHUB_OUTPUT << 'EOF'
PROMPT<<PROMPT_END
You're an issue triage assistant for FastMCP, a Python framework for building Model Context Protocol servers and clients. Your task is to analyze issues/PRs and apply appropriate labels.
IMPORTANT: Your primary action should be to apply labels using mcp__github__update_issue. DO NOT post comments EXCEPT when applying the too-long label (see below).
Issue/PR Information:
- REPO: ${{ github.repository }}
- NUMBER: ${{ github.event.issue.number || github.event.pull_request.number || inputs.issue_number }}
- TYPE: ${{ github.event.issue && 'issue' || (github.event.pull_request && 'pull_request') || 'unknown' }}
TRIAGE PROCESS:
1. Get available labels:
Run: `gh label list`
2. Retrieve issue/PR details using GitHub tools:
- mcp__github__get_issue: Get the issue/PR details
- mcp__github__get_issue_comments: Read any discussion
- If the issue/PR mentions other issues (e.g., "fixes #123", "related to #456"), use mcp__github__get_issue to read those linked issues for additional context
3. Analyze and apply labels based on these guidelines:
CORE CATEGORIES (apply EXACTLY ONE - these are mutually exclusive; skip if applying too-long):
- bug: Reports of broken functionality OR PRs that fix bugs
- enhancement: New functions/endpoints, improvements to existing features, internal tooling, workflow improvements, minor new capabilities
- feature: ONLY for major headline functionality worthy of a blog post announcement (2-4 per release, never for issues)
- documentation: Primary change is to user-facing docs, examples, or guides
SPECIAL DOCUMENTATION RULES:
- DO NOT apply "documentation" label if PR only updates auto-generated SDK docs (docs/python-sdk/**)
- DO apply "documentation" label for significant user-facing documentation changes (guides, examples, API docs)
- Auto-generated docs updates should get appropriate category label (enhancement, bug, etc.) based on the underlying code changes
FEATURE vs ENHANCEMENT guidance:
- feature: Major systems like new auth systems, MCP composition, proxying MCP servers, major CLI commands that transform workflows
- enhancement: New functions/endpoints, internal workflows, CI improvements, developer tooling, refactoring, utilities, typical new CLI commands
- If unsure between feature/enhancement, choose enhancement
Note: If a PR fixes a bug, label it "bug" not "enhancement"
SPECIAL CATEGORY (can be combined with above):
- breaking change: Changes that break backward compatibility (in addition to core category)
PRIORITY (apply if clearly evident):
- high-priority: Critical bugs affecting many users, security issues, or blocking core functionality
- low-priority: Edge cases, nice-to-have improvements, or cosmetic issues
- Default to no priority label if unclear
STATUS (apply if applicable):
- needs more info: Issue lacks reproduction steps, error messages, or clear description
- invalid: Spam, completely off-topic, or nonsensical (often LLM-generated)
- too-long: Issue/PR goes beyond what the contributor guidelines ask for. Typical signs: "Root cause" or "Fix" sections, proposed code changes, multi-step diagnostic writeups, speculative analysis, or structured reports that read like LLM output. The contributor guidelines ask for a short problem description and an MRE — anything beyond that (unless it reflects genuine, non-obvious investigation) is too much. This applies even when the extra content is accurate — unsolicited diagnosis transfers triage burden to maintainers. Apply this label and do not apply other triage labels. The author needs to condense before triage is worthwhile.
WHEN APPLYING too-long: After labeling, post a brief comment using mcp__github__add_issue_comment:
"Thanks for the report. This issue goes beyond what our contributor guidelines ask for — we just need a short problem description and an MRE. Please see [our pinned guidelines](https://github.com/PrefectHQ/fastmcp/issues/3506) and condense this issue. We'll triage it once it's trimmed down."
Use this exact text (or very close to it). Do not editorialize or add details.
AREA LABELS (apply ONLY when thematically central to the issue):
- cli: Issues primarily about FastMCP CLI commands (run, dev, install)
- client: Issues primarily about the Client SDK or client-side functionality
- server: Issues primarily about FastMCP server implementation
- auth: Authentication is the main concern (Bearer, JWT, OAuth, WorkOS)
- openapi: OpenAPI integration/parsing is the primary topic
- http: HTTP transport or networking is the main issue
- contrib: Specifically about community contributions in src/contrib/
- tests: Issues primarily about testing infrastructure, CI/CD workflows, or test coverage
- security: Apply ONLY when the issue/PR addresses an exploitable vulnerability or hardens against one. Examples: SSRF, LFI, path traversal, injection, auth bypass allowing unauthorized access, scope escalation, open redirects. Do NOT apply for ordinary auth bugs (wrong scopes returned, token refresh logic, OAuth flow correctness) unless an attacker could exploit the bug to bypass access controls or escalate privileges. The key question: "Could a malicious actor exploit this?" If the answer is just "it breaks for legitimate users," that's a bug, not a security issue.
IMPORTANT LABELING RULES:
- Be selective - only apply labels that are clearly relevant
- Don't apply area labels just because a file in that area is mentioned
- The issue must be PRIMARILY about that area to get the label
- When in doubt, don't apply the label
- Apply 2-5 labels total typically (category + maybe priority + maybe 1-2 areas)
META LABELS (rarely needed for issues):
- dependencies: Only for dependabot PRs or issues specifically about package updates
- DON'T MERGE: Only if PR author explicitly states it's not ready
4. Apply selected labels:
Use mcp__github__update_issue to apply your selected labels
DO NOT post any comments unless applying too-long (see above)
PROMPT_END
EOF
- name: Clean up stale Claude locks
run: rm -rf ~/.claude/.locks ~/.local/state/claude/locks || true
- name: Run Marvin for Issue Triage
uses: anthropics/claude-code-action@v1
with:
github_token: ${{ steps.marvin-token.outputs.token }}
bot_name: "Marvin Context Protocol"
prompt: ${{ steps.triage-prompt.outputs.PROMPT }}
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY_FOR_CI }}
allowed_non_write_users: "*"
allowed_bots: "marvin-context-protocol"
claude_args: |
--allowedTools Bash(gh label list),mcp__github__get_issue,mcp__github__get_issue_comments,mcp__github__update_issue,mcp__github__add_issue_comment,mcp__github__get_pull_request_files
settings: |
{
"model": "claude-sonnet-4-6",
"env": {
"GH_TOKEN": "${{ steps.marvin-token.outputs.token }}"
}
}
================================================
FILE: .github/workflows/minimize-resolved-reviews.yml
================================================
# Minimize resolved PR review comments to reduce noise.
#
# Runs automatically on review activity for same-repo PRs. Fork PRs are
# skipped because GITHUB_TOKEN is read-only in that context. Collaborators
# can comment "/tidy" on any PR (including forks) to trigger manually.
name: Minimize Resolved Reviews
on:
pull_request_review:
types: [submitted]
pull_request_review_comment:
types: [created, edited]
issue_comment:
types: [created]
concurrency:
group: minimize-reviews-${{ github.event.pull_request.number || github.event.issue.number }}
cancel-in-progress: true
permissions:
pull-requests: write
jobs:
minimize:
# /tidy comment: collaborators can trigger on any PR (token has write access)
# Review events: skip fork PRs where GITHUB_TOKEN lacks write permissions
if: >-
(
github.event_name == 'issue_comment' &&
github.event.issue.pull_request &&
contains(github.event.comment.body, '/tidy') &&
contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association)
) || (
github.event_name != 'issue_comment' &&
github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name
)
runs-on: ubuntu-latest
steps:
- name: Minimize resolved review comments
uses: strawgate/minimize-resolved-pr-reviews@v0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
================================================
FILE: .github/workflows/publish.yml
================================================
name: Publish FastMCP to PyPI
on:
release:
types: [published]
workflow_dispatch:
jobs:
pypi-publish:
name: Upload to PyPI
runs-on: ubuntu-latest
permissions:
id-token: write # For PyPI's trusted publishing
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: "Install uv"
uses: astral-sh/setup-uv@v7
- name: Build
run: uv build
- name: Publish to PyPi
run: uv publish -v dist/*
================================================
FILE: .github/workflows/run-static.yml
================================================
name: Run static analysis
env:
PY_COLORS: 1
on:
push:
branches: ["main"]
paths:
- "src/**"
- "tests/**"
- "uv.lock"
- "pyproject.toml"
- ".github/workflows/**"
# run on all pull requests because these checks are required and will block merges otherwise
pull_request:
workflow_dispatch:
permissions:
contents: read
jobs:
static_analysis:
timeout-minutes: 2
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Setup uv
uses: ./.github/actions/setup-uv
with:
resolution: locked
- name: Run prek
uses: j178/prek-action@v1
env:
SKIP: no-commit-to-branch
================================================
FILE: .github/workflows/run-tests.yml
================================================
name: Tests
env:
PY_COLORS: 1
on:
push:
branches: ["main"]
paths:
- "src/**"
- "tests/**"
- "uv.lock"
- "pyproject.toml"
- ".github/workflows/**"
# run on all pull requests because these checks are required and will block merges otherwise
pull_request:
workflow_dispatch:
permissions:
contents: read
jobs:
run_tests:
name: "Tests: Python ${{ matrix.python-version }} on ${{ matrix.os }}"
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
python-version: ["3.10"]
include:
- os: ubuntu-latest
python-version: "3.13"
fail-fast: false
timeout-minutes: 10
steps:
- uses: actions/checkout@v6
- name: Setup uv
uses: ./.github/actions/setup-uv
with:
python-version: ${{ matrix.python-version }}
resolution: locked
- name: Run unit tests
uses: ./.github/actions/run-pytest
- name: Run client process tests
uses: ./.github/actions/run-pytest
with:
test-type: client_process
run_tests_lowest_direct:
name: "Tests with lowest-direct dependencies"
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v6
- name: Setup uv (lowest-direct)
uses: ./.github/actions/setup-uv
with:
resolution: lowest-direct
- name: Run unit tests
uses: ./.github/actions/run-pytest
- name: Run client process tests
uses: ./.github/actions/run-pytest
with:
test-type: client_process
run_integration_tests:
name: "Integration tests"
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v6
- name: Setup uv
uses: ./.github/actions/setup-uv
with:
resolution: locked
- name: Run integration tests
uses: ./.github/actions/run-pytest
with:
test-type: integration
env:
FASTMCP_GITHUB_TOKEN: ${{ secrets.FASTMCP_GITHUB_TOKEN }}
FASTMCP_TEST_AUTH_GITHUB_CLIENT_ID: ${{ secrets.FASTMCP_TEST_AUTH_GITHUB_CLIENT_ID }}
FASTMCP_TEST_AUTH_GITHUB_CLIENT_SECRET: ${{ secrets.FASTMCP_TEST_AUTH_GITHUB_CLIENT_SECRET }}
================================================
FILE: .github/workflows/run-upgrade-checks.yml
================================================
name: Upgrade checks
env:
PY_COLORS: 1
on:
push:
branches: ["main"]
paths:
- "src/**"
- "tests/**"
- "uv.lock"
- "pyproject.toml"
- ".github/workflows/**"
schedule:
# Run daily at 2 AM UTC
- cron: "0 2 * * *"
workflow_dispatch:
permissions:
contents: read
issues: write
jobs:
static_analysis:
name: Static analysis
timeout-minutes: 2
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Setup uv (upgrade)
uses: ./.github/actions/setup-uv
with:
resolution: upgrade
- name: Run prek
uses: j178/prek-action@v1
env:
SKIP: no-commit-to-branch
run_tests:
name: "Tests: Python ${{ matrix.python-version }} on ${{ matrix.os }}"
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
python-version: ["3.10"]
include:
- os: ubuntu-latest
python-version: "3.13"
fail-fast: false
timeout-minutes: 10
steps:
- uses: actions/checkout@v6
- name: Setup uv (upgrade)
uses: ./.github/actions/setup-uv
with:
python-version: ${{ matrix.python-version }}
resolution: upgrade
- name: Run unit tests
uses: ./.github/actions/run-pytest
- name: Run client process tests
uses: ./.github/actions/run-pytest
with:
test-type: client_process
run_integration_tests:
name: "Integration tests"
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v6
- name: Setup uv (upgrade)
uses: ./.github/actions/setup-uv
with:
resolution: upgrade
- name: Run integration tests
uses: ./.github/actions/run-pytest
with:
test-type: integration
env:
FASTMCP_GITHUB_TOKEN: ${{ secrets.FASTMCP_GITHUB_TOKEN }}
FASTMCP_TEST_AUTH_GITHUB_CLIENT_ID: ${{ secrets.FASTMCP_TEST_AUTH_GITHUB_CLIENT_ID }}
FASTMCP_TEST_AUTH_GITHUB_CLIENT_SECRET: ${{ secrets.FASTMCP_TEST_AUTH_GITHUB_CLIENT_SECRET }}
notify:
name: Notify on failure
needs: [static_analysis, run_tests, run_integration_tests]
if: failure() && github.event.pull_request == null
runs-on: ubuntu-latest
steps:
- name: Create or update failure issue
uses: jayqi/failed-build-issue-action@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
label: "build failed"
title-template: "Upgrade checks failing on main branch"
body-template: |
## Upgrade Checks Failure on Main Branch
The upgrade checks workflow has failed on the main branch.
**Workflow Run**: [#{{runNumber}}]({{serverUrl}}/{{repo.owner}}/{{repo.repo}}/actions/runs/{{runId}})
**Commit**: {{sha}}
**Branch**: {{ref}}
**Event**: {{eventName}}
### Common causes
- **ty (type checker)**: New ty releases frequently add stricter checks that flag previously-accepted code. Run `uv run ty check` locally with the latest ty to reproduce. Fix the type errors or bump the ty version floor in `pyproject.toml`.
- **ruff**: New lint rules or stricter defaults in a ruff upgrade.
- **mcp SDK**: Breaking changes in the `mcp` package (new method signatures, renamed types).
### What to do
1. Check the workflow logs to identify which job failed (static analysis vs tests)
2. Reproduce locally with `uv sync --upgrade && uv run prek run --all-files && uv run pytest -n auto`
3. Fix the code or adjust dependency constraints as needed
---
*This issue was automatically created by a GitHub Action.*
close-on-success:
name: Close issue on success
needs: [static_analysis, run_tests, run_integration_tests]
if: success() && github.event.pull_request == null && github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- name: Close resolved failure issue
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
issue=$(gh issue list \
--repo "$GITHUB_REPOSITORY" \
--label "build failed" \
--state open \
--json number \
--jq '.[0].number // empty')
if [ -n "$issue" ]; then
gh issue close "$issue" \
--repo "$GITHUB_REPOSITORY" \
--comment "Upgrade checks are passing again as of [\`${GITHUB_SHA::7}\`](${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/commit/${GITHUB_SHA})."
fi
================================================
FILE: .github/workflows/update-config-schema.yml
================================================
name: Update MCPServerConfig Schema
# Regenerates config schema on pushes to main and opens a long-lived PR
# with the changes, so contributor PRs stay clean.
on:
push:
branches: ["main"]
paths:
- "src/fastmcp/utilities/mcp_server_config/**"
- "!src/fastmcp/utilities/mcp_server_config/v1/schema.json"
workflow_dispatch:
permissions:
contents: write
pull-requests: write
jobs:
update-config-schema:
timeout-minutes: 5
runs-on: ubuntu-latest
steps:
- name: Generate Marvin App token
id: marvin-token
uses: actions/create-github-app-token@v3
with:
app-id: ${{ secrets.MARVIN_APP_ID }}
private-key: ${{ secrets.MARVIN_APP_PRIVATE_KEY }}
- uses: actions/checkout@v6
with:
token: ${{ steps.marvin-token.outputs.token }}
- name: Install uv
uses: astral-sh/setup-uv@v7
with:
enable-cache: true
cache-dependency-glob: "uv.lock"
- name: Install dependencies
run: uv sync --python 3.12
- name: Generate config schema
run: |
uv run python -c "
from fastmcp.utilities.mcp_server_config import generate_schema
generate_schema('docs/public/schemas/fastmcp.json/latest.json')
generate_schema('docs/public/schemas/fastmcp.json/v1.json')
generate_schema('src/fastmcp/utilities/mcp_server_config/v1/schema.json')
"
- name: Create Pull Request
uses: peter-evans/create-pull-request@v8
with:
token: ${{ steps.marvin-token.outputs.token }}
commit-message: "chore: Update fastmcp.json schema"
title: "chore: Update fastmcp.json schema"
body: |
This PR updates the fastmcp.json schema files to match the current source code.
The schema is automatically generated from `src/fastmcp/utilities/mcp_server_config/` to ensure consistency.
**Note:** This PR is fully automated and will update itself with any subsequent changes to the schema, or close automatically if the schema becomes up-to-date through other means.
🤖 Generated by Marvin
branch: marvin/update-config-schema
labels: |
ignore in release notes
delete-branch: true
author: "marvin-context-protocol[bot] <225465937+marvin-context-protocol[bot]@users.noreply.github.com>"
committer: "marvin-context-protocol[bot] <225465937+marvin-context-protocol[bot]@users.noreply.github.com>"
================================================
FILE: .github/workflows/update-sdk-docs.yml
================================================
name: Update SDK Documentation
# Regenerates SDK docs on pushes to main and opens a long-lived PR
# with the changes, so contributor PRs stay clean.
on:
push:
branches: ["main"]
paths:
- "src/**"
- "pyproject.toml"
workflow_dispatch:
permissions:
contents: write
pull-requests: write
jobs:
update-sdk-docs:
timeout-minutes: 5
runs-on: ubuntu-latest
steps:
- name: Generate Marvin App token
id: marvin-token
uses: actions/create-github-app-token@v3
with:
app-id: ${{ secrets.MARVIN_APP_ID }}
private-key: ${{ secrets.MARVIN_APP_PRIVATE_KEY }}
- uses: actions/checkout@v6
with:
token: ${{ steps.marvin-token.outputs.token }}
- name: Install uv
uses: astral-sh/setup-uv@v7
with:
enable-cache: true
cache-dependency-glob: "uv.lock"
- name: Install dependencies
run: uv sync --python 3.12
- name: Install just
uses: extractions/setup-just@v3
- name: Generate SDK documentation
run: just api-ref-all
- name: Create Pull Request
uses: peter-evans/create-pull-request@v8
with:
token: ${{ steps.marvin-token.outputs.token }}
commit-message: "chore: Update SDK documentation"
title: "chore: Update SDK documentation"
body: |
This PR updates the auto-generated SDK documentation to reflect the latest source code changes.
📚 Documentation is automatically generated from the source code docstrings and type annotations.
**Note:** This PR is fully automated and will update itself with any subsequent changes to the SDK, or close automatically if the documentation becomes up-to-date through other means. Feel free to leave it open until you're ready to merge.
🤖 Generated by Marvin
branch: marvin/update-sdk-docs
labels: |
ignore in release notes
delete-branch: true
author: "marvin-context-protocol[bot] <225465937+marvin-context-protocol[bot]@users.noreply.github.com>"
committer: "marvin-context-protocol[bot] <225465937+marvin-context-protocol[bot]@users.noreply.github.com>"
================================================
FILE: .gitignore
================================================
# Python-generated files
__pycache__/
*.py[cod]
*$py.class
build/
dist/
wheels/
*.egg-info/
*.egg
MANIFEST
.pytest_cache/
.loq_cache
.coverage
htmlcov/
.tox/
nosetests.xml
coverage.xml
*.cover
# Virtual environments
.venv
venv/
env/
ENV/
.env
# System files
.DS_Store
# Version file
src/fastmcp/_version.py
# Editors and IDEs
.cursorrules
.vscode/
.idea/
*.swp
*.swo
*~
.project
.pydevproject
.settings/
# Jupyter Notebook
.ipynb_checkpoints
# Type checking
.mypy_cache/
.dmypy.json
dmypy.json
.pyre/
.pytype/
# Local development
.python-version
.envrc
.envrc.private
.direnv/
# Logs and databases
*.log
*.sqlite
*.db
*.ddb
# Claude worktree management
.claude-wt/worktrees
.claude/worktrees/
# Agents
/PLAN.md
/TODO.md
/STATUS.md
plans/
# Common FastMCP test files
/test.py
/server.py
/client.py
/test.json
================================================
FILE: .pre-commit-config.yaml
================================================
fail_fast: false
repos:
- repo: https://github.com/abravalheri/validate-pyproject
rev: v0.24.1
hooks:
- id: validate-pyproject
- repo: https://github.com/pre-commit/mirrors-prettier
rev: v3.1.0
hooks:
- id: prettier
types_or: [yaml, json5]
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.14.10
hooks:
# Run the linter.
- id: ruff-check
args: [--fix, --exit-non-zero-on-fix]
# Run the formatter.
- id: ruff-format
- repo: local
hooks:
- id: ty
name: ty check
entry: uv run --isolated ty check
language: system
types: [python]
files: ^src/|^tests/
pass_filenames: false
require_serial: true
- id: loq
name: loq (file size limits)
entry: bash -c 'uv run loq || printf "\nloq violations not enforced... yet!\n"'
language: system
pass_filenames: false
verbose: true
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
- id: no-commit-to-branch
name: prevent commits to main
args: [--branch, main]
- repo: https://github.com/codespell-project/codespell
rev: v2.4.1
hooks:
- id: codespell # See pyproject.toml for args
additional_dependencies:
- tomli
================================================
FILE: CLAUDE.md
================================================
# FastMCP Development Guidelines
> **Audience**: LLM-driven engineering agents and human developers
> **Note**: `AGENTS.md` is a symlink to this file. Edit `CLAUDE.md` directly.
FastMCP is a comprehensive Python framework (Python ≥3.10) for building Model Context Protocol (MCP) servers and clients. This is the actively maintained v2.0 providing a complete toolkit for the MCP ecosystem.
## Required Development Workflow
**CRITICAL**: Always run these commands in sequence before committing.
```bash
uv sync # Install dependencies
uv run pytest -n auto # Run full test suite
```
In addition, you must pass static checks. This is generally done as a pre-commit hook with `prek` but you can run it manually with:
```bash
uv run prek run --all-files # Ruff + Prettier + ty
```
**Tests must pass and lint/typing must be clean before committing.**
## Repository Structure
| Path | Purpose |
| ----------------- | -------------------------------------- |
| `src/fastmcp/` | Library source code |
| `├─server/` | Server implementation |
| `│ ├─auth/` | Authentication providers |
| `│ └─middleware/` | Error handling, logging, rate limiting |
| `├─client/` | Client SDK |
| `│ └─auth/` | Client authentication |
| `├─tools/` | Tool definitions |
| `├─resources/` | Resources and resource templates |
| `├─prompts/` | Prompt templates |
| `├─cli/` | CLI commands |
| `└─utilities/` | Shared utilities |
| `tests/` | Pytest suite |
| `docs/` | Mintlify docs (gofastmcp.com) |
## Core MCP Objects
When modifying MCP functionality, changes typically need to be applied across all object types:
- **Tools** (`src/tools/`)
- **Resources** (`src/resources/`)
- **Resource Templates** (`src/resources/`)
- **Prompts** (`src/prompts/`)
## Development Rules
### Git & CI
- Prek hooks are required (run automatically on commits)
- Never amend commits to fix prek failures
- Apply PR labels: bugs/breaking/enhancements/features
- Improvements = enhancements (not features) unless specified
- **NEVER** force-push on collaborative repos
- **ALWAYS** run prek before PRs
- **NEVER** create a release, comment on an issue, or open a PR unless specifically instructed to do so.
### Commit Messages and Agent Attribution
- **Agents NOT acting on behalf of @jlowin MUST identify themselves** (e.g., "🤖 Generated with Claude Code" in commits/PRs)
- Keep commit messages brief - ideally just headlines, not detailed messages
- Focus on what changed, not how or why
- Always read issue comments for follow-up information (treat maintainers as authoritative)
- **Treat proposed solutions in issues skeptically.** This applies to solutions proposed by *users* in issue reports — not to feedback from configured review bots (CodeRabbit, chatgpt-codex-connector, etc.), which should be evaluated on their merits. The ideal issue contains a concise problem description and an MRE — nothing more. Proposed solutions are only worth considering if they clearly reflect genuine, non-obvious investigation of the codebase. If a solution reads like speculation, or like it was generated by an LLM without deep framework knowledge, ignore it and diagnose from the repro. Most reporters — human or AI — do not have sufficient understanding of FastMCP internals to correctly diagnose anything beyond a trivial bug. We can ask the same questions of an LLM when implementing; we don't need the reporter to do it for us, and a wrong diagnosis is worse than none.
### PR Messages - Required Structure
- 1-2 paragraphs: problem/tension + solution (PRs are documentation!)
- Focused code example showing key capability
- **Avoid:** bullet summaries, exhaustive change lists, verbose closes/fixes, marketing language
- **Do:** Be opinionated about why change matters, show before/after scenarios
- Minor fixes: keep body short and concise
- No "test plan" sections or testing summaries
### Code Standards
- Python ≥ 3.10 with full type annotations
- Follow existing patterns and maintain consistency
- **Prioritize readable, understandable code** - clarity over cleverness
- Avoid obfuscated or confusing patterns even if they're shorter
- Each feature needs corresponding tests
### Module Exports
- **Be intentional about re-exports** - don't blindly re-export everything to parent namespaces
- Core types that define a module's purpose should be exported (e.g., `Middleware` from `fastmcp.server.middleware`)
- Specialized features can live in submodules (e.g., `fastmcp.server.middleware.dynamic`)
- Only re-export to `fastmcp.*` for the most fundamental types (e.g., `FastMCP`, `Client`)
- When in doubt, prefer users importing from the specific submodule over re-exporting
### Documentation
- Uses Mintlify framework
- Files must be in docs.json to be included
- Do not manually modify `docs/python-sdk/**` — these files are auto-generated from source code by a bot and maintained via a long-lived PR. Do not include changes to these files in contributor PRs.
- Do not manually modify `docs/public/schemas/**` or `src/fastmcp/utilities/mcp_server_config/v1/schema.json` — these are auto-generated and maintained via a long-lived PR.
- **Core Principle:** A feature doesn't exist unless it is documented!
- When adding or modifying settings in `src/fastmcp/settings.py`, update `docs/more/settings.mdx` to match.
### Documentation Guidelines
- **Code Examples:** Explain before showing code, make blocks fully runnable (include imports)
- **Code Formatting:** Keep code blocks visually clean — avoid deeply nested function calls. Extract intermediate values into named variables rather than inlining everything into one expression. Code in docs is read more than it's run; optimize for scannability.
- **Structure:** Headers form navigation guide, logical H2/H3 hierarchy
- **Content:** User-focused sections, motivate features (why) before mechanics (how)
- **Style:** Prose over code comments for important information
- **Docstrings:** FastMCP docstrings are automatically compiled into MDX documents. Use markdown (single backticks, fenced code blocks), not RST (no double backticks). Bare `{}` in examples will be interpreted as JSX — wrap in backticks instead.
## Critical Patterns
- Never use bare `except` - be specific with exception types
- File sizes enforced by [loq](https://github.com/jakekaplan/loq). Edit `loq.toml` to raise limits; `loq baseline` to ratchet down.
- Always `uv sync` first when debugging build issues
- Default test timeout is 5s - optimize or mark as integration tests
================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
chris@prefect.io.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to FastMCP
FastMCP is an actively maintained, high-traffic project. We welcome contributions — but the most impactful way to contribute might not be what you expect.
## The best contribution is a great issue
FastMCP is an opinionated framework, and its maintainers use AI-assisted tooling that is deeply tuned to those opinions — the design philosophy, the API patterns, the way the framework is meant to evolve. A well-written issue with a clear problem description is often more valuable than a pull request, because it lets maintainers produce a solution that isn't just correct, but consistent with how the framework wants to work. That matters more than speed, though it's faster too.
**A great issue looks like this:**
1. A short, motivating description of the problem or gap
2. A minimal reproducible example (for bugs) or a concrete use case (for enhancements)
3. A brief note on expected vs. actual behavior
That's it. No need to diagnose root causes, propose API designs, or suggest implementations. If you've done genuine investigation and have a non-obvious insight, include it.
## Using AI to contribute
We encourage you to use LLMs to help identify bugs, write MREs, and prepare contributions. But if you do, your LLM must take into account the conventions and contributing guidelines of this repo — including how we want issues formatted and when it's appropriate to open a PR. Generic LLM output that ignores these guidelines tells us the contribution wasn't made thoughtfully, and we will close it. A good AI-assisted contribution is indistinguishable from a good human one. A bad one is obvious.
## When to open a pull request
**Bug fixes** — PRs are welcome for simple, well-scoped bug fixes where the problem and solution are both straightforward. "The function raises `TypeError` when passed `None` because of a missing guard" is a good candidate. If the fix requires design decisions or touches multiple subsystems, open an issue instead.
**Documentation** — Typo fixes, clarifications, and improvements to examples are always welcome as PRs.
**Enhancements and features** — For changes that affect the behavior or design of the framework, please open an issue first. Maintainers will typically implement these themselves. FastMCP is opinionated, and enhancements need to reflect those opinions — not just solve the problem, but solve it in a way that's consistent with the framework's design. That's hard to do from the outside, and it's why a clear problem description is more useful than a proposed solution.
**Integrations** — FastMCP generally does not accept PRs that add third-party integrations (custom middleware, provider-specific adapters, etc.). If you're building something for your users, ship it as a standalone package — that's a feature, not a limitation. Authentication providers are an exception, since auth is tightly coupled to the framework.
## PR guidelines
If you do open a PR:
- **Reference an issue.** Every PR should address a tracked issue. If there isn't one, open an issue first. This isn't a permission step — you don't need to wait for a response. But the issue gives us context on the problem, and if a maintainer is already working on it, we can let you know before you invest time in code.
- **Keep it focused.** One logical change per PR. Don't bundle unrelated fixes or refactors.
- **Match existing patterns.** Follow the code style, type annotation conventions, and test patterns you see in the codebase. Run `uv run prek run --all-files` before submitting.
- **Write tests.** Bug fixes should include a test that fails without the fix. Enhancements should include tests for the new behavior.
- **Don't submit generated boilerplate.** We review every line. PRs that read like unedited LLM output — verbose descriptions, speculative changes, shotgun-style fixes — will be closed.
## What we'll close without review
To keep the project maintainable, we will close PRs that:
- Don't reference an issue or address a clearly self-evident bug
- Make sweeping changes without prior discussion
- Add third-party integrations that belong in a separate package
- Are difficult to review due to size, scope, or generated content
This isn't personal. FastMCP receives a high volume of contributions and we need to focus maintainer time where it has the most impact — which is why a good issue is often the best thing you can do for the project.
================================================
FILE: LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: README.md
================================================
<div align="center">
<!-- omit in toc -->
<picture>
<source width="550" media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/PrefectHQ/fastmcp/main/docs/assets/brand/f-watercolor-waves-4-dark.png">
<source width="550" media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/PrefectHQ/fastmcp/main/docs/assets/brand/f-watercolor-waves-4.png">
<img width="550" alt="FastMCP Logo" src="https://raw.githubusercontent.com/PrefectHQ/fastmcp/main/docs/assets/brand/f-watercolor-waves-2.png">
</picture>
# FastMCP 🚀
<strong>Move fast and make things.</strong>
*Made with 💙 by [Prefect](https://www.prefect.io/)*
[](https://gofastmcp.com)
[](https://discord.gg/uu8dJCgttd)
[](https://pypi.org/project/fastmcp)
[](https://github.com/PrefectHQ/fastmcp/actions/workflows/run-tests.yml)
[](https://github.com/PrefectHQ/fastmcp/blob/main/LICENSE)
<a href="https://trendshift.io/repositories/13266" target="_blank"><img src="https://trendshift.io/api/badge/repositories/13266" alt="prefecthq%2Ffastmcp | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
</div>
---
The [Model Context Protocol](https://modelcontextprotocol.io/) (MCP) connects LLMs to tools and data. FastMCP gives you everything you need to go from prototype to production:
```python
from fastmcp import FastMCP
mcp = FastMCP("Demo 🚀")
@mcp.tool
def add(a: int, b: int) -> int:
"""Add two numbers"""
return a + b
if __name__ == "__main__":
mcp.run()
```
## Why FastMCP
Building an effective MCP application is harder than it looks. FastMCP handles all of it. Declare a tool with a Python function, and the schema, validation, and documentation are generated automatically. Connect to a server with a URL, and transport negotiation, authentication, and protocol lifecycle are managed for you. You focus on your logic, and the MCP part just works: **with FastMCP, best practices are built in.**
**That's why FastMCP is the standard framework for working with MCP.** FastMCP 1.0 was incorporated into the official MCP Python SDK in 2024. Today, the actively maintained standalone project is downloaded a million times a day, and some version of FastMCP powers 70% of MCP servers across all languages.
FastMCP has three pillars:
<table>
<tr>
<td align="center" valign="top" width="33%">
<a href="https://gofastmcp.com/servers/server">
<img src="https://raw.githubusercontent.com/PrefectHQ/fastmcp/main/docs/assets/images/servers-card.png" alt="Servers" />
<br /><strong>Servers</strong>
</a>
<br />Expose tools, resources, and prompts to LLMs.
</td>
<td align="center" valign="top" width="33%">
<a href="https://gofastmcp.com/apps/overview">
<img src="https://raw.githubusercontent.com/PrefectHQ/fastmcp/main/docs/assets/images/apps-card.png" alt="Apps" />
<br /><strong>Apps</strong>
</a>
<br />Give your tools interactive UIs rendered directly in the conversation.
</td>
<td align="center" valign="top" width="33%">
<a href="https://gofastmcp.com/clients/client">
<img src="https://raw.githubusercontent.com/PrefectHQ/fastmcp/main/docs/assets/images/clients-card.png" alt="Clients" />
<br /><strong>Clients</strong>
</a>
<br />Connect to any MCP server — local or remote, programmatic or CLI.
</td>
</tr>
</table>
**[Servers](https://gofastmcp.com/servers/server)** wrap your Python functions into MCP-compliant tools, resources, and prompts. **[Clients](https://gofastmcp.com/clients/client)** connect to any server with full protocol support. And **[Apps](https://gofastmcp.com/apps/overview)** give your tools interactive UIs rendered directly in the conversation.
Ready to build? Start with the [installation guide](https://gofastmcp.com/getting-started/installation) or jump straight to the [quickstart](https://gofastmcp.com/getting-started/quickstart). When you're ready to deploy, [Prefect Horizon](https://www.prefect.io/horizon) offers free hosting for FastMCP users.
## Installation
We recommend installing FastMCP with [uv](https://docs.astral.sh/uv/):
```bash
uv pip install fastmcp
```
For full installation instructions, including verification and upgrading, see the [**Installation Guide**](https://gofastmcp.com/getting-started/installation).
**Upgrading?** We have guides for:
- [Upgrading from FastMCP v2](https://gofastmcp.com/getting-started/upgrading/from-fastmcp-2)
- [Upgrading from the MCP Python SDK](https://gofastmcp.com/getting-started/upgrading/from-mcp-sdk)
- [Upgrading from the low-level SDK](https://gofastmcp.com/getting-started/upgrading/from-low-level-sdk)
## 📚 Documentation
FastMCP's complete documentation is available at **[gofastmcp.com](https://gofastmcp.com)**, including detailed guides, API references, and advanced patterns.
Documentation is also available in [llms.txt format](https://llmstxt.org/), which is a simple markdown standard that LLMs can consume easily:
- [`llms.txt`](https://gofastmcp.com/llms.txt) is essentially a sitemap, listing all the pages in the documentation.
- [`llms-full.txt`](https://gofastmcp.com/llms-full.txt) contains the entire documentation. Note this may exceed the context window of your LLM.
**Community:** Join our [Discord server](https://discord.gg/uu8dJCgttd) to connect with other FastMCP developers and share what you're building.
## Contributing
We welcome contributions! See the [Contributing Guide](https://gofastmcp.com/development/contributing) for setup instructions, testing requirements, and PR guidelines.
================================================
FILE: SECURITY.md
================================================
# Security Policy
## Supported Versions
| Version | Supported |
| ------- | ------------------ |
| 3.x | :white_check_mark: |
| 2.x | :x: |
| 1.x | :x: |
| 0.x | :x: |
## Reporting a Vulnerability
Please report security vulnerabilities privately using [GitHub's security advisory feature](https://github.com/PrefectHQ/fastmcp/security/advisories/new). Do not open public issues for security concerns.
## Scope
We accept reports for vulnerabilities in FastMCP itself — the library code in this repository.
The following are **out of scope**:
- Vulnerabilities in third-party dependencies or the MCP SDK itself. We'll bump version floors for known CVEs, but the fix belongs upstream.
- Limitations of upstream identity providers that FastMCP cannot control.
- Issues that require the attacker to already have server-side access or control of the MCP server configuration.
## Disclosure Process
When we receive a valid report:
1. We triage the report and determine whether it affects FastMCP directly.
2. We develop and test a fix on a private branch.
3. We coordinate CVE assignment through GitHub's advisory process when warranted.
4. We publish the advisory and release a patched version.
5. We credit the reporter in the advisory (unless they prefer otherwise).
================================================
FILE: docs/.ccignore
================================================
changelog.mdx
python-sdk/
================================================
FILE: docs/.cursor/rules/mintlify.mdc
================================================
---
description:
globs: *.mdx
alwaysApply: false
---
# Mintlify technical writing assistant
You are an AI writing assistant specialized in creating exceptional technical documentation using Mintlify components and following industry-leading technical writing practices.
## Core writing principles
### Language and style requirements
- Use clear, direct language appropriate for technical audiences
- Write in second person ("you") for instructions and procedures
- Use active voice over passive voice
- Employ present tense for current states, future tense for outcomes
- Maintain consistent terminology throughout all documentation
- Keep sentences concise while providing necessary context
- Use parallel structure in lists, headings, and procedures
### Content organization standards
- Lead with the most important information (inverted pyramid structure)
- Use progressive disclosure: basic concepts before advanced ones
- Break complex procedures into numbered steps
- Include prerequisites and context before instructions
- Provide expected outcomes for each major step
- End sections with next steps or related information
- Use descriptive, keyword-rich headings for navigation and SEO
### User-centered approach
- Focus on user goals and outcomes rather than system features
- Anticipate common questions and address them proactively
- Include troubleshooting for likely failure points
- Provide multiple pathways when appropriate (beginner vs advanced), but offer an opinionated path for people to follow to avoid overwhelming with options
## Mintlify component reference
### Callout components
#### Note - Additional helpful information
<Note>
Supplementary information that supports the main content without interrupting flow
</Note>
#### Tip - Best practices and pro tips
<Tip>
Expert advice, shortcuts, or best practices that enhance user success
</Tip>
#### Warning - Important cautions
<Warning>
Critical information about potential issues, breaking changes, or destructive actions
</Warning>
#### Info - Neutral contextual information
<Info>
Background information, context, or neutral announcements
</Info>
#### Check - Success confirmations
<Check>
Positive confirmations, successful completions, or achievement indicators
</Check>
### Code components
#### Single code block
```javascript config.js
const apiConfig = {
baseURL: 'https://api.example.com',
timeout: 5000,
headers: {
'Authorization': `Bearer ${process.env.API_TOKEN}`
}
};
```
#### Code group with multiple languages
<CodeGroup>
```javascript Node.js
const response = await fetch('/api/endpoint', {
headers: { Authorization: `Bearer ${apiKey}` }
});
```
```python Python
import requests
response = requests.get('/api/endpoint',
headers={'Authorization': f'Bearer {api_key}'})
```
```curl cURL
curl -X GET '/api/endpoint' \
-H 'Authorization: Bearer YOUR_API_KEY'
```
</CodeGroup>
#### Request/Response examples
<RequestExample>
```bash cURL
curl -X POST 'https://api.example.com/users' \
-H 'Content-Type: application/json' \
-d '{"name": "John Doe", "email": "john@example.com"}'
```
</RequestExample>
<ResponseExample>
```json Success
{
"id": "user_123",
"name": "John Doe",
"email": "john@example.com",
"created_at": "2024-01-15T10:30:00Z"
}
```
</ResponseExample>
### Structural components
#### Steps for procedures
<Steps>
<Step title="Install dependencies">
Run `npm install` to install required packages.
<Check>
Verify installation by running `npm list`.
</Check>
</Step>
<Step title="Configure environment">
Create a `.env` file with your API credentials.
```bash
API_KEY=your_api_key_here
```
<Warning>
Never commit API keys to version control.
</Warning>
</Step>
</Steps>
#### Tabs for alternative content
<Tabs>
<Tab title="macOS">
```bash
brew install node
npm install -g package-name
```
</Tab>
<Tab title="Windows">
```powershell
choco install nodejs
npm install -g package-name
```
</Tab>
<Tab title="Linux">
```bash
sudo apt install nodejs npm
npm install -g package-name
```
</Tab>
</Tabs>
#### Accordions for collapsible content
<AccordionGroup>
<Accordion title="Troubleshooting connection issues">
- **Firewall blocking**: Ensure ports 80 and 443 are open
- **Proxy configuration**: Set HTTP_PROXY environment variable
- **DNS resolution**: Try using 8.8.8.8 as DNS server
</Accordion>
<Accordion title="Advanced configuration">
```javascript
const config = {
performance: { cache: true, timeout: 30000 },
security: { encryption: 'AES-256' }
};
```
</Accordion>
</AccordionGroup>
### API documentation components
#### Parameter fields
<ParamField path="user_id" type="string" required>
Unique identifier for the user. Must be a valid UUID v4 format.
</ParamField>
<ParamField body="email" type="string" required>
User's email address. Must be valid and unique within the system.
</ParamField>
<ParamField query="limit" type="integer" default="10">
Maximum number of results to return. Range: 1-100.
</ParamField>
<ParamField header="Authorization" type="string" required>
Bearer token for API authentication. Format: `Bearer YOUR_API_KEY`
</ParamField>
#### Response fields
<ResponseField name="user_id" type="string" required>
Unique identifier assigned to the newly created user.
</ResponseField>
<ResponseField name="created_at" type="timestamp">
ISO 8601 formatted timestamp of when the user was created.
</ResponseField>
<ResponseField name="permissions" type="array">
List of permission strings assigned to this user.
</ResponseField>
#### Expandable nested fields
<ResponseField name="user" type="object">
Complete user object with all associated data.
<Expandable title="User properties">
<ResponseField name="profile" type="object">
User profile information including personal details.
<Expandable title="Profile details">
<ResponseField name="first_name" type="string">
User's first name as entered during registration.
</ResponseField>
<ResponseField name="avatar_url" type="string | null">
URL to user's profile picture. Returns null if no avatar is set.
</ResponseField>
</Expandable>
</ResponseField>
</Expandable>
</ResponseField>
### Interactive components
#### Cards for navigation
<Card title="Getting started guide" icon="rocket" href="/quickstart">
Complete walkthrough from installation to your first API call in under 10 minutes.
</Card>
<CardGroup cols={2}>
<Card title="Authentication" icon="key" href="/auth">
Learn how to authenticate requests using API keys or JWT tokens.
</Card>
<Card title="Rate limiting" icon="clock" href="/rate-limits">
Understand rate limits and best practices for high-volume usage.
</Card>
</CardGroup>
### Media and advanced components
#### Frames for images
Wrap all images in frames.
<Frame>
<img src="/images/dashboard.png" alt="Main dashboard showing analytics overview" />
</Frame>
<Frame caption="The analytics dashboard provides real-time insights">
<img src="/images/analytics.png" alt="Analytics dashboard with charts" />
</Frame>
#### Tooltips and updates
<Tooltip tip="Application Programming Interface - protocols for building software">
API
</Tooltip>
<Update label="Version 2.1.0" description="Released March 15, 2024">
## New features
- Added bulk user import functionality
- Improved error messages with actionable suggestions
## Bug fixes
- Fixed pagination issue with large datasets
- Resolved authentication timeout problems
</Update>
## Required page structure
Every documentation page must begin with YAML frontmatter:
```yaml
---
title: "Clear, specific, keyword-rich title"
description: "Concise description explaining page purpose and value"
---
```
## Content quality standards
### Code examples requirements
- Always include complete, runnable examples that users can copy and execute
- Show proper error handling and edge case management
- Use realistic data instead of placeholder values
- Include expected outputs and results for verification
- Test all code examples thoroughly before publishing
- Specify language and include filename when relevant
- Add explanatory comments for complex logic
### API documentation requirements
- Document all parameters including optional ones with clear descriptions
- Show both success and error response examples with realistic data
- Include rate limiting information with specific limits
- Provide authentication examples showing proper format
- Explain all HTTP status codes and error handling
- Cover complete request/response cycles
### Accessibility requirements
- Include descriptive alt text for all images and diagrams
- Use specific, actionable link text instead of "click here"
- Ensure proper heading hierarchy starting with H2
- Provide keyboard navigation considerations
- Use sufficient color contrast in examples and visuals
- Structure content for easy scanning with headers and lists
## AI assistant instructions
### Component selection logic
- Use **Steps** for procedures, tutorials, setup guides, and sequential instructions
- Use **Tabs** for platform-specific content or alternative approaches
- Use **CodeGroup** when showing the same concept in multiple languages
- Use **Accordions** for supplementary information that might interrupt flow
- Use **Cards and CardGroup** for navigation, feature overviews, and related resources
- Use **RequestExample/ResponseExample** specifically for API endpoint documentation
- Use **ParamField** for API parameters, **ResponseField** for API responses
- Use **Expandable** for nested object properties or hierarchical information
### Quality assurance checklist
- Verify all code examples are syntactically correct and executable
- Test all links to ensure they are functional and lead to relevant content
- Validate Mintlify component syntax with all required properties
- Confirm proper heading hierarchy with H2 for main sections, H3 for subsections
- Ensure content flows logically from basic concepts to advanced topics
- Check for consistency in terminology, formatting, and component usage
### Error prevention strategies
- Always include realistic error handling in code examples
- Provide dedicated troubleshooting sections for complex procedures
- Explain prerequisites clearly before beginning instructions
- Include verification and testing steps with expected outcomes
- Add appropriate warnings for destructive or security-sensitive actions
- Validate all technical information through testing before publication
================================================
FILE: docs/apps/development.mdx
================================================
---
title: Development
sidebarTitle: Development
description: Preview and test your app tools locally without a full MCP host.
icon: flask
---
import { VersionBadge } from '/snippets/version-badge.mdx'
<VersionBadge version="3.2.0" />
`fastmcp dev apps` launches a browser-based preview for your app tools. It starts your MCP server and a local dev UI side by side — you pick a tool, fill in its arguments, and see the rendered result in a new tab. No MCP host client needed.
This works with both [Prefab apps](/apps/prefab) and [custom HTML apps](/apps/low-level).
## Quick Start
```bash
pip install "fastmcp[apps]"
fastmcp dev apps server.py
```
The dev UI opens at `http://localhost:8080`. Your MCP server runs on port 8000 with auto-reload enabled by default — save a file and the server restarts automatically.
## How It Works
The dev server does three things:
The **picker page** connects to your MCP server, finds all tools with UI metadata, and renders a form for each one. The forms are auto-generated from the tool's input schema — text fields, dropdowns, checkboxes, all wired up.
When you submit a form, the dev server **calls your tool** via the MCP protocol and opens the result in a new tab. The result page loads the tool's UI resource (the Prefab renderer or your custom HTML) inside an AppBridge — the same protocol that real MCP hosts use.
A **reverse proxy** on `/mcp` forwards requests from the browser to your MCP server, avoiding CORS issues that would otherwise block the iframe-based renderer from talking to a different port.
## Options
```bash
fastmcp dev apps server.py:mcp --mcp-port 9000 --dev-port 9090 --no-reload
```
| Option | Flag | Default | Description |
| ------ | ---- | ------- | ----------- |
| MCP Port | `--mcp-port` | `8000` | Port for your MCP server |
| Dev Port | `--dev-port` | `8080` | Port for the dev UI |
| Auto-Reload | `--reload` / `--no-reload` | On | Watch files and restart the server on changes |
## Multiple Tools
If your server has multiple app tools, the picker shows a dropdown. Each tool gets its own form and launch button. The tool's `title` is displayed when available, falling back to the tool name.
```bash
# Server with multiple app tools
fastmcp dev apps examples/apps/contacts/contacts_server.py
```
================================================
FILE: docs/apps/low-level.mdx
================================================
---
title: Custom HTML Apps
sidebarTitle: Custom HTML
description: Build apps with your own HTML, CSS, and JavaScript using the MCP Apps extension directly.
icon: code
tag: NEW
---
import { VersionBadge } from '/snippets/version-badge.mdx'
<VersionBadge version="3.0.0" />
The [MCP Apps extension](https://modelcontextprotocol.io/docs/extensions/apps) is an open protocol that lets tools return interactive UIs — an HTML page rendered in a sandboxed iframe inside the host client. [Prefab UI](/apps/prefab) builds on this protocol so you never have to think about it, but when you need full control — custom rendering, a specific JavaScript framework, maps, 3D, video — you can use the MCP Apps extension directly.
This page covers how to write custom HTML apps and wire them up in FastMCP. You'll be working with the [`@modelcontextprotocol/ext-apps`](https://github.com/modelcontextprotocol/ext-apps) JavaScript SDK for host communication, and FastMCP's `AppConfig` for resource and CSP management.
## How It Works
An MCP App has two parts:
1. A **tool** that does the work and returns data
2. A **`ui://` resource** containing the HTML that renders that data
The tool declares which resource to use via `AppConfig`. When the host calls the tool, it also fetches the linked resource, renders it in a sandboxed iframe, and pushes the tool result into the app via `postMessage`. The app can also call tools back, enabling interactive workflows.
```python
import json
from fastmcp import FastMCP
from fastmcp.server.apps import AppConfig, ResourceCSP
mcp = FastMCP("My App Server")
# The tool does the work
@mcp.tool(app=AppConfig(resource_uri="ui://my-app/view.html"))
def generate_chart(data: list[float]) -> str:
return json.dumps({"values": data})
# The resource provides the UI
@mcp.resource("ui://my-app/view.html")
def chart_view() -> str:
return "<html>...</html>"
```
## AppConfig
`AppConfig` controls how a tool or resource participates in the Apps extension. Import it from `fastmcp.server.apps`:
```python
from fastmcp.server.apps import AppConfig
```
On **tools**, you'll typically set `resource_uri` to point to the UI resource:
```python
@mcp.tool(app=AppConfig(resource_uri="ui://my-app/view.html"))
def my_tool() -> str:
return "result"
```
You can also pass a raw dict with camelCase keys, matching the wire format:
```python
@mcp.tool(app={"resourceUri": "ui://my-app/view.html"})
def my_tool() -> str:
return "result"
```
### Tool Visibility
The `visibility` field controls where a tool appears:
- `["model"]` — visible to the LLM (the default behavior)
- `["app"]` — only callable from within the app UI, hidden from the LLM
- `["model", "app"]` — both
This is useful when you have tools that only make sense as part of the app's interactive flow, not as standalone LLM actions.
```python
@mcp.tool(
app=AppConfig(
resource_uri="ui://my-app/view.html",
visibility=["app"],
)
)
def refresh_data() -> str:
"""Only callable from the app UI, not by the LLM."""
return fetch_latest()
```
### AppConfig Fields
| Field | Type | Description |
|-------|------|-------------|
| `resource_uri` | `str` | URI of the UI resource. Tools only. |
| `visibility` | `list[str]` | Where the tool appears: `"model"`, `"app"`, or both. Tools only. |
| `csp` | `ResourceCSP` | Content Security Policy for the iframe. |
| `permissions` | `ResourcePermissions` | Iframe sandbox permissions. |
| `domain` | `str` | Stable sandbox origin for the iframe. |
| `prefers_border` | `bool` | Whether the UI prefers a visible border. |
<Note>
On **resources**, `resource_uri` and `visibility` must not be set — the resource *is* the UI. Use `AppConfig` on resources only for `csp`, `permissions`, and other display settings.
</Note>
## UI Resources
Resources using the `ui://` scheme are automatically served with the MIME type `text/html;profile=mcp-app`. You don't need to set this manually.
```python
@mcp.resource("ui://my-app/view.html")
def my_view() -> str:
return "<html>...</html>"
```
The HTML can be anything — a full single-page app, a simple display, or a complex interactive tool. The host renders it in a sandboxed iframe and establishes a `postMessage` channel for communication.
### Writing the App HTML
Your HTML app communicates with the host using the [`@modelcontextprotocol/ext-apps`](https://github.com/modelcontextprotocol/ext-apps) JavaScript SDK. The simplest approach is to load it from a CDN:
```html
<script type="module">
import { App } from "https://unpkg.com/@modelcontextprotocol/ext-apps@0.4.0/app-with-deps";
const app = new App({ name: "My App", version: "1.0.0" });
// Receive tool results pushed by the host
app.ontoolresult = ({ content }) => {
const text = content?.find(c => c.type === 'text');
if (text) {
document.getElementById('output').textContent = text.text;
}
};
// Connect to the host
await app.connect();
</script>
```
The `App` object provides:
- **`app.ontoolresult`** — callback that receives tool results pushed by the host
- **`app.callServerTool({name, arguments})`** — call a tool on the server from within the app
- **`app.onhostcontextchanged`** — callback for host context changes (e.g., safe area insets)
- **`app.getHostContext()`** — get current host context
<Note>
If your HTML loads external scripts, styles, or makes API calls, you need to declare those domains in the CSP configuration. See [Security](#security) below.
</Note>
## Security
Apps run in sandboxed iframes with a deny-by-default Content Security Policy. By default, only inline scripts and styles are allowed — no external network access.
### Content Security Policy
If your app needs to load external resources (CDN scripts, API calls, embedded iframes), declare the allowed domains with `ResourceCSP`:
```python
from fastmcp.server.apps import AppConfig, ResourceCSP
@mcp.resource(
"ui://my-app/view.html",
app=AppConfig(
csp=ResourceCSP(
resource_domains=["https://unpkg.com", "https://cdn.example.com"],
connect_domains=["https://api.example.com"],
)
),
)
def my_view() -> str:
return "<html>...</html>"
```
| CSP Field | Controls |
|-----------|----------|
| `connect_domains` | `fetch`, XHR, WebSocket (`connect-src`) |
| `resource_domains` | Scripts, images, styles, fonts (`script-src`, etc.) |
| `frame_domains` | Nested iframes (`frame-src`) |
| `base_uri_domains` | Document base URI (`base-uri`) |
### Permissions
If your app needs browser capabilities like camera or clipboard access, request them via `ResourcePermissions`:
```python
from fastmcp.server.apps import AppConfig, ResourcePermissions
@mcp.resource(
"ui://my-app/view.html",
app=AppConfig(
permissions=ResourcePermissions(
camera={},
clipboard_write={},
)
),
)
def my_view() -> str:
return "<html>...</html>"
```
Hosts may or may not grant these permissions. Your app should use JavaScript feature detection as a fallback.
## Example: QR Code Server
This example creates a tool that generates QR codes and an app that renders them as images. It's based on the [official MCP Apps example](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/qr-server). Requires the `qrcode[pil]` package.
```python expandable
import base64
import io
import qrcode
from mcp import types
from fastmcp import FastMCP
from fastmcp.server.apps import AppConfig, ResourceCSP
from fastmcp.tools import ToolResult
mcp = FastMCP("QR Code Server")
VIEW_URI = "ui://qr-server/view.html"
@mcp.tool(app=AppConfig(resource_uri=VIEW_URI))
def generate_qr(text: str = "https://gofastmcp.com") -> ToolResult:
"""Generate a QR code from text."""
qr = qrcode.QRCode(version=1, box_size=10, border=4)
qr.add_data(text)
qr.make(fit=True)
img = qr.make_image()
buffer = io.BytesIO()
img.save(buffer, format="PNG")
b64 = base64.b64encode(buffer.getvalue()).decode()
return ToolResult(
content=[types.ImageContent(type="image", data=b64, mimeType="image/png")]
)
@mcp.resource(
VIEW_URI,
app=AppConfig(csp=ResourceCSP(resource_domains=["https://unpkg.com"])),
)
def view() -> str:
"""Interactive QR code viewer."""
return """\
<!DOCTYPE html>
<html>
<head>
<meta name="color-scheme" content="light dark">
<style>
body { display: flex; justify-content: center;
align-items: center; height: 340px; width: 340px;
margin: 0; background: transparent; }
img { width: 300px; height: 300px; border-radius: 8px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
</style>
</head>
<body>
<div id="qr"></div>
<script type="module">
import { App } from
"https://unpkg.com/@modelcontextprotocol/ext-apps@0.4.0/app-with-deps";
const app = new App({ name: "QR View", version: "1.0.0" });
app.ontoolresult = ({ content }) => {
const img = content?.find(c => c.type === 'image');
if (img) {
const el = document.createElement('img');
el.src = `data:${img.mimeType};base64,${img.data}`;
el.alt = "QR Code";
document.getElementById('qr').replaceChildren(el);
}
};
await app.connect();
</script>
</body>
</html>"""
```
The tool generates a QR code as a base64 PNG. The resource loads the MCP Apps JS SDK from unpkg (declared in the CSP), listens for tool results, and renders the image. The host wires them together — when the LLM calls `generate_qr`, the QR code appears in an interactive frame inside the conversation.
## Checking Client Support
Not all hosts support the Apps extension. You can check at runtime using the tool's [context](/servers/context):
```python
from fastmcp import Context
from fastmcp.server.apps import AppConfig, UI_EXTENSION_ID
@mcp.tool(app=AppConfig(resource_uri="ui://my-app/view.html"))
async def my_tool(ctx: Context) -> str:
if ctx.client_supports_extension(UI_EXTENSION_ID):
# Return data optimized for UI rendering
return rich_response()
else:
# Fall back to plain text
return plain_text_response()
```
================================================
FILE: docs/apps/overview.mdx
================================================
---
title: Apps
sidebarTitle: Overview
description: Give your tools interactive UIs rendered directly in the conversation.
icon: grid-2
tag: NEW
---
import { VersionBadge } from '/snippets/version-badge.mdx'
<VersionBadge version="3.0.0" />
MCP Apps let your tools return interactive UIs — rendered in a sandboxed iframe right inside the host client's conversation. Instead of returning plain text, a tool can show a chart, a sortable table, a form, or anything you can build with HTML.
FastMCP implements the [MCP Apps extension](https://modelcontextprotocol.io/docs/extensions/apps) and provides two approaches:
## Prefab Apps (Recommended)
<VersionBadge version="3.1.0" />
<Tip>
[Prefab](https://prefab.prefect.io) is in extremely early, active development — its API changes frequently and breaking changes can occur with any release. The FastMCP integration is equally new and under rapid development. These docs are included for users who want to work on the cutting edge; production use is not recommended. Always [pin `prefab-ui` to a specific version](/apps/prefab#getting-started) in your dependencies.
</Tip>
[Prefab UI](https://prefab.prefect.io) is a declarative UI framework for Python. You describe layouts, charts, tables, forms, and interactive behaviors using a Python DSL — and the framework compiles them to a JSON protocol that a shared renderer interprets. It started as a component library inside FastMCP and grew into its own framework with [comprehensive documentation](https://prefab.prefect.io).
```python
from prefab_ui.components import Column, Heading, BarChart, ChartSeries
from prefab_ui.app import PrefabApp
from fastmcp import FastMCP
mcp = FastMCP("Dashboard")
@mcp.tool(app=True)
def sales_chart(year: int) -> PrefabApp:
"""Show sales data as an interactive chart."""
data = get_sales_data(year)
with Column(gap=4, css_class="p-6") as view:
Heading(f"{year} Sales")
BarChart(
data=data,
series=[ChartSeries(data_key="revenue", label="Revenue")],
x_axis="month",
)
return PrefabApp(view=view)
```
Install with `pip install "fastmcp[apps]"` and see [Prefab Apps](/apps/prefab) for the integration guide.
## Custom HTML Apps
The [MCP Apps extension](https://modelcontextprotocol.io/docs/extensions/apps) is an open protocol, and you can use it directly when you need full control. You write your own HTML/CSS/JavaScript and communicate with the host via the [`@modelcontextprotocol/ext-apps`](https://github.com/modelcontextprotocol/ext-apps) SDK.
This is the right choice for custom rendering (maps, 3D, video), specific JavaScript frameworks, or capabilities beyond what the component library offers.
```python
from fastmcp import FastMCP
from fastmcp.server.apps import AppConfig, ResourceCSP
mcp = FastMCP("Custom App")
@mcp.tool(app=AppConfig(resource_uri="ui://my-app/view.html"))
def my_tool() -> str:
return '{"values": [1, 2, 3]}'
@mcp.resource(
"ui://my-app/view.html",
app=AppConfig(csp=ResourceCSP(resource_domains=["https://unpkg.com"])),
)
def view() -> str:
return "<html>...</html>"
```
See [Custom HTML Apps](/apps/low-level) for the full reference.
================================================
FILE: docs/apps/patterns.mdx
================================================
---
title: Patterns
sidebarTitle: Patterns
description: Charts, tables, forms, and other common tool UIs.
icon: grid-2-plus
tag: SOON
---
import { VersionBadge } from '/snippets/version-badge.mdx'
<VersionBadge version="3.1.0" />
<Tip>
[Prefab](https://prefab.prefect.io) is in extremely early, active development — its API changes frequently and breaking changes can occur with any release. The FastMCP integration is equally new and under rapid development. These docs are included for users who want to work on the cutting edge; production use is not recommended. Always pin `prefab-ui` t
gitextract_xwrq15g3/
├── .ccignore
├── .claude/
│ ├── hooks/
│ │ └── session-init.sh
│ ├── settings.json
│ └── skills/
│ ├── code-review/
│ │ └── SKILL.md
│ ├── python-tests/
│ │ └── SKILL.md
│ └── review-pr/
│ └── SKILL.md
├── .coderabbit.yaml
├── .cursor/
│ └── rules/
│ └── core-mcp-objects.mdc
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug.yml
│ │ ├── config.yml
│ │ └── enhancement.yml
│ ├── actions/
│ │ ├── run-claude/
│ │ │ └── action.yml
│ │ ├── run-pytest/
│ │ │ └── action.yml
│ │ └── setup-uv/
│ │ └── action.yml
│ ├── dependabot.yml
│ ├── pull_request_template.md
│ ├── release.yml
│ ├── scripts/
│ │ ├── mention/
│ │ │ ├── gh-get-review-threads.sh
│ │ │ └── gh-resolve-review-thread.sh
│ │ └── pr-review/
│ │ ├── pr-comment.sh
│ │ ├── pr-diff.sh
│ │ ├── pr-existing-comments.sh
│ │ ├── pr-remove-comment.sh
│ │ └── pr-review.sh
│ └── workflows/
│ ├── auto-close-duplicates.yml
│ ├── auto-close-needs-mre.yml
│ ├── martian-test-failure.yml
│ ├── martian-triage-issue.yml
│ ├── marvin-comment-on-issue.yml
│ ├── marvin-comment-on-pr.yml
│ ├── marvin-dedupe-issues.yml
│ ├── marvin-label-triage.yml
│ ├── minimize-resolved-reviews.yml
│ ├── publish.yml
│ ├── run-static.yml
│ ├── run-tests.yml
│ ├── run-upgrade-checks.yml
│ ├── update-config-schema.yml
│ └── update-sdk-docs.yml
├── .gitignore
├── .pre-commit-config.yaml
├── CLAUDE.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── SECURITY.md
├── docs/
│ ├── .ccignore
│ ├── .cursor/
│ │ └── rules/
│ │ └── mintlify.mdc
│ ├── apps/
│ │ ├── development.mdx
│ │ ├── low-level.mdx
│ │ ├── overview.mdx
│ │ ├── patterns.mdx
│ │ └── prefab.mdx
│ ├── assets/
│ │ └── schemas/
│ │ └── mcp_server_config/
│ │ ├── latest.json
│ │ └── v1.json
│ ├── changelog.mdx
│ ├── cli/
│ │ ├── auth.mdx
│ │ ├── client.mdx
│ │ ├── generate-cli.mdx
│ │ ├── inspecting.mdx
│ │ ├── install-mcp.mdx
│ │ ├── overview.mdx
│ │ └── running.mdx
│ ├── clients/
│ │ ├── auth/
│ │ │ ├── bearer.mdx
│ │ │ ├── cimd.mdx
│ │ │ └── oauth.mdx
│ │ ├── cli.mdx
│ │ ├── client.mdx
│ │ ├── elicitation.mdx
│ │ ├── generate-cli.mdx
│ │ ├── logging.mdx
│ │ ├── notifications.mdx
│ │ ├── progress.mdx
│ │ ├── prompts.mdx
│ │ ├── resources.mdx
│ │ ├── roots.mdx
│ │ ├── sampling.mdx
│ │ ├── tasks.mdx
│ │ ├── tools.mdx
│ │ └── transports.mdx
│ ├── community/
│ │ ├── README.md
│ │ └── showcase.mdx
│ ├── css/
│ │ ├── banner.css
│ │ ├── python-sdk.css
│ │ ├── style.css
│ │ └── version-badge.css
│ ├── deployment/
│ │ ├── http.mdx
│ │ ├── prefect-horizon.mdx
│ │ ├── running-server.mdx
│ │ └── server-configuration.mdx
│ ├── development/
│ │ ├── contributing.mdx
│ │ ├── releases.mdx
│ │ ├── tests.mdx
│ │ └── v3-notes/
│ │ ├── auth-provider-env-vars.mdx
│ │ └── v3-features.mdx
│ ├── docs.json
│ ├── getting-started/
│ │ ├── installation.mdx
│ │ ├── quickstart.mdx
│ │ ├── upgrading/
│ │ │ ├── from-fastmcp-2.mdx
│ │ │ ├── from-low-level-sdk.mdx
│ │ │ └── from-mcp-sdk.mdx
│ │ └── welcome.mdx
│ ├── integrations/
│ │ ├── anthropic.mdx
│ │ ├── auth0.mdx
│ │ ├── authkit.mdx
│ │ ├── aws-cognito.mdx
│ │ ├── azure.mdx
│ │ ├── chatgpt.mdx
│ │ ├── claude-code.mdx
│ │ ├── claude-desktop.mdx
│ │ ├── cursor.mdx
│ │ ├── descope.mdx
│ │ ├── discord.mdx
│ │ ├── eunomia-authorization.mdx
│ │ ├── fastapi.mdx
│ │ ├── gemini-cli.mdx
│ │ ├── gemini.mdx
│ │ ├── github.mdx
│ │ ├── google.mdx
│ │ ├── goose.mdx
│ │ ├── mcp-json-configuration.mdx
│ │ ├── oci.mdx
│ │ ├── openai.mdx
│ │ ├── openapi.mdx
│ │ ├── permit.mdx
│ │ ├── propelauth.mdx
│ │ ├── scalekit.mdx
│ │ ├── supabase.mdx
│ │ └── workos.mdx
│ ├── more/
│ │ └── settings.mdx
│ ├── patterns/
│ │ ├── cli.mdx
│ │ ├── contrib.mdx
│ │ └── testing.mdx
│ ├── public/
│ │ └── schemas/
│ │ └── fastmcp.json/
│ │ ├── latest.json
│ │ └── v1.json
│ ├── python-sdk/
│ │ ├── fastmcp-cli-__init__.mdx
│ │ ├── fastmcp-cli-apps_dev.mdx
│ │ ├── fastmcp-cli-auth.mdx
│ │ ├── fastmcp-cli-cimd.mdx
│ │ ├── fastmcp-cli-cli.mdx
│ │ ├── fastmcp-cli-client.mdx
│ │ ├── fastmcp-cli-discovery.mdx
│ │ ├── fastmcp-cli-generate.mdx
│ │ ├── fastmcp-cli-install-__init__.mdx
│ │ ├── fastmcp-cli-install-claude_code.mdx
│ │ ├── fastmcp-cli-install-claude_desktop.mdx
│ │ ├── fastmcp-cli-install-cursor.mdx
│ │ ├── fastmcp-cli-install-gemini_cli.mdx
│ │ ├── fastmcp-cli-install-goose.mdx
│ │ ├── fastmcp-cli-install-mcp_json.mdx
│ │ ├── fastmcp-cli-install-shared.mdx
│ │ ├── fastmcp-cli-install-stdio.mdx
│ │ ├── fastmcp-cli-run.mdx
│ │ ├── fastmcp-cli-tasks.mdx
│ │ ├── fastmcp-client-__init__.mdx
│ │ ├── fastmcp-client-auth-__init__.mdx
│ │ ├── fastmcp-client-auth-bearer.mdx
│ │ ├── fastmcp-client-auth-oauth.mdx
│ │ ├── fastmcp-client-client.mdx
│ │ ├── fastmcp-client-elicitation.mdx
│ │ ├── fastmcp-client-logging.mdx
│ │ ├── fastmcp-client-messages.mdx
│ │ ├── fastmcp-client-mixins-__init__.mdx
│ │ ├── fastmcp-client-mixins-prompts.mdx
│ │ ├── fastmcp-client-mixins-resources.mdx
│ │ ├── fastmcp-client-mixins-task_management.mdx
│ │ ├── fastmcp-client-mixins-tools.mdx
│ │ ├── fastmcp-client-oauth_callback.mdx
│ │ ├── fastmcp-client-progress.mdx
│ │ ├── fastmcp-client-roots.mdx
│ │ ├── fastmcp-client-sampling-__init__.mdx
│ │ ├── fastmcp-client-sampling-handlers-__init__.mdx
│ │ ├── fastmcp-client-sampling-handlers-anthropic.mdx
│ │ ├── fastmcp-client-sampling-handlers-google_genai.mdx
│ │ ├── fastmcp-client-sampling-handlers-openai.mdx
│ │ ├── fastmcp-client-tasks.mdx
│ │ ├── fastmcp-client-telemetry.mdx
│ │ ├── fastmcp-client-transports-__init__.mdx
│ │ ├── fastmcp-client-transports-base.mdx
│ │ ├── fastmcp-client-transports-config.mdx
│ │ ├── fastmcp-client-transports-http.mdx
│ │ ├── fastmcp-client-transports-inference.mdx
│ │ ├── fastmcp-client-transports-memory.mdx
│ │ ├── fastmcp-client-transports-sse.mdx
│ │ ├── fastmcp-client-transports-stdio.mdx
│ │ ├── fastmcp-decorators.mdx
│ │ ├── fastmcp-dependencies.mdx
│ │ ├── fastmcp-exceptions.mdx
│ │ ├── fastmcp-experimental-__init__.mdx
│ │ ├── fastmcp-experimental-sampling-__init__.mdx
│ │ ├── fastmcp-experimental-sampling-handlers.mdx
│ │ ├── fastmcp-experimental-transforms-__init__.mdx
│ │ ├── fastmcp-experimental-transforms-code_mode.mdx
│ │ ├── fastmcp-mcp_config.mdx
│ │ ├── fastmcp-prompts-__init__.mdx
│ │ ├── fastmcp-prompts-base.mdx
│ │ ├── fastmcp-prompts-function_prompt.mdx
│ │ ├── fastmcp-resources-__init__.mdx
│ │ ├── fastmcp-resources-base.mdx
│ │ ├── fastmcp-resources-function_resource.mdx
│ │ ├── fastmcp-resources-template.mdx
│ │ ├── fastmcp-resources-types.mdx
│ │ ├── fastmcp-server-__init__.mdx
│ │ ├── fastmcp-server-app.mdx
│ │ ├── fastmcp-server-apps.mdx
│ │ ├── fastmcp-server-auth-__init__.mdx
│ │ ├── fastmcp-server-auth-auth.mdx
│ │ ├── fastmcp-server-auth-authorization.mdx
│ │ ├── fastmcp-server-auth-cimd.mdx
│ │ ├── fastmcp-server-auth-jwt_issuer.mdx
│ │ ├── fastmcp-server-auth-middleware.mdx
│ │ ├── fastmcp-server-auth-oauth_proxy-__init__.mdx
│ │ ├── fastmcp-server-auth-oauth_proxy-consent.mdx
│ │ ├── fastmcp-server-auth-oauth_proxy-models.mdx
│ │ ├── fastmcp-server-auth-oauth_proxy-proxy.mdx
│ │ ├── fastmcp-server-auth-oauth_proxy-ui.mdx
│ │ ├── fastmcp-server-auth-oidc_proxy.mdx
│ │ ├── fastmcp-server-auth-providers-__init__.mdx
│ │ ├── fastmcp-server-auth-providers-auth0.mdx
│ │ ├── fastmcp-server-auth-providers-aws.mdx
│ │ ├── fastmcp-server-auth-providers-azure.mdx
│ │ ├── fastmcp-server-auth-providers-debug.mdx
│ │ ├── fastmcp-server-auth-providers-descope.mdx
│ │ ├── fastmcp-server-auth-providers-discord.mdx
│ │ ├── fastmcp-server-auth-providers-github.mdx
│ │ ├── fastmcp-server-auth-providers-google.mdx
│ │ ├── fastmcp-server-auth-providers-in_memory.mdx
│ │ ├── fastmcp-server-auth-providers-introspection.mdx
│ │ ├── fastmcp-server-auth-providers-jwt.mdx
│ │ ├── fastmcp-server-auth-providers-oci.mdx
│ │ ├── fastmcp-server-auth-providers-propelauth.mdx
│ │ ├── fastmcp-server-auth-providers-scalekit.mdx
│ │ ├── fastmcp-server-auth-providers-supabase.mdx
│ │ ├── fastmcp-server-auth-providers-workos.mdx
│ │ ├── fastmcp-server-auth-redirect_validation.mdx
│ │ ├── fastmcp-server-auth-ssrf.mdx
│ │ ├── fastmcp-server-context.mdx
│ │ ├── fastmcp-server-dependencies.mdx
│ │ ├── fastmcp-server-elicitation.mdx
│ │ ├── fastmcp-server-event_store.mdx
│ │ ├── fastmcp-server-http.mdx
│ │ ├── fastmcp-server-lifespan.mdx
│ │ ├── fastmcp-server-low_level.mdx
│ │ ├── fastmcp-server-middleware-__init__.mdx
│ │ ├── fastmcp-server-middleware-authorization.mdx
│ │ ├── fastmcp-server-middleware-caching.mdx
│ │ ├── fastmcp-server-middleware-dereference.mdx
│ │ ├── fastmcp-server-middleware-error_handling.mdx
│ │ ├── fastmcp-server-middleware-logging.mdx
│ │ ├── fastmcp-server-middleware-middleware.mdx
│ │ ├── fastmcp-server-middleware-ping.mdx
│ │ ├── fastmcp-server-middleware-rate_limiting.mdx
│ │ ├── fastmcp-server-middleware-response_limiting.mdx
│ │ ├── fastmcp-server-middleware-timing.mdx
│ │ ├── fastmcp-server-middleware-tool_injection.mdx
│ │ ├── fastmcp-server-mixins-__init__.mdx
│ │ ├── fastmcp-server-mixins-lifespan.mdx
│ │ ├── fastmcp-server-mixins-mcp_operations.mdx
│ │ ├── fastmcp-server-mixins-transport.mdx
│ │ ├── fastmcp-server-openapi-__init__.mdx
│ │ ├── fastmcp-server-openapi-components.mdx
│ │ ├── fastmcp-server-openapi-routing.mdx
│ │ ├── fastmcp-server-openapi-server.mdx
│ │ ├── fastmcp-server-providers-__init__.mdx
│ │ ├── fastmcp-server-providers-aggregate.mdx
│ │ ├── fastmcp-server-providers-base.mdx
│ │ ├── fastmcp-server-providers-fastmcp_provider.mdx
│ │ ├── fastmcp-server-providers-filesystem.mdx
│ │ ├── fastmcp-server-providers-filesystem_discovery.mdx
│ │ ├── fastmcp-server-providers-local_provider-__init__.mdx
│ │ ├── fastmcp-server-providers-local_provider-decorators-__init__.mdx
│ │ ├── fastmcp-server-providers-local_provider-decorators-prompts.mdx
│ │ ├── fastmcp-server-providers-local_provider-decorators-resources.mdx
│ │ ├── fastmcp-server-providers-local_provider-decorators-tools.mdx
│ │ ├── fastmcp-server-providers-local_provider-local_provider.mdx
│ │ ├── fastmcp-server-providers-openapi-__init__.mdx
│ │ ├── fastmcp-server-providers-openapi-components.mdx
│ │ ├── fastmcp-server-providers-openapi-provider.mdx
│ │ ├── fastmcp-server-providers-openapi-routing.mdx
│ │ ├── fastmcp-server-providers-proxy.mdx
│ │ ├── fastmcp-server-providers-skills-__init__.mdx
│ │ ├── fastmcp-server-providers-skills-claude_provider.mdx
│ │ ├── fastmcp-server-providers-skills-directory_provider.mdx
│ │ ├── fastmcp-server-providers-skills-skill_provider.mdx
│ │ ├── fastmcp-server-providers-skills-vendor_providers.mdx
│ │ ├── fastmcp-server-providers-wrapped_provider.mdx
│ │ ├── fastmcp-server-proxy.mdx
│ │ ├── fastmcp-server-sampling-__init__.mdx
│ │ ├── fastmcp-server-sampling-run.mdx
│ │ ├── fastmcp-server-sampling-sampling_tool.mdx
│ │ ├── fastmcp-server-server.mdx
│ │ ├── fastmcp-server-tasks-__init__.mdx
│ │ ├── fastmcp-server-tasks-capabilities.mdx
│ │ ├── fastmcp-server-tasks-config.mdx
│ │ ├── fastmcp-server-tasks-elicitation.mdx
│ │ ├── fastmcp-server-tasks-handlers.mdx
│ │ ├── fastmcp-server-tasks-keys.mdx
│ │ ├── fastmcp-server-tasks-notifications.mdx
│ │ ├── fastmcp-server-tasks-requests.mdx
│ │ ├── fastmcp-server-tasks-routing.mdx
│ │ ├── fastmcp-server-tasks-subscriptions.mdx
│ │ ├── fastmcp-server-telemetry.mdx
│ │ ├── fastmcp-server-transforms-__init__.mdx
│ │ ├── fastmcp-server-transforms-catalog.mdx
│ │ ├── fastmcp-server-transforms-namespace.mdx
│ │ ├── fastmcp-server-transforms-prompts_as_tools.mdx
│ │ ├── fastmcp-server-transforms-resources_as_tools.mdx
│ │ ├── fastmcp-server-transforms-search-__init__.mdx
│ │ ├── fastmcp-server-transforms-search-base.mdx
│ │ ├── fastmcp-server-transforms-search-bm25.mdx
│ │ ├── fastmcp-server-transforms-search-regex.mdx
│ │ ├── fastmcp-server-transforms-tool_transform.mdx
│ │ ├── fastmcp-server-transforms-version_filter.mdx
│ │ ├── fastmcp-server-transforms-visibility.mdx
│ │ ├── fastmcp-settings.mdx
│ │ ├── fastmcp-telemetry.mdx
│ │ ├── fastmcp-tools-__init__.mdx
│ │ ├── fastmcp-tools-base.mdx
│ │ ├── fastmcp-tools-function_parsing.mdx
│ │ ├── fastmcp-tools-function_tool.mdx
│ │ ├── fastmcp-tools-tool_transform.mdx
│ │ ├── fastmcp-utilities-__init__.mdx
│ │ ├── fastmcp-utilities-async_utils.mdx
│ │ ├── fastmcp-utilities-auth.mdx
│ │ ├── fastmcp-utilities-cli.mdx
│ │ ├── fastmcp-utilities-components.mdx
│ │ ├── fastmcp-utilities-exceptions.mdx
│ │ ├── fastmcp-utilities-http.mdx
│ │ ├── fastmcp-utilities-inspect.mdx
│ │ ├── fastmcp-utilities-json_schema.mdx
│ │ ├── fastmcp-utilities-json_schema_type.mdx
│ │ ├── fastmcp-utilities-lifespan.mdx
│ │ ├── fastmcp-utilities-logging.mdx
│ │ ├── fastmcp-utilities-mcp_server_config-__init__.mdx
│ │ ├── fastmcp-utilities-mcp_server_config-v1-__init__.mdx
│ │ ├── fastmcp-utilities-mcp_server_config-v1-environments-__init__.mdx
│ │ ├── fastmcp-utilities-mcp_server_config-v1-environments-base.mdx
│ │ ├── fastmcp-utilities-mcp_server_config-v1-environments-uv.mdx
│ │ ├── fastmcp-utilities-mcp_server_config-v1-mcp_server_config.mdx
│ │ ├── fastmcp-utilities-mcp_server_config-v1-sources-__init__.mdx
│ │ ├── fastmcp-utilities-mcp_server_config-v1-sources-base.mdx
│ │ ├── fastmcp-utilities-mcp_server_config-v1-sources-filesystem.mdx
│ │ ├── fastmcp-utilities-openapi-__init__.mdx
│ │ ├── fastmcp-utilities-openapi-director.mdx
│ │ ├── fastmcp-utilities-openapi-formatters.mdx
│ │ ├── fastmcp-utilities-openapi-json_schema_converter.mdx
│ │ ├── fastmcp-utilities-openapi-models.mdx
│ │ ├── fastmcp-utilities-openapi-parser.mdx
│ │ ├── fastmcp-utilities-openapi-schemas.mdx
│ │ ├── fastmcp-utilities-pagination.mdx
│ │ ├── fastmcp-utilities-skills.mdx
│ │ ├── fastmcp-utilities-tests.mdx
│ │ ├── fastmcp-utilities-timeout.mdx
│ │ ├── fastmcp-utilities-token_cache.mdx
│ │ ├── fastmcp-utilities-types.mdx
│ │ ├── fastmcp-utilities-ui.mdx
│ │ ├── fastmcp-utilities-version_check.mdx
│ │ └── fastmcp-utilities-versions.mdx
│ ├── servers/
│ │ ├── auth/
│ │ │ ├── authentication.mdx
│ │ │ ├── full-oauth-server.mdx
│ │ │ ├── multi-auth.mdx
│ │ │ ├── oauth-proxy.mdx
│ │ │ ├── oidc-proxy.mdx
│ │ │ ├── remote-oauth.mdx
│ │ │ └── token-verification.mdx
│ │ ├── authorization.mdx
│ │ ├── composition.mdx
│ │ ├── context.mdx
│ │ ├── dependency-injection.mdx
│ │ ├── elicitation.mdx
│ │ ├── icons.mdx
│ │ ├── lifespan.mdx
│ │ ├── logging.mdx
│ │ ├── middleware.mdx
│ │ ├── pagination.mdx
│ │ ├── progress.mdx
│ │ ├── prompts.mdx
│ │ ├── providers/
│ │ │ ├── custom.mdx
│ │ │ ├── filesystem.mdx
│ │ │ ├── local.mdx
│ │ │ ├── overview.mdx
│ │ │ ├── proxy.mdx
│ │ │ └── skills.mdx
│ │ ├── resources.mdx
│ │ ├── sampling.mdx
│ │ ├── server.mdx
│ │ ├── storage-backends.mdx
│ │ ├── tasks.mdx
│ │ ├── telemetry.mdx
│ │ ├── testing.mdx
│ │ ├── tools.mdx
│ │ ├── transforms/
│ │ │ ├── code-mode.mdx
│ │ │ ├── namespace.mdx
│ │ │ ├── namespacing.mdx
│ │ │ ├── prompts-as-tools.mdx
│ │ │ ├── resources-as-tools.mdx
│ │ │ ├── tool-search.mdx
│ │ │ ├── tool-transformation.mdx
│ │ │ └── transforms.mdx
│ │ ├── versioning.mdx
│ │ └── visibility.mdx
│ ├── snippets/
│ │ ├── local-focus.mdx
│ │ ├── version-badge.mdx
│ │ └── youtube-embed.mdx
│ ├── tutorials/
│ │ ├── create-mcp-server.mdx
│ │ ├── mcp.mdx
│ │ └── rest-api.mdx
│ ├── unify-intent.js
│ ├── updates.mdx
│ ├── v2/
│ │ ├── changelog.mdx
│ │ ├── clients/
│ │ │ ├── auth/
│ │ │ │ ├── bearer.mdx
│ │ │ │ └── oauth.mdx
│ │ │ ├── client.mdx
│ │ │ ├── elicitation.mdx
│ │ │ ├── logging.mdx
│ │ │ ├── messages.mdx
│ │ │ ├── progress.mdx
│ │ │ ├── prompts.mdx
│ │ │ ├── resources.mdx
│ │ │ ├── roots.mdx
│ │ │ ├── sampling.mdx
│ │ │ ├── tasks.mdx
│ │ │ ├── tools.mdx
│ │ │ └── transports.mdx
│ │ ├── community/
│ │ │ └── showcase.mdx
│ │ ├── deployment/
│ │ │ ├── http.mdx
│ │ │ ├── running-server.mdx
│ │ │ └── server-configuration.mdx
│ │ ├── development/
│ │ │ ├── contributing.mdx
│ │ │ ├── releases.mdx
│ │ │ ├── tests.mdx
│ │ │ └── upgrade-guide.mdx
│ │ ├── getting-started/
│ │ │ ├── installation.mdx
│ │ │ ├── quickstart.mdx
│ │ │ └── welcome.mdx
│ │ ├── integrations/
│ │ │ ├── anthropic.mdx
│ │ │ ├── auth0.mdx
│ │ │ ├── authkit.mdx
│ │ │ ├── aws-cognito.mdx
│ │ │ ├── azure.mdx
│ │ │ ├── chatgpt.mdx
│ │ │ ├── claude-code.mdx
│ │ │ ├── claude-desktop.mdx
│ │ │ ├── cursor.mdx
│ │ │ ├── descope.mdx
│ │ │ ├── discord.mdx
│ │ │ ├── eunomia-authorization.mdx
│ │ │ ├── fastapi.mdx
│ │ │ ├── gemini-cli.mdx
│ │ │ ├── gemini.mdx
│ │ │ ├── github.mdx
│ │ │ ├── google.mdx
│ │ │ ├── mcp-json-configuration.mdx
│ │ │ ├── oci.mdx
│ │ │ ├── openai.mdx
│ │ │ ├── openapi.mdx
│ │ │ ├── permit.mdx
│ │ │ ├── scalekit.mdx
│ │ │ ├── supabase.mdx
│ │ │ └── workos.mdx
│ │ ├── patterns/
│ │ │ ├── cli.mdx
│ │ │ ├── contrib.mdx
│ │ │ ├── decorating-methods.mdx
│ │ │ ├── testing.mdx
│ │ │ └── tool-transformation.mdx
│ │ ├── servers/
│ │ │ ├── auth/
│ │ │ │ ├── authentication.mdx
│ │ │ │ ├── full-oauth-server.mdx
│ │ │ │ ├── oauth-proxy.mdx
│ │ │ │ ├── oidc-proxy.mdx
│ │ │ │ ├── remote-oauth.mdx
│ │ │ │ └── token-verification.mdx
│ │ │ ├── composition.mdx
│ │ │ ├── context.mdx
│ │ │ ├── elicitation.mdx
│ │ │ ├── icons.mdx
│ │ │ ├── logging.mdx
│ │ │ ├── middleware.mdx
│ │ │ ├── progress.mdx
│ │ │ ├── prompts.mdx
│ │ │ ├── proxy.mdx
│ │ │ ├── resources.mdx
│ │ │ ├── sampling.mdx
│ │ │ ├── server.mdx
│ │ │ ├── storage-backends.mdx
│ │ │ ├── tasks.mdx
│ │ │ └── tools.mdx
│ │ ├── tutorials/
│ │ │ ├── create-mcp-server.mdx
│ │ │ ├── mcp.mdx
│ │ │ └── rest-api.mdx
│ │ └── updates.mdx
│ └── v2-banner.js
├── examples/
│ ├── apps/
│ │ ├── chart_server.py
│ │ ├── contacts/
│ │ │ └── contacts_server.py
│ │ ├── datatable_server.py
│ │ ├── greet_server.py
│ │ ├── patterns_server.py
│ │ └── qr_server/
│ │ ├── README.md
│ │ ├── fastmcp.json
│ │ ├── pyproject.toml
│ │ └── qr_server.py
│ ├── atproto_mcp/
│ │ ├── README.md
│ │ ├── demo.py
│ │ ├── fastmcp.json
│ │ ├── pyproject.toml
│ │ └── src/
│ │ └── atproto_mcp/
│ │ ├── __init__.py
│ │ ├── __main__.py
│ │ ├── _atproto/
│ │ │ ├── __init__.py
│ │ │ ├── _client.py
│ │ │ ├── _posts.py
│ │ │ ├── _profile.py
│ │ │ ├── _read.py
│ │ │ └── _social.py
│ │ ├── py.typed
│ │ ├── server.py
│ │ ├── settings.py
│ │ └── types.py
│ ├── auth/
│ │ ├── authkit_dcr/
│ │ │ ├── README.md
│ │ │ ├── client.py
│ │ │ └── server.py
│ │ ├── aws_oauth/
│ │ │ ├── README.md
│ │ │ ├── client.py
│ │ │ ├── requirements.txt
│ │ │ └── server.py
│ │ ├── azure_oauth/
│ │ │ ├── README.md
│ │ │ ├── client.py
│ │ │ └── server.py
│ │ ├── discord_oauth/
│ │ │ ├── README.md
│ │ │ ├── client.py
│ │ │ └── server.py
│ │ ├── github_oauth/
│ │ │ ├── README.md
│ │ │ ├── client.py
│ │ │ └── server.py
│ │ ├── google_oauth/
│ │ │ ├── README.md
│ │ │ ├── client.py
│ │ │ └── server.py
│ │ ├── mounted/
│ │ │ ├── README.md
│ │ │ ├── client.py
│ │ │ └── server.py
│ │ ├── propelauth_oauth/
│ │ │ ├── README.md
│ │ │ ├── client.py
│ │ │ └── server.py
│ │ ├── scalekit_oauth/
│ │ │ ├── README.md
│ │ │ ├── client.py
│ │ │ └── server.py
│ │ └── workos_oauth/
│ │ ├── README.md
│ │ ├── client.py
│ │ └── server.py
│ ├── code_mode/
│ │ ├── README.md
│ │ ├── client.py
│ │ └── server.py
│ ├── complex_inputs.py
│ ├── config_server.py
│ ├── custom_tool_serializer_decorator.py
│ ├── desktop.py
│ ├── diagnostics/
│ │ ├── client_with_tracing.py
│ │ └── server.py
│ ├── echo.py
│ ├── elicitation.py
│ ├── fastmcp_config/
│ │ ├── env_interpolation_example.json
│ │ ├── fastmcp.json
│ │ ├── full_example.fastmcp.json
│ │ ├── server.py
│ │ └── simple.fastmcp.json
│ ├── fastmcp_config_demo/
│ │ ├── README.md
│ │ ├── fastmcp.json
│ │ └── server.py
│ ├── filesystem-provider/
│ │ ├── mcp/
│ │ │ ├── prompts/
│ │ │ │ └── assistant.py
│ │ │ ├── resources/
│ │ │ │ └── config.py
│ │ │ └── tools/
│ │ │ ├── calculator.py
│ │ │ └── greeting.py
│ │ └── server.py
│ ├── get_file.py
│ ├── in_memory_proxy_example.py
│ ├── memory.fastmcp.json
│ ├── memory.py
│ ├── mount_example.fastmcp.json
│ ├── mount_example.py
│ ├── namespace_activation/
│ │ ├── README.md
│ │ ├── client.py
│ │ └── server.py
│ ├── persistent_state/
│ │ ├── README.md
│ │ ├── client.py
│ │ ├── client_stdio.py
│ │ └── server.py
│ ├── prompts_as_tools/
│ │ ├── client.py
│ │ └── server.py
│ ├── providers/
│ │ └── sqlite/
│ │ ├── README.md
│ │ ├── server.py
│ │ └── setup_db.py
│ ├── resources_as_tools/
│ │ ├── client.py
│ │ └── server.py
│ ├── run_with_tracing.py
│ ├── sampling/
│ │ ├── README.md
│ │ ├── server_fallback.py
│ │ ├── structured_output.py
│ │ ├── text.py
│ │ └── tool_use.py
│ ├── screenshot.fastmcp.json
│ ├── screenshot.py
│ ├── search/
│ │ ├── README.md
│ │ ├── client_bm25.py
│ │ ├── client_regex.py
│ │ ├── server_bm25.py
│ │ └── server_regex.py
│ ├── simple_echo.py
│ ├── skills/
│ │ ├── README.md
│ │ ├── client.py
│ │ ├── download_skills.py
│ │ ├── sample_skills/
│ │ │ ├── code-review/
│ │ │ │ └── SKILL.md
│ │ │ └── pdf-processing/
│ │ │ ├── SKILL.md
│ │ │ └── reference.md
│ │ └── server.py
│ ├── smart_home/
│ │ ├── README.md
│ │ ├── hub.fastmcp.json
│ │ ├── lights.fastmcp.json
│ │ ├── pyproject.toml
│ │ └── src/
│ │ └── smart_home/
│ │ ├── __init__.py
│ │ ├── __main__.py
│ │ ├── hub.py
│ │ ├── lights/
│ │ │ ├── __init__.py
│ │ │ ├── hue_utils.py
│ │ │ └── server.py
│ │ ├── py.typed
│ │ └── settings.py
│ ├── tags_example.py
│ ├── task_elicitation.py
│ ├── tasks/
│ │ ├── README.md
│ │ ├── client.py
│ │ ├── docker-compose.yml
│ │ └── server.py
│ ├── testing_demo/
│ │ ├── README.md
│ │ ├── pyproject.toml
│ │ ├── server.py
│ │ └── tests/
│ │ └── test_server.py
│ ├── text_me.py
│ ├── tool_result_echo.py
│ └── versioning/
│ ├── client_version_selection.py
│ ├── version_filters.py
│ └── versioned_components.py
├── justfile
├── logo.py
├── loq.toml
├── pyproject.toml
├── scripts/
│ ├── auto_close_duplicates.py
│ ├── auto_close_needs_mre.py
│ └── benchmark_imports.py
├── skills/
│ └── fastmcp-client-cli/
│ └── SKILL.md
├── src/
│ └── fastmcp/
│ ├── __init__.py
│ ├── cli/
│ │ ├── __init__.py
│ │ ├── __main__.py
│ │ ├── apps_dev.py
│ │ ├── auth.py
│ │ ├── cimd.py
│ │ ├── cli.py
│ │ ├── client.py
│ │ ├── discovery.py
│ │ ├── generate.py
│ │ ├── install/
│ │ │ ├── __init__.py
│ │ │ ├── claude_code.py
│ │ │ ├── claude_desktop.py
│ │ │ ├── cursor.py
│ │ │ ├── gemini_cli.py
│ │ │ ├── goose.py
│ │ │ ├── mcp_json.py
│ │ │ ├── shared.py
│ │ │ └── stdio.py
│ │ ├── run.py
│ │ └── tasks.py
│ ├── client/
│ │ ├── __init__.py
│ │ ├── auth/
│ │ │ ├── __init__.py
│ │ │ ├── bearer.py
│ │ │ └── oauth.py
│ │ ├── client.py
│ │ ├── elicitation.py
│ │ ├── logging.py
│ │ ├── messages.py
│ │ ├── mixins/
│ │ │ ├── __init__.py
│ │ │ ├── prompts.py
│ │ │ ├── resources.py
│ │ │ ├── task_management.py
│ │ │ └── tools.py
│ │ ├── oauth_callback.py
│ │ ├── progress.py
│ │ ├── roots.py
│ │ ├── sampling/
│ │ │ ├── __init__.py
│ │ │ └── handlers/
│ │ │ ├── __init__.py
│ │ │ ├── anthropic.py
│ │ │ ├── google_genai.py
│ │ │ └── openai.py
│ │ ├── tasks.py
│ │ ├── telemetry.py
│ │ └── transports/
│ │ ├── __init__.py
│ │ ├── base.py
│ │ ├── config.py
│ │ ├── http.py
│ │ ├── inference.py
│ │ ├── memory.py
│ │ ├── sse.py
│ │ └── stdio.py
│ ├── contrib/
│ │ ├── README.md
│ │ ├── bulk_tool_caller/
│ │ │ ├── README.md
│ │ │ ├── __init__.py
│ │ │ ├── bulk_tool_caller.py
│ │ │ └── example.py
│ │ ├── component_manager/
│ │ │ ├── README.md
│ │ │ ├── __init__.py
│ │ │ ├── component_manager.py
│ │ │ └── example.py
│ │ └── mcp_mixin/
│ │ ├── README.md
│ │ ├── __init__.py
│ │ ├── example.py
│ │ └── mcp_mixin.py
│ ├── decorators.py
│ ├── dependencies.py
│ ├── exceptions.py
│ ├── experimental/
│ │ ├── __init__.py
│ │ ├── sampling/
│ │ │ ├── __init__.py
│ │ │ └── handlers/
│ │ │ ├── __init__.py
│ │ │ └── openai.py
│ │ ├── server/
│ │ │ └── openapi/
│ │ │ └── __init__.py
│ │ ├── transforms/
│ │ │ ├── __init__.py
│ │ │ └── code_mode.py
│ │ └── utilities/
│ │ └── openapi/
│ │ └── __init__.py
│ ├── mcp_config.py
│ ├── prompts/
│ │ ├── __init__.py
│ │ ├── base.py
│ │ └── function_prompt.py
│ ├── py.typed
│ ├── resources/
│ │ ├── __init__.py
│ │ ├── base.py
│ │ ├── function_resource.py
│ │ ├── template.py
│ │ └── types.py
│ ├── server/
│ │ ├── __init__.py
│ │ ├── app.py
│ │ ├── apps.py
│ │ ├── auth/
│ │ │ ├── __init__.py
│ │ │ ├── auth.py
│ │ │ ├── authorization.py
│ │ │ ├── cimd.py
│ │ │ ├── handlers/
│ │ │ │ └── authorize.py
│ │ │ ├── jwt_issuer.py
│ │ │ ├── middleware.py
│ │ │ ├── oauth_proxy/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── consent.py
│ │ │ │ ├── models.py
│ │ │ │ ├── proxy.py
│ │ │ │ └── ui.py
│ │ │ ├── oidc_proxy.py
│ │ │ ├── providers/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── auth0.py
│ │ │ │ ├── aws.py
│ │ │ │ ├── azure.py
│ │ │ │ ├── debug.py
│ │ │ │ ├── descope.py
│ │ │ │ ├── discord.py
│ │ │ │ ├── github.py
│ │ │ │ ├── google.py
│ │ │ │ ├── in_memory.py
│ │ │ │ ├── introspection.py
│ │ │ │ ├── jwt.py
│ │ │ │ ├── oci.py
│ │ │ │ ├── propelauth.py
│ │ │ │ ├── scalekit.py
│ │ │ │ ├── supabase.py
│ │ │ │ └── workos.py
│ │ │ ├── redirect_validation.py
│ │ │ └── ssrf.py
│ │ ├── context.py
│ │ ├── dependencies.py
│ │ ├── elicitation.py
│ │ ├── event_store.py
│ │ ├── http.py
│ │ ├── lifespan.py
│ │ ├── low_level.py
│ │ ├── middleware/
│ │ │ ├── __init__.py
│ │ │ ├── authorization.py
│ │ │ ├── caching.py
│ │ │ ├── dereference.py
│ │ │ ├── error_handling.py
│ │ │ ├── logging.py
│ │ │ ├── middleware.py
│ │ │ ├── ping.py
│ │ │ ├── rate_limiting.py
│ │ │ ├── response_limiting.py
│ │ │ ├── timing.py
│ │ │ └── tool_injection.py
│ │ ├── mixins/
│ │ │ ├── __init__.py
│ │ │ ├── lifespan.py
│ │ │ ├── mcp_operations.py
│ │ │ └── transport.py
│ │ ├── openapi/
│ │ │ ├── __init__.py
│ │ │ ├── components.py
│ │ │ ├── routing.py
│ │ │ └── server.py
│ │ ├── providers/
│ │ │ ├── __init__.py
│ │ │ ├── aggregate.py
│ │ │ ├── base.py
│ │ │ ├── fastmcp_provider.py
│ │ │ ├── filesystem.py
│ │ │ ├── filesystem_discovery.py
│ │ │ ├── local_provider/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── decorators/
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── prompts.py
│ │ │ │ │ ├── resources.py
│ │ │ │ │ └── tools.py
│ │ │ │ └── local_provider.py
│ │ │ ├── openapi/
│ │ │ │ ├── README.md
│ │ │ │ ├── __init__.py
│ │ │ │ ├── components.py
│ │ │ │ ├── provider.py
│ │ │ │ └── routing.py
│ │ │ ├── proxy.py
│ │ │ ├── skills/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── _common.py
│ │ │ │ ├── claude_provider.py
│ │ │ │ ├── directory_provider.py
│ │ │ │ ├── skill_provider.py
│ │ │ │ └── vendor_providers.py
│ │ │ └── wrapped_provider.py
│ │ ├── proxy.py
│ │ ├── sampling/
│ │ │ ├── __init__.py
│ │ │ ├── run.py
│ │ │ └── sampling_tool.py
│ │ ├── server.py
│ │ ├── tasks/
│ │ │ ├── __init__.py
│ │ │ ├── capabilities.py
│ │ │ ├── config.py
│ │ │ ├── elicitation.py
│ │ │ ├── handlers.py
│ │ │ ├── keys.py
│ │ │ ├── notifications.py
│ │ │ ├── requests.py
│ │ │ ├── routing.py
│ │ │ └── subscriptions.py
│ │ ├── telemetry.py
│ │ └── transforms/
│ │ ├── __init__.py
│ │ ├── catalog.py
│ │ ├── namespace.py
│ │ ├── prompts_as_tools.py
│ │ ├── resources_as_tools.py
│ │ ├── search/
│ │ │ ├── __init__.py
│ │ │ ├── base.py
│ │ │ ├── bm25.py
│ │ │ └── regex.py
│ │ ├── tool_transform.py
│ │ ├── version_filter.py
│ │ └── visibility.py
│ ├── settings.py
│ ├── telemetry.py
│ ├── tools/
│ │ ├── __init__.py
│ │ ├── base.py
│ │ ├── function_parsing.py
│ │ ├── function_tool.py
│ │ └── tool_transform.py
│ └── utilities/
│ ├── __init__.py
│ ├── async_utils.py
│ ├── auth.py
│ ├── cli.py
│ ├── components.py
│ ├── exceptions.py
│ ├── http.py
│ ├── inspect.py
│ ├── json_schema.py
│ ├── json_schema_type.py
│ ├── lifespan.py
│ ├── logging.py
│ ├── mcp_server_config/
│ │ ├── __init__.py
│ │ └── v1/
│ │ ├── __init__.py
│ │ ├── environments/
│ │ │ ├── __init__.py
│ │ │ ├── base.py
│ │ │ └── uv.py
│ │ ├── mcp_server_config.py
│ │ ├── schema.json
│ │ └── sources/
│ │ ├── __init__.py
│ │ ├── base.py
│ │ └── filesystem.py
│ ├── openapi/
│ │ ├── README.md
│ │ ├── __init__.py
│ │ ├── director.py
│ │ ├── formatters.py
│ │ ├── json_schema_converter.py
│ │ ├── models.py
│ │ ├── parser.py
│ │ └── schemas.py
│ ├── pagination.py
│ ├── skills.py
│ ├── tests.py
│ ├── timeout.py
│ ├── token_cache.py
│ ├── types.py
│ ├── ui.py
│ ├── version_check.py
│ └── versions.py
├── tests/
│ ├── __init__.py
│ ├── cli/
│ │ ├── __init__.py
│ │ ├── test_cimd_cli.py
│ │ ├── test_cli.py
│ │ ├── test_client_commands.py
│ │ ├── test_config.py
│ │ ├── test_cursor.py
│ │ ├── test_discovery.py
│ │ ├── test_generate_cli.py
│ │ ├── test_goose.py
│ │ ├── test_install.py
│ │ ├── test_mcp_server_config_integration.py
│ │ ├── test_mcp_server_config_schema.py
│ │ ├── test_project_prepare.py
│ │ ├── test_run.py
│ │ ├── test_run_config.py
│ │ ├── test_server_args.py
│ │ ├── test_shared.py
│ │ ├── test_tasks.py
│ │ └── test_with_argv.py
│ ├── client/
│ │ ├── __init__.py
│ │ ├── auth/
│ │ │ ├── __init__.py
│ │ │ ├── test_oauth_cimd.py
│ │ │ ├── test_oauth_client.py
│ │ │ └── test_oauth_static_client.py
│ │ ├── client/
│ │ │ ├── __init__.py
│ │ │ ├── test_auth.py
│ │ │ ├── test_client.py
│ │ │ ├── test_error_handling.py
│ │ │ ├── test_initialize.py
│ │ │ ├── test_session.py
│ │ │ ├── test_timeout.py
│ │ │ └── test_transport.py
│ │ ├── sampling/
│ │ │ ├── __init__.py
│ │ │ └── handlers/
│ │ │ ├── __init__.py
│ │ │ ├── test_anthropic_handler.py
│ │ │ ├── test_google_genai_handler.py
│ │ │ └── test_openai_handler.py
│ │ ├── tasks/
│ │ │ ├── conftest.py
│ │ │ ├── test_client_prompt_tasks.py
│ │ │ ├── test_client_resource_tasks.py
│ │ │ ├── test_client_task_notifications.py
│ │ │ ├── test_client_task_protocol.py
│ │ │ ├── test_client_tool_tasks.py
│ │ │ ├── test_task_context_validation.py
│ │ │ └── test_task_result_caching.py
│ │ ├── telemetry/
│ │ │ ├── __init__.py
│ │ │ └── test_client_tracing.py
│ │ ├── test_elicitation.py
│ │ ├── test_elicitation_enums.py
│ │ ├── test_logs.py
│ │ ├── test_notifications.py
│ │ ├── test_oauth_callback_race.py
│ │ ├── test_oauth_callback_xss.py
│ │ ├── test_openapi.py
│ │ ├── test_progress.py
│ │ ├── test_roots.py
│ │ ├── test_sampling.py
│ │ ├── test_sampling_result_types.py
│ │ ├── test_sampling_tool_loop.py
│ │ ├── test_sse.py
│ │ ├── test_stdio.py
│ │ ├── test_streamable_http.py
│ │ └── transports/
│ │ ├── __init__.py
│ │ ├── test_memory_transport.py
│ │ ├── test_no_redirect.py
│ │ ├── test_transports.py
│ │ └── test_uv_transport.py
│ ├── conftest.py
│ ├── contrib/
│ │ ├── __init__.py
│ │ ├── test_bulk_tool_caller.py
│ │ ├── test_component_manager.py
│ │ └── test_mcp_mixin.py
│ ├── deprecated/
│ │ ├── __init__.py
│ │ ├── conftest.py
│ │ ├── openapi/
│ │ │ └── test_openapi.py
│ │ ├── server/
│ │ │ ├── __init__.py
│ │ │ └── test_include_exclude_tags.py
│ │ ├── test_add_tool_transformation.py
│ │ ├── test_deprecated.py
│ │ ├── test_exclude_args.py
│ │ ├── test_function_component_imports.py
│ │ ├── test_import_server.py
│ │ ├── test_openapi_deprecations.py
│ │ ├── test_settings.py
│ │ ├── test_tool_injection_middleware.py
│ │ └── test_tool_serializer.py
│ ├── experimental/
│ │ ├── README.md
│ │ ├── __init__.py
│ │ └── transforms/
│ │ ├── test_code_mode.py
│ │ ├── test_code_mode_discovery.py
│ │ └── test_code_mode_serialization.py
│ ├── fs/
│ │ ├── test_discovery.py
│ │ └── test_provider.py
│ ├── integration_tests/
│ │ ├── __init__.py
│ │ ├── auth/
│ │ │ ├── __init__.py
│ │ │ └── test_github_provider_integration.py
│ │ ├── conftest.py
│ │ ├── test_github_mcp_remote.py
│ │ └── test_timeout_fix.py
│ ├── prompts/
│ │ ├── __init__.py
│ │ ├── test_prompt.py
│ │ └── test_standalone_decorator.py
│ ├── resources/
│ │ ├── __init__.py
│ │ ├── test_file_resources.py
│ │ ├── test_function_resources.py
│ │ ├── test_resource_template.py
│ │ ├── test_resource_template_meta.py
│ │ ├── test_resource_template_query_params.py
│ │ ├── test_resources.py
│ │ └── test_standalone_decorator.py
│ ├── server/
│ │ ├── __init__.py
│ │ ├── auth/
│ │ │ ├── __init__.py
│ │ │ ├── oauth_proxy/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── conftest.py
│ │ │ │ ├── test_authorization.py
│ │ │ │ ├── test_client_registration.py
│ │ │ │ ├── test_config.py
│ │ │ │ ├── test_e2e.py
│ │ │ │ ├── test_oauth_proxy.py
│ │ │ │ ├── test_tokens.py
│ │ │ │ └── test_ui.py
│ │ │ ├── providers/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── test_auth0.py
│ │ │ │ ├── test_aws.py
│ │ │ │ ├── test_azure.py
│ │ │ │ ├── test_azure_scopes.py
│ │ │ │ ├── test_descope.py
│ │ │ │ ├── test_discord.py
│ │ │ │ ├── test_github.py
│ │ │ │ ├── test_google.py
│ │ │ │ ├── test_http_client.py
│ │ │ │ ├── test_introspection.py
│ │ │ │ ├── test_propelauth.py
│ │ │ │ ├── test_scalekit.py
│ │ │ │ ├── test_supabase.py
│ │ │ │ └── test_workos.py
│ │ │ ├── test_auth_provider.py
│ │ │ ├── test_authorization.py
│ │ │ ├── test_cimd.py
│ │ │ ├── test_cimd_validators.py
│ │ │ ├── test_debug_verifier.py
│ │ │ ├── test_enhanced_error_responses.py
│ │ │ ├── test_jwt_issuer.py
│ │ │ ├── test_jwt_provider.py
│ │ │ ├── test_jwt_provider_bearer.py
│ │ │ ├── test_multi_auth.py
│ │ │ ├── test_oauth_consent_flow.py
│ │ │ ├── test_oauth_consent_page.py
│ │ │ ├── test_oauth_mounting.py
│ │ │ ├── test_oauth_proxy_redirect_validation.py
│ │ │ ├── test_oauth_proxy_storage.py
│ │ │ ├── test_oidc_proxy.py
│ │ │ ├── test_oidc_proxy_token.py
│ │ │ ├── test_redirect_validation.py
│ │ │ ├── test_remote_auth_provider.py
│ │ │ ├── test_ssrf_protection.py
│ │ │ └── test_static_token_verifier.py
│ │ ├── http/
│ │ │ ├── __init__.py
│ │ │ ├── test_bearer_auth_backend.py
│ │ │ ├── test_custom_routes.py
│ │ │ ├── test_http_auth_middleware.py
│ │ │ ├── test_http_dependencies.py
│ │ │ ├── test_http_middleware.py
│ │ │ └── test_stale_access_token.py
│ │ ├── middleware/
│ │ │ ├── __init__.py
│ │ │ ├── test_caching.py
│ │ │ ├── test_dereference.py
│ │ │ ├── test_error_handling.py
│ │ │ ├── test_initialization_middleware.py
│ │ │ ├── test_logging.py
│ │ │ ├── test_middleware.py
│ │ │ ├── test_middleware_nested.py
│ │ │ ├── test_ping.py
│ │ │ ├── test_rate_limiting.py
│ │ │ ├── test_response_limiting.py
│ │ │ ├── test_timing.py
│ │ │ └── test_tool_injection.py
│ │ ├── mount/
│ │ │ ├── __init__.py
│ │ │ ├── test_advanced.py
│ │ │ ├── test_filtering.py
│ │ │ ├── test_mount.py
│ │ │ ├── test_prompts.py
│ │ │ ├── test_proxy.py
│ │ │ └── test_resources.py
│ │ ├── providers/
│ │ │ ├── __init__.py
│ │ │ ├── local_provider_tools/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── test_context.py
│ │ │ │ ├── test_decorator.py
│ │ │ │ ├── test_enabled.py
│ │ │ │ ├── test_local_provider_tools.py
│ │ │ │ ├── test_output_schema.py
│ │ │ │ ├── test_parameters.py
│ │ │ │ └── test_tags.py
│ │ │ ├── openapi/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── test_comprehensive.py
│ │ │ │ ├── test_deepobject_style.py
│ │ │ │ ├── test_end_to_end_compatibility.py
│ │ │ │ ├── test_openapi_features.py
│ │ │ │ ├── test_openapi_performance.py
│ │ │ │ ├── test_parameter_collisions.py
│ │ │ │ ├── test_performance_comparison.py
│ │ │ │ └── test_server.py
│ │ │ ├── proxy/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── test_proxy_client.py
│ │ │ │ ├── test_proxy_server.py
│ │ │ │ └── test_stateful_proxy_client.py
│ │ │ ├── test_base_provider.py
│ │ │ ├── test_fastmcp_provider.py
│ │ │ ├── test_local_provider.py
│ │ │ ├── test_local_provider_prompts.py
│ │ │ ├── test_local_provider_resources.py
│ │ │ ├── test_skills_provider.py
│ │ │ ├── test_skills_vendor_providers.py
│ │ │ └── test_transforming_provider.py
│ │ ├── sampling/
│ │ │ ├── __init__.py
│ │ │ ├── test_prepare_tools.py
│ │ │ └── test_sampling_tool.py
│ │ ├── tasks/
│ │ │ ├── __init__.py
│ │ │ ├── conftest.py
│ │ │ ├── test_context_background_task.py
│ │ │ ├── test_custom_subclass_tasks.py
│ │ │ ├── test_notifications.py
│ │ │ ├── test_progress_dependency.py
│ │ │ ├── test_resource_task_meta_parameter.py
│ │ │ ├── test_server_tasks_parameter.py
│ │ │ ├── test_sync_function_task_disabled.py
│ │ │ ├── test_task_capabilities.py
│ │ │ ├── test_task_config.py
│ │ │ ├── test_task_dependencies.py
│ │ │ ├── test_task_elicitation_relay.py
│ │ │ ├── test_task_meta_parameter.py
│ │ │ ├── test_task_metadata.py
│ │ │ ├── test_task_methods.py
│ │ │ ├── test_task_mount.py
│ │ │ ├── test_task_prompts.py
│ │ │ ├── test_task_protocol.py
│ │ │ ├── test_task_proxy.py
│ │ │ ├── test_task_resources.py
│ │ │ ├── test_task_return_types.py
│ │ │ ├── test_task_security.py
│ │ │ ├── test_task_status_notifications.py
│ │ │ ├── test_task_tools.py
│ │ │ └── test_task_ttl.py
│ │ ├── telemetry/
│ │ │ ├── __init__.py
│ │ │ ├── test_provider_tracing.py
│ │ │ └── test_server_tracing.py
│ │ ├── test_app_state.py
│ │ ├── test_auth_integration.py
│ │ ├── test_auth_integration_errors.py
│ │ ├── test_context.py
│ │ ├── test_dependencies.py
│ │ ├── test_dependencies_advanced.py
│ │ ├── test_event_store.py
│ │ ├── test_file_server.py
│ │ ├── test_icons.py
│ │ ├── test_input_validation.py
│ │ ├── test_log_level.py
│ │ ├── test_logging.py
│ │ ├── test_pagination.py
│ │ ├── test_providers.py
│ │ ├── test_run_server.py
│ │ ├── test_server.py
│ │ ├── test_server_docket.py
│ │ ├── test_server_lifespan.py
│ │ ├── test_session_visibility.py
│ │ ├── test_streamable_http_no_redirect.py
│ │ ├── test_tool_annotations.py
│ │ ├── test_tool_transformation.py
│ │ ├── transforms/
│ │ │ ├── test_catalog.py
│ │ │ ├── test_prompts_as_tools.py
│ │ │ ├── test_resources_as_tools.py
│ │ │ ├── test_search.py
│ │ │ └── test_visibility.py
│ │ └── versioning/
│ │ ├── __init__.py
│ │ ├── test_calls.py
│ │ ├── test_filtering.py
│ │ ├── test_mounting.py
│ │ ├── test_versioning.py
│ │ └── test_visibility_version_fallback.py
│ ├── telemetry/
│ │ ├── __init__.py
│ │ └── test_module.py
│ ├── test_apps.py
│ ├── test_apps_prefab.py
│ ├── test_fastmcp_app.py
│ ├── test_json_schema_generation.py
│ ├── test_mcp_config.py
│ ├── tools/
│ │ ├── __init__.py
│ │ ├── test_standalone_decorator.py
│ │ ├── test_tool_future_annotations.py
│ │ ├── test_tool_timeout.py
│ │ ├── tool/
│ │ │ ├── __init__.py
│ │ │ ├── test_callable.py
│ │ │ ├── test_content.py
│ │ │ ├── test_output_schema.py
│ │ │ ├── test_results.py
│ │ │ ├── test_title.py
│ │ │ └── test_tool.py
│ │ └── tool_transform/
│ │ ├── __init__.py
│ │ ├── test_args.py
│ │ ├── test_metadata.py
│ │ ├── test_schemas.py
│ │ └── test_tool_transform.py
│ └── utilities/
│ ├── __init__.py
│ ├── json_schema_type/
│ │ ├── __init__.py
│ │ ├── test_advanced.py
│ │ ├── test_constraints.py
│ │ ├── test_containers.py
│ │ ├── test_formats.py
│ │ ├── test_json_schema_type.py
│ │ └── test_unions.py
│ ├── openapi/
│ │ ├── __init__.py
│ │ ├── conftest.py
│ │ ├── test_allof_requestbody.py
│ │ ├── test_circular_references.py
│ │ ├── test_direct_array_schemas.py
│ │ ├── test_director.py
│ │ ├── test_legacy_compatibility.py
│ │ ├── test_models.py
│ │ ├── test_nullable_fields.py
│ │ ├── test_parser.py
│ │ ├── test_propertynames_ref_rewrite.py
│ │ ├── test_schemas.py
│ │ └── test_transitive_references.py
│ ├── test_async_utils.py
│ ├── test_auth.py
│ ├── test_cli.py
│ ├── test_components.py
│ ├── test_inspect.py
│ ├── test_inspect_icons.py
│ ├── test_json_schema.py
│ ├── test_logging.py
│ ├── test_skills.py
│ ├── test_tests.py
│ ├── test_token_cache.py
│ ├── test_typeadapter.py
│ ├── test_types.py
│ └── test_version_check.py
└── v3-notes/
├── get-methods-consolidation.md
├── prompt-internal-types.md
├── provider-architecture.md
├── provider-test-pattern.md
├── resource-internal-types.md
├── task-meta-parameter.md
└── visibility.md
Showing preview only (859K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (8642 symbols across 591 files)
FILE: docs/unify-intent.js
function isAuthPage (line 5) | function isAuthPage() {
function loadUnify (line 10) | function loadUnify() {
function update (line 47) | function update() {
FILE: docs/v2-banner.js
function addBanner (line 5) | function addBanner() {
function run (line 22) | function run() {
FILE: examples/apps/chart_server.py
function sales_chart (line 19) | def sales_chart(stacked: bool = False) -> Column:
FILE: examples/apps/contacts/contacts_server.py
class ContactModel (line 65) | class ContactModel(BaseModel):
function save_contact (line 84) | def save_contact(data: ContactModel) -> list[dict]:
function search_contacts (line 91) | def search_contacts(query: str) -> list[dict]:
function list_contacts (line 98) | def list_contacts() -> list[dict]:
function contact_manager (line 104) | def contact_manager() -> PrefabApp:
FILE: examples/apps/datatable_server.py
function team_directory (line 46) | def team_directory(department: str | None = None) -> Column:
FILE: examples/apps/greet_server.py
function greet (line 27) | def greet(
function farewell (line 50) | def farewell(
FILE: examples/apps/patterns_server.py
function quarterly_revenue (line 233) | def quarterly_revenue(year: int = 2025) -> PrefabApp:
function usage_trend (line 251) | def usage_trend() -> PrefabApp:
function ticket_breakdown (line 267) | def ticket_breakdown() -> PrefabApp:
function employee_directory (line 288) | def employee_directory() -> PrefabApp:
function contact_form (line 314) | def contact_form() -> PrefabApp:
function save_contact (line 350) | def save_contact(
function system_status (line 368) | def system_status() -> PrefabApp:
function feature_flags (line 404) | def feature_flags() -> PrefabApp:
function project_overview (line 432) | def project_overview() -> PrefabApp:
function api_health (line 468) | def api_health() -> PrefabApp:
FILE: examples/apps/qr_server/qr_server.py
function generate_qr (line 108) | def generate_qr(
function view (line 164) | def view() -> str:
FILE: examples/atproto_mcp/demo.py
function main (line 20) | async def main(enable_posting: bool = False):
FILE: examples/atproto_mcp/src/atproto_mcp/__main__.py
function main (line 4) | def main():
FILE: examples/atproto_mcp/src/atproto_mcp/_atproto/_client.py
function get_client (line 10) | def get_client() -> Client:
FILE: examples/atproto_mcp/src/atproto_mcp/_atproto/_posts.py
function create_post (line 19) | def create_post(
function _build_facets (line 92) | def _build_facets(
function _build_reply_ref (line 184) | def _build_reply_ref(reply_to: str, reply_root: str | None, client):
function _build_quote_embed (line 208) | def _build_quote_embed(quote_uri: str, client):
function _build_quote_with_images_embed (line 223) | def _build_quote_with_images_embed(
function _send_images (line 261) | def _send_images(
function create_thread (line 329) | def create_thread(posts: list[ThreadPost]) -> ThreadResult:
FILE: examples/atproto_mcp/src/atproto_mcp/_atproto/_profile.py
function get_profile_info (line 8) | def get_profile_info() -> ProfileInfo:
FILE: examples/atproto_mcp/src/atproto_mcp/_atproto/_read.py
function fetch_timeline (line 14) | def fetch_timeline(limit: int = 10) -> TimelineResult:
function search_for_posts (line 51) | def search_for_posts(query: str, limit: int = 10) -> SearchResult:
function fetch_notifications (line 91) | def fetch_notifications(limit: int = 10) -> NotificationsResult:
FILE: examples/atproto_mcp/src/atproto_mcp/_atproto/_social.py
function follow_user_by_handle (line 8) | def follow_user_by_handle(handle: str) -> FollowResult:
function like_post_by_uri (line 43) | def like_post_by_uri(uri: str) -> LikeResult:
function repost_by_uri (line 77) | def repost_by_uri(uri: str) -> RepostResult:
FILE: examples/atproto_mcp/src/atproto_mcp/server.py
function atproto_status (line 30) | def atproto_status() -> ProfileInfo:
function get_timeline (line 36) | def get_timeline() -> TimelineResult:
function get_notifications (line 42) | def get_notifications() -> NotificationsResult:
function post (line 49) | def post(
function follow (line 89) | def follow(
function like (line 102) | def like(
function repost (line 110) | def repost(
function search (line 118) | def search(
function create_thread (line 129) | def create_thread(
FILE: examples/atproto_mcp/src/atproto_mcp/settings.py
class Settings (line 5) | class Settings(BaseSettings):
FILE: examples/atproto_mcp/src/atproto_mcp/types.py
class ProfileInfo (line 6) | class ProfileInfo(TypedDict):
class PostResult (line 19) | class PostResult(TypedDict):
class Post (line 30) | class Post(TypedDict):
class TimelineResult (line 43) | class TimelineResult(TypedDict):
class SearchResult (line 52) | class SearchResult(TypedDict):
class Notification (line 62) | class Notification(TypedDict):
class NotificationsResult (line 73) | class NotificationsResult(TypedDict):
class FollowResult (line 82) | class FollowResult(TypedDict):
class LikeResult (line 92) | class LikeResult(TypedDict):
class RepostResult (line 101) | class RepostResult(TypedDict):
class RichTextLink (line 110) | class RichTextLink(TypedDict):
class RichTextMention (line 117) | class RichTextMention(TypedDict):
class ThreadPost (line 124) | class ThreadPost(TypedDict, total=False):
class ThreadResult (line 135) | class ThreadResult(TypedDict):
FILE: examples/auth/authkit_dcr/client.py
function main (line 17) | async def main():
FILE: examples/auth/authkit_dcr/server.py
function echo (line 26) | def echo(message: str) -> str:
FILE: examples/auth/aws_oauth/client.py
function main (line 16) | async def main():
FILE: examples/auth/aws_oauth/server.py
function echo (line 42) | def echo(message: str) -> str:
function get_access_token_claims (line 48) | async def get_access_token_claims() -> dict:
FILE: examples/auth/azure_oauth/client.py
function main (line 16) | async def main():
FILE: examples/auth/azure_oauth/server.py
function echo (line 38) | def echo(message: str) -> str:
FILE: examples/auth/discord_oauth/client.py
function main (line 16) | async def main():
FILE: examples/auth/discord_oauth/server.py
function echo (line 29) | def echo(message: str) -> str:
FILE: examples/auth/github_oauth/client.py
function main (line 16) | async def main():
FILE: examples/auth/github_oauth/server.py
function echo (line 29) | def echo(message: str) -> str:
FILE: examples/auth/google_oauth/client.py
function main (line 16) | async def main():
FILE: examples/auth/google_oauth/server.py
function echo (line 31) | def echo(message: str) -> str:
FILE: examples/auth/mounted/client.py
function main (line 17) | async def main():
FILE: examples/auth/mounted/server.py
function github_echo (line 49) | def github_echo(message: str) -> str:
function github_info (line 55) | def github_info() -> str:
function google_echo (line 72) | def google_echo(message: str) -> str:
function google_info (line 78) | def google_info() -> str:
FILE: examples/auth/propelauth_oauth/client.py
function main (line 16) | async def main():
FILE: examples/auth/propelauth_oauth/server.py
function echo (line 39) | def echo(message: str) -> str:
function whoami (line 45) | def whoami() -> dict:
FILE: examples/auth/scalekit_oauth/client.py
function main (line 16) | async def main():
FILE: examples/auth/scalekit_oauth/server.py
function echo (line 41) | def echo(message: str) -> str:
function auth_status (line 47) | def auth_status() -> dict:
FILE: examples/auth/workos_oauth/client.py
function main (line 16) | async def main():
FILE: examples/auth/workos_oauth/server.py
function echo (line 31) | def echo(message: str) -> str:
FILE: examples/code_mode/client.py
function _get_result (line 26) | def _get_result(result) -> Any:
function _format_params (line 36) | def _format_params(tool: dict) -> str:
function _tool_table (line 49) | def _tool_table(
function main (line 70) | async def main():
FILE: examples/code_mode/server.py
function add (line 22) | def add(a: int, b: int) -> int:
function multiply (line 28) | def multiply(x: float, y: float) -> float:
function fibonacci (line 34) | def fibonacci(n: int) -> list[int]:
function reverse_string (line 45) | def reverse_string(text: str) -> str:
function word_count (line 51) | def word_count(text: str) -> int:
function to_uppercase (line 57) | def to_uppercase(text: str) -> str:
function list_files (line 63) | def list_files(directory: str) -> list[str]:
function read_file (line 71) | def read_file(path: str) -> str:
FILE: examples/complex_inputs.py
class ShrimpTank (line 16) | class ShrimpTank(BaseModel):
class Shrimp (line 17) | class Shrimp(BaseModel):
function name_shrimp (line 24) | def name_shrimp(
FILE: examples/config_server.py
function get_status (line 28) | def get_status() -> dict[str, str | bool]:
function echo_message (line 38) | def echo_message(message: str) -> str:
FILE: examples/custom_tool_serializer_decorator.py
function with_serializer (line 19) | def with_serializer(serializer: Callable[[Any], str]):
function get_example_data (line 46) | def get_example_data() -> dict:
function get_json_data (line 52) | def get_json_data() -> dict:
function example_usage (line 57) | async def example_usage():
FILE: examples/desktop.py
function desktop (line 16) | def desktop() -> list[str]:
function get_greeting (line 24) | def get_greeting(name: str) -> str:
function add (line 30) | def add(a: int, b: int) -> int:
FILE: examples/diagnostics/client_with_tracing.py
function setup_tracing (line 32) | def setup_tracing():
function main (line 48) | async def main():
FILE: examples/diagnostics/server.py
function lifespan (line 20) | async def lifespan(server: FastMCP) -> AsyncIterator[None]:
function ping (line 78) | def ping() -> str:
function status_resource (line 84) | def status_resource() -> str:
function echo_template (line 90) | def echo_template(message: str) -> str:
function greet_prompt (line 96) | def greet_prompt(name: str = "World") -> str:
function fail_tool (line 105) | def fail_tool(message: str = "Intentional tool failure") -> str:
function error_resource (line 111) | def error_resource() -> str:
function error_template (line 117) | def error_template(code: str) -> str:
function fail_prompt (line 123) | def fail_prompt() -> str:
FILE: examples/echo.py
function echo_tool (line 12) | def echo_tool(text: str) -> str:
function echo_resource (line 18) | def echo_resource() -> str:
function echo_template (line 23) | def echo_template(text: str) -> str:
function echo_prompt (line 29) | def echo_prompt(text: str) -> str:
FILE: examples/elicitation.py
function greet (line 21) | async def greet(ctx: Context) -> str:
function survey (line 31) | async def survey(ctx: Context) -> str:
FILE: examples/fastmcp_config/server.py
function echo (line 10) | def echo(text: str) -> str:
function add (line 16) | def add(a: int, b: int) -> int:
function get_example_config (line 22) | def get_example_config() -> str:
FILE: examples/fastmcp_config_demo/server.py
function take_screenshot (line 20) | def take_screenshot() -> Image:
function analyze_colors (line 38) | def analyze_colors() -> dict:
FILE: examples/filesystem-provider/mcp/prompts/assistant.py
function code_review (line 7) | def code_review(code: str, language: str = "python") -> str:
function explain (line 32) | def explain(topic: str, audience: str = "developer") -> str:
FILE: examples/filesystem-provider/mcp/resources/config.py
function get_app_config (line 10) | def get_app_config() -> str:
function get_env_config (line 24) | def get_env_config(env: str) -> str:
function get_feature_flags (line 46) | def get_feature_flags() -> str:
FILE: examples/filesystem-provider/mcp/tools/calculator.py
function add (line 11) | def add(a: float, b: float) -> float:
function multiply (line 17) | def multiply(a: float, b: float) -> float:
FILE: examples/filesystem-provider/mcp/tools/greeting.py
function greet (line 7) | def greet(name: str) -> str:
function farewell (line 17) | def farewell(name: str) -> str:
function _format_message (line 27) | def _format_message(msg: str) -> str:
FILE: examples/get_file.py
function create_server (line 13) | def create_server():
FILE: examples/in_memory_proxy_example.py
class EchoService (line 18) | class EchoService:
method echo (line 21) | def echo(self, message: str) -> str:
function main (line 25) | async def main():
FILE: examples/memory.py
function cosine_similarity (line 48) | def cosine_similarity(a: list[float], b: list[float]) -> float:
function do_ai (line 56) | async def do_ai(
class Deps (line 72) | class Deps:
function get_db_pool (line 77) | async def get_db_pool() -> asyncpg.Pool:
class MemoryNode (line 86) | class MemoryNode(BaseModel):
method from_content (line 98) | async def from_content(cls, content: str, deps: Deps):
method save (line 102) | async def save(self, deps: Deps):
method merge_with (line 136) | async def merge_with(self, other: Self, deps: Deps):
method get_effective_importance (line 156) | def get_effective_importance(self):
function get_embedding (line 160) | async def get_embedding(text: str, deps: Deps) -> list[float]:
function delete_memory (line 168) | async def delete_memory(memory_id: int, deps: Deps):
function add_memory (line 173) | async def add_memory(content: str, deps: Deps):
function find_similar_memories (line 189) | async def find_similar_memories(embedding: list[float], deps: Deps) -> l...
function update_importance (line 215) | async def update_importance(user_embedding: list[float], deps: Deps):
function prune_memories (line 241) | async def prune_memories(deps: Deps):
function display_memory_tree (line 256) | async def display_memory_tree(deps: Deps) -> str:
function remember (line 278) | async def remember(
function read_profile (line 293) | async def read_profile() -> str:
function initialize_database (line 300) | async def initialize_database():
FILE: examples/mount_example.py
function get_weather_forecast (line 20) | def get_weather_forecast(location: str) -> str:
function weather_data (line 26) | async def weather_data():
function get_news_headlines (line 36) | def get_news_headlines() -> list[str]:
function news_data (line 46) | async def news_data():
function check_app_status (line 60) | def check_app_status() -> dict[str, str]:
function get_server_details (line 71) | async def get_server_details():
FILE: examples/namespace_activation/client.py
function load_server (line 17) | def load_server():
function show_tools (line 31) | def show_tools(tools: list, title: str) -> None:
function main (line 37) | async def main():
FILE: examples/namespace_activation/server.py
function analyze_portfolio (line 16) | def analyze_portfolio(symbols: list[str]) -> str:
function get_market_data (line 22) | def get_market_data(symbol: str) -> dict:
function execute_trade (line 28) | def execute_trade(symbol: str, quantity: int, side: str) -> str:
function list_users (line 35) | def list_users() -> list[str]:
function reset_user_password (line 41) | def reset_user_password(username: str) -> str:
function activate_finance (line 48) | async def activate_finance(ctx: Context) -> str:
function activate_admin (line 55) | async def activate_admin(ctx: Context) -> str:
function deactivate_all (line 62) | async def deactivate_all(ctx: Context) -> str:
FILE: examples/persistent_state/client.py
function main (line 21) | async def main() -> None:
FILE: examples/persistent_state/client_stdio.py
function main (line 27) | async def main() -> None:
FILE: examples/persistent_state/server.py
function set_value (line 17) | async def set_value(key: str, value: str, ctx: Context) -> str:
function get_value (line 24) | async def get_value(key: str, ctx: Context) -> str:
function list_session_info (line 33) | async def list_session_info(ctx: Context) -> dict[str, str | None]:
FILE: examples/prompts_as_tools/client.py
function main (line 16) | async def main():
FILE: examples/prompts_as_tools/server.py
function explain_concept (line 18) | def explain_concept(concept: str) -> str:
function analyze_code (line 33) | def analyze_code(code: str, language: str = "python", focus: str = "all"...
function review_pull_request (line 53) | def review_pull_request(
FILE: examples/providers/sqlite/server.py
class ConfigurableTool (line 31) | class ConfigurableTool(Tool):
method run (line 40) | async def run(self, arguments: dict[str, Any]) -> ToolResult:
class SQLiteToolProvider (line 67) | class SQLiteToolProvider(Provider):
method __init__ (line 74) | def __init__(self, db_path: str):
method list_tools (line 78) | async def list_tools(self) -> Sequence[Tool]:
method get_tool (line 85) | async def get_tool(self, name: str) -> Tool | None:
method _make_tool (line 94) | def _make_tool(self, row: aiosqlite.Row) -> ConfigurableTool:
function server_info (line 109) | def server_info() -> dict[str, str]:
function main (line 118) | async def main():
FILE: examples/providers/sqlite/setup_db.py
function setup_database (line 19) | async def setup_database() -> None:
FILE: examples/resources_as_tools/client.py
function main (line 16) | async def main():
FILE: examples/resources_as_tools/server.py
function app_config (line 18) | def app_config() -> str:
function readme (line 31) | def readme() -> str:
function user_profile (line 42) | def user_profile(user_id: str) -> str:
function read_file (line 55) | def read_file(directory: str, filename: str) -> str:
FILE: examples/run_with_tracing.py
function main (line 22) | def main() -> None:
FILE: examples/sampling/server_fallback.py
function summarize (line 41) | async def summarize(text: str, ctx: Context) -> str:
function translate (line 56) | async def translate(text: str, target_language: str, ctx: Context) -> str:
function main (line 70) | async def main():
FILE: examples/sampling/structured_output.py
class LoggingAnthropicHandler (line 28) | class LoggingAnthropicHandler(AnthropicSamplingHandler):
method __call__ (line 29) | async def __call__(
class SentimentAnalysis (line 39) | class SentimentAnalysis(BaseModel):
function analyze_sentiment (line 51) | async def analyze_sentiment(text: str, ctx: Context) -> dict:
function main (line 65) | async def main():
FILE: examples/sampling/text.py
class LoggingAnthropicHandler (line 27) | class LoggingAnthropicHandler(AnthropicSamplingHandler):
method __call__ (line 28) | async def __call__(
function write_haiku (line 42) | async def write_haiku(topic: str, ctx: Context) -> str:
function main (line 58) | async def main():
FILE: examples/sampling/tool_use.py
class LoggingAnthropicHandler (line 29) | class LoggingAnthropicHandler(AnthropicSamplingHandler):
method __call__ (line 30) | async def __call__(
function add (line 40) | def add(a: float, b: float) -> str:
function multiply (line 47) | def multiply(a: float, b: float) -> str:
function get_current_time (line 54) | def get_current_time() -> str:
function roll_dice (line 60) | def roll_dice(sides: int = 6) -> str:
class AssistantResponse (line 68) | class AssistantResponse(BaseModel):
function ask_assistant (line 81) | async def ask_assistant(question: str, ctx: Context) -> dict:
function main (line 96) | async def main():
FILE: examples/screenshot.py
function take_screenshot (line 22) | def take_screenshot() -> Image:
FILE: examples/search/client_bm25.py
function _get_result (line 23) | def _get_result(result) -> Any:
function _format_params (line 33) | def _format_params(tool: dict) -> str:
function _tool_table (line 46) | def _tool_table(
function main (line 67) | async def main():
FILE: examples/search/client_regex.py
function _get_result (line 23) | def _get_result(result) -> Any:
function _format_params (line 33) | def _format_params(tool: dict) -> str:
function _tool_table (line 46) | def _tool_table(
function main (line 67) | async def main():
FILE: examples/search/server_bm25.py
function add (line 24) | def add(a: int, b: int) -> int:
function multiply (line 30) | def multiply(x: float, y: float) -> float:
function fibonacci (line 36) | def fibonacci(n: int) -> list[int]:
function reverse_string (line 47) | def reverse_string(text: str) -> str:
function word_count (line 53) | def word_count(text: str) -> int:
function to_uppercase (line 59) | def to_uppercase(text: str) -> str:
function list_files (line 65) | def list_files(directory: str) -> list[str]:
function read_file (line 71) | def read_file(path: str) -> str:
FILE: examples/search/server_regex.py
function add (line 28) | def add(a: int, b: int) -> int:
function multiply (line 34) | def multiply(x: float, y: float) -> float:
function fibonacci (line 40) | def fibonacci(n: int) -> list[int]:
function reverse_string (line 51) | def reverse_string(text: str) -> str:
function word_count (line 57) | def word_count(text: str) -> int:
function to_uppercase (line 63) | def to_uppercase(text: str) -> str:
FILE: examples/simple_echo.py
function echo (line 12) | def echo(text: str) -> str:
FILE: examples/skills/client.py
function main (line 17) | async def main():
FILE: examples/skills/download_skills.py
function main (line 29) | async def main():
FILE: examples/smart_home/src/smart_home/__main__.py
function main (line 4) | def main():
FILE: examples/smart_home/src/smart_home/hub.py
function hub_status (line 16) | def hub_status() -> str:
FILE: examples/smart_home/src/smart_home/lights/hue_utils.py
function _get_bridge (line 9) | def _get_bridge() -> Bridge | None:
function handle_phue_error (line 23) | def handle_phue_error(
FILE: examples/smart_home/src/smart_home/lights/server.py
class HueAttributes (line 19) | class HueAttributes(TypedDict, total=False):
function read_all_lights (line 61) | def read_all_lights() -> list[str]:
function toggle_light (line 77) | def toggle_light(light_name: str, state: bool) -> dict[str, Any]:
function set_brightness (line 94) | def set_brightness(light_name: str, brightness: int) -> dict[str, Any]:
function list_groups (line 118) | def list_groups() -> list[str]:
function list_scenes (line 131) | def list_scenes() -> dict[str, list[str]] | list[str]:
function activate_scene (line 172) | def activate_scene(group_name: str, scene_name: str) -> dict[str, Any]:
function set_light_attributes (line 233) | def set_light_attributes(light_name: str, attributes: HueAttributes) -> ...
function set_group_attributes (line 260) | def set_group_attributes(group_name: str, attributes: HueAttributes) -> ...
function list_lights_by_group (line 285) | def list_lights_by_group() -> dict[str, list[str]] | list[str]:
FILE: examples/smart_home/src/smart_home/settings.py
class Settings (line 5) | class Settings(BaseSettings):
FILE: examples/tags_example.py
function get_users (line 20) | async def get_users():
function create_user (line 26) | async def create_user(name: str):
function get_admin_stats (line 32) | async def get_admin_stats():
function health_check (line 38) | async def health_check():
function get_metrics (line 44) | async def get_metrics():
function main (line 49) | async def main():
FILE: examples/task_elicitation.py
class DinnerPrefs (line 35) | class DinnerPrefs:
function plan_dinner (line 41) | async def plan_dinner(ctx: Context) -> str:
function handle_elicitation (line 63) | async def handle_elicitation(message, response_type, params, context):
function main (line 70) | async def main():
FILE: examples/tasks/client.py
function load_server (line 33) | def load_server():
function print_notification (line 51) | def print_notification(status: GetTaskResult) -> None:
function task (line 83) | async def task(
function immediate (line 132) | async def immediate(
FILE: examples/tasks/server.py
function slow_computation (line 33) | async def slow_computation(
FILE: examples/testing_demo/server.py
function add (line 16) | def add(a: int, b: int) -> int:
function greet (line 22) | def greet(name: str, greeting: str = "Hello") -> str:
function async_multiply (line 28) | async def async_multiply(x: float, y: float) -> float:
function server_info (line 35) | def server_info() -> str:
function greeting_resource (line 41) | def greeting_resource(name: str) -> str:
function hello_prompt (line 48) | def hello_prompt(name: str = "World") -> str:
function explain_prompt (line 54) | def explain_prompt(topic: str, detail_level: str = "medium") -> str:
FILE: examples/testing_demo/tests/test_server.py
function client (line 14) | async def client():
function test_add_tool (line 28) | async def test_add_tool(client: Client):
function test_greet_tool_default (line 34) | async def test_greet_tool_default(client: Client):
function test_greet_tool_custom (line 40) | async def test_greet_tool_custom(client: Client):
function test_async_multiply_tool (line 46) | async def test_async_multiply_tool(client: Client):
function test_add_parametrized (line 61) | async def test_add_parametrized(client: Client, a: int, b: int, expected...
function test_server_info_resource (line 67) | async def test_server_info_resource(client: Client):
function test_greeting_resource_template (line 74) | async def test_greeting_resource_template(client: Client):
function test_hello_prompt_default (line 81) | async def test_hello_prompt_default(client: Client):
function test_hello_prompt_custom (line 87) | async def test_hello_prompt_custom(client: Client):
function test_explain_prompt_levels (line 93) | async def test_explain_prompt_levels(client: Client):
function test_list_tools (line 110) | async def test_list_tools(client: Client):
function test_list_resources (line 120) | async def test_list_resources(client: Client):
function test_list_prompts (line 131) | async def test_list_prompts(client: Client):
function test_greet_with_dirty_equals (line 141) | async def test_greet_with_dirty_equals(client: Client):
function test_tool_schema_structure (line 149) | async def test_tool_schema_structure(client: Client):
FILE: examples/text_me.py
class SurgeSettings (line 30) | class SurgeSettings(BaseSettings):
function text_me (line 50) | def text_me(text_content: str) -> str:
FILE: examples/tool_result_echo.py
class EchoData (line 19) | class EchoData:
function echo (line 25) | def echo(text: str) -> ToolResult:
FILE: examples/versioning/client_version_selection.py
function charge (line 21) | def charge(amount: int, currency: str = "USD") -> dict:
function charge (line 27) | def charge( # noqa: F811
function charge (line 35) | def charge( # noqa: F811
function main (line 45) | async def main():
FILE: examples/versioning/version_filters.py
function process (line 24) | def process(data: str) -> str:
function process (line 30) | def process(data: str, mode: str = "upper") -> str: # noqa: F811
function process (line 36) | def process(data: str, mode: str = "upper", repeat: int = 1) -> str: # ...
function health (line 44) | def health() -> str:
function show_surface (line 60) | async def show_surface(name: str, server: FastMCP):
function main (line 76) | async def main():
FILE: examples/versioning/versioned_components.py
function calculate (line 25) | def calculate(x: int, y: int) -> int:
function calculate (line 31) | def calculate(x: int, y: int, z: int = 0) -> int: # noqa: F811
function config_v1 (line 41) | def config_v1() -> str:
function config_v2 (line 46) | def config_v2() -> str:
function summarize (line 55) | def summarize(text: str) -> str:
function summarize (line 60) | def summarize(text: str, style: str = "concise") -> str: # noqa: F811
function main (line 64) | async def main():
FILE: scripts/auto_close_duplicates.py
class Issue (line 23) | class Issue:
class Comment (line 35) | class Comment:
class Reaction (line 47) | class Reaction:
class GitHubClient (line 55) | class GitHubClient:
method __init__ (line 58) | def __init__(self, token: str, owner: str, repo: str):
method get_potential_duplicate_issues (line 68) | def get_potential_duplicate_issues(self) -> list[Issue]:
method get_issue_comments (line 115) | def get_issue_comments(self, issue_number: int) -> list[Comment]:
method get_comment_reactions (line 152) | def get_comment_reactions(
method remove_label (line 177) | def remove_label(self, issue_number: int, label: str) -> bool:
method close_issue (line 184) | def close_issue(self, issue_number: int, comment: str) -> bool:
function find_duplicate_comment (line 219) | def find_duplicate_comment(comments: list[Comment]) -> Comment | None:
function was_already_auto_closed (line 231) | def was_already_auto_closed(comments: list[Comment]) -> bool:
function is_past_cooldown (line 242) | def is_past_cooldown(duplicate_comment: Comment) -> bool:
function has_human_activity (line 251) | def has_human_activity(
function main (line 285) | def main():
FILE: scripts/auto_close_needs_mre.py
class Issue (line 24) | class Issue:
class Comment (line 37) | class Comment:
class Event (line 48) | class Event:
class GitHubClient (line 56) | class GitHubClient:
method __init__ (line 59) | def __init__(self, token: str, owner: str, repo: str):
method get_issues_with_label (line 69) | def get_issues_with_label(
method get_issue_events (line 112) | def get_issue_events(self, issue_number: int) -> list[Event]:
method get_issue_comments (line 150) | def get_issue_comments(self, issue_number: int) -> list[Comment]:
method get_issue_timeline (line 186) | def get_issue_timeline(self, issue_number: int) -> list[dict]:
method close_issue (line 218) | def close_issue(self, issue_number: int, comment: str) -> tuple[bool, ...
function find_label_application_date (line 257) | def find_label_application_date(
function has_author_activity_after (line 268) | def has_author_activity_after(
function should_close_as_needs_mre (line 303) | def should_close_as_needs_mre(
function main (line 323) | def main():
FILE: scripts/benchmark_imports.py
class BenchmarkCase (line 24) | class BenchmarkCase:
function measure_once (line 120) | def measure_once(stmt: str, prereqs: str) -> float | None:
function measure (line 139) | def measure(case: BenchmarkCase, runs: int) -> dict[str, float | str | N...
function print_table (line 161) | def print_table(results: list[dict[str, float | str | None]]) -> None:
function main (line 185) | def main() -> None:
FILE: src/fastmcp/__init__.py
function __getattr__ (line 39) | def __getattr__(name: str) -> object:
FILE: src/fastmcp/cli/apps_dev.py
function _has_ui_resource (line 288) | def _has_ui_resource(tool: dict[str, Any]) -> bool:
function _model_from_schema (line 299) | def _model_from_schema(tool_name: str, input_schema: dict[str, Any]) -> ...
function _build_picker_html (line 352) | def _build_picker_html(tools: list[dict[str, Any]]) -> str:
function _list_tools (line 448) | async def _list_tools(mcp_url: str) -> list[dict[str, Any]]:
function _read_mcp_resource (line 467) | async def _read_mcp_resource(mcp_url: str, uri: str) -> str | None:
function _fetch_app_bridge_bundle_sync (line 496) | def _fetch_app_bridge_bundle_sync(
function _fetch_app_bridge_bundle (line 590) | async def _fetch_app_bridge_bundle(
function _make_dev_app (line 606) | def _make_dev_app(
function _start_user_server (line 775) | async def _start_user_server(
function _wait_for_server (line 807) | async def _wait_for_server(url: str, timeout: float = 15.0) -> bool:
function run_dev_apps (line 825) | async def run_dev_apps(
FILE: src/fastmcp/cli/cimd.py
function create_command (line 32) | def create_command(
function validate_command (line 144) | def validate_command(
FILE: src/fastmcp/cli/cli.py
function _get_npx_command (line 49) | def _get_npx_command():
function _parse_env_var (line 63) | def _parse_env_var(env_var: str) -> tuple[str, str]:
function with_argv (line 73) | def with_argv(args: list[str] | None):
function version (line 96) | def version(
function inspector (line 142) | async def inspector(
function apps (line 337) | async def apps(
function run (line 385) | async def run(
function inspect (line 760) | async def inspect(
function prepare (line 1002) | async def prepare(
FILE: src/fastmcp/cli/client.py
function resolve_server_spec (line 43) | def resolve_server_spec(
function _build_stdio_from_command (line 115) | def _build_stdio_from_command(command_str: str) -> StdioTransport:
function _resolve_json_spec (line 130) | def _resolve_json_spec(path: Path) -> str | dict[str, Any]:
function _is_http_target (line 158) | def _is_http_target(resolved: str | dict[str, Any] | ClientTransport) ->...
function _terminal_elicitation_handler (line 169) | async def _terminal_elicitation_handler(
function _build_client (line 228) | def _build_client(
function coerce_value (line 264) | def coerce_value(raw: str, schema: dict[str, Any]) -> Any:
function parse_tool_arguments (line 298) | def parse_tool_arguments(
function _json_schema_type_to_str (line 356) | def _json_schema_type_to_str(schema: dict[str, Any]) -> str:
function format_tool_signature (line 370) | def format_tool_signature(tool: mcp.types.Tool) -> str:
function _print_schema (line 401) | def _print_schema(label: str, schema: dict[str, Any]) -> None:
function _sanitize_untrusted_text (line 409) | def _sanitize_untrusted_text(value: str) -> str:
function _format_call_result_text (line 420) | def _format_call_result_text(result: CallToolResult) -> None:
function _content_block_to_dict (line 452) | def _content_block_to_dict(block: mcp.types.ContentBlock) -> dict[str, A...
function _call_result_to_dict (line 463) | def _call_result_to_dict(result: CallToolResult) -> dict[str, Any]:
function _tools_to_json (line 473) | def _tools_to_json(tools: list[mcp.types.Tool]) -> list[dict[str, Any]]:
function _handle_tool_call (line 492) | async def _handle_tool_call(
function _handle_resource (line 541) | async def _handle_resource(
function _handle_prompt (line 579) | async def _handle_prompt(
function list_command (line 641) | async def list_command(
function call_command (line 796) | async def call_command(
function discover_command (line 897) | async def discover_command(
FILE: src/fastmcp/cli/discovery.py
class DiscoveredServer (line 37) | class DiscoveredServer:
method qualified_name (line 46) | def qualified_name(self) -> str:
method transport_summary (line 51) | def transport_summary(self) -> str:
function _normalize_server_entry (line 68) | def _normalize_server_entry(entry: dict[str, Any]) -> dict[str, Any]:
function _parse_mcp_servers (line 90) | def _parse_mcp_servers(
function _parse_mcp_config (line 120) | def _parse_mcp_config(path: Path, source: str) -> list[DiscoveredServer]:
function _scan_claude_desktop (line 140) | def _scan_claude_desktop() -> list[DiscoveredServer]:
function _scan_claude_code (line 157) | def _scan_claude_code(start_dir: Path) -> list[DiscoveredServer]:
function _scan_cursor_workspace (line 204) | def _scan_cursor_workspace(start_dir: Path) -> list[DiscoveredServer]:
function _scan_project_mcp_json (line 223) | def _scan_project_mcp_json(start_dir: Path) -> list[DiscoveredServer]:
function _scan_gemini (line 231) | def _scan_gemini(start_dir: Path) -> list[DiscoveredServer]:
function _scan_goose (line 251) | def _scan_goose() -> list[DiscoveredServer]:
function discover_servers (line 314) | def discover_servers(start_dir: Path | None = None) -> list[DiscoveredSe...
function resolve_name (line 331) | def resolve_name(name: str, start_dir: Path | None = None) -> ClientTran...
FILE: src/fastmcp/cli/generate.py
function _is_simple_type (line 32) | def _is_simple_type(schema: dict[str, Any]) -> bool:
function _is_simple_array (line 41) | def _is_simple_array(schema: dict[str, Any]) -> tuple[bool, str | None]:
function _schema_to_python_type (line 69) | def _schema_to_python_type(schema: dict[str, Any]) -> tuple[str, bool]:
function _format_schema_for_help (line 107) | def _format_schema_for_help(schema: dict[str, Any]) -> str:
function serialize_transport (line 122) | def serialize_transport(
function _to_python_identifier (line 155) | def _to_python_identifier(name: str) -> str:
function _tool_function_source (line 166) | def _tool_function_source(tool: mcp.types.Tool) -> str:
function generate_cli_script (line 283) | def generate_cli_script(
function _param_to_cli_flag (line 536) | def _param_to_cli_flag(prop_name: str) -> str:
function _schema_type_label (line 550) | def _schema_type_label(prop_schema: dict[str, Any]) -> str:
function _tool_skill_section (line 569) | def _tool_skill_section(tool: mcp.types.Tool, cli_filename: str) -> str:
function generate_skill_content (line 621) | def generate_skill_content(
function generate_cli_command (line 672) | async def generate_cli_command(
function _derive_server_name (line 792) | def _derive_server_name(server_spec: str) -> str:
FILE: src/fastmcp/cli/install/claude_code.py
function find_claude_command (line 20) | def find_claude_command() -> str | None:
function check_claude_code_available (line 68) | def check_claude_code_available() -> bool:
function install_claude_code (line 73) | def install_claude_code(
function claude_code_command (line 155) | async def claude_code_command(
FILE: src/fastmcp/cli/install/claude_desktop.py
function get_claude_config_path (line 20) | def get_claude_config_path(config_path: Path | None = None) -> Path | None:
function install_claude_desktop (line 49) | def install_claude_desktop(
function claude_desktop_command (line 139) | async def claude_desktop_command(
FILE: src/fastmcp/cli/install/cursor.py
function generate_cursor_deeplink (line 22) | def generate_cursor_deeplink(
function open_deeplink (line 47) | def open_deeplink(deeplink: str) -> bool:
function install_cursor_workspace (line 59) | def install_cursor_workspace(
function install_cursor (line 143) | def install_cursor(
function cursor_command (line 228) | async def cursor_command(
FILE: src/fastmcp/cli/install/gemini_cli.py
function find_gemini_command (line 20) | def find_gemini_command() -> str | None:
function check_gemini_cli_available (line 64) | def check_gemini_cli_available() -> bool:
function install_gemini_cli (line 69) | def install_gemini_cli(
function gemini_cli_command (line 152) | async def gemini_cli_command(
FILE: src/fastmcp/cli/install/goose.py
function _slugify (line 19) | def _slugify(name: str) -> str:
function generate_goose_deeplink (line 29) | def generate_goose_deeplink(
function _build_uvx_command (line 59) | def _build_uvx_command(
function install_goose (line 86) | def install_goose(
function goose_command (line 136) | async def goose_command(
FILE: src/fastmcp/cli/install/mcp_json.py
function install_mcp_json (line 20) | def install_mcp_json(
function mcp_json_command (line 98) | async def mcp_json_command(
FILE: src/fastmcp/cli/install/shared.py
function validate_server_name (line 28) | def validate_server_name(name: str) -> str:
function parse_env_var (line 42) | def parse_env_var(env_var: str) -> tuple[str, str]:
function process_common_args (line 53) | async def process_common_args(
function open_deeplink (line 169) | def open_deeplink(url: str, *, expected_scheme: str) -> bool:
FILE: src/fastmcp/cli/install/stdio.py
function install_stdio (line 21) | def install_stdio(
function stdio_command (line 78) | async def stdio_command(
FILE: src/fastmcp/cli/run.py
function is_url (line 83) | def is_url(path: str) -> bool:
function create_client_server (line 89) | def create_client_server(url: str) -> Any:
function create_mcp_config_server (line 109) | def create_mcp_config_server(mcp_config_path: Path) -> FastMCP[None]:
function load_mcp_server_config (line 118) | def load_mcp_server_config(config_path: Path) -> MCPServerConfig:
function run_command (line 135) | async def run_command(
function run_module_command (line 260) | def run_module_command(
function run_v1_server_async (line 299) | async def run_v1_server_async(
function _watch_filter (line 327) | def _watch_filter(_change: Change, path: str) -> bool:
function _terminate_process (line 332) | async def _terminate_process(process: asyncio.subprocess.Process) -> None:
function run_with_reload (line 364) | async def run_with_reload(
FILE: src/fastmcp/cli/tasks.py
function check_distributed_backend (line 22) | def check_distributed_backend() -> None:
function worker (line 61) | def worker(
FILE: src/fastmcp/client/auth/bearer.py
class BearerAuth (line 11) | class BearerAuth(httpx.Auth):
method __init__ (line 12) | def __init__(self, token: str):
method auth_flow (line 15) | def auth_flow(self, request):
FILE: src/fastmcp/client/auth/oauth.py
class ClientNotFoundError (line 37) | class ClientNotFoundError(Exception):
function check_if_auth_required (line 41) | async def check_if_auth_required(
class TokenStorageAdapter (line 71) | class TokenStorageAdapter(TokenStorage):
method __init__ (line 77) | def __init__(self, async_key_value: AsyncKeyValue, server_url: str):
method _get_token_cache_key (line 93) | def _get_token_cache_key(self) -> str:
method _get_client_info_cache_key (line 96) | def _get_client_info_cache_key(self) -> str:
method clear (line 99) | async def clear(self) -> None:
method get_tokens (line 104) | async def get_tokens(self) -> OAuthToken | None:
method set_tokens (line 108) | async def set_tokens(self, tokens: OAuthToken) -> None:
method get_client_info (line 119) | async def get_client_info(self) -> OAuthClientInformationFull | None:
method set_client_info (line 125) | async def set_client_info(self, client_info: OAuthClientInformationFul...
class OAuth (line 138) | class OAuth(OAuthClientProvider):
method __init__ (line 148) | def __init__(
method _bind (line 201) | def _bind(self, mcp_url: str) -> None:
method _initialize (line 279) | async def _initialize(self) -> None:
method redirect_handler (line 290) | async def redirect_handler(self, authorization_url: str) -> None:
method callback_handler (line 311) | async def callback_handler(self) -> tuple[str, str | None]:
method async_auth_flow (line 350) | async def async_auth_flow(
FILE: src/fastmcp/client/client.py
class ClientSessionState (line 97) | class ClientSessionState:
class CallToolResult (line 114) | class CallToolResult:
class Client (line 124) | class Client(
method __init__ (line 191) | def __init__(self: Client[T], transport: T, *args: Any, **kwargs: Any)...
method __init__ (line 194) | def __init__(
method __init__ (line 202) | def __init__(
method __init__ (line 210) | def __init__(
method __init__ (line 218) | def __init__(
method __init__ (line 226) | def __init__(
method __init__ (line 238) | def __init__(
method _reset_session_state (line 356) | def _reset_session_state(self, full: bool = False) -> None:
method session (line 371) | def session(self) -> ClientSession:
method initialize_result (line 381) | def initialize_result(self) -> mcp.types.InitializeResult | None:
method set_roots (line 385) | def set_roots(self, roots: RootsList | RootsHandler) -> None:
method set_sampling_callback (line 389) | def set_sampling_callback(
method set_elicitation_callback (line 404) | def set_elicitation_callback(
method is_connected (line 412) | def is_connected(self) -> bool:
method new (line 416) | def new(self) -> Client[ClientTransportT]:
method _context_manager (line 445) | async def _context_manager(self):
method initialize (line 461) | async def initialize(
method __aenter__ (line 512) | async def __aenter__(self):
method __aexit__ (line 515) | async def __aexit__(self, exc_type, exc_val, exc_tb):
method _connect (line 522) | async def _connect(self):
method _disconnect (line 612) | async def _disconnect(self, force: bool = False):
method _session_runner (line 650) | async def _session_runner(self):
method _await_with_session_monitoring (line 675) | async def _await_with_session_monitoring(
method _handle_task_status_notification (line 740) | def _handle_task_status_notification(
method close (line 762) | async def close(self):
method ping (line 768) | async def ping(self) -> bool:
method cancel (line 773) | async def cancel(
method progress (line 790) | async def progress(
method set_logging_level (line 802) | async def set_logging_level(self, level: mcp.types.LoggingLevel) -> None:
method send_roots_list_changed (line 806) | async def send_roots_list_changed(self) -> None:
method complete_mcp (line 812) | async def complete_mcp(
method complete (line 843) | async def complete(
method generate_name (line 870) | def generate_name(cls, name: str | None = None) -> str:
FILE: src/fastmcp/client/elicitation.py
class ElicitResult (line 22) | class ElicitResult(MCPElicitResult, Generic[T]):
function create_elicitation_callback (line 38) | def create_elicitation_callback(
FILE: src/fastmcp/client/logging.py
function default_log_handler (line 17) | async def default_log_handler(message: LogMessage) -> None:
function create_log_callback (line 47) | def create_log_callback(handler: LogHandler | None = None) -> LoggingFnT:
FILE: src/fastmcp/client/messages.py
class MessageHandler (line 16) | class MessageHandler:
method __call__ (line 22) | async def __call__(
method dispatch (line 30) | async def dispatch(self, message: Message) -> None:
method on_message (line 76) | async def on_message(self, message: Message) -> None:
method on_request (line 79) | async def on_request(
method on_ping (line 84) | async def on_ping(self, message: mcp.types.PingRequest) -> None:
method on_list_roots (line 87) | async def on_list_roots(self, message: mcp.types.ListRootsRequest) -> ...
method on_create_message (line 90) | async def on_create_message(self, message: mcp.types.CreateMessageRequ...
method on_notification (line 93) | async def on_notification(self, message: mcp.types.ServerNotification)...
method on_exception (line 96) | async def on_exception(self, message: Exception) -> None:
method on_progress (line 99) | async def on_progress(self, message: mcp.types.ProgressNotification) -...
method on_logging_message (line 102) | async def on_logging_message(
method on_tool_list_changed (line 107) | async def on_tool_list_changed(
method on_resource_list_changed (line 112) | async def on_resource_list_changed(
method on_prompt_list_changed (line 117) | async def on_prompt_list_changed(
method on_resource_updated (line 122) | async def on_resource_updated(
method on_cancelled (line 127) | async def on_cancelled(self, message: mcp.types.CancelledNotification)...
FILE: src/fastmcp/client/mixins/prompts.py
class ClientPromptsMixin (line 31) | class ClientPromptsMixin:
method list_prompts_mcp (line 36) | async def list_prompts_mcp(
method list_prompts (line 59) | async def list_prompts(
method get_prompt_mcp (line 107) | async def get_prompt_mcp(
method get_prompt (line 176) | async def get_prompt(
method get_prompt (line 187) | async def get_prompt(
method get_prompt (line 199) | async def get_prompt(
method _get_prompt_as_task (line 247) | async def _get_prompt_as_task(
FILE: src/fastmcp/client/mixins/resources.py
class ClientResourcesMixin (line 30) | class ClientResourcesMixin:
method list_resources_mcp (line 35) | async def list_resources_mcp(
method list_resources (line 58) | async def list_resources(
method list_resource_templates_mcp (line 105) | async def list_resource_templates_mcp(
method list_resource_templates (line 128) | async def list_resource_templates(
method read_resource_mcp (line 177) | async def read_resource_mcp(
method read_resource (line 233) | async def read_resource(
method read_resource (line 243) | async def read_resource(
method read_resource (line 254) | async def read_resource(
method _read_resource_as_task (line 308) | async def _read_resource_as_task(
FILE: src/fastmcp/client/mixins/task_management.py
class ClientTaskManagementMixin (line 30) | class ClientTaskManagementMixin:
method get_task_status (line 33) | async def get_task_status(self: Client, task_id: str) -> GetTaskResult:
method get_task_result (line 56) | async def get_task_result(self: Client, task_id: str) -> Any:
method list_tasks (line 85) | async def list_tasks(
method cancel_task (line 135) | async def cancel_task(self: Client, task_id: str) -> mcp.types.CancelT...
FILE: src/fastmcp/client/mixins/tools.py
class ClientToolsMixin (line 34) | class ClientToolsMixin:
method list_tools_mcp (line 39) | async def list_tools_mcp(
method list_tools (line 62) | async def list_tools(
method call_tool_mcp (line 111) | async def call_tool_mcp(
method _parse_call_tool_result (line 164) | async def _parse_call_tool_result(
method call_tool (line 191) | async def call_tool(
method call_tool (line 205) | async def call_tool(
method call_tool (line 220) | async def call_tool(
method _call_tool_as_task (line 291) | async def _call_tool_as_task(
function _parse_call_tool_result (line 361) | async def _parse_call_tool_result(
FILE: src/fastmcp/client/oauth_callback.py
function create_callback_html (line 34) | def create_callback_html(
class CallbackResponse (line 80) | class CallbackResponse:
method from_dict (line 87) | def from_dict(cls, data: dict[str, str]) -> CallbackResponse:
method to_dict (line 90) | def to_dict(self) -> dict[str, str]:
class OAuthCallbackResult (line 95) | class OAuthCallbackResult:
function create_oauth_callback_server (line 103) | def create_oauth_callback_server(
FILE: src/fastmcp/client/progress.py
function default_progress_handler (line 12) | async def default_progress_handler(
FILE: src/fastmcp/client/roots.py
function convert_roots_list (line 19) | def convert_roots_list(roots: RootsList) -> list[mcp.types.Root]:
function create_roots_callback (line 33) | def create_roots_callback(
function _create_roots_callback_from_roots (line 45) | def _create_roots_callback_from_roots(
function _create_roots_callback_from_fn (line 58) | def _create_roots_callback_from_fn(
FILE: src/fastmcp/client/sampling/__init__.py
function create_sampling_callback (line 44) | def create_sampling_callback(
FILE: src/fastmcp/client/sampling/handlers/anthropic.py
function _image_content_to_anthropic_block (line 55) | def _image_content_to_anthropic_block(content: ImageContent) -> ImageBlo...
class AnthropicSamplingHandler (line 72) | class AnthropicSamplingHandler:
method __init__ (line 90) | def __init__(
method __call__ (line 96) | async def __call__(
method _iter_models_from_preferences (line 150) | def _iter_models_from_preferences(
method _convert_to_anthropic_messages (line 173) | def _convert_to_anthropic_messages(
method _message_to_create_message_result (line 328) | def _message_to_create_message_result(
method _select_model_from_preferences (line 349) | def _select_model_from_preferences(
method _convert_tools_to_anthropic (line 360) | def _convert_tools_to_anthropic(tools: list[Tool]) -> list[ToolParam]:
method _convert_tool_choice_to_anthropic (line 379) | def _convert_tool_choice_to_anthropic(
method _message_to_result_with_tools (line 399) | def _message_to_result_with_tools(
FILE: src/fastmcp/client/sampling/handlers/google_genai.py
class GoogleGenaiSamplingHandler (line 56) | class GoogleGenaiSamplingHandler:
method __init__ (line 76) | def __init__(
method __call__ (line 86) | async def __call__(
method _get_model (line 136) | def _get_model(self, model_preferences: ModelPreferences | None) -> str:
function _convert_tool_to_google_genai (line 144) | def _convert_tool_to_google_genai(tool: MCPTool) -> GoogleTool:
function _convert_tool_choice_to_google_genai (line 161) | def _convert_tool_choice_to_google_genai(tool_choice: ToolChoice | None)...
function _sampling_content_to_google_genai_part (line 191) | def _sampling_content_to_google_genai_part(
function _convert_messages_to_google_genai_content (line 268) | def _convert_messages_to_google_genai_content(
function _get_candidate_from_response (line 306) | def _get_candidate_from_response(response: GenerateContentResponse) -> C...
function _response_to_create_message_result (line 314) | def _response_to_create_message_result(
function _response_to_result_with_tools (line 331) | def _response_to_result_with_tools(
FILE: src/fastmcp/client/sampling/handlers/openai.py
function _image_content_to_openai_part (line 63) | def _image_content_to_openai_part(
function _audio_content_to_openai_part (line 79) | def _audio_content_to_openai_part(
class OpenAISamplingHandler (line 95) | class OpenAISamplingHandler:
method __init__ (line 98) | def __init__(
method __call__ (line 106) | async def __call__(
method _iter_models_from_preferences (line 157) | def _iter_models_from_preferences(
method _convert_to_openai_messages (line 182) | def _convert_to_openai_messages(
method _chat_completion_to_create_message_result (line 382) | def _chat_completion_to_create_message_result(
method _select_model_from_preferences (line 399) | def _select_model_from_preferences(
method _convert_tools_to_openai (line 410) | def _convert_tools_to_openai(tools: list[Tool]) -> list[ChatCompletion...
method _convert_tool_choice_to_openai (line 432) | def _convert_tool_choice_to_openai(
method _chat_completion_to_result_with_tools (line 446) | def _chat_completion_to_result_with_tools(
FILE: src/fastmcp/client/tasks.py
class TaskNotificationHandler (line 26) | class TaskNotificationHandler(MessageHandler):
method __init__ (line 29) | def __init__(self, client: Client):
method dispatch (line 33) | async def dispatch(self, message: Message) -> None:
class Task (line 47) | class Task(abc.ABC, Generic[TaskResultT]):
method __init__ (line 60) | def __init__(
method _check_client_connected (line 87) | def _check_client_connected(self) -> None:
method task_id (line 105) | def task_id(self) -> str:
method returned_immediately (line 110) | def returned_immediately(self) -> bool:
method _handle_status_notification (line 119) | def _handle_status_notification(self, status: GetTaskResult) -> None:
method on_status_change (line 145) | def on_status_change(
method status (line 171) | async def status(self) -> GetTaskResult:
method result (line 202) | async def result(self) -> TaskResultT:
method wait (line 209) | async def wait(
method cancel (line 272) | async def cancel(self) -> None:
method __await__ (line 289) | def __await__(self):
class ToolTask (line 294) | class ToolTask(Task["CallToolResult"]):
method __init__ (line 317) | def __init__(
method result (line 336) | async def result(self) -> CallToolResult:
class PromptTask (line 396) | class PromptTask(Task[mcp.types.GetPromptResult]):
method __init__ (line 408) | def __init__(
method result (line 427) | async def result(self) -> mcp.types.GetPromptResult:
class ResourceTask (line 461) | class ResourceTask(
method __init__ (line 475) | def __init__(
method result (line 497) | async def result(
FILE: src/fastmcp/client/telemetry.py
function client_span (line 12) | def client_span(
FILE: src/fastmcp/client/transports/base.py
class SessionKwargs (line 23) | class SessionKwargs(TypedDict, total=False):
class ClientTransport (line 36) | class ClientTransport(abc.ABC):
method connect_session (line 47) | async def connect_session(
method __repr__ (line 69) | def __repr__(self) -> str:
method close (line 73) | async def close(self): # noqa: B027
method get_session_id (line 76) | def get_session_id(self) -> str | None:
method _set_auth (line 80) | def _set_auth(self, auth: httpx.Auth | Literal["oauth"] | str | None):
FILE: src/fastmcp/client/transports/config.py
class MCPConfigTransport (line 25) | class MCPConfigTransport(ClientTransport):
method __init__ (line 72) | def __init__(self, config: MCPConfig | dict, name_as_prefix: bool = Tr...
method connect_session (line 88) | async def connect_session(
method _create_proxy (line 135) | async def _create_proxy(
method close (line 205) | async def close(self):
method __repr__ (line 209) | def __repr__(self) -> str:
FILE: src/fastmcp/client/transports/http.py
class StreamableHttpTransport (line 26) | class StreamableHttpTransport(ClientTransport):
method __init__ (line 29) | def __init__(
method _set_auth (line 98) | def _set_auth(self, auth: httpx.Auth | Literal["oauth"] | str | None):
method _make_verify_factory (line 121) | def _make_verify_factory(self) -> McpHttpClientFactory | None:
method connect_session (line 147) | async def connect_session(
method get_session_id (line 200) | def get_session_id(self) -> str | None:
method close (line 208) | async def close(self):
method __repr__ (line 212) | def __repr__(self) -> str:
FILE: src/fastmcp/client/transports/inference.py
function infer_transport (line 24) | def infer_transport(transport: ClientTransportT) -> ClientTransportT: ...
function infer_transport (line 28) | def infer_transport(transport: FastMCP) -> FastMCPTransport: ...
function infer_transport (line 32) | def infer_transport(transport: FastMCP1Server) -> FastMCPTransport: ...
function infer_transport (line 36) | def infer_transport(transport: MCPConfig) -> MCPConfigTransport: ...
function infer_transport (line 40) | def infer_transport(transport: dict[str, Any]) -> MCPConfigTransport: ...
function infer_transport (line 44) | def infer_transport(
function infer_transport (line 50) | def infer_transport(
function infer_transport (line 58) | def infer_transport(transport: Path) -> PythonStdioTransport | NodeStdio...
function infer_transport (line 61) | def infer_transport(
FILE: src/fastmcp/client/transports/memory.py
class FastMCPTransport (line 14) | class FastMCPTransport(ClientTransport):
method __init__ (line 23) | def __init__(self, mcp: FastMCP | FastMCP1Server, raise_exceptions: bo...
method connect_session (line 33) | async def connect_session(
method __repr__ (line 84) | def __repr__(self) -> str:
function _enter_server_lifespan (line 89) | async def _enter_server_lifespan(
FILE: src/fastmcp/client/transports/sse.py
class SSETransport (line 25) | class SSETransport(ClientTransport):
method __init__ (line 28) | def __init__(
method _set_auth (line 66) | def _set_auth(self, auth: httpx.Auth | Literal["oauth"] | str | None):
method _make_verify_factory (line 89) | def _make_verify_factory(self) -> McpHttpClientFactory | None:
method connect_session (line 115) | async def connect_session(
method __repr__ (line 151) | def __repr__(self) -> str:
FILE: src/fastmcp/client/transports/stdio.py
class StdioTransport (line 22) | class StdioTransport(ClientTransport):
method __init__ (line 30) | def __init__(
method connect_session (line 72) | async def connect_session(
method connect (line 84) | async def connect(
method disconnect (line 120) | async def disconnect(self):
method close (line 135) | async def close(self):
method __del__ (line 138) | def __del__(self):
method __repr__ (line 143) | def __repr__(self) -> str:
function _stdio_transport_connect_task (line 149) | async def _stdio_transport_connect_task(
class PythonStdioTransport (line 205) | class PythonStdioTransport(StdioTransport):
method __init__ (line 208) | def __init__(
class FastMCPStdioTransport (line 258) | class FastMCPStdioTransport(StdioTransport):
method __init__ (line 261) | def __init__(
class NodeStdioTransport (line 287) | class NodeStdioTransport(StdioTransport):
method __init__ (line 290) | def __init__(
class UvStdioTransport (line 340) | class UvStdioTransport(StdioTransport):
method __init__ (line 343) | def __init__(
class UvxStdioTransport (line 419) | class UvxStdioTransport(StdioTransport):
method __init__ (line 422) | def __init__(
class NpxStdioTransport (line 484) | class NpxStdioTransport(StdioTransport):
method __init__ (line 487) | def __init__(
FILE: src/fastmcp/contrib/bulk_tool_caller/bulk_tool_caller.py
class CallToolRequest (line 16) | class CallToolRequest(BaseModel):
class CallToolRequestResult (line 25) | class CallToolRequestResult(CallToolResult):
method from_call_tool_result (line 37) | def from_call_tool_result(
class BulkToolCaller (line 51) | class BulkToolCaller(MCPMixin):
method register_tools (line 58) | def register_tools(
method call_tools_bulk (line 72) | async def call_tools_bulk(
method call_tool_bulk (line 93) | async def call_tool_bulk(
method _call_tool (line 120) | async def _call_tool(
FILE: src/fastmcp/contrib/bulk_tool_caller/example.py
function echo_tool (line 10) | def echo_tool(text: str) -> str:
FILE: src/fastmcp/contrib/component_manager/component_manager.py
function set_up_component_manager (line 17) | def set_up_component_manager(
function _build_routes (line 50) | def _build_routes(server: FastMCP, base_path: str) -> list[Route]:
function _make_endpoint (line 91) | def _make_endpoint(server: FastMCP, component_type: str, action: str):
FILE: src/fastmcp/contrib/component_manager/example.py
function get_greeting (line 51) | def get_greeting() -> str:
function get_info (line 57) | def get_info() -> str:
FILE: src/fastmcp/contrib/mcp_mixin/example.py
class Sample (line 16) | class Sample(MCPMixin):
method __init__ (line 17) | def __init__(self, name):
method first_tool (line 21) | def first_tool(self):
method first_resource (line 26) | def first_resource(self):
method first_prompt (line 31) | def first_prompt(self):
function list_components (line 43) | async def list_components() -> None:
FILE: src/fastmcp/contrib/mcp_mixin/mcp_mixin.py
function mcp_tool (line 45) | def mcp_tool(
function mcp_resource (line 94) | def mcp_resource(
function mcp_prompt (line 140) | def mcp_prompt(
class MCPMixin (line 180) | class MCPMixin:
method _get_methods_to_register (line 190) | def _get_methods_to_register(self, registration_type: str):
method register_tools (line 202) | def register_tools(
method register_resources (line 232) | def register_resources(
method register_prompts (line 267) | def register_prompts(
method register_all (line 297) | def register_all(
FILE: src/fastmcp/decorators.py
function resolve_task_config (line 17) | def resolve_task_config(task: bool | TaskConfig | None) -> bool | TaskCo...
class HasFastMCPMeta (line 23) | class HasFastMCPMeta(Protocol):
function get_fastmcp_meta (line 29) | def get_fastmcp_meta(fn: Any) -> Any | None:
FILE: src/fastmcp/exceptions.py
class FastMCPError (line 6) | class FastMCPError(Exception):
class ValidationError (line 10) | class ValidationError(FastMCPError):
class ResourceError (line 14) | class ResourceError(FastMCPError):
class ToolError (line 18) | class ToolError(FastMCPError):
class PromptError (line 22) | class PromptError(FastMCPError):
class InvalidSignature (line 26) | class InvalidSignature(Exception):
class ClientError (line 30) | class ClientError(Exception):
class NotFoundError (line 34) | class NotFoundError(Exception):
class DisabledError (line 38) | class DisabledError(Exception):
class AuthorizationError (line 42) | class AuthorizationError(FastMCPError):
FILE: src/fastmcp/experimental/transforms/code_mode.py
function _ensure_async (line 40) | def _ensure_async(fn: Callable[..., Any]) -> Callable[..., Any]:
function _unwrap_tool_result (line 50) | def _unwrap_tool_result(result: ToolResult) -> dict[str, Any] | str:
class SandboxProvider (line 73) | class SandboxProvider(Protocol):
method run (line 82) | async def run(
class MontySandboxProvider (line 91) | class MontySandboxProvider:
method __init__ (line 102) | def __init__(
method run (line 109) | async def run(
function _render_tools (line 156) | def _render_tools(tools: Sequence[Tool], detail: ToolDetailLevel) -> str:
class Search (line 179) | class Search:
method __init__ (line 194) | def __init__(
method __call__ (line 212) | def __call__(self, get_catalog: GetToolCatalog) -> Tool:
class GetSchemas (line 261) | class GetSchemas:
method __init__ (line 273) | def __init__(
method __call__ (line 282) | def __call__(self, get_catalog: GetToolCatalog) -> Tool:
class GetTags (line 322) | class GetTags:
method __init__ (line 335) | def __init__(
method __call__ (line 344) | def __call__(self, get_catalog: GetToolCatalog) -> Tool:
class ListTools (line 389) | class ListTools:
method __init__ (line 400) | def __init__(
method __call__ (line 409) | def __call__(self, get_catalog: GetToolCatalog) -> Tool:
function _default_discovery_tools (line 434) | def _default_discovery_tools() -> list[DiscoveryToolFactory]:
class CodeMode (line 438) | class CodeMode(CatalogTransform):
method __init__ (line 451) | def __init__(
method _build_discovery_tools (line 472) | def _build_discovery_tools(self) -> list[Tool]:
method transform_tools (line 488) | async def transform_tools(self, tools: Sequence[Tool]) -> Sequence[Tool]:
method get_tool (line 491) | async def get_tool(
method _build_execute_description (line 505) | def _build_execute_description(self) -> str:
method _find_tool (line 516) | def _find_tool(name: str, tools: Sequence[Tool]) -> Tool | None:
method _get_execute_tool (line 523) | def _get_execute_tool(self) -> Tool:
method _make_execute_tool (line 528) | def _make_execute_tool(self) -> Tool:
FILE: src/fastmcp/mcp_config.py
function infer_transport_type_from_url (line 56) | def infer_transport_type_from_url(
class _TransformingMCPServerMixin (line 76) | class _TransformingMCPServerMixin(FastMCPBaseModel):
method _require_at_least_one_transform_field (line 94) | def _require_at_least_one_transform_field(
method _to_server_and_underlying_transport (line 113) | def _to_server_and_underlying_transport(
method to_transport (line 148) | def to_transport(self) -> ClientTransport:
class StdioMCPServer (line 155) | class StdioMCPServer(BaseModel):
method to_transport (line 188) | def to_transport(self) -> StdioTransport:
class TransformingStdioMCPServer (line 200) | class TransformingStdioMCPServer(_TransformingMCPServerMixin, StdioMCPSe...
class RemoteMCPServer (line 204) | class RemoteMCPServer(BaseModel):
method to_transport (line 240) | def to_transport(self) -> StreamableHttpTransport | SSETransport:
class TransformingRemoteMCPServer (line 265) | class TransformingRemoteMCPServer(_TransformingMCPServerMixin, RemoteMCP...
class MCPConfig (line 276) | class MCPConfig(BaseModel):
method wrap_servers_at_root (line 290) | def wrap_servers_at_root(cls, values: dict[str, Any]) -> dict[str, Any]:
method add_server (line 303) | def add_server(self, name: str, server: MCPServerTypes) -> None:
method from_dict (line 308) | def from_dict(cls, config: dict[str, Any]) -> Self:
method to_dict (line 312) | def to_dict(self) -> dict[str, Any]:
method write_to_file (line 316) | def write_to_file(self, file_path: Path) -> None:
method from_file (line 322) | def from_file(cls, file_path: Path) -> Self:
class CanonicalMCPConfig (line 330) | class CanonicalMCPConfig(MCPConfig):
method add_server (line 340) | def add_server(self, name: str, server: CanonicalMCPServerTypes) -> None:
function update_config_file (line 345) | def update_config_file(
FILE: src/fastmcp/prompts/base.py
class Message (line 43) | class Message(pydantic.BaseModel):
method __init__ (line 68) | def __init__(
method to_mcp_prompt_message (line 98) | def to_mcp_prompt_message(self) -> PromptMessage:
class PromptArgument (line 103) | class PromptArgument(FastMCPBaseModel):
class PromptResult (line 115) | class PromptResult(pydantic.BaseModel):
method __init__ (line 151) | def __init__(
method _normalize_messages (line 168) | def _normalize_messages(
method to_mcp_prompt_result (line 187) | def to_mcp_prompt_result(self) -> GetPromptResult:
class Prompt (line 197) | class Prompt(FastMCPComponent):
method to_mcp_prompt (line 209) | def to_mcp_prompt(
method from_function (line 235) | def from_function(
method render (line 271) | async def render(
method convert_result (line 284) | def convert_result(self, raw_value: Any) -> PromptResult:
method _render (line 321) | async def _render(
method _render (line 328) | async def _render(
method _render (line 334) | async def _render(
method register_with_docket (line 374) | def register_with_docket(self, docket: Docket) -> None:
method add_to_docket (line 380) | async def add_to_docket( # type: ignore[override]
method get_span_attributes (line 403) | def get_span_attributes(self) -> dict[str, Any]:
function __getattr__ (line 418) | def __getattr__(name: str) -> Any:
FILE: src/fastmcp/prompts/function_prompt.py
class DecoratedPrompt (line 53) | class DecoratedPrompt(Protocol):
method __call__ (line 58) | def __call__(self, *args: Any, **kwargs: Any) -> Any: ...
class PromptMeta (line 62) | class PromptMeta:
class FunctionPrompt (line 78) | class FunctionPrompt(Prompt):
method from_function (line 84) | def from_function(
method _convert_string_arguments (line 241) | def _convert_string_arguments(self, kwargs: dict[str, Any]) -> dict[st...
method render (line 285) | async def render(
method register_with_docket (line 335) | def register_with_docket(self, docket: Docket) -> None:
method add_to_docket (line 345) | async def add_to_docket(
function prompt (line 372) | def prompt(fn: F) -> F: ...
function prompt (line 374) | def prompt(
function prompt (line 387) | def prompt(
function prompt (line 402) | def prompt(
FILE: src/fastmcp/resources/base.py
class ResourceContent (line 37) | class ResourceContent(pydantic.BaseModel):
method __init__ (line 63) | def __init__(
method to_mcp_resource_contents (line 92) | def to_mcp_resource_contents(
class ResourceResult (line 119) | class ResourceResult(pydantic.BaseModel):
method __init__ (line 158) | def __init__(
method _normalize_contents (line 173) | def _normalize_contents(
method to_mcp_result (line 194) | def to_mcp_result(self, uri: AnyUrl | str) -> mcp.types.ReadResourceRe...
class Resource (line 210) | class Resource(FastMCPComponent):
method from_function (line 235) | def from_function(
method set_default_mime_type (line 274) | def set_default_mime_type(cls, mime_type: str | None) -> str:
method set_default_name (line 281) | def set_default_name(self) -> Self:
method read (line 291) | async def read(
method convert_result (line 303) | def convert_result(self, raw_value: Any) -> ResourceResult:
method _read (line 335) | async def _read(self, task_meta: None = None) -> ResourceResult: ...
method _read (line 338) | async def _read(self, task_meta: TaskMeta) -> mcp.types.CreateTaskResu...
method _read (line 340) | async def _read(
method to_mcp_resource (line 374) | def to_mcp_resource(
method __repr__ (line 393) | def __repr__(self) -> str:
method key (line 397) | def key(self) -> str:
method register_with_docket (line 402) | def register_with_docket(self, docket: Docket) -> None:
method add_to_docket (line 408) | async def add_to_docket( # type: ignore[override]
method get_span_attributes (line 429) | def get_span_attributes(self) -> dict[str, Any]:
function __getattr__ (line 443) | def __getattr__(name: str) -> Any:
FILE: src/fastmcp/resources/function_resource.py
class DecoratedResource (line 40) | class DecoratedResource(Protocol):
method __call__ (line 45) | def __call__(self, *args: Any, **kwargs: Any) -> Any: ...
class ResourceMeta (line 49) | class ResourceMeta:
class FunctionResource (line 68) | class FunctionResource(Resource):
method from_function (line 84) | def from_function(
method read (line 208) | async def read(
method register_with_docket (line 229) | def register_with_docket(self, docket: Docket) -> None:
function resource (line 240) | def resource(
FILE: src/fastmcp/resources/template.py
function extract_query_params (line 39) | def extract_query_params(uri_template: str) -> set[str]:
function build_regex (line 47) | def build_regex(template: str) -> re.Pattern[str] | None:
function match_uri_template (line 79) | def match_uri_template(uri: str, uri_template: str) -> dict[str, str] | ...
class ResourceTemplate (line 112) | class ResourceTemplate(FastMCPComponent):
method __repr__ (line 135) | def __repr__(self) -> str:
method from_function (line 139) | def from_function(
method set_default_mime_type (line 172) | def set_default_mime_type(cls, mime_type: str | None) -> str:
method matches (line 178) | def matches(self, uri: str) -> dict[str, Any] | None:
method read (line 182) | async def read(self, arguments: dict[str, Any]) -> str | bytes | Resou...
method convert_result (line 188) | def convert_result(self, raw_value: Any) -> ResourceResult:
method _read (line 205) | async def _read(
method _read (line 210) | async def _read(
method _read (line 214) | async def _read(
method create_resource (line 252) | async def create_resource(self, uri: str, params: dict[str, Any]) -> R...
method to_mcp_template (line 263) | def to_mcp_template(
method from_mcp_template (line 283) | def from_mcp_template(cls, mcp_template: SDKResourceTemplate) -> Resou...
method key (line 296) | def key(self) -> str:
method register_with_docket (line 301) | def register_with_docket(self, docket: Docket) -> None:
method add_to_docket (line 307) | async def add_to_docket( # type: ignore[override]
method get_span_attributes (line 330) | def get_span_attributes(self) -> dict[str, Any]:
class FunctionResourceTemplate (line 337) | class FunctionResourceTemplate(ResourceTemplate):
method _read (line 343) | async def _read(
method _read (line 348) | async def _read(
method _read (line 352) | async def _read(
method create_resource (line 383) | async def create_resource(self, uri: str, params: dict[str, Any]) -> R...
method read (line 402) | async def read(self, arguments: dict[str, Any]) -> str | bytes | Resou...
method register_with_docket (line 441) | def register_with_docket(self, docket: Docket) -> None:
method add_to_docket (line 451) | async def add_to_docket(
method from_function (line 477) | def from_function(
FILE: src/fastmcp/resources/types.py
class TextResource (line 21) | class TextResource(Resource):
method read (line 26) | async def read(self) -> ResourceResult:
class BinaryResource (line 37) | class BinaryResource(Resource):
method read (line 42) | async def read(self) -> ResourceResult:
class FileResource (line 53) | class FileResource(Resource):
method _async_path (line 70) | def _async_path(self) -> AsyncPath:
method validate_absolute_path (line 75) | def validate_absolute_path(cls, path: Path) -> Path:
method set_binary_from_mime_type (line 83) | def set_binary_from_mime_type(cls, is_binary: bool, info: ValidationIn...
method read (line 91) | async def read(self) -> ResourceResult:
class HttpResource (line 105) | class HttpResource(Resource):
method read (line 114) | async def read(self) -> ResourceResult:
class DirectoryResource (line 126) | class DirectoryResource(Resource):
method _async_path (line 141) | def _async_path(self) -> AsyncPath:
method validate_absolute_path (line 146) | def validate_absolute_path(cls, path: Path) -> Path:
method list_files (line 152) | async def list_files(self) -> list[Path]:
method read (line 168) | async def read(self) -> ResourceResult:
FILE: src/fastmcp/server/__init__.py
function __getattr__ (line 7) | def __getattr__(name: str) -> object:
FILE: src/fastmcp/server/app.py
function get_global_tool (line 61) | def get_global_tool(name: str) -> Tool | None:
function _make_global_key (line 71) | def _make_global_key(name: str) -> str:
function _register_global_key (line 76) | def _register_global_key(tool: Tool, fn: Any, global_key: str) -> None:
function _stamp_global_key (line 82) | def _stamp_global_key(tool: Tool, global_key: str) -> None:
function _resolve_tool_ref (line 96) | def _resolve_tool_ref(fn: Any) -> Any:
function _dispatch_decorator (line 132) | def _dispatch_decorator(
class FastMCPApp (line 167) | class FastMCPApp(Provider):
method __init__ (line 176) | def __init__(self, name: str) -> None:
method __repr__ (line 181) | def __repr__(self) -> str:
method tool (line 189) | def tool(
method tool (line 201) | def tool(
method tool (line 212) | def tool(
method ui (line 274) | def ui(
method ui (line 289) | def ui(
method ui (line 303) | def ui(
method add_tool (line 389) | def add_tool(
method _list_tools (line 428) | async def _list_tools(self) -> Sequence[Tool]:
method _get_tool (line 431) | async def _get_tool(self, name: str, version: Any = None) -> Tool | None:
method _list_resources (line 434) | async def _list_resources(self) -> Sequence[Any]:
method _get_resource (line 437) | async def _get_resource(self, uri: str, version: Any = None) -> Any | ...
method _list_resource_templates (line 440) | async def _list_resource_templates(self) -> Sequence[Any]:
method _get_resource_template (line 443) | async def _get_resource_template(self, uri: str, version: Any = None) ...
method _list_prompts (line 446) | async def _list_prompts(self) -> Sequence[Any]:
method _get_prompt (line 449) | async def _get_prompt(self, name: str, version: Any = None) -> Any | N...
method lifespan (line 453) | async def lifespan(self) -> AsyncIterator[None]:
method run (line 461) | def run(
FILE: src/fastmcp/server/apps.py
class ResourceCSP (line 18) | class ResourceCSP(BaseModel):
class ResourcePermissions (line 50) | class ResourcePermissions(BaseModel):
class AppConfig (line 77) | class AppConfig(BaseModel):
function app_config_to_meta_dict (line 115) | def app_config_to_meta_dict(app: AppConfig | dict[str, Any]) -> dict[str...
function resolve_ui_mime_type (line 122) | def resolve_ui_mime_type(uri: str, explicit_mime_type: str | None) -> st...
FILE: src/fastmcp/server/auth/__init__.py
function __getattr__ (line 34) | def __getattr__(name: str) -> object:
FILE: src/fastmcp/server/auth/auth.py
class AccessToken (line 54) | class AccessToken(_SDKAccessToken):
class TokenHandler (line 60) | class TokenHandler(_SDKTokenHandler):
method handle (line 76) | async def handle(self, request: Any):
class PrivateKeyJWTClientAuthenticator (line 126) | class PrivateKeyJWTClientAuthenticator(_SDKClientAuthenticator):
method __init__ (line 139) | def __init__(
method authenticate_request (line 156) | async def authenticate_request(
class AuthProvider (line 207) | class AuthProvider(TokenVerifierProtocol):
method __init__ (line 216) | def __init__(
method verify_token (line 236) | async def verify_token(self, token: str) -> AccessToken | None:
method set_mcp_path (line 249) | def set_mcp_path(self, mcp_path: str | None) -> None:
method get_routes (line 263) | def get_routes(
method get_well_known_routes (line 286) | def get_well_known_routes(
method get_middleware (line 318) | def get_middleware(self) -> list:
method _get_resource_url (line 333) | def _get_resource_url(self, path: str | None = None) -> AnyHttpUrl | N...
class TokenVerifier (line 352) | class TokenVerifier(AuthProvider):
method __init__ (line 359) | def __init__(
method scopes_supported (line 374) | def scopes_supported(self) -> list[str]:
method verify_token (line 384) | async def verify_token(self, token: str) -> AccessToken | None:
class RemoteAuthProvider (line 389) | class RemoteAuthProvider(AuthProvider):
method __init__ (line 404) | def __init__(
method verify_token (line 436) | async def verify_token(self, token: str) -> AccessToken | None:
method get_routes (line 440) | def get_routes(
class MultiAuth (line 472) | class MultiAuth(AuthProvider):
method __init__ (line 495) | def __init__(
method verify_token (line 537) | async def verify_token(self, token: str) -> AccessToken | None:
method set_mcp_path (line 558) | def set_mcp_path(self, mcp_path: str | None) -> None:
method get_routes (line 566) | def get_routes(self, mcp_path: str | None = None) -> list[Route]:
method get_well_known_routes (line 572) | def get_well_known_routes(self, mcp_path: str | None = None) -> list[R...
class OAuthProvider (line 583) | class OAuthProvider(
method __init__ (line 593) | def __init__(
method verify_token (line 646) | async def verify_token(self, token: str) -> AccessToken | None:
method get_routes (line 661) | def get_routes(
method get_well_known_routes (line 740) | def get_well_known_routes(
FILE: src/fastmcp/server/auth/authorization.py
class AuthContext (line 48) | class AuthContext:
method tool (line 64) | def tool(self) -> Tool | None:
function require_scopes (line 78) | def require_scopes(*scopes: str) -> AuthCheck:
function restrict_tag (line 106) | def restrict_tag(tag: str, *, scopes: list[str]) -> AuthCheck:
function run_auth_checks (line 134) | async def run_auth_checks(
FILE: src/fastmcp/server/auth/cimd.py
class CIMDDocument (line 45) | class CIMDDocument(BaseModel):
method validate_auth_method (line 125) | def validate_auth_method(cls, v: str) -> str:
method validate_redirect_uris (line 137) | def validate_redirect_uris(cls, v: list[str]) -> list[str]:
class CIMDValidationError (line 154) | class CIMDValidationError(Exception):
class CIMDFetchError (line 158) | class CIMDFetchError(Exception):
class _CIMDCacheEntry (line 163) | class _CIMDCacheEntry:
class _CIMDCachePolicy (line 175) | class _CIMDCachePolicy:
class CIMDFetcher (line 186) | class CIMDFetcher:
method __init__ (line 200) | def __init__(
method _parse_cache_policy (line 212) | def _parse_cache_policy(
method _has_freshness_headers (line 265) | def _has_freshness_headers(self, headers: Mapping[str, str]) -> bool:
method is_cimd_client_id (line 270) | def is_cimd_client_id(self, client_id: str) -> bool:
method fetch (line 287) | async def fetch(self, client_id_url: str) -> CIMDDocument:
method validate_redirect_uri (line 422) | def validate_redirect_uri(self, doc: CIMDDocument, redirect_uri: str) ...
class CIMDAssertionValidator (line 452) | class CIMDAssertionValidator:
method __init__ (line 467) | def __init__(self):
method _cleanup_expired_jtis (line 479) | def _cleanup_expired_jtis(self) -> None:
method _maybe_cleanup (line 488) | def _maybe_cleanup(self) -> None:
method validate_assertion (line 495) | async def validate_assertion(
method _extract_public_key_from_jwks (line 621) | def _extract_public_key_from_jwks(self, token: str, jwks: dict) -> str:
class CIMDClientManager (line 677) | class CIMDClientManager:
method __init__ (line 690) | def __init__(
method is_cimd_client_id (line 711) | def is_cimd_client_id(self, client_id: str) -> bool:
method get_client (line 722) | async def get_client(self, client_id_url: str):
method validate_private_key_jwt (line 771) | async def validate_private_key_jwt(
FILE: src/fastmcp/server/auth/handlers/authorize.py
function create_unregistered_client_html (line 41) | def create_unregistered_client_html(
class AuthorizationHandler (line 161) | class AuthorizationHandler(SDKAuthorizationHandler):
method __init__ (line 176) | def __init__(
method handle (line 196) | async def handle(self, request: Request) -> Response:
method _create_enhanced_error_response (line 245) | async def _create_enhanced_error_response(
FILE: src/fastmcp/server/auth/jwt_issuer.py
function derive_jwt_key (line 30) | def derive_jwt_key(*, high_entropy_material: str, salt: str) -> bytes:
function derive_jwt_key (line 35) | def derive_jwt_key(*, low_entropy_material: str, salt: str) -> bytes:
function derive_jwt_key (line 39) | def derive_jwt_key(
class JWTIssuer (line 79) | class JWTIssuer:
method __init__ (line 87) | def __init__(
method issue_access_token (line 105) | def issue_access_token(
method issue_refresh_token (line 157) | def issue_refresh_token(
method verify_token (line 210) | def verify_token(
FILE: src/fastmcp/server/auth/middleware.py
class RequireAuthMiddleware (line 22) | class RequireAuthMiddleware(SDKRequireAuthMiddleware):
method _send_auth_error (line 30) | async def _send_auth_error(
FILE: src/fastmcp/server/auth/oauth_proxy/consent.py
class ConsentMixin (line 35) | class ConsentMixin:
method _normalize_uri (line 45) | def _normalize_uri(self, uri: str) -> str:
method _make_client_key (line 54) | def _make_client_key(self, client_id: str, redirect_uri: str | AnyUrl)...
method _cookie_name (line 59) | def _cookie_name(self: OAuthProxy, base_name: str) -> str:
method _cookie_signing_key (line 65) | def _cookie_signing_key(self: OAuthProxy) -> bytes:
method _sign_cookie (line 76) | def _sign_cookie(self: OAuthProxy, payload: str) -> str:
method _verify_cookie (line 86) | def _verify_cookie(self: OAuthProxy, signed_value: str) -> str | None:
method _decode_list_cookie (line 109) | def _decode_list_cookie(
method _encode_list_cookie (line 138) | def _encode_list_cookie(self: OAuthProxy, values: list[str]) -> str:
method _set_list_cookie (line 147) | def _set_list_cookie(
method _read_consent_bindings (line 165) | def _read_consent_bindings(self: OAuthProxy, request: Request) -> dict...
method _write_consent_bindings (line 190) | def _write_consent_bindings(
method _set_consent_binding_cookie (line 221) | def _set_consent_binding_cookie(
method _clear_consent_binding_cookie (line 238) | def _clear_consent_binding_cookie(
method _verify_consent_binding_cookie (line 249) | def _verify_consent_binding_cookie(
method _build_upstream_authorize_url (line 262) | def _build_upstream_authorize_url(
method _handle_consent (line 298) | async def _handle_consent(
method _show_consent_page (line 306) | async def _show_consent_page(
method _submit_consent (line 415) | async def _submit_consent(
FILE: src/fastmcp/server/auth/oauth_proxy/models.py
class OAuthTransaction (line 40) | class OAuthTransaction(BaseModel):
class ClientCode (line 62) | class ClientCode(BaseModel):
class UpstreamTokenSet (line 80) | class UpstreamTokenSet(BaseModel):
class JTIMapping (line 102) | class JTIMapping(BaseModel):
class RefreshTokenMetadata (line 114) | class RefreshTokenMetadata(BaseModel):
function _hash_token (line 127) | def _hash_token(token: str) -> str:
class ProxyDCRClient (line 136) | class ProxyDCRClient(OAuthClientInformationFull):
method validate_redirect_uri (line 167) | def validate_redirect_uri(self, redirect_uri: AnyUrl | None) -> AnyUrl:
FILE: src/fastmcp/server/auth/oauth_proxy/proxy.py
function _normalize_resource_url (line 95) | def _normalize_resource_url(url: str) -> str:
function _server_url_has_query (line 114) | def _server_url_has_query(url: str) -> bool:
class OAuthProxy (line 119) | class OAuthProxy(OAuthProvider, ConsentMixin):
method __init__ (line 229) | def __init__(
method set_mcp_path (line 558) | def set_mcp_path(self, mcp_path: str | None) -> None:
method jwt_issuer (line 582) | def jwt_issuer(self) -> JWTIssuer:
method _create_upstream_oauth_client (line 599) | def _create_upstream_oauth_client(self) -> AsyncOAuth2Client:
method _generate_pkce_pair (line 622) | def _generate_pkce_pair(self) -> tuple[str, str]:
method get_client (line 642) | async def get_client(self, client_id: str) -> OAuthClientInformationFu...
method register_client (line 686) | async def register_client(self, client_info: OAuthClientInformationFul...
method authorize (line 739) | async def authorize(
method load_authorization_code (line 858) | async def load_authorization_code(
method exchange_authorization_code (line 906) | async def exchange_authorization_code(
method _prepare_scopes_for_token_exchange (line 1106) | def _prepare_scopes_for_token_exchange(self, scopes: list[str]) -> lis...
method _prepare_scopes_for_upstream_refresh (line 1120) | def _prepare_scopes_for_upstream_refresh(self, scopes: list[str]) -> l...
method _extract_upstream_claims (line 1137) | async def _extract_upstream_claims(
method load_refresh_token (line 1164) | async def load_refresh_token(
method exchange_refresh_token (line 1193) | async def exchange_refresh_token(
method _get_verification_token (line 1433) | def _get_verification_token(
method _uses_alternate_verification (line 1444) | def _uses_alternate_verification(self) -> bool:
method load_access_token (line 1460) | async def load_access_token(self, token: str) -> AccessToken | None: ...
method revoke_token (line 1539) | async def revoke_token(self, token: AccessToken | RefreshToken) -> None:
method get_routes (line 1585) | def get_routes(
method _handle_idp_callback (line 1717) | async def _handle_idp_callback(
FILE: src/fastmcp/server/auth/oauth_proxy/ui.py
function create_consent_html (line 20) | def create_consent_html(
function create_error_html (line 215) | def create_error_html(
FILE: src/fastmcp/server/auth/oidc_proxy.py
class OIDCConfiguration (line 29) | class OIDCConfiguration(BaseModel):
method _enforce_strict (line 111) | def _enforce_strict(self) -> Self:
method get_oidc_configuration (line 144) | def get_oidc_configuration(
class OIDCProxy (line 174) | class OIDCProxy(OAuthProxy):
method __init__ (line 199) | def __init__(
method _get_verification_token (line 423) | def _get_verification_token(
method _uses_alternate_verification (line 441) | def _uses_alternate_verification(self) -> bool:
method get_oidc_configuration (line 450) | def get_oidc_configuration(
method get_token_verifier (line 467) | def get_token_verifier(
FILE: src/fastmcp/server/auth/providers/auth0.py
class Auth0Provider (line 36) | class Auth0Provider(OIDCProxy):
method __init__ (line 60) | def __init__(
FILE: src/fastmcp/server/auth/providers/aws.py
class AWSCognitoTokenVerifier (line 40) | class AWSCognitoTokenVerifier(JWTVerifier):
method verify_token (line 43) | async def verify_token(self, token: str) -> AccessToken | None:
class AWSCognitoProvider (line 67) | class AWSCognitoProvider(OIDCProxy):
method __init__ (line 98) | def __init__(
method get_token_verifier (line 178) | def get_token_verifier(
FILE: src/fastmcp/server/auth/providers/azure.py
class AzureProvider (line 35) | class AzureProvider(OAuthProxy):
method __init__ (line 95) | def __init__(
method authorize (line 259) | async def authorize(
method _prefix_scopes_for_azure (line 296) | def _prefix_scopes_for_azure(self, scopes: list[str]) -> list[str]:
method _build_upstream_authorize_url (line 331) | def _build_upstream_authorize_url(
method _prepare_scopes_for_token_exchange (line 356) | def _prepare_scopes_for_token_exchange(self, scopes: list[str]) -> lis...
method _prepare_scopes_for_upstream_refresh (line 382) | def _prepare_scopes_for_upstream_refresh(self, scopes: list[str]) -> l...
method _extract_upstream_claims (line 413) | async def _extract_upstream_claims(
method get_obo_credential (line 485) | async def get_obo_credential(self, user_assertion: str) -> OnBehalfOfC...
method close_obo_credentials (line 536) | async def close_obo_credentials(self) -> None:
class AzureJWTVerifier (line 547) | class AzureJWTVerifier(JWTVerifier):
method __init__ (line 580) | def __init__(
method scopes_supported (line 627) | def scopes_supported(self) -> list[str]:
function _require_azure_identity (line 651) | def _require_azure_identity(feature: str) -> None:
class _EntraOBOToken (line 662) | class _EntraOBOToken(Dependency[str]):
method __init__ (line 671) | def __init__(self, scopes: list[str]):
method __aenter__ (line 674) | async def __aenter__(self) -> str:
function EntraOBOToken (line 700) | def EntraOBOToken(scopes: list[str]) -> str:
FILE: src/fastmcp/server/auth/providers/debug.py
class DebugTokenVerifier (line 40) | class DebugTokenVerifier(TokenVerifier):
method __init__ (line 55) | def __init__(
method verify_token (line 77) | async def verify_token(self, token: str) -> AccessToken | None:
FILE: src/fastmcp/server/auth/providers/descope.py
class DescopeProvider (line 25) | class DescopeProvider(RemoteAuthProvider):
method __init__ (line 63) | def __init__(
method get_routes (line 165) | def get_routes(
FILE: src/fastmcp/server/auth/providers/discord.py
class DiscordTokenVerifier (line 42) | class DiscordTokenVerifier(TokenVerifier):
method __init__ (line 49) | def __init__(
method verify_token (line 72) | async def verify_token(self, token: str) -> AccessToken | None:
class DiscordProvider (line 165) | class DiscordProvider(OAuthProxy):
method __init__ (line 193) | def __init__(
FILE: src/fastmcp/server/auth/providers/github.py
class GitHubTokenVerifier (line 41) | class GitHubTokenVerifier(TokenVerifier):
method __init__ (line 52) | def __init__(
method verify_token (line 82) | async def verify_token(self, token: str) -> AccessToken | None:
class GitHubProvider (line 178) | class GitHubProvider(OAuthProxy):
method __init__ (line 206) | def __init__(
FILE: src/fastmcp/server/auth/providers/google.py
function _normalize_google_scope (line 47) | def _normalize_google_scope(scope: str) -> str:
class GoogleTokenVerifier (line 57) | class GoogleTokenVerifier(TokenVerifier):
method __init__ (line 64) | def __init__(
method verify_token (line 89) | async def verify_token(self, token: str) -> AccessToken | None:
class GoogleProvider (line 190) | class GoogleProvider(OAuthProxy):
method __init__ (line 218) | def __init__(
FILE: src/fastmcp/server/auth/providers/in_memory.py
class InMemoryOAuthProvider (line 31) | class InMemoryOAuthProvider(OAuthProvider):
method __init__ (line 37) | def __init__(
method get_client (line 65) | async def get_client(self, client_id: str) -> OAuthClientInformationFu...
method register_client (line 68) | async def register_client(self, client_info: OAuthClientInformationFul...
method authorize (line 92) | async def authorize(
method load_authorization_code (line 149) | async def load_authorization_code(
method exchange_authorization_code (line 162) | async def exchange_authorization_code(
method load_refresh_token (line 215) | async def load_refresh_token(
method exchange_refresh_token (line 230) | async def exchange_refresh_token(
method load_access_token (line 287) | async def load_access_token(self, token: str) -> AccessToken | None: ...
method verify_token (line 298) | async def verify_token(self, token: str) -> AccessToken | None: # typ...
method _revoke_internal (line 313) | def _revoke_internal(
method revoke_token (line 355) | async def revoke_token(
FILE: src/fastmcp/server/auth/providers/introspection.py
class IntrospectionTokenVerifier (line 45) | class IntrospectionTokenVerifier(TokenVerifier):
method __init__ (line 80) | def __init__(
method _create_basic_auth_header (line 150) | def _create_basic_auth_header(self) -> str:
method _extract_scopes (line 156) | def _extract_scopes(self, introspection_response: dict[str, Any]) -> l...
method verify_token (line 179) | async def verify_token(self, token: str) -> AccessToken | None:
FILE: src/fastmcp/server/auth/providers/jwt.py
class JWKData (line 27) | class JWKData(TypedDict, total=False):
class JWKSData (line 40) | class JWKSData(TypedDict):
class RSAKeyPair (line 47) | class RSAKeyPair:
method generate (line 54) | def generate(cls) -> RSAKeyPair:
method create_token (line 89) | def create_token(
function _looks_like_pem_public_key (line 142) | def _looks_like_pem_public_key(key: str | bytes) -> bool:
class JWTVerifier (line 156) | class JWTVerifier(TokenVerifier):
method __init__ (line 175) | def __init__(
method _get_verification_key (line 279) | async def _get_verification_key(self, token: str) -> str | bytes:
method _get_jwks_key (line 293) | async def _get_jwks_key(self, kid: str | None) -> str:
method _fetch_jwks (line 357) | async def _fetch_jwks(self) -> dict[str, Any]:
method _extract_scopes (line 380) | def _extract_scopes(self, claims: dict[str, Any]) -> list[str]:
method load_access_token (line 397) | async def load_access_token(self, token: str) -> AccessToken | None:
method verify_token (line 515) | async def verify_token(self, token: str) -> AccessToken | None:
class StaticTokenVerifier (line 531) | class StaticTokenVerifier(TokenVerifier):
method __init__ (line 549) | def __init__(
method verify_token (line 565) | async def verify_token(self, token: str) -> AccessToken | None:
FILE: src/fastmcp/server/auth/providers/oci.py
class OCIProvider (line 92) | class OCIProvider(OIDCProxy):
method __init__ (line 119) | def __init__(
FILE: src/fastmcp/server/auth/providers/propelauth.py
class PropelAuthTokenIntrospectionOverrides (line 36) | class PropelAuthTokenIntrospectionOverrides(TypedDict, total=False):
class PropelAuthProvider (line 43) | class PropelAuthProvider(RemoteAuthProvider):
method __init__ (line 75) | def __init__(
method get_routes (line 141) | def get_routes(
method verify_token (line 185) | async def verify_token(self, token: str) -> AccessToken | None:
method _create_token_verifier (line 202) | def _create_token_verifier(
FILE: src/fastmcp/server/auth/providers/scalekit.py
class ScalekitProvider (line 23) | class ScalekitProvider(RemoteAuthProvider):
method __init__ (line 63) | def __init__(
method get_routes (line 156) | def get_routes(
FILE: src/fastmcp/server/auth/providers/supabase.py
class SupabaseProvider (line 25) | class SupabaseProvider(RemoteAuthProvider):
method __init__ (line 71) | def __init__(
method get_routes (line 137) | def get_routes(
FILE: src/fastmcp/server/auth/providers/workos.py
class WorkOSTokenVerifier (line 31) | class WorkOSTokenVerifier(TokenVerifier):
method __init__ (line 38) | def __init__(
method verify_token (line 61) | async def verify_token(self, token: str) -> AccessToken | None:
class WorkOSProvider (line 126) | class WorkOSProvider(OAuthProxy):
method __init__ (line 160) | def __init__(
class AuthKitProvider (line 249) | class AuthKitProvider(RemoteAuthProvider):
method __init__ (line 285) | def __init__(
method get_routes (line 347) | def get_routes(
FILE: src/fastmcp/server/auth/redirect_validation.py
function _parse_host_port (line 13) | def _parse_host_port(netloc: str) -> tuple[str | None, str | None]:
function _match_host (line 45) | def _match_host(uri_host: str | None, pattern_host: str | None) -> bool:
function _match_port (line 71) | def _match_port(
function _match_path (line 98) | def _match_path(uri_path: str, pattern_path: str) -> bool:
function matches_allowed_pattern (line 121) | def matches_allowed_pattern(uri: str, pattern: str) -> bool:
function validate_redirect_uri (line 175) | def validate_redirect_uri(
FILE: src/fastmcp/server/auth/ssrf.py
function format_ip_for_url (line 26) | def format_ip_for_url(ip_str: str) -> str:
class SSRFError (line 47) | class SSRFError(Exception):
class SSRFFetchError (line 51) | class SSRFFetchError(Exception):
function is_ip_allowed (line 55) | def is_ip_allowed(ip_str: str) -> bool:
function resolve_hostname (line 98) | async def resolve_hostname(hostname: str, port: int = 443) -> list[str]:
class ValidatedURL (line 128) | class ValidatedURL:
class SSRFFetchResponse (line 139) | class SSRFFetchResponse:
function validate_url (line 147) | async def validate_url(url: str, require_path: bool = False) -> Validate...
function ssrf_safe_fetch (line 196) | async def ssrf_safe_fetch(
function ssrf_safe_fetch_response (line 239) | async def ssrf_safe_fetch_response(
FILE: src/fastmcp/server/context.py
function set_transport (line 88) | def set_transport(
function reset_transport (line 95) | def reset_transport(token: Token[TransportType | None]) -> None:
class LogData (line 101) | class LogData:
function set_context (line 125) | def set_context(context: Context) -> Generator[Context, None, None]:
class Context (line 134) | class Context:
method __init__ (line 189) | def __init__(
method is_background_task (line 207) | def is_background_task(self) -> bool:
method task_id (line 226) | def task_id(self) -> str | None:
method origin_request_id (line 234) | def origin_request_id(self) -> str | None:
method fastmcp (line 246) | def fastmcp(self) -> FastMCP:
method __aenter__ (line 253) | async def __aenter__(self) -> Context:
method __aexit__ (line 292) | async def __aexit__(self, exc_type, exc_val, exc_tb) -> None:
method request_context (line 321) | def request_context(self) -> RequestContext[ServerSession, Any, Reques...
method lifespan_context (line 350) | def lifespan_context(self) -> dict[str, Any]:
method report_progress (line 381) | async def report_progress(
method _paginate_list (line 443) | async def _paginate_list(
method list_resources (line 474) | async def list_resources(self) -> list[SDKResource]:
method list_prompts (line 490) | async def list_prompts(self) -> list[SDKPrompt]:
method get_prompt (line 506) | async def get_prompt(
method read_resource (line 525) | async def read_resource(self, uri: str | AnyUrl) -> ResourceResult:
method log (line 541) | async def log(
method transport (line 571) | def transport(self) -> TransportType | None:
method client_supports_extension (line 579) | def client_supports_extension(self, extension_id: str) -> bool:
method client_id (line 607) | def client_id(self) -> str | None:
method request_id (line 616) | def request_id(self) -> str:
method session_id (line 629) | def session_id(self) -> str:
method session (line 686) | def session(self) -> ServerSession:
method debug (line 712) | async def debug(
method info (line 728) | async def info(
method warning (line 744) | async def warning(
method error (line 760) | async def error(
method list_roots (line 776) | async def list_roots(self) -> list[Root]:
method send_notification (line 781) | async def send_notification(
method close_sse_stream (line 791) | async def close_sse_stream(self) -> None:
method sample_step (line 830) | async def sample_step(
method sample (line 909) | async def sample(
method sample (line 925) | async def sample(
method sample (line 940) | async def sample(
method elicit (line 1015) | async def elicit(
method elicit (line 1027) | async def elicit(
method elicit (line 1037) | async def elicit(
method elicit (line 1047) | async def elicit(
method elicit (line 1057) | async def elicit(
method elicit (line 1069) | async def elicit(
method elicit (line 1081) | async def elicit(
method _elicit_for_task (line 1151) | async def _elicit_for_task(
method _make_state_key (line 1191) | def _make_state_key(self, key: str) -> str:
method set_state (line 1195) | async def set_state(
method get_state (line 1237) | async def get_state(self, key: str) -> Any:
method delete_state (line 1251) | async def delete_state(self, key: str) -> None:
method _get_visibility_rules (line 1264) | async def _get_visibility_rules(self) -> list[dict[str, Any]]:
method _get_session_transforms (line 1268) | async def _get_session_transforms(self) -> list[Visibility]:
method enable_components (line 1272) | async def enable_components(
method disable_components (line 1310) | async def disable_components(
method reset_visibility (line 1348) | async def reset_visibility(self) -> None:
function _log_to_server_and_client (line 1371) | async def _log_to_server_and_client(
FILE: src/fastmcp/server/dependencies.py
class TaskContextInfo (line 87) | class TaskContextInfo:
function get_task_context (line 101) | def get_task_context() -> TaskContextInfo | None:
function register_task_session (line 139) | def register_task_session(session_id: str, session: ServerSession) -> None:
function get_task_session (line 153) | def get_task_session(session_id: str) -> ServerSession | None:
function is_docket_available (line 189) | def is_docket_available() -> bool:
function require_docket (line 202) | def require_docket(feature: str) -> None:
function transform_context_annotations (line 227) | def transform_context_annotations(fn: Callable[..., Any]) -> Callable[.....
function _clear_signature_caches (line 352) | def _clear_signature_caches(fn: Callable[..., Any]) -> None:
function get_context (line 368) | def get_context() -> Context:
function get_server (line 378) | def get_server() -> FastMCP:
function get_http_request (line 396) | def get_http_request() -> Request:
function get_http_headers (line 416) | def get_http_headers(
function get_access_token (line 473) | def get_access_token() -> AccessToken | None:
function without_injected_parameters (line 545) | def without_injected_parameters(fn: Callable[..., Any]) -> Callable[...,...
function _resolve_fastmcp_dependencies (line 625) | async def _resolve_fastmcp_dependencies(
function resolve_dependencies (line 694) | async def resolve_dependencies(
function _restore_task_access_token (line 741) | async def _restore_task_access_token(
function _restore_task_origin_request_id (line 774) | async def _restore_task_origin_request_id(session_id: str, task_id: str)...
class _CurrentContext (line 804) | class _CurrentContext(Dependency["Context"]):
method __aenter__ (line 815) | async def __aenter__(self) -> Context:
method __aexit__ (line 858) | async def __aexit__(
class _OptionalCurrentContext (line 874) | class _OptionalCurrentContext(Dependency["Context | None"]):
method __aenter__ (line 884) | async def __aenter__(self) -> Context | None:
method __aexit__ (line 895) | async def __aexit__(
function CurrentContext (line 907) | def CurrentContext() -> Context:
function OptionalCurrentContext (line 932) | def OptionalCurrentContext() -> Context | None:
class _CurrentDocket (line 937) | class _CurrentDocket(Dependency["Docket"]):
method __aenter__ (line 940) | async def __aenter__(self) -> Docket:
method __aexit__ (line 951) | async def __aexit__(
function CurrentDocket (line 960) | def CurrentDocket() -> Docket:
class _CurrentWorker (line 987) | class _CurrentWorker(Dependency["Worker"]):
method __aenter__ (line 990) | async def __aenter__(self) -> Worker:
method __aexit__ (line 1001) | async def __aexit__(
function CurrentWorker (line 1010) | def CurrentWorker() -> Worker:
class _CurrentFastMCP (line 1036) | class _CurrentFastMCP(Dependency["FastMCP"]):
method __aenter__ (line 1039) | async def __aenter__(self) -> FastMCP:
method __aexit__ (line 1048) | async def __aexit__(
function CurrentFastMCP (line 1057) | def CurrentFastMCP() -> FastMCP:
class _CurrentRequest (line 1082) | class _CurrentRequest(Dependency[Request]):
method __aenter__ (line 1085) | async def __aenter__(self) -> Request:
method __aexit__ (line 1088) | async def __aexit__(
function CurrentRequest (line 1097) | def CurrentRequest() -> Request:
class _CurrentHeaders (line 1123) | class _CurrentHeaders(Dependency[dict[str, str]]):
method __aenter__ (line 1126) | async def __aenter__(self) -> dict[str, str]:
method __aexit__ (line 1129) | async def __aexit__(
function CurrentHeaders (line 1138) | def CurrentHeaders() -> dict[str, str]:
class ProgressLike (line 1166) | class ProgressLike(Protocol):
method current (line 1174) | def current(self) -> int | None:
method total (line 1179) | def total(self) -> int:
method message (line 1184) | def message(self) -> str | None:
method set_total (line 1188) | async def set_total(self, total: int) -> None:
method increment (line 1192) | async def increment(self, amount: int = 1) -> None:
method set_message (line 1196) | async def set_message(self, message: str | None) -> None:
class InMemoryProgress (line 1201) | class InMemoryProgress:
method __init__ (line 1209) | def __init__(self) -> None:
method __aenter__ (line 1214) | async def __aenter__(self) -> InMemoryProgress:
method __aexit__ (line 1217) | async def __aexit__(
method current (line 1226) | def current(self) -> int | None:
method total (line 1230) | def total(self) -> int:
method message (line 1234) | def message(self) -> str | None:
method set_total (line 1237) | async def set_total(self, total: int) -> None:
method increment (line 1243) | async def increment(self, amount: int = 1) -> None:
method set_message (line 1252) | async def set_message(self, message: str | None) -> None:
class Progress (line 1257) | class Progress(Dependency["Progress"]):
method __aenter__ (line 1272) | async def __aenter__(self) -> Progress:
method __aexit__ (line 1290) | async def __aexit__(
method current (line 1299) | def current(self) -> int | None:
method total (line 1305) | def total(self) -> int:
method message (line 1311) | def message(self) -> str | None:
method set_total (line 1316) | async def set_total(self, total: int) -> None:
method increment (line 1321) | async def increment(self, amount: int = 1) -> None:
method set_message (line 1326) | async def set_message(self, message: str | None) -> None:
class _CurrentAccessToken (line 1335) | class _CurrentAccessToken(Dependency[AccessToken]):
method __aenter__ (line 1340) | async def __aenter__(self) -> AccessToken:
method __aexit__ (line 1361) | async def __aexit__(
function CurrentAccessToken (line 1372) | def CurrentAccessToken() -> AccessToken:
class _TokenClaim (line 1400) | class _TokenClaim(Dependency[str]):
method __init__ (line 1403) | def __init__(self, claim_name: str):
method __aenter__ (line 1406) | async def __aenter__(self) -> str:
method __aexit__ (line 1420) | async def __aexit__(
function TokenClaim (line 1429) | def TokenClaim(name: str) -> str:
FILE: src/fastmcp/server/elicitation.py
class ElicitationJsonSchema (line 36) | class ElicitationJsonSchema(GenerateJsonSchema):
method generate_inner (line 44) | def generate_inner(self, schema: core_schema.CoreSchema) -> JsonSchema...
method list_schema (line 57) | def list_schema(self, schema: core_schema.ListSchema) -> JsonSchemaValue:
method enum_schema (line 94) | def enum_schema(self, schema: core_schema.EnumSchema) -> JsonSchemaValue:
class AcceptedElicitation (line 105) | class AcceptedElicitation(BaseModel, Generic[T]):
class ScalarElicitationType (line 113) | class ScalarElicitationType(Generic[T]):
class ElicitConfig (line 118) | class ElicitConfig:
function parse_elicit_response_type (line 132) | def parse_elicit_response_type(response_type: Any) -> ElicitConfig:
function _is_scalar_type (line 173) | def _is_scalar_type(response_type: Any) -> bool:
function _parse_dict_syntax (line 182) | def _parse_dict_syntax(d: dict[str, Any]) -> ElicitConfig:
function _parse_list_syntax (line 198) | def _parse_list_syntax(lst: list[Any]) -> ElicitConfig:
function _parse_generic_list (line 245) | def _parse_generic_list(response_type: Any) -> ElicitConfig:
function _parse_scalar_type (line 255) | def _parse_scalar_type(response_type: Any) -> ElicitConfig:
function handle_elicit_accept (line 265) | def handle_elicit_accept(
function _dict_to_enum_schema (line 299) | def _dict_to_enum_schema(
function get_elicitation_schema (line 324) | def get_elicitation_schema(response_type: type[T]) -> dict[str, Any]:
function validate_elicitation_json_schema (line 343) | def validate_elicitation_json_schema(schema: dict[str, Any]) -> None:
FILE: src/fastmcp/server/event_store.py
class EventEntry (line 26) | class EventEntry(FastMCPBaseModel):
class StreamEventList (line 34) | class StreamEventList(FastMCPBaseModel):
class EventStore (line 40) | class EventStore(SDKEventStore):
method __init__ (line 70) | def __init__(
method store_event (line 94) | async def store_event(
method replay_events_after (line 135) | async def replay_events_after(
FILE: src/fastmcp/server/http.py
class StreamableHTTPASGIApp (line 32) | class StreamableHTTPASGIApp:
method __init__ (line 35) | def __init__(self, session_manager):
method __call__ (line 38) | async def __call__(self, scope: Scope, receive: Receive, send: Send) -...
class StarletteWithLifespan (line 70) | class StarletteWithLifespan(Starlette):
method lifespan (line 72) | def lifespan(self) -> Lifespan[Starlette]:
function set_http_request (line 77) | def set_http_request(request: Request) -> Generator[Request, None, None]:
class RequestContextMiddleware (line 85) | class RequestContextMiddleware:
method __init__ (line 90) | def __init__(self, app):
method __call__ (line 93) | async def __call__(self, scope, receive, send):
function create_base_app (line 110) | def create_base_app(
function create_sse_app (line 139) | def create_sse_app(
function create_streamable_http_app (line 266) | def create_streamable_http_app(
FILE: src/fastmcp/server/lifespan.py
class Lifespan (line 61) | class Lifespan:
method __init__ (line 68) | def __init__(self, fn: LifespanFn) -> None:
method __call__ (line 78) | async def __call__(self, server: FastMCP[Any]) -> AsyncIterator[dict[s...
method __or__ (line 90) | def __or__(self, other: Lifespan) -> ComposedLifespan:
class ContextManagerLifespan (line 110) | class ContextManagerLifespan(Lifespan):
method __init__ (line 118) | def __init__(self, fn: LifespanContextManagerFn) -> None:
method __call__ (line 123) | async def __call__(self, server: FastMCP[Any]) -> AsyncIterator[dict[s...
class ComposedLifespan (line 137) | class ComposedLifespan(Lifespan):
method __init__ (line 144) | def __init__(self, left: Lifespan, right: Lifespan) -> None:
method __call__ (line 156) | async def __call__(self, server: FastMCP[Any]) -> AsyncIterator[dict[s...
function lifespan (line 172) | def lifespan(fn: LifespanFn) -> Lifespan:
FILE: src/fastmcp/server/low_level.py
class MiddlewareServerSession (line 36) | class MiddlewareServerSession(ServerSession):
method __init__ (line 39) | def __init__(self, fastmcp: FastMCP, *args, **kwargs):
method fastmcp (line 48) | def fastmcp(self) -> FastMCP:
method client_supports_extension (line 55) | def client_supports_extension(self, extension_id: str) -> bool:
method _received_request (line 74) | async def _received_request(
class LowLevelServer (line 155) | class LowLevelServer(_Server[LifespanResultT, RequestT]):
method __init__ (line 156) | def __init__(self, fastmcp: FastMCP, *args: Any, **kwargs: Any):
method fastmcp (line 169) | def fastmcp(self) -> FastMCP:
method create_initialization_options (line 176) | def create_initialization_options(
method get_capabilities (line 191) | def get_capabilities(
method run (line 225) | async def run(
method read_resource (line 261) | def read_resource(
method get_prompt (line 305) | def get_prompt(
FILE: src/fastmcp/server/middleware/authorization.py
class AuthMiddleware (line 51) | class AuthMiddleware(Middleware):
method __init__ (line 82) | def __init__(self, auth: AuthCheck | list[AuthCheck]) -> None:
method on_list_tools (line 85) | async def on_list_tools(
method on_call_tool (line 113) | async def on_call_tool(
method on_list_resources (line 156) | async def on_list_resources(
method on_read_resource (line 183) | async def on_read_resource(
method on_list_resource_templates (line 226) | async def on_list_resource_templates(
method on_list_prompts (line 255) | async def on_list_prompts(
method on_get_prompt (line 282) | async def on_get_prompt(
FILE: src/fastmcp/server/middleware/caching.py
class CachableResourceContent (line 39) | class CachableResourceContent(FastMCPBaseModel):
class CachableResourceResult (line 47) | class CachableResourceResult(FastMCPBaseModel):
method get_size (line 53) | def get_size(self) -> int:
method wrap (line 57) | def wrap(cls, value: ResourceResult) -> Self:
method unwrap (line 68) | def unwrap(self) -> ResourceResult:
class CachableToolResult (line 80) | class CachableToolResult(FastMCPBaseModel):
method wrap (line 86) | def wrap(cls, value: ToolResult) -> Self:
method unwrap (line 93) | def unwrap(self) -> ToolResult:
class CachableMessage (line 101) | class CachableMessage(FastMCPBaseModel):
class CachablePromptResult (line 113) | class CachablePromptResult(FastMCPBaseModel):
method get_size (line 120) | def get_size(self) -> int:
method wrap (line 124) | def wrap(cls, value: PromptResult) -> Self:
method unwrap (line 133) | def unwrap(self) -> PromptResult:
class SharedMethodSettings (line 144) | class SharedMethodSettings(TypedDict):
class ListToolsSettings (line 151) | class ListToolsSettings(SharedMethodSettings):
class ListResourcesSettings (line 155) | class ListResourcesSettings(SharedMethodSettings):
class ListPromptsSettings (line 159) | class ListPromptsSettings(SharedMethodSettings):
class CallToolSettings (line 163) | class CallToolSettings(SharedMethodSettings):
class ReadResourceSettings (line 170) | class ReadResourceSettings(SharedMethodSettings):
class GetPromptSettings (line 174) | class GetPromptSettings(SharedMethodSettings):
class ResponseCachingStatistics (line 178) | class ResponseCachingStatistics(FastMCPBaseModel):
class ResponseCachingMiddleware (line 187) | class ResponseCachingMiddleware(Middleware):
method __init__ (line 200) | def __init__(
method on_list_tools (line 291) | async def on_list_tools(
method on_list_resources (line 330) | async def on_list_resources(
method on_list_prompts (line 369) | async def on_list_prompts(
method on_call_tool (line 406) | async def on_call_tool(
method on_read_resource (line 439) | async def on_read_resource(
method on_get_prompt (line 467) | async def on_get_prompt(
method _matches_tool_cache_settings (line 492) | def _matches_tool_cache_settings(self, tool_name: str) -> bool:
method statistics (line 505) | def statistics(self) -> ResponseCachingStatistics:
function _get_arguments_str (line 517) | def _get_arguments_str(arguments: dict[str, Any] | None) -> str:
function _hash_cache_key (line 530) | def _hash_cache_key(value: str) -> str:
function _make_call_tool_cache_key (line 536) | def _make_call_tool_cache_key(msg: mcp.types.CallToolRequestParams) -> str:
function _make_read_resource_cache_key (line 542) | def _make_read_resource_cache_key(msg: mcp.types.ReadResourceRequestPara...
function _make_get_prompt_cache_key (line 548) | def _make_get_prompt_cache_key(msg: mcp.types.GetPromptRequestParams) ->...
FILE: src/fastmcp/server/middleware/dereference.py
class DereferenceRefsMiddleware (line 15) | class DereferenceRefsMiddleware(Middleware):
method on_list_tools (line 24) | async def on_list_tools(
method on_list_resource_templates (line 33) | async def on_list_resource_templates(
function _dereference_tool (line 44) | def _dereference_tool(tool: Tool) -> Tool:
function _dereference_resource_template (line 58) | def _dereference_resource_template(template: ResourceTemplate) -> Resour...
function _has_ref (line 67) | def _has_ref(schema: dict[str, Any]) -> bool:
FILE: src/fastmcp/server/middleware/error_handling.py
class ErrorHandlingMiddleware (line 18) | class ErrorHandlingMiddleware(Middleware):
method __init__ (line 37) | def __init__(
method _log_error (line 58) | def _log_error(self, error: Exception, context: MiddlewareContext) -> ...
method _transform_error (line 81) | def _transform_error(
method on_message (line 120) | async def on_message(self, context: MiddlewareContext, call_next: Call...
method get_error_stats (line 131) | def get_error_stats(self) -> dict[str, int]:
class RetryMiddleware (line 136) | class RetryMiddleware(Middleware):
method __init__ (line 157) | def __init__(
method _should_retry (line 183) | def _should_retry(self, error: Exception) -> bool:
method _calculate_delay (line 187) | def _calculate_delay(self, attempt: int) -> float:
method on_request (line 192) | async def on_request(self, context: MiddlewareContext, call_next: Call...
FILE: src/fastmcp/server/middleware/logging.py
function default_serializer (line 15) | def default_serializer(data: Any) -> str:
class BaseLoggingMiddleware (line 20) | class BaseLoggingMiddleware(Middleware):
method _serialize_payload (line 33) | def _serialize_payload(self, context: MiddlewareContext[Any]) -> str:
method _format_message (line 49) | def _format_message(self, message: dict[str, str | int | float]) -> str:
method _create_before_message (line 56) | def _create_before_message(
method _create_error_message (line 89) | def _create_error_message(
method _create_after_message (line 105) | def _create_after_message(
method _log_message (line 119) | def _log_message(
method on_message (line 124) | async def on_message(
class LoggingMiddleware (line 148) | class LoggingMiddleware(BaseLoggingMiddleware):
method __init__ (line 167) | def __init__(
class StructuredLoggingMiddleware (line 203) | class StructuredLoggingMiddleware(BaseLoggingMiddleware):
method __init__ (line 219) | def __init__(
function _get_duration_ms (line 255) | def _get_duration_ms(start_time: float, /) -> float:
FILE: src/fastmcp/server/middleware/middleware.py
class CallNext (line 42) | class CallNext(Protocol[T, R]):
method __call__ (line 43) | def __call__(self, context: MiddlewareContext[T]) -> Awaitable[R]: ...
class MiddlewareContext (line 47) | class MiddlewareContext(Generic[T]):
method copy (line 62) | def copy(self, **kwargs: Any) -> MiddlewareContext[T]:
function make_middleware_wrapper (line 66) | def make_middleware_wrapper(
class Middleware (line 79) | class Middleware:
method __call__ (line 82) | async def __call__(
method _dispatch_handler (line 94) | async def _dispatch_handler(
method on_message (line 128) | async def on_message(
method on_request (line 135) | async def on_request(
method on_notification (line 142) | async def on_notification(
method on_initialize (line 149) | async def on_initialize(
method on_call_tool (line 156) | async def on_call_tool(
method on_read_resource (line 163) | async def on_read_resource(
method on_get_prompt (line 170) | async def on_get_prompt(
method on_list_tools (line 177) | async def on_list_tools(
method on_list_resources (line 184) | async def on_list_resources(
method on_list_resource_templates (line 191) | async def on_list_resource_templates(
method on_list_prompts (line 200) | async def on_list_prompts(
FILE: src/fastmcp/server/middleware/ping.py
class PingMiddleware (line 10) | class PingMiddleware(Middleware):
method __init__ (line 27) | def __init__(self, interval_ms: int = 30000):
method on_message (line 42) | async def on_message(self, context: MiddlewareContext, call_next: Call...
method _ping_loop (line 63) | async def _ping_loop(self, session: Any, session_id: int) -> None:
FILE: src/fastmcp/server/middleware/rate_limiting.py
class RateLimitError (line 15) | class RateLimitError(McpError):
method __init__ (line 18) | def __init__(self, message: str = "Rate limit exceeded"):
class TokenBucketRateLimiter (line 22) | class TokenBucketRateLimiter:
method __init__ (line 25) | def __init__(self, capacity: int, refill_rate: float):
method consume (line 38) | async def consume(self, tokens: int = 1) -> bool:
class SlidingWindowRateLimiter (line 61) | class SlidingWindowRateLimiter:
method __init__ (line 64) | def __init__(self, max_requests: int, window_seconds: int):
method is_allowed (line 76) | async def is_allowed(self) -> bool:
class RateLimitingMiddleware (line 92) | class RateLimitingMiddleware(Middleware):
method __init__ (line 113) | def __init__(
method _get_client_identifier (line 146) | def _get_client_identifier(self, context: MiddlewareContext) -> str:
method on_request (line 152) | async def on_request(self, context: MiddlewareContext, call_next: Call...
class SlidingWindowRateLimitingMiddleware (line 170) | class SlidingWindowRateLimitingMiddleware(Middleware):
method __init__ (line 191) | def __init__(
method _get_client_identifier (line 213) | def _get_client_identifier(self, context: MiddlewareContext) -> str:
method on_request (line 219) | async def on_request(self, context: MiddlewareContext, call_next: Call...
FILE: src/fastmcp/server/middleware/response_limiting.py
class ResponseLimitingMiddleware (line 20) | class ResponseLimitingMiddleware(Middleware):
method __init__ (line 49) | def __init__(
method _truncate_to_result (line 70) | def _truncate_to_result(self, text: str) -> ToolResult:
method on_call_tool (line 93) | async def on_call_tool(
FILE: src/fastmcp/server/middleware/timing.py
class TimingMiddleware (line 10) | class TimingMiddleware(Middleware):
method __init__ (line 27) | def __init__(
method on_request (line 39) | async def on_request(self, context: MiddlewareContext, call_next: Call...
class DetailedTimingMiddleware (line 60) | class DetailedTimingMiddleware(Middleware):
method __init__ (line 79) | def __init__(
method _time_operation (line 91) | async def _time_operation(
method on_call_tool (line 111) | async def on_call_tool(
method on_read_resource (line 118) | async def on_read_resource(
method on_get_prompt (line 127) | async def on_get_prompt(
method on_list_tools (line 134) | async def on_list_tools(
method on_list_resources (line 140) | async def on_list_resources(
method on_list_resource_templates (line 146) | async def on_list_resource_templates(
method on_list_prompts (line 152) | async def on_list_prompts(
FILE: src/fastmcp/server/middleware/tool_injection.py
class ToolInjectionMiddleware (line 23) | class ToolInjectionMiddleware(Middleware):
method __init__ (line 26) | def __init__(self, tools: Sequence[Tool]):
method on_list_tools (line 34) | async def on_list_tools(
method on_call_tool (line 43) | async def on_call_tool(
function list_prompts (line 56) | async def list_prompts(context: Context) -> list[Prompt]:
function get_prompt (line 66) | async def get_prompt(
class PromptToolMiddleware (line 82) | class PromptToolMiddleware(ToolInjectionMiddleware):
method __init__ (line 89) | def __init__(self) -> None:
function list_resources (line 101) | async def list_resources(context: Context) -> list[mcp.types.Resource]:
function read_resource (line 111) | async def read_resource(
class ResourceToolMiddleware (line 124) | class ResourceToolMiddleware(ToolInjectionMiddleware):
method __init__ (line 131) | def __init__(self) -> None:
FILE: src/fastmcp/server/mixins/lifespan.py
class LifespanMixin (line 25) | class LifespanMixin:
method docket (line 29) | def docket(self: FastMCP) -> Docket | None:
method _docket_lifespan (line 37) | async def _docket_lifespan(self: FastMCP) -> AsyncIterator[None]:
method _lifespan_manager (line 140) | async def _lifespan_manager(self: FastMCP) -> AsyncIterator[None]:
method _setup_task_protocol_handlers (line 192) | def _setup_task_protocol_handlers(self: FastMCP) -> None:
FILE: src/fastmcp/server/mixins/mcp_operations.py
function _apply_pagination (line 27) | def _apply_pagination(
class MCPOperationsMixin (line 44) | class MCPOperationsMixin:
method _setup_handlers (line 54) | def _setup_handlers(self: FastMCP) -> None:
method _wrap_list_handler (line 87) | def _wrap_list_handler(
method _list_tools_mcp (line 98) | async def _list_tools_mcp(
method _list_resources_mcp (line 120) | async def _list_resources_mcp(
method _list_resource_templates_mcp (line 143) | async def _list_resource_templates_mcp(
method _list_prompts_mcp (line 168) | async def _list_prompts_mcp(
method _call_tool_mcp (line 188) | async def _call_tool_mcp(
method _read_resource_mcp (line 248) | async def _read_resource_mcp(
method _get_prompt_mcp (line 304) | async def _get_prompt_mcp(
method _set_logging_level_mcp (line 357) | async def _set_logging_level_mcp(self, level: mcp.types.LoggingLevel) ...
FILE: src/fastmcp/server/mixins/transport.py
class TransportMixin (line 37) | class TransportMixin:
method run_async (line 43) | async def run_async(
method run (line 77) | def run(
method custom_route (line 100) | def custom_route(
method _get_additional_http_routes (line 150) | def _get_additional_http_routes(self: FastMCP) -> list[BaseRoute]:
method run_stdio_async (line 184) | async def run_stdio_async(
method run_http_async (line 226) | async def run_http_async(
method http_app (line 305) | def http_app(
FILE: src/fastmcp/server/openapi/server.py
class FastMCPOpenAPI (line 30) | class FastMCPOpenAPI(FastMCP):
method __init__ (line 60) | def __init__(
FILE: src/fastmcp/server/providers/__init__.py
function __getattr__ (line 61) | def __getattr__(name: str):
FILE: src/fastmcp/server/providers/aggregate.py
class AggregateProvider (line 46) | class AggregateProvider(Provider):
method __init__ (line 68) | def __init__(self, providers: Sequence[Provider] | None = None) -> None:
method add_provider (line 78) | def add_provider(self, provider: Provider, *, namespace: str = "") -> ...
method _collect_list_results (line 106) | def _collect_list_results(
method _get_highest_version_result (line 121) | def _get_highest_version_result(
method __repr__ (line 146) | def __repr__(self) -> str:
method _list_tools (line 153) | async def _list_tools(self) -> Sequence[Tool]:
method _get_tool (line 161) | async def _get_tool(
method _list_resources (line 175) | async def _list_resources(self) -> Sequence[Resource]:
method _get_resource (line 183) | async def _get_resource(
method _list_resource_templates (line 197) | async def _list_resource_templates(self) -> Sequence[ResourceTemplate]:
method _get_resource_template (line 205) | async def _get_resource_template(
method _list_prompts (line 221) | async def _list_prompts(self) -> Sequence[Prompt]:
method _get_prompt (line 229) | async def _get_prompt(
method get_tasks (line 243) | async def get_tasks(self) -> Sequence[FastMCPComponent]:
method lifespan (line 256) | async def lifespan(self) -> AsyncIterator[None]:
FILE: src/fastmcp/server/providers/base.py
class Provider (line 51) | class Provider:
method __init__ (line 69) | def __init__(self) -> None:
method __repr__ (line 72) | def __repr__(self) -> str:
method transforms (line 76) | def transforms(self) -> list[Transform]:
method add_transform (line 80) | def add_transform(self, transform: Transform) -> None:
method wrap_transform (line 100) | def wrap_transform(self, transform: Transform) -> Provider:
method list_tools (line 136) | async def list_tools(self) -> Sequence[Tool]:
method get_tool (line 152) | async def get_tool(
method list_resources (line 178) | async def list_resources(self) -> Sequence[Resource]:
method get_resource (line 188) | async def get_resource(
method list_resource_templates (line 213) | async def list_resource_templates(self) -> Sequence[ResourceTemplate]:
method get_resource_template (line 223) | async def get_resource_template(
method list_prompts (line 250) | async def list_prompts(self) -> Sequence[Prompt]:
method get_prompt (line 260) | async def get_prompt(
method _list_tools (line 289) | async def _list_tools(self) -> Sequence[Tool]:
method _get_tool (line 297) | async def _get_tool(
method _list_resources (line 321) | async def _list_resources(self) -> Sequence[Resource]:
method _get_resource (line 329) | async def _get_resource(
method _list_resource_templates (line 352) | async def _list_resource_templates(self) -> Sequence[ResourceTemplate]:
method _get_resource_template (line 360) | async def _get_resource_template(
method _list_prompts (line 383) | async def _list_prompts(self) -> Sequence[Prompt]:
method _get_prompt (line 391) | async def _get_prompt(
method get_tasks (line 418) | async def get_tasks(self) -> Sequence[FastMCPComponent]:
method lifespan (line 463) | async def lifespan(self) -> AsyncIterator[None]:
method enable (line 492) | def enable(
method disable (line 541) | def disable(
FILE: src/fastmcp/server/providers/fastmcp_provider.py
function _expand_uri_template (line 39) | def _expand_uri_template(template: str, params: dict[str, Any]) -> str:
class FastMCPProviderTool (line 72) | class FastMCPProviderTool(Tool):
method __init__ (line 83) | def __init__(
method wrap (line 94) | def wrap(cls, server: Any, tool: Tool) -> FastMCPProviderTool:
method _run (line 113) | async def _run(
method _run (line 120) | async def _run(
method _run (line 126) | async def _run(
method run (line 147) | async def run(self, arguments: dict[str, Any]) -> ToolResult:
method get_span_attributes (line 166) | def get_span_attributes(self) -> dict[str, Any]:
class FastMCPProviderResource (line 173) | class FastMCPProviderResource(Resource):
method __init__ (line 183) | def __init__(
method wrap (line 194) | def wrap(cls, server: Any, resource: Resource) -> FastMCPProviderResou...
method _read (line 213) | async def _read(self, task_meta: None = None) -> ResourceResult: ...
method _read (line 216) | async def _read(self, task_meta: TaskMeta) -> mcp.types.CreateTaskResu...
method _read (line 218) | async def _read(
method get_span_attributes (line 237) | def get_span_attributes(self) -> dict[str, Any]:
class FastMCPProviderPrompt (line 244) | class FastMCPProviderPrompt(Prompt):
method __init__ (line 254) | def __init__(
method wrap (line 265) | def wrap(cls, server: Any, prompt: Prompt) -> FastMCPProviderPrompt:
method _render (line 282) | async def _render(
method _render (line 289) | async def _render(
method _render (line 295) | async def _render(
method render (line 316) | async def render(self, arguments: dict[str, Any] | None = None) -> Pro...
method get_span_attributes (line 335) | def get_span_attributes(self) -> dict[str, Any]:
class FastMCPProviderResourceTemplate (line 342) | class FastMCPProviderResourceTemplate(ResourceTemplate):
method __init__ (line 353) | def __init__(
method wrap (line 364) | def wrap(
method create_resource (line 385) | async def create_resource(self, uri: str, params: dict[str, Any]) -> R...
method _read (line 404) | async def _read(
method _read (line 409) | async def _read(
method _read (line 413) | async def _read(
method read (line 435) | async def read(self, arguments: dict[str, Any]) -> str | bytes | Resou...
method register_with_docket (line 456) | def register_with_docket(self, docket: Docket) -> None:
method add_to_docket (line 459) | async def add_to_docket(
method get_span_attributes (line 478) | def get_span_attributes(self) -> dict[str, Any]:
class FastMCPProvider (line 490) | class FastMCPProvider(Provider):
method __init__ (line 528) | def __init__(self, server: FastMCP[Any]):
method _list_tools (line 541) | async def _list_tools(self) -> Sequence[Tool]:
method _get_tool (line 551) | async def _get_tool(
method _list_resources (line 569) | async def _list_resources(self) -> Sequence[Resource]:
method _get_resource (line 579) | async def _get_resource(
method _list_resource_templates (line 597) | async def _list_resource_templates(self) -> Sequence[ResourceTemplate]:
method _get_resource_template (line 609) | async def _get_resource_template(
method _list_prompts (line 627) | async def _list_prompts(self) -> Sequence[Prompt]:
method _get_prompt (line 637) | async def _get_prompt(
method get_tasks (line 655) | async def get_tasks(self) -> Sequence[FastMCPComponent]:
method lifespan (line 696) | async def lifespan(self) -> AsyncIterator[None]:
FILE: src/fastmcp/server/providers/filesystem.py
class FileSystemProvider (line 47) | class FileSystemProvider(LocalProvider):
method __init__ (line 85) | def __init__(
method _load_components (line 103) | def _load_components(self) -> None:
method _register_component (line 144) | def _register_component(self, component: FastMCPComponent) -> None:
method _ensure_loaded (line 157) | async def _ensure_loaded(self) -> None:
method _list_tools (line 177) | async def _list_tools(self) -> Sequence[Tool]:
method _get_tool (line 182) | async def _get_tool(
method _list_resources (line 189) | async def _list_resources(self) -> Sequence[Resource]:
method _get_resource (line 194) | async def _get_resource(
method _list_resource_templates (line 201) | async def _list_resource_templates(self) -> Sequence[ResourceTemplate]:
method _get_resource_template (line 206) | async def _get_resource_template(
method _list_prompts (line 213) | async def _list_prompts(self) -> Sequence[Prompt]:
method _get_prompt (line 218) | async def _get_prompt(
method __repr__ (line 225) | def __repr__(self) -> str:
FILE: src/fastmcp/server/providers/filesystem_discovery.py
class DiscoveryResult (line 24) | class DiscoveryResult:
function discover_files (line 32) | def discover_files(root: Path) -> list[Path]:
function _is_package_dir (line 66) | def _is_package_dir(directory: Path) -> bool:
function _find_package_root (line 71) | def _find_package_root(file_path: Path) -> Path | None:
function _compute_module_name (line 92) | def _compute_module_name(file_path: Path, package_root: Path) -> str:
function import_module_from_file (line 109) | def import_module_from_file(file_path: Path) -> ModuleType:
function extract_components (line 175) | def extract_components(module: ModuleType) -> list[FastMCPComponent]:
function discover_and_import (line 299) | def discover_and_import(root: Path) -> DiscoveryResult:
FILE: src/fastmcp/server/providers/local_provider/decorators/prompts.py
class PromptDecoratorMixin (line 29) | class PromptDecoratorMixin:
method add_prompt (line 37) | def add_prompt(self: LocalProvider, prompt: Prompt | Callable[..., Any...
method prompt (line 74) | def prompt(
method prompt (line 91) | def prompt(
method prompt (line 107) | def prompt(
FILE: src/fastmcp/server/providers/local_provider/decorators/resources.py
class ResourceDecoratorMixin (line 29) | class ResourceDecoratorMixin:
method add_resource (line 38) | def add_resource(
method add_template (line 101) | def add_template(
method resource (line 107) | def resource(
FILE: src/fastmcp/server/providers/local_provider/decorators/tools.py
function _is_prefab_type (line 55) | def _is_prefab_type(tp: Any) -> bool:
function _has_prefab_return_type (line 65) | def _has_prefab_return_type(tool: Tool) -> bool:
function _ensure_prefab_renderer (line 75) | def _ensure_prefab_renderer(provider: LocalProvider) -> None:
function _expand_prefab_ui_meta (line 108) | def _expand_prefab_ui_meta(tool: Tool) -> None:
function _maybe_apply_prefab_ui (line 127) | def _maybe_apply_prefab_ui(provider: LocalProvider, tool: Tool) -> None:
class ToolDecoratorMixin (line 146) | class ToolDecoratorMixin:
method add_tool (line 154) | def add_tool(self: LocalProvider, tool: Tool | Callable[..., Any]) -> ...
method tool (line 206) | def tool(
method tool (line 228) | def tool(
method tool (line 253) | def tool(
FILE: src/fastmcp/server/providers/local_provider/local_provider.py
class LocalProvider (line 51) | class LocalProvider(
method __init__ (line 91) | def __init__(
method _get_component_identity (line 113) | def _get_component_identity(self, component: FastMCPComponent) -> tupl...
method _check_version_mixing (line 134) | def _check_version_mixing(self, component: _C) -> None:
method _add_component (line 178) | def _add_component(self, component: _C) -> _C:
method _remove_component (line 203) | def _remove_component(self, key: str) -> None:
method _get_component (line 218) | def _get_component(self, key: str) -> FastMCPComponent | None:
method remove_tool (line 229) | def remove_tool(self, name: str, version: str | None = None) -> None:
method remove_resource (line 257) | def remove_resource(self, uri: str, version: str | None = None) -> None:
method remove_template (line 285) | def remove_template(self, uri_template: str, version: str | None = Non...
method remove_prompt (line 315) | def remove_prompt(self, name: str, version: str | None = None) -> None:
method _list_tools (line 347) | async def _list_tools(self) -> Sequence[Tool]:
method _get_tool (line 351) | async def _get_tool(
method _list_resources (line 371) | async def _list_resources(self) -> Sequence[Resource]:
method _get_resource (line 375) | async def _get_resource(
method _list_resource_templates (line 395) | async def _list_resource_templates(self) -> Sequence[ResourceTemplate]:
method _get_resource_template (line 399) | async def _get_resource_template(
method _list_prompts (line 421) | async def _list_prompts(self) -> Sequence[Prompt]:
method _get_prompt (line 425) | async def _get_prompt(
method get_tasks (line 449) | async def get_tasks(self) -> Sequence[FastMCPComponent]:
FILE: src/fastmcp/server/providers/openapi/components.py
function _redact_headers (line 47) | def _redact_headers(headers: httpx.Headers) -> dict[str, str]:
function _extract_mime_type_from_route (line 64) | def _extract_mime_type_from_route(route: HTTPRoute) -> str:
function _slugify (line 114) | def _slugify(text: str) -> str:
class OpenAPITool (line 137) | class OpenAPITool(Tool):
method __init__ (line 142) | def __init__(
method __repr__ (line 176) | def __repr__(self) -> str:
method run (line 179) | async def run(self, arguments: dict[str, Any]) -> ToolResult:
class OpenAPIResource (line 256) | class OpenAPIResource(Resource):
method __init__ (line 261) | def __init__(
method __repr__ (line 283) | def __repr__(self) -> str:
method read (line 286) | async def read(self) -> ResourceResult:
class OpenAPIResourceTemplate (line 370) | class OpenAPIResourceTemplate(ResourceTemplate):
method __init__ (line 375) | def __init__(
method __repr__ (line 399) | def __repr__(self) -> str:
method create_resource (line 402) | async def create_resource(
FILE: src/fastmcp/server/providers/openapi/provider.py
class OpenAPIProvider (line 51) | class OpenAPIProvider(Provider):
method __init__ (line 71) | def __init__(
method _create_default_client (line 169) | def _create_default_client(cls, openapi_spec: dict[str, Any]) -> httpx...
method lifespan (line 181) | async def lifespan(self) -> AsyncIterator[None]:
method _generate_default_name (line 189) | def _generate_default_name(
method _get_unique_name (line 210) | def _get_unique_name(
method _create_openapi_tool (line 226) | def _create_openapi_tool(
method _create_openapi_resource (line 278) | def _create_openapi_resource(
method _create_openapi_template (line 313) | def _create_openapi_template(
method _list_tools (line 380) | async def _list_tools(self) -> Sequence[Tool]:
method _get_tool (line 384) | async def _get_tool(
method _list_resources (line 395) | async def _list_resources(self) -> Sequence[Resource]:
method _get_resource (line 399) | async def _get_resource(
method _list_resource_templates (line 410) | async def _list_resource_templates(self) -> Sequence[ResourceTemplate]:
method _get_resource_template (line 414) | async def _get_resource_template(
method _list_prompts (line 427) | async def _list_prompts(self) -> Sequence[Prompt]:
method get_tasks (line 431) | async def get_tasks(self) -> Sequence[FastMCPComponent]:
FILE: src/fastmcp/server/providers/openapi/routing.py
class MCPType (line 42) | class MCPType(enum.Enum):
class RouteMap (line 59) | class RouteMap:
function _determine_route_type (line 86) | def _determine_route_type(
FILE: src/fastmcp/server/providers/proxy.py
class ProxyTool (line 69) | class ProxyTool(Tool):
method __init__ (line 75) | def __init__(self, client_factory: ClientFactoryT, **kwargs: Any):
method _get_client (line 79) | async def _get_client(self) -> Client:
method model_copy (line 86) | def model_copy(self, **kwargs: Any) -> ProxyTool:
method from_mcp_tool (line 96) | def from_mcp_tool(
method run (line 113) | async def run(
method get_span_attributes (line 168) | def get_span_attributes(self) -> dict[str, Any]:
class ProxyResource (line 175) | class ProxyResource(Resource):
method __init__ (line 182) | def __init__(
method _get_client (line 193) | async def _get_client(self) -> Client:
method model_copy (line 200) | def model_copy(self, **kwargs: Any) -> ProxyResource:
method from_mcp_resource (line 210) | def from_mcp_resource(
method read (line 230) | async def read(self) -> ResourceResult:
method get_span_attributes (line 275) | def get_span_attributes(self) -> dict[str, Any]:
class ProxyTemplate (line 282) | class ProxyTemplate(ResourceTemplate):
method __init__ (line 288) | def __init__(self, client_factory: ClientFactoryT, **kwargs: Any):
method _get_client (line 292) | async def _get_client(self) -> Client:
method model_copy (line 299) | def model_copy(self, **kwargs: Any) -> ProxyTemplate:
method from_mcp_template (line 309) | def from_mcp_template( # type: ignore[override]
method create_resource (line 328) | async def create_resource(
method get_span_attributes (line 390) | def get_span_attributes(self) -> dict[str, Any]:
class ProxyPrompt (line 397) | class ProxyPrompt(Prompt):
method __init__ (line 403) | def __init__(self, client_factory: ClientFactoryT, **kwargs):
method _get_client (line 407) | async def _get_client(self) -> Client:
method model_copy (line 414) | def model_copy(self, **kwargs: Any) -> ProxyPrompt:
method from_mcp_prompt (line 424) | def from_mcp_prompt(
method render (line 448) | async def render(self, arguments: dict[str, Any]) -> PromptResult: # ...
method get_span_attributes (line 470) | def get_span_attributes(self) -> dict[str, Any]:
class _CacheEntry (line 482) | class _CacheEntry:
method __init__ (line 487) | def __init__(self, items: Sequence[Any], timestamp: float):
method is_fresh (line 491) | def is_fresh(self, ttl: float) -> bool:
class ProxyProvider (line 498) | class ProxyProvider(Provider):
method __init__ (line 533) | def __init__(
method _get_client (line 556) | async def _get_client(self) -> Client:
method _list_tools (line 567) | async def _list_tools(self) -> Sequence[Tool]:
method _get_tool (line 584) | async def _get_tool(
method _list_resources (line 603) | async def _list_resources(self) -> Sequence[Resource]:
method _get_resource (line 621) | async def _get_resource(
method _list_resource_templates (line 640) | async def _list_resource_templates(self) -> Sequence[ResourceTemplate]:
method _get_resource_template (line 658) | async def _get_resource_template(
method _list_prompts (line 677) | async def _list_prompts(self) -> Sequence[Prompt]:
method _get_prompt (line 695) | async def _get_prompt(
method get_tasks (line 714) | async def get_tasks(self) -> Sequence[FastMCPComponent]:
function _create_client_factory (line 732) | def _create_client_factory(
class FastMCPProxy (line 795) | class FastMCPProxy(FastMCP):
method __init__ (line 814) | def __init__(
function default_proxy_roots_handler (line 842) | async def default_proxy_roots_handler(
function default_proxy_sampling_handler (line 850) | async def default_proxy_sampling_handler(
function default_proxy_elicitation_handler (line 873) | async def default_proxy_elicitation_handler(
function default_proxy_log_handler (line 895) | async def default_proxy_log_handler(message: LogMessage) -> None:
function default_proxy_progress_handler (line 903) | async def default_proxy_progress_handler(
function _restore_request_context (line 913) | def _restore_request_context(
function _make_restoring_handler (line 952) | def _make_restoring_handler(handler: Callable, rc_ref: list[Any]) -> Cal...
class ProxyClient (line 967) | class ProxyClient(Client[ClientTransportT]):
method __init__ (line 973) | def __init__(
class StatefulProxyClient (line 1000) | class StatefulProxyClient(ProxyClient[ClientTransportT]):
method __init__ (line 1028) | def __init__(self, *args: Any, **kwargs: Any):
method __aexit__ (line 1045) | async def __aexit__(self, exc_type, exc_value, traceback) -> None: # ...
method clear (line 1051) | async def clear(self):
method new_stateful (line 1057) | def new_stateful(self) -> Client[ClientTransportT]:
FILE: src/fastmcp/server/providers/skills/_common.py
class SkillFileInfo (line 13) | class SkillFileInfo:
class SkillInfo (line 22) | class SkillInfo:
function parse_frontmatter (line 33) | def parse_frontmatter(content: str) -> tuple[dict[str, Any], str]:
function compute_file_hash (line 77) | def compute_file_hash(path: Path) -> str:
function scan_skill_files (line 86) | def scan_skill_files(skill_dir: Path) -> list[SkillFileInfo]:
FILE: src/fastmcp/server/providers/skills/claude_provider.py
class ClaudeSkillsProvider (line 11) | class ClaudeSkillsProvider(SkillsDirectoryProvider):
method __init__ (line 32) | def __init__(
FILE: src/fastmcp/server/providers/skills/directory_provider.py
class SkillsDirectoryProvider (line 19) | class SkillsDirectoryProvider(AggregateProvider):
method __init__ (line 55) | def __init__(
method _discover_skills (line 76) | def _discover_skills(self) -> None:
method _ensure_discovered (line 122) | async def _ensure_discovered(self) -> None:
method _list_resources (line 128) | async def _list_resources(self) -> Sequence[Resource]:
method _list_resource_templates (line 132) | async def _list_resource_templates(self) -> Sequence[ResourceTemplate]:
method _get_resource (line 136) | async def _get_resource(
method _get_resource_template (line 142) | async def _get_resource_template(
method __repr__ (line 148) | def __repr__(self) -> str:
FILE: src/fastmcp/server/providers/skills/skill_provider.py
class SkillResource (line 35) | class SkillResource(Resource):
method get_meta (line 41) | def get_meta(self) -> dict[str, Any]:
method read (line 50) | async def read(self) -> str | bytes | ResourceResult:
method _generate_manifest (line 58) | def _generate_manifest(self) -> str:
class SkillFileTemplate (line 70) | class SkillFileTemplate(ResourceTemplate):
method read (line 75) | async def read(self, arguments: dict[str, Any]) -> str | bytes | Resou...
method _read (line 101) | async def _read( # type: ignore[override]
method create_resource (line 115) | async def create_resource(self, uri: str, params: dict[str, Any]) -> R...
class SkillFileResource (line 141) | class SkillFileResource(Resource):
method get_meta (line 147) | def get_meta(self) -> dict[str, Any]:
method read (line 155) | async def read(self) -> str | bytes | ResourceResult:
class SkillProvider (line 179) | class SkillProvider(Provider):
method __init__ (line 213) | def __init__(
method _load_skill (line 228) | def _load_skill(self) -> None:
method skill_info (line 271) | def skill_info(self) -> SkillInfo:
method _list_resources (line 281) | async def _list_resources(self) -> Sequence[Resource]:
method _get_resource (line 331) | async def _get_resource(
method _list_resource_templates (line 384) | async def _list_resource_templates(self) -> Sequence[ResourceTemplate]:
method _get_resource_template (line 406) | async def _get_resource_template(
method __repr__ (line 445) | def __repr__(self) -> str:
FILE: src/fastmcp/server/providers/skills/vendor_providers.py
class CursorSkillsProvider (line 11) | class CursorSkillsProvider(SkillsDirectoryProvider):
method __init__ (line 14) | def __init__(
class VSCodeSkillsProvider (line 29) | class VSCodeSkillsProvider(SkillsDirectoryProvider):
method __init__ (line 32) | def __init__(
class CodexSkillsProvider (line 47) | class CodexSkillsProvider(SkillsDirectoryProvider):
method __init__ (line 54) | def __init__(
class GeminiSkillsProvider (line 73) | class GeminiSkillsProvider(SkillsDirectoryProvider):
method __init__ (line 76) | def __init__(
class GooseSkillsProvider (line 91) | class GooseSkillsProvider(SkillsDirectoryProvider):
method __init__ (line 94) | def __init__(
class CopilotSkillsProvider (line 109) | class CopilotSkillsProvider(SkillsDirectoryProvider):
method __init__ (line 112) | def __init__(
class OpenCodeSkillsProvider (line 127) | class OpenCodeSkillsProvider(SkillsDirectoryProvider):
method __init__ (line 130) | def __init__(
FILE: src/fastmcp/server/providers/wrapped_provider.py
class _WrappedProvider (line 25) | class _WrappedProvider(Provider):
method __init__ (line 36) | def __init__(self, inner: Provider, transform: Transform) -> None:
method __repr__ (line 49) | def __repr__(self) -> str:
method _list_tools (line 56) | async def _list_tools(self) -> Sequence[Tool]:
method _get_tool (line 60) | async def _get_tool(
method _list_resources (line 66) | async def _list_resources(self) -> Sequence[Resource]:
method _get_resource (line 70) | async def _get_resource(
method _list_resource_templates (line 76) | async def _list_resource_templates(self) -> Sequence[ResourceTemplate]:
method _get_resource_template (line 80) | async def _get_resource_template(
method _list_prompts (line 86) | async def _list_prompts(self) -> Sequence[Prompt]:
method _get_prompt (line 90) | async def _get_prompt(
method get_tasks (line 96) | async def get_tasks(self) -> Sequence[FastMCPComponent]:
method lifespan (line 137) | async def lifespan(self) -> AsyncIterator[None]:
FILE: src/fastmcp/server/sampling/run.py
class SamplingResult (line 54) | class SamplingResult(Generic[ResultT]):
class SampleStep (line 69) | class SampleStep:
method is_tool_use (line 79) | def is_tool_use(self) -> bool:
method text (line 86) | def text(self) -> str | None:
method tool_calls (line 99) | def tool_calls(self) -> list[ToolUseContent]:
function _parse_model_preferences (line 109) | def _parse_model_preferences(
function determine_handler_mode (line 132) | def determine_handler_mode(context: Context, needs_tools: bool) -> bool:
function call_sampling_handler (line 191) | async def call_sampling_handler(
function execute_tools (line 244) | async def execute_tools(
function prepare_messages (line 354) | def prepare_messages(
function prepare_tools (line 373) | def prepare_tools(
function extract_tool_calls (line 409) | def extract_tool_calls(
function create_final_response_tool (line 421) | def create_final_response_tool(result_type: type) -> SamplingTool:
function sample_step_impl (line 457) | async def sample_step_impl(
function sample_impl (line 574) | async def sample_impl(
FILE: src/fastmcp/server/sampling/sampling_tool.py
class SamplingTool (line 23) | class SamplingTool(FastMCPBaseModel):
method run (line 54) | async def run(self, arguments: dict[str, Any] | None = None) -> Any:
method _to_sdk_tool (line 71) | def _to_sdk_tool(self) -> SDKTool:
method from_function (line 84) | def from_function(
method from_callable_tool (line 126) | def from_callable_tool(
FILE: src/fastmcp/server/server.py
function _check_removed_kwargs (line 127) | def _check_removed_kwargs(kwargs: dict[str, Any]) -> None:
function _get_auth_context (line 151) | def _get_auth_context() -> tuple[bool, Any]:
function default_lifespan (line 171) | async def default_lifespan(server: FastMCP[LifespanResultT]) -> AsyncIte...
function _lifespan_proxy (line 183) | def _lifespan_proxy(
class StateValue (line 207) | class StateValue(FastMCPBaseModel):
class FastMCP (line 213) | class FastMCP(
method __init__ (line 220) | def __init__(
method __repr__ (line 359) | def __repr__(self) -> str:
method name (line 363) | def name(self) -> str:
method instructions (line 367) | def instructions(self) -> str | None:
method instructions (line 371) | def instructions(self, value: str | None) -> None:
method version (line 375) | def version(self) -> str | None:
method website_url (line 379) | def website_url(self) -> str | None:
method icons (line 383) | def icons(self) -> list[mcp.types.Icon]:
method local_provider (line 390) | def local_provider(self) -> LocalProvider:
method _run_middleware (line 401) | async def _run_middleware(
method add_middleware (line 412) | def add_middleware(self, middleware: Middleware) -> None:
method add_provider (line 415) | def add_provider(self, provider: Provider, *, namespace: str = "") -> ...
method get_tasks (line 437) | async def get_tasks(self) -> Sequence[FastMCPComponent]:
method add_transform (line 466) | def add_transform(self, transform: Transform) -> None:
method add_tool_transformation (line 486) | def add_tool_transformation(
method remove_tool_transformation (line 503) | def remove_tool_transformation(self, _tool_name: str) -> None:
method list_tools (line 518) | async def list_tools(self, *, run_middleware: bool = True) -> Sequence...
method _get_tool (line 557) | async def _get_tool(
method get_tool (line 588) | async def get_tool(
method list_resources (line 641) | async def list_resources(
method _get_resource (line 682) | async def _get_resource(
method get_resource (line 713) | async def get_resource(
method list_resource_templates (line 763) | async def list_resource_templates(
method _get_resource_template (line 806) | async def _get_resource_template(
method get_resource_template (line 837) | async def get_resource_template(
method list_prompts (line 891) | async def list_prompts(self, *, run_middleware: bool = True) -> Sequen...
method _get_prompt (line 930) | async def _get_prompt(
method get_prompt (line 961) | async def get_prompt(
method call_tool (line 1012) | async def call_tool(
method call_tool (line 1023) | async def call_tool(
method call_tool (line 1033) | async def call_tool(
method read_resource (line 1148) | async def read_resource(
method read_resource (line 1158) | async def read_resource(
method read_resource (line 1167) | async def read_resource(
method render_prompt (line 1301) | async def render_prompt(
method render_prompt (line 1312) | async def render_prompt(
method render_prompt (line 1322) | async def render_prompt(
method add_tool (line 1398) | def add_tool(self, tool: Tool | Callable[..., Any]) -> Tool:
method remove_tool (line 1412) | def remove_tool(self, name: str, version: str | None = None) -> None:
method tool (line 1442) | def tool(
method tool (line 1463) | def tool(
method tool (line 1483) | def tool(
method add_resource (line 1582) | def add_resource(
method add_template (line 1595) | def add_template(self, template: ResourceTemplate) -> ResourceTemplate:
method resource (line 1606) | def resource(
method add_prompt (line 1725) | def add_prompt(self, prompt: Prompt | Callable[..., Any]) -> Prompt:
method prompt (line 1737) | def prompt(
method prompt (line 1753) | def prompt(
method prompt (line 1768) | def prompt(
method mount (line 1868) | def mount(
method import_server (line 1962) | async def import_server(
method from_openapi (line 2062) | def from_openapi(
method from_fastapi (line 2113) | def from_fastapi(
method as_proxy (line 2168) | def as_proxy(
method generate_name (line 2205) | def generate_name(cls, name: str | None = None) -> str:
function create_proxy (line 2219) | def create_proxy(
FILE: src/fastmcp/server/tasks/capabilities.py
function _is_docket_available (line 15) | def _is_docket_available() -> bool:
function get_task_capabilities (line 20) | def get_task_capabilities() -> ServerTasksCapability | None:
FILE: src/fastmcp/server/tasks/config.py
class TaskMeta (line 28) | class TaskMeta:
class TaskConfig (line 44) | class TaskConfig:
method from_bool (line 82) | def from_bool(cls, value: bool) -> TaskConfig:
method supports_tasks (line 93) | def supports_tasks(self) -> bool:
method validate_function (line 101) | def validate_function(self, fn: Callable[..., Any], name: str) -> None:
FILE: src/fastmcp/server/tasks/elicitation.py
function elicit_for_task (line 42) | async def elicit_for_task(
function relay_elicitation (line 234) | async def relay_elicitation(
function handle_task_input (line 290) | async def handle_task_input(
FILE: src/fastmcp/server/tasks/handlers.py
function submit_to_docket (line 34) | async def submit_to_docket(
FILE: src/fastmcp/server/tasks/keys.py
function build_task_key (line 15) | def build_task_key(
function parse_task_key (line 47) | def parse_task_key(task_key: str) -> dict[str, str]:
function get_client_task_id_from_key (line 78) | def get_client_task_id_from_key(task_key: str) -> str:
FILE: src/fastmcp/server/tasks/notifications.py
function push_notification (line 48) | async def push_notification(
function notification_subscriber_loop (line 76) | async def notification_subscriber_loop(
function _send_mcp_notification (line 165) | async def _send_mcp_notification(
function ensure_subscriber_running (line 238) | async def ensure_subscriber_running(
function stop_subscriber (line 278) | async def stop_subscriber(session_id: str) -> None:
function get_subscriber_count (line 298) | def get_subscriber_count() -> int:
FILE: src/fastmcp/server/tasks/requests.py
function _parse_key_version (line 52) | def _parse_key_version(key_suffix: str) -> tuple[str, str | None]:
function _lookup_task_execution (line 71) | async def _lookup_task_execution(
function tasks_get_handler (line 137) | async def tasks_get_handler(server: FastMCP, params: dict[str, Any]) -> ...
function tasks_result_handler (line 222) | async def tasks_result_handler(server: FastMCP, params: dict[str, Any]) ...
function tasks_list_handler (line 403) | async def tasks_list_handler(
function tasks_cancel_handler (line 421) | async def tasks_cancel_handler(
FILE: src/fastmcp/server/tasks/routing.py
function check_background_task (line 26) | async def check_background_task(
FILE: src/fastmcp/server/tasks/subscriptions.py
function subscribe_to_task_updates (line 31) | async def subscribe_to_task_updates(
function _send_status_notification (line 93) | async def _send_status_notification(
function _send_progress_notification (line 163) | async def _send_progress_notification(
FILE: src/fastmcp/server/telemetry.py
function get_auth_span_attributes (line 13) | def get_auth_span_attributes() -> dict[str, str]:
function get_session_span_attributes (line 30) | def get_session_span_attributes() -> dict[str, str]:
function _get_parent_trace_context (line 44) | def _get_parent_trace_context() -> Context | None:
function server_span (line 56) | def server_span(
function delegate_span (line 100) | def delegate_span(
FILE: src/fastmcp/server/transforms/__init__.py
class GetToolNext (line 36) | class GetToolNext(Protocol):
method __call__ (line 39) | def __call__(
class GetResourceNext (line 44) | class GetResourceNext(Protocol):
method __call__ (line 47) | def __call__(
class GetResourceTemplateNext (line 52) | class GetResourceTemplateNext(Protocol):
method __call__ (line 55) | def __call__(
class GetPromptNext (line 60) | class GetPromptNext(Protocol):
method __call__ (line 63) | def __call__(
class Transform (line 68) | class Transform:
method __repr__ (line 88) | def __repr__(self) -> str:
method list_tools (line 95) | async def list_tools(self, tools: Sequence[Tool]) -> Sequence[Tool]:
method get_tool (line 106) | async def get_tool(
method list_resources (line 125) | async def list_resources(self, resources: Sequence[Resource]) -> Seque...
method get_resource (line 136) | async def get_resource(
method list_resource_templates (line 159) | async def list_resource_templates(
method get_resource_template (line 172) | async def get_resource_template(
method list_prompts (line 195) | async def list_prompts(self, prompts: Sequence[Prompt]) -> Sequence[Pr...
method get_prompt (line 206) | async def get_prompt(
FILE: src/fastmcp/server/transforms/catalog.py
class CatalogTransform (line 65) | class CatalogTransform(Transform):
method __init__ (line 79) | def __init__(self) -> None:
method list_tools (line 89) | async def list_tools(self, tools: Sequence[Tool]) -> Sequence[Tool]:
method list_resources (line 94) | async def list_resources(self, resources: Sequence[Resource]) -> Seque...
method list_resource_templates (line 99) | async def list_resource_templates(
method list_prompts (line 106) | async def list_prompts(self, prompts: Sequence[Prompt]) -> Sequence[Pr...
method transform_tools (line 115) | async def transform_tools(self, tools: Sequence[Tool]) -> Sequence[Tool]:
method transform_resources (line 127) | async def transform_resources(
method transform_resource_templates (line 141) | async def transform_resource_templates(
method transform_prompts (line 155) | async def transform_prompts(self, prompts: Sequence[Prompt]) -> Sequen...
method get_tool_catalog (line 171) | async def get_tool_catalog(
method get_resource_catalog (line 193) | async def get_resource_catalog(
method get_prompt_catalog (line 210) | async def get_prompt_catalog(
method get_resource_template_catalog (line 227) | async def get_resource_template_catalog(
FILE: src/fastmcp/server/transforms/namespace.py
class Namespace (line 28) | class Namespace(Transform):
method __init__ (line 44) | def __init__(self, prefix: str) -> None:
method __repr__ (line 53) | def __repr__(self) -> str:
method _transform_name (line 60) | def _transform_name(self, name: str) -> str:
method _reverse_name (line 64) | def _reverse_name(self, name: str) -> str | None:
method _transform_uri (line 74) | def _transform_uri(self, uri: str) -> str:
method _reverse_uri (line 82) | def _reverse_uri(self, uri: str) -> str | None:
method list_tools (line 97) | async def list_tools(self, tools: Sequence[Tool]) -> Sequence[Tool]:
method get_tool (line 103) | async def get_tool(
method list_resources (line 119) | async def list_resources(self, resources: Sequence[Resource]) -> Seque...
method get_resource (line 126) | async def get_resource(
method list_resource_templates (line 146) | async def list_resource_templates(
method get_resource_template (line 155) | async def get_resource_template(
method list_prompts (line 177) | async def list_prompts(self, prompts: Sequence[Prompt]) -> Sequence[Pr...
method get_prompt (line 183) | async def get_prompt(
FILE: src/fastmcp/server/transforms/prompts_as_tools.py
class PromptsAsTools (line 38) | class PromptsAsTools(Transform):
method __init__ (line 60) | def __init__(self, provider: Provider) -> None:
method __repr__ (line 72) | def __repr__(self) -> str:
method list_tools (line 75) | async def list_tools(self, tools: Sequence[Tool]) -> Sequence[Tool]:
method get_tool (line 83) | async def get_tool(
method _make_list_prompts_tool (line 93) | def _make_list_prompts_tool(self) -> Tool:
method _make_get_prompt_tool (line 126) | def _make_get_prompt_tool(self) -> Tool:
function _format_prompt_result (line 149) | def _format_prompt_result(result: Any) -> str:
FILE: src/fastmcp/server/transforms/resources_as_tools.py
class ResourcesAsTools (line 41) | class ResourcesAsTools(Transform):
method __init__ (line 63) | def __init__(self, provider: Provider) -> None:
method __repr__ (line 75) | def __repr__(self) -> str:
method list_tools (line 78) | async def list_tools(self, tools: Sequence[Tool]) -> Sequence[Tool]:
method get_tool (line 86) | async def get_tool(
method _make_list_resources_tool (line 96) | def _make_list_resources_tool(self) -> Tool:
method _make_read_resource_tool (line 135) | def _make_read_resource_tool(self) -> Tool:
function _format_result (line 156) | def _format_result(result: Any) -> str:
FILE: src/fastmcp/server/transforms/search/base.py
function _extract_searchable_text (line 41) | def _extract_searchable_text(tool: Tool) -> str:
function serialize_tools_for_output_json (line 60) | def serialize_tools_for_output_json(tools: Sequence[Tool]) -> list[dict[...
function _invoke_serializer (line 70) | async def _invoke_serializer(
function _union_type (line 80) | def _union_type(branches: list[Any]) -> str:
function _schema_type (line 90) | def _schema_type(schema: Any) -> str:
function _schema_section (line 114) | def _schema_section(schema: dict[str, Any] | None, title: str) -> list[s...
function serialize_tools_for_output_markdown (line 138) | def serialize_tools_for_output_markdown(tools: Sequence[Tool]) -> str:
class BaseSearchTransform (line 154) | class BaseSearchTransform(CatalogTransform):
method __init__ (line 177) | def __init__(
method transform_tools (line 199) | async def transform_tools(self, tools: Sequence[Tool]) -> Sequence[Tool]:
method get_tool (line 204) | async def get_tool(
method _make_search_tool (line 219) | def _make_search_tool(self) -> Tool:
method _make_call_tool (line 223) | def _make_call_tool(self) -> Tool:
method _render_results (line 250) | async def _render_results(self, tools: Sequence[Tool]) -> Any:
method _get_visible_tools (line 257) | async def _get_visible_tools(self, ctx: Context) -> Sequence[Tool]:
method _search (line 267) | async def _search(self, tools: Sequence[Tool], query: str) -> Sequence...
FILE: src/fastmcp/server/transforms/search/bm25.py
function _tokenize (line 18) | def _tokenize(text: str) -> list[str]:
class _BM25Index (line 23) | class _BM25Index:
method __init__ (line 26) | def __init__(self, k1: float = 1.5, b: float = 0.75) -> None:
method build (line 36) | def build(self, documents: list[str]) -> None:
method query (line 54) | def query(self, text: str, top_k: int) -> list[int]:
function _catalog_hash (line 80) | def _catalog_hash(tools: Sequence[Tool]) -> str:
class BM25SearchTransform (line 86) | class BM25SearchTransform(BaseSearchTransform):
method __init__ (line 93) | def __init__(
method _make_search_tool (line 113) | def _make_search_tool(self) -> Tool:
method _search (line 131) | async def _search(self, tools: Sequence[Tool], query: str) -> Sequence...
FILE: src/fastmcp/server/transforms/search/regex.py
class RegexSearchTransform (line 15) | class RegexSearchTransform(BaseSearchTransform):
method _make_search_tool (line 22) | def _make_search_tool(self) -> Tool:
method _search (line 42) | async def _search(self, tools: Sequence[Tool], query: str) -> Sequence...
FILE: src/fastmcp/server/transforms/tool_transform.py
class ToolTransform (line 16) | class ToolTransform(Transform):
method __init__ (line 33) | def __init__(self, transforms: dict[str, ToolTransformConfig]) -> None:
method __repr__ (line 58) | def __repr__(self) -> str:
method list_tools (line 64) | async def list_tools(self, tools: Sequence[Tool]) -> Sequence[Tool]:
method get_tool (line 75) | async def get_tool(
FILE: src/fastmcp/server/transforms/version_filter.py
class VersionFilter (line 24) | class VersionFilter(Transform):
method __init__ (line 50) | def __init__(
method __repr__ (line 66) | def __repr__(self) -> str:
method list_tools (line 80) | async def list_tools(self, tools: Sequence[Tool]) -> Sequence[Tool]:
method get_tool (line 87) | async def get_tool(
method list_resources (line 96) | async def list_resources(self, resources: Sequence[Resource]) -> Seque...
method get_resource (line 103) | async def get_resource(
method list_resource_templates (line 116) | async def list_resource_templates(
method get_resource_template (line 125) | async def get_resource_template(
method list_prompts (line 138) | async def list_prompts(self, prompts: Sequence[Prompt]) -> Sequence[Pr...
method get_prompt (line 145) | async def get_prompt(
FILE: src/fastmcp/server/transforms/visibility.py
class Visibility (line 39) | class Visibility(Transform):
method __init__ (line 60) | def __init__(
method __repr__ (line 92) | def __repr__(self) -> str:
method _matches (line 111) | def _matches(self, component: FastMCPComponent) -> bool:
method _mark_component (line 173) | def _mark_component(self, component: T) -> T:
method list_tools (line 196) | async def list_tools(self, tools: Sequence[Tool]) -> Sequence[Tool]:
method get_tool (line 200) | async def get_tool(
method list_resources (line 213) | async def list_resources(self, resources: Sequence[Resource]) -> Seque...
method get_resource (line 217) | async def get_resource(
method list_resource_templates (line 234) | async def list_resource_templates(
method get_resource_template (line 240) | async def get_resource_template(
method list_prompts (line 257) | async def list_prompts(self, prompts: Sequence[Prompt]) -> Sequence[Pr...
method get_prompt (line 261) | async def get_prompt(
function is_enabled (line 271) | def is_enabled(component: FastMCPComponent) -> bool:
function get_visibility_rules (line 300) | async def get_visibility_rules(context: Context) -> list[dict[str, Any]]:
function save_visibility_rules (line 305) | async def save_visibility_rules(
function create_visibility_transforms (line 332) | def create_visibility_transforms(rules: list[dict[str, Any]]) -> list[Vi...
function get_session_transforms (line 360) | async def get_session_transforms(context: Context) -> list[Visibility]:
function enable_components (line 372) | async def enable_components(
function disable_components (line 426) | async def disable_components(
function reset_visibility (line 480) | async def reset_visibility(context: Context) -> None:
function apply_session_transforms (line 497) | async def apply_session_transforms(
FILE: src/fastmcp/settings.py
class DocketSettings (line 33) | class DocketSettings(BaseSettings):
class Settings (line 136) | class Settings(BaseSettings):
method get_setting (line 148) | def get_setting(self, attr: str) -> Any:
method set_setting (line 161) | def set_setting(self, attr: str, value: Any) -> None:
method normalize_log_level (line 183) | def normalize_log_level(cls, v):
FILE: src/fastmcp/telemetry.py
function get_tracer (line 38) | def get_tracer(version: str | None = None) -> Tracer:
function inject_trace_context (line 50) | def inject_trace_context(
function record_span_error (line 76) | def record_span_error(span: Span, exception: BaseException) -> None:
function extract_trace_context (line 82) | def extract_trace_context(meta: dict[str, Any] | None) -> Context:
FILE: src/fastmcp/tools/base.py
function default_serializer (line 64) | def default_serializer(data: Any) -> str:
class ToolResult (line 68) | class ToolResult(BaseModel):
method __init__ (line 79) | def __init__(
method to_mcp_result (line 123) | def to_mcp_result(
class Tool (line 139) | class Tool(FastMCPComponent):
method _validate_tool_name (line 176) | def _validate_tool_name(self) -> Tool:
method to_mcp_tool (line 181) | def to_mcp_tool(
method from_function (line 208) | def from_function(
method run (line 248) | async def run(self, arguments: dict[str, Any]) -> ToolResult:
method convert_result (line 260) | def convert_result(self, raw_value: Any) -> ToolResult:
method _run (line 308) | async def _run(
method _run (line 315) | async def _run(
method _run (line 321) | async def _run(
method register_with_docket (line 359) | def register_with_docket(self, docket: Docket) -> None:
method add_to_docket (line 365) | async def add_to_docket( # type: ignore[override]
method from_tool (line 389) | def from_tool(
method _ensure_tool (line 423) | def _ensure_tool(cls, tool: Tool | Callable[..., Any]) -> Tool:
method get_span_attributes (line 437) | def get_span_attributes(self) -> dict[str, Any]:
function _serialize_with_fallback (line 444) | def _serialize_with_fallback(
function _convert_to_single_content_block (line 460) | def _convert_to_single_content_block(
function _get_tool_resolver (line 485) | def _get_tool_resolver() -> Callable[..., str] | None:
function _prefab_to_json (line 495) | def _prefab_to_json(app: Any) -> dict[str, Any]:
function _prefab_to_tool_result (line 500) | def _prefab_to_tool_result(app: Any) -> ToolResult:
function _convert_to_content (line 508) | def _convert_to_content(
function __getattr__ (line 540) | def __getattr__(name: str) -> Any:
FILE: src/fastmcp/tools/function_parsing.py
function _contains_prefab_type (line 42) | def _contains_prefab_type(tp: Any) -> bool:
class _WrappedResult (line 58) | class _WrappedResult(Generic[T]):
class _UnserializableType (line 64) | class _UnserializableType:
function _is_object_schema (line 68) | def _is_object_schema(
class ParsedFunction (line 117) | class ParsedFunction:
method from_function (line 126) | def from_function(
FILE: src/fastmcp/tools/function_tool.py
class DecoratedTool (line 59) | class DecoratedTool(Protocol):
method __call__ (line 64) | def __call__(self, *args: Any, **kwargs: Any) -> Any: ...
class ToolMeta (line 68) | class ToolMeta:
class FunctionTool (line 90) | class FunctionTool(Tool):
method to_mcp_tool (line 94) | def to_mcp_tool(
method from_function (line 113) | def from_function(
method run (line 256) | async def run(self, arguments: dict[str, Any]) -> ToolResult:
method register_with_docket (line 301) | def register_with_docket(self, docket: Docket) -> None:
method add_to_docket (line 311) | async def add_to_docket(
function tool (line 338) | def tool(fn: F) -> F: ...
function tool (line 340) | def tool(
function tool (line 358) | def tool(
function tool (line 378) | def tool(
FILE: src/fastmcp/tools/tool_transform.py
function forward (line 41) | async def forward(**kwargs: Any) -> ToolResult:
function forward_raw (line 71) | async def forward_raw(**kwargs: Any) -> ToolResult:
class ArgTransform (line 98) | class ArgTransform:
method __post_init__ (line 176) | def __post_init__(self):
class ArgTransformConfig (line 212) | class ArgTransformConfig(FastMCPBaseModel):
method to_arg_transform (line 230) | def to_arg_transform(self) -> ArgTransform:
class TransformedTool (line 236) | class TransformedTool(Tool):
method run (line 265) | async def run(self, arguments: dict[str, Any]) -> ToolResult:
method from_tool (line 361) | def from_tool(
method _create_forwarding_transform (line 609) | def _create_forwarding_transform(
method _apply_single_transform (line 732) | def _apply_single_transform(
method _merge_schema_with_precedence (line 801) | def _merge_schema_with_precedence(
method _function_has_kwargs (line 880) | def _function_has_kwargs(fn: Callable[..., Any]) -> bool:
function _set_visibility_metadata (line 898) | def _set_visibility_metadata(tool: Tool, *, enabled: bool) -> None:
class ToolTransformConfig (line 921) | class ToolTransformConfig(FastMCPBaseModel):
method apply (line 954) | def apply(self, tool: Tool) -> TransformedTool:
function apply_transformations_to_tools (line 975) | def apply_transformations_to_tools(
FILE: src/fastmcp/utilities/async_utils.py
function is_coroutine_function (line 15) | def is_coroutine_function(fn: Any) -> bool:
function call_sync_fn_in_threadpool (line 27) | async def call_sync_fn_in_threadpool(
function gather (line 39) | async def gather(
function gather (line 46) | async def gather(
function gather (line 52) | async def gather(
FILE: src/fastmcp/utilities/auth.py
function _decode_jwt_part (line 10) | def _decode_jwt_part(token: str, part_index: int) -> dict[str, Any]:
function decode_jwt_header (line 32) | def decode_jwt_header(token: str) -> dict[str, Any]:
function decode_jwt_payload (line 49) | def decode_jwt_payload(token: str) -> dict[str, Any]:
function parse_scopes (line 66) | def parse_scopes(value: Any) -> list[str] | None:
FILE: src/fastmcp/utilities/cli.py
function is_already_in_uv_subprocess (line 28) | def is_already_in_uv_subprocess() -> bool:
function load_and_merge_config (line 33) | def load_and_merge_config(
function log_server_banner (line 201) | def log_server_banner(server: FastMCP[Any]) -> None:
FILE: src/fastmcp/utilities/components.py
class FastMCPMeta (line 20) | class FastMCPMeta(TypedDict, total=False):
function get_fastmcp_metadata (line 26) | def get_fastmcp_metadata(meta: dict[str, Any] | None) -> FastMCPMeta:
function _convert_set_default_none (line 43) | def _convert_set_default_none(maybe_set: set[T] | Sequence[T] | None) ->...
function _coerce_version (line 52) | def _coerce_version(v: str | int | float | None) -> str | None:
class FastMCPComponent (line 74) | class FastMCPComponent(FastMCPBaseModel):
method __init_subclass__ (line 79) | def __init_subclass__(cls, **kwargs: Any) -> None:
method make_key (line 125) | def make_key(cls, identifier: str) -> str:
method key (line 139) | def key(self) -> str:
method get_meta (line 154) | def get_meta(self) -> dict[str, Any]:
method __eq__ (line 182) | def __eq__(self, other: object) -> bool:
method __repr__ (line 189) | def __repr__(self) -> str:
method enable (line 202) | def enable(self) -> None:
method disable (line 209) | def disable(self) -> None:
method copy (line 216) | def copy(self) -> Self: # type: ignore[override]
method register_with_docket (line 220) | def register_with_docket(self, docket: Docket) -> None:
method add_to_docket (line 228) | async def add_to_docket(
method get_span_attributes (line 250) | def get_span_attributes(self) -> dict[str, Any]:
FILE: src/fastmcp/utilities/exceptions.py
function iter_exc (line 12) | def iter_exc(group: BaseExceptionGroup):
function _exception_handler (line 20) | def _exception_handler(group: BaseExceptionGroup):
function get_catch_handlers (line 42) | def get_catch_handlers() -> Mapping[
FILE: src/fastmcp/utilities/http.py
function find_available_port (line 4) | def find_available_port() -> int:
FILE: src/fastmcp/utilities/inspect.py
class ToolInfo (line 19) | class ToolInfo:
class PromptInfo (line 35) | class PromptInfo:
class ResourceInfo (line 49) | class ResourceInfo:
class TemplateInfo (line 65) | class TemplateInfo:
class FastMCPInfo (line 82) | class FastMCPInfo:
function inspect_fastmcp_v2 (line 100) | async def inspect_fastmcp_v2(mcp: FastMCP[Any]) -> FastMCPInfo:
function inspect_fastmcp_v1 (line 236) | async def inspect_fastmcp_v1(mcp: FastMCP1x) -> FastMCPInfo:
function inspect_fastmcp (line 378) | async def inspect_fastmcp(mcp: FastMCP[Any] | FastMCP1x) -> FastMCPInfo:
class InspectFormat (line 396) | class InspectFormat(str, Enum):
function format_fastmcp_info (line 403) | def format_fastmcp_info(info: FastMCPInfo) -> bytes:
function format_mcp_info (line 432) | async def format_mcp_info(mcp: FastMCP[Any] | FastMCP1x) -> bytes:
function format_info (line 465) | async def format_info(
FILE: src/fastmcp/utilities/json_schema.py
function _defs_have_cycles (line 9) | def _defs_have_cycles(defs: dict[str, Any]) -> bool:
function _strip_remote_refs (line 56) | def _strip_remote_refs(obj: Any) -> Any:
function dereference_refs (line 76) | def dereference_refs(schema: dict[str, Any]) -> dict[str, Any]:
function _merge_ref_siblings (line 146) | def _merge_ref_siblings(
function resolve_root_ref (line 213) | def resolve_root_ref(schema: dict[str, Any]) -> dict[str, Any]:
function _prune_param (line 252) | def _prune_param(schema: dict[str, Any], param: str) -> dict[str, Any]:
function _single_pass_optimize (line 273) | def _single_pass_optimize(
function compress_schema (line 446) | def compress_schema(
FILE: src/fastmcp/utilities/json_schema_type.py
class JSONSchema (line 78) | class JSONSchema(TypedDict):
function json_schema_to_type (line 111) | def json_schema_to_type(
function _hash_schema (line 195) | def _hash_schema(schema: Mapping[str, Any]) -> str:
function _resolve_ref (line 200) | def _resolve_ref(ref: str, schemas: Mapping[str, Any]) -> Mapping[str, A...
function _create_string_type (line 209) | def _create_string_type(schema: Mapping[str, Any]) -> type | Annotated[A...
function _create_numeric_type (line 234) | def _create_numeric_type(
function _create_enum (line 256) | def _create_enum(name: str, values: list[Any]) -> type:
function _create_array_type (line 262) | def _create_array_type(
function _return_Any (line 290) | def _return_Any() -> Any:
function _get_from_type_handler (line 294) | def _get_from_type_handler(
function _schema_to_type (line 315) | def _schema_to_type(
function _sanitize_name (line 400) | def _sanitize_name(name: str) -> str:
function _get_default_value (line 418) | def _get_default_value(
function _create_field_with_default (line 433) | def _create_field_with_default(
function _create_pydantic_model (line 447) | def _create_pydantic_model(
function _create_dataclass (line 505) | def _create_dataclass(
function _merge_defaults (line 590) | def _merge_defaults(
FILE: src/fastmcp/utilities/lifespan.py
function combine_lifespans (line 12) | def combine_lifespans(
FILE: src/fastmcp/utilities/logging.py
function get_logger (line 14) | def get_logger(name: str) -> logging.Logger:
function configure_logging (line 29) | def configure_logging(
function temporary_log_level (line 111) | def temporary_log_level(
class _ClampedLogFilter (line 174) | class _ClampedLogFilter(logging.Filter):
method __init__ (line 178) | def __init__(
method filter (line 196) | def filter(self, record: logging.LogRecord) -> bool:
function _clamp_logger (line 215) | def _clamp_logger(
function _unclamp_logger (line 234) | def _unclamp_logger(logger: logging.Logger) -> None:
FILE: src/fastmcp/utilities/mcp_server_config/v1/environments/base.py
class Environment (line 7) | class Environment(BaseModel, ABC):
method build_command (line 13) | def build_command(self, command: list[str]) -> list[str]:
method prepare (line 23) | async def prepare(self, output_dir: Path | None = None) -> None:
FILE: src/fastmcp/utilities/mcp_server_config/v1/environments/uv.py
class UVEnvironment (line 14) | class UVEnvironment(Environment):
method build_command (line 49) | def build_command(self, command: list[str]) -> list[str]:
method _must_run_with_uv (line 93) | def _must_run_with_uv(self) -> bool:
method prepare (line 109) | async def prepare(self, output_dir: Path | None = None) -> None:
FILE: src/fastmcp/utilities/mcp_server_config/v1/mcp_server_config.py
class Deployment (line 36) | class Deployment(BaseModel):
method apply_runtime_settings (line 85) | def apply_runtime_settings(self, config_path: Path | None = None) -> N...
method _interpolate_env_vars (line 112) | def _interpolate_env_vars(self, value: str) -> str:
class MCPServerConfig (line 134) | class MCPServerConfig(BaseModel):
method __init__ (line 174) | def __init__(self, *, source: dict | FileSystemSource, **data) -> None...
method __init__ (line 176) | def __init__(self, *, environment: dict | UVEnvironment, **data) -> No...
method __init__ (line 178) | def __init__(self, *, deployment: dict | Deployment, **data) -> None: ...
method __init__ (line 179) | def __init__(self, **data) -> None: ...
method validate_source (line 183) | def validate_source(cls, v: dict | Source) -> SourceType:
method validate_environment (line 199) | def validate_environment(cls, v: dict | Any) -> EnvironmentType:
method validate_deployment (line 210) | def validate_deployment(cls, v: dict | Deployment) -> Deployment:
method from_file (line 223) | def from_file(cls, file_path: Path) -> MCPServerConfig:
method from_cli_args (line 246) | def from_cli_args(
method find_config (line 323) | def find_config(cls, start_path: Path | None = None) -> Path | None:
method prepare (line 342) | async def prepare(
method prepare_environment (line 363) | async def prepare_environment(self, output_dir: Path | None = None) ->...
method prepare_source (line 374) | async def prepare_source(self) -> None:
method run_server (line 381) | async def run_server(self, **kwargs: Any) -> None:
function generate_schema (line 416) | def generate_schema(output_path: Path | str | None = None) -> dict[str, ...
FILE: src/fastmcp/utilities/mcp_server_config/v1/sources/base.py
class Source (line 7) | class Source(BaseModel, ABC):
method prepare (line 12) | async def prepare(self) -> None:
method load_server (line 22) | async def load_server(self) -> Any:
FILE: src/fastmcp/utilities/mcp_server_config/v1/sources/filesystem.py
class FileSystemSource (line 16) | class FileSystemSource(Source):
method parse_path_with_object (line 29) | def parse_path_with_object(cls, v: str) -> str:
method __init__ (line 46) | def __init__(self, **data: Any) -> None:
method load_server (line 64) | async def load_server(self) -> Any:
method _import_module (line 83) | def _import_module(self, file_path: Path) -> Any:
method _find_server_object (line 109) | async def _find_server_object(self, module: Any, file_path: Path) -> Any:
method _resolve_factory (line 169) | async def _resolve_factory(self, obj: Any, file_path: Path, name: str)...
FILE: src/fastmcp/utilities/openapi/director.py
class RequestDirector (line 16) | class RequestDirector:
method __init__ (line 19) | def __init__(self, spec: SchemaPath):
method build (line 23) | def build(
method _unflatten_arguments (line 80) | def _unflatten_arguments(
method _build_url (line 194) | def _build_url(
FILE: src/fastmcp/utilities/openapi/formatters.py
function format_array_parameter (line 12) | def format_array_parameter(
function format_deep_object_parameter (line 66) | def format_deep_object_parameter(
function generate_example_from_schema (line 100) | def generate_example_from_schema(schema: JsonSchema | None) -> Any:
function format_json_for_description (line 183) | def format_json_for_description(data: Any, indent: int = 2) -> str:
function format_description_with_responses (line 192) | def format_description_with_responses(
FILE: src/fastmcp/utilities/openapi/json_schema_converter.py
function convert_openapi_schema_to_json_schema (line 38) | def convert_openapi_schema_to_json_schema(
function _convert_nullable_field (line 150) | def _convert_nullable_field(schema: dict[str, Any]) -> dict[str, Any]:
function _has_read_only_properties (line 186) | def _has_read_only_properties(schema: dict[str, Any]) -> bool:
function _has_write_only_properties (line 196) | def _has_write_only_properties(schema: dict[str, Any]) -> bool:
function _needs_recursive_processing (line 206) | def _needs_recursive_processing(
function _filter_properties_by_access (line 287) | def _filter_properties_by_access(
function convert_schema_definitions (line 322) | def convert_schema_definitions(
FILE: src/fastmcp/utilities/openapi/models.py
class ParameterInfo (line 17) | class ParameterInfo(FastMCPBaseModel):
class RequestBodyInfo (line 29) | class RequestBodyInfo(FastMCPBaseModel):
class ResponseInfo (line 39) | class ResponseInfo(FastMCPBaseModel):
class HTTPRoute (line 47) | class HTTPRoute(FastMCPBaseModel):
FILE: src/fastmcp/utilities/openapi/parser.py
function parse_openapi_to_http_routes (line 55) | def parse_openapi_to_http_routes(openapi_dict: dict[str, Any]) -> list[H...
class OpenAPIParser (line 109) | class OpenAPIParser(
method __init__ (line 123) | def __init__(
method _convert_to_parameter_location (line 146) | def _convert_to_parameter_location(self, param_in: str) -> ParameterLo...
method _resolve_ref (line 153) | def _resolve_ref(self, item: Any) -> Any:
method _extract_schema_as_dict (line 208) | def _extract_schema_as_dict(self, schema_obj: Any) -> JsonSchema:
method _extract_parameters (line 240) | def _extract_parameters(
method _extract_request_body (line 339) | def _extract_request_body(self, request_body_or_ref: Any) -> RequestBo...
method _is_success_status_code (line 405) | def _is_success_status_code(self, status_code: str) -> bool:
method _get_primary_success_response (line 414) | def _get_primary_success_response(
method _extract_responses (line 437) | def _extract_responses(
method _extract_schema_dependencies (line 535) | def _extract_schema_dependencies(
method _extract_input_schema_dependencies (line 586) | def _extract_input_schema_dependencies(
method _extract_output_schema_dependencies (line 622) | def _extract_output_schema_dependencies(
method parse (line 663) | def parse(self) -> list[HTTPRoute]:
FILE: src/fastmcp/utilities/openapi/schemas.py
function clean_schema_for_display (line 12) | def clean_schema_for_display(schema: JsonSchema | None) -> JsonSchema | ...
function _replace_ref_with_defs (line 74) | def _replace_ref_with_defs(
function _make_optional_parameter_nullable (line 144) | def _make_optional_parameter_nullable(schema: dict[str, Any]) -> dict[st...
function _combine_schemas_and_map_params (line 222) | def _combine_schemas_and_map_params(
function _combine_schemas (line 457) | def _combine_schemas(route: HTTPRoute) -> dict[str, Any]:
function extract_output_schema_from_responses (line 474) | def extract_output_schema_from_responses(
FILE: src/fastmcp/utilities/pagination.py
class CursorState (line 16) | class CursorState:
method encode (line 25) | def encode(self) -> str:
method decode (line 31) | def decode(cls, cursor: str) -> CursorState:
function paginate_sequence (line 50) | def paginate_sequence(
FILE: src/fastmcp/utilities/skills.py
class SkillSummary (line 18) | class SkillSummary:
class SkillFile (line 27) | class SkillFile:
class SkillManifest (line 36) | class SkillManifest:
function list_skills (line 43) | async def list_skills(client: Client) -> list[SkillSummary]:
function get_skill_manifest (line 87) | async def get_skill_manifest(client: Client, skill_name: str) -> SkillMa...
function download_skill (line 127) | async def download_skill(
function sync_skills (line 218) | async def sync_skills(
FILE: src/fastmcp/utilities/tests.py
function temporary_settings (line 24) | def temporary_settings(**kwargs: Any):
function _run_server (line 56) | def _run_server(mcp_server: FastMCP, transport: Literal["sse"], port: in...
function run_server_in_process (line 75) | def run_server_in_process(
function run_server_async (line 143) | async def run_server_async(
class HeadlessOAuth (line 225) | class HeadlessOAuth(OAuth):
method __init__ (line 233) | def __init__(self, mcp_url: str, **kwargs):
method redirect_handler (line 238) | async def redirect_handler(self, authorization_url: str) -> None:
method callback_handler (line 244) | async def callback_handler(self) -> tuple[str, str | None]:
FILE: src/fastmcp/utilities/timeout.py
function normalize_timeout_to_timedelta (line 8) | def normalize_timeout_to_timedelta(
function normalize_timeout_to_seconds (line 28) | def normalize_timeout_to_seconds(
FILE: src/fastmcp/utilities/token_cache.py
class _CacheEntry (line 39) | class _CacheEntry:
class TokenCache (line 46) | class TokenCache:
method __init__ (line 62) | def __init__(
method enabled (line 89) | def enabled(self) -> bool:
method get (line 95) | def get(self, token: str) -> tuple[bool, AccessToken | None]:
method set (line 118) | def set(self, token: str, result: AccessToken) -> None:
method _hash_token (line 146) | def _hash_token(token: str) -> str:
method _cleanup_expired (line 150) | def _cleanup_expired(self) -> None:
method _maybe_cleanup (line 159) | def _maybe_cleanup(self) -> None:
method _enforce_size_limit (line 166) | def _enforce_size_limit(self) -> None:
FILE: src/fastmcp/utilities/types.py
function get_fn_name (line 34) | def get_fn_name(fn: Callable[..., Any]) -> str:
class FastMCPBaseModel (line 38) | class FastMCPBaseModel(BaseModel):
function get_cached_typeadapter (line 45) | def get_cached_typeadapter(cls: T) -> TypeAdapter[T]:
function issubclass_safe (line 123) | def issubclass_safe(cls: type, base: type) -> bool:
function is_class_member_of_type (line 133) | def is_class_member_of_type(cls: Any, base: type) -> bool:
function find_kwarg_by_type (line 155) | def find_kwarg_by_type(fn: Callable, kwarg_type: type) -> str | None:
function create_function_without_params (line 181) | def create_function_without_params(
class Image (line 238) | class Image:
method __init__ (line 241) | def __init__(
method _get_expanded_path (line 260) | def _get_expanded_path(path: str | Path | None) -> Path | None:
method _get_mime_type (line 264) | def _get_mime_type(self) -> str:
method _get_data (line 278) | def _get_data(self) -> str:
method to_image_content (line 289) | def to_image_content(
method to_data_uri (line 304) | def to_data_uri(self, mime_type: str | None = None) -> str:
class Audio (line 310) | class Audio:
method __init__ (line 313) | def __init__(
method _get_mime_type (line 331) | def _get_mime_type(self) -> str:
method to
Copy disabled (too large)
Download .json
Condensed preview — 1240 files, each showing path, character count, and a content snippet. Download the .json file for the full structured content (10,384K chars).
[
{
"path": ".ccignore",
"chars": 115,
"preview": ".pre-commit-config.yaml\n.github/\ndocs/changelog.mdx\ndocs/python-sdk/\nexamples/\nsrc/fastmcp/contrib/\ntests/contrib/\n"
},
{
"path": ".claude/hooks/session-init.sh",
"chars": 824,
"preview": "#!/bin/bash\nset -e\n\n# Only run in remote/cloud environments\nif [ \"$CLAUDE_CODE_REMOTE\" != \"true\" ]; then\n exit 0\nfi\n\nco"
},
{
"path": ".claude/settings.json",
"chars": 261,
"preview": "{\n \"hooks\": {\n \"SessionStart\": [\n {\n \"hooks\": [\n {\n \"type\": \"command\",\n \""
},
{
"path": ".claude/skills/code-review/SKILL.md",
"chars": 4777,
"preview": "---\nname: reviewing-code\ndescription: Review code for quality, maintainability, and correctness. Use when reviewing pull"
},
{
"path": ".claude/skills/python-tests/SKILL.md",
"chars": 5362,
"preview": "---\nname: testing-python\ndescription: Write and evaluate effective Python tests using pytest. Use when writing tests, re"
},
{
"path": ".claude/skills/review-pr/SKILL.md",
"chars": 4966,
"preview": "---\nname: review-pr\ndescription: Monitor and respond to automated PR reviews (Codex bot). Use when pushing a PR, checkin"
},
{
"path": ".coderabbit.yaml",
"chars": 53,
"preview": "reviews:\n path_filters:\n - \"!docs/python-sdk/**\"\n"
},
{
"path": ".cursor/rules/core-mcp-objects.mdc",
"chars": 527,
"preview": "---\ndescription: \nglobs: \nalwaysApply: true\n---\nThere are four major MCP object types:\n\n- Tools (src/tools/)\n- Resources"
},
{
"path": ".github/ISSUE_TEMPLATE/bug.yml",
"chars": 3102,
"preview": "name: 🐛 Bug Report\ndescription: Report a bug or unexpected behavior in FastMCP\nlabels: [bug, pending]\n\nbody:\n - type: m"
},
{
"path": ".github/ISSUE_TEMPLATE/config.yml",
"chars": 445,
"preview": "blank_issues_enabled: false\ncontact_links:\n - name: FastMCP Documentation\n url: https://gofastmcp.com\n about: Ple"
},
{
"path": ".github/ISSUE_TEMPLATE/enhancement.yml",
"chars": 1675,
"preview": "name: 💡 Enhancement Request\ndescription: Suggest an idea or improvement for FastMCP\nlabels: [enhancement, pending]\n\nbody"
},
{
"path": ".github/actions/run-claude/action.yml",
"chars": 3060,
"preview": "# Composite Action for running Claude Code Action\n#\n# Wraps anthropics/claude-code-action with MCP server configuration."
},
{
"path": ".github/actions/run-pytest/action.yml",
"chars": 1259,
"preview": "name: \"Run Pytest\"\ndescription: \"Run pytest with appropriate flags for the test type and platform\"\n\ninputs:\n test-type:"
},
{
"path": ".github/actions/setup-uv/action.yml",
"chars": 888,
"preview": "name: \"Setup UV Environment\"\ndescription: \"Install uv and dependencies (requires checkout first)\"\n\ninputs:\n python-vers"
},
{
"path": ".github/dependabot.yml",
"chars": 274,
"preview": "version: 2\nupdates:\n - package-ecosystem: \"pip\"\n directory: \"/\"\n schedule:\n interval: \"daily\"\n labels:\n "
},
{
"path": ".github/pull_request_template.md",
"chars": 848,
"preview": "## Description\n\n<!-- What does this PR do? Link to the issue it addresses. -->\n\nCloses #\n\n## Contribution type\n\n<!-- Che"
},
{
"path": ".github/release.yml",
"chars": 932,
"preview": "changelog:\n exclude:\n labels:\n - ignore in release notes\n\n categories:\n - title: New Features 🎉\n label"
},
{
"path": ".github/scripts/mention/gh-get-review-threads.sh",
"chars": 1617,
"preview": "#!/usr/bin/env bash\nset -euo pipefail\n\n# Get PR review threads with comments via GitHub GraphQL API\n#\n# Usage:\n# gh-ge"
},
{
"path": ".github/scripts/mention/gh-resolve-review-thread.sh",
"chars": 1787,
"preview": "#!/usr/bin/env bash\nset -euo pipefail\n\n# Resolve a GitHub PR review thread, optionally posting a comment first\n#\n# Usage"
},
{
"path": ".github/scripts/pr-review/pr-comment.sh",
"chars": 6650,
"preview": "#!/bin/bash\n# pr-comment.sh - Queue a structured inline review comment for the PR review\n#\n# Usage:\n# pr-comment.sh <f"
},
{
"path": ".github/scripts/pr-review/pr-diff.sh",
"chars": 4501,
"preview": "#!/bin/bash\n# pr-diff.sh - Show changed files or diff for a specific file\n#\n# Usage: \n# pr-diff.sh - List al"
},
{
"path": ".github/scripts/pr-review/pr-existing-comments.sh",
"chars": 6438,
"preview": "#!/bin/bash\n# pr-existing-comments.sh - Fetch existing review threads on a PR\n#\n# Usage:\n# pr-existing-comments.sh "
},
{
"path": ".github/scripts/pr-review/pr-remove-comment.sh",
"chars": 2522,
"preview": "#!/bin/bash\n# pr-remove-comment.sh - Remove a queued review comment\n#\n# Usage:\n# pr-remove-comment.sh <file> <line-num"
},
{
"path": ".github/scripts/pr-review/pr-review.sh",
"chars": 4798,
"preview": "#!/bin/bash\n# pr-review.sh - Submit a PR review (approve, request changes, or comment)\n#\n# Usage: pr-review.sh <APPROVE|"
},
{
"path": ".github/workflows/auto-close-duplicates.yml",
"chars": 1041,
"preview": "name: Auto-close duplicate issues\ndescription: Auto-closes issues that are duplicates of existing issues\non:\n schedule:"
},
{
"path": ".github/workflows/auto-close-needs-mre.yml",
"chars": 1074,
"preview": "name: Auto-close needs MRE issues\ndescription: Auto-closes issues that need minimal reproducible examples after 7 days o"
},
{
"path": ".github/workflows/martian-test-failure.yml",
"chars": 7891,
"preview": "name: Marvin Test Failure Analysis\n\non:\n workflow_run:\n workflows: [\"Tests\", \"Run static analysis\"]\n types:\n "
},
{
"path": ".github/workflows/martian-triage-issue.yml",
"chars": 12021,
"preview": "# Triage new issues: investigate, recommend, apply labels\n# Calls run-claude directly with triage prompt (elastic issue-"
},
{
"path": ".github/workflows/marvin-comment-on-issue.yml",
"chars": 5815,
"preview": "# Respond to /marvin mentions in issue comments (elastic mention-in-issue style)\n# Calls run-claude directly\n\nname: Comm"
},
{
"path": ".github/workflows/marvin-comment-on-pr.yml",
"chars": 14465,
"preview": "# Respond to /marvin mentions in PR review comments and issue comments on PRs\n# Calls run-claude directly\n\nname: Comment"
},
{
"path": ".github/workflows/marvin-dedupe-issues.yml",
"chars": 5070,
"preview": "name: Marvin Issue Dedupe\n# description: Automatically dedupe GitHub issues using Marvin\non:\n issues:\n types: [opene"
},
{
"path": ".github/workflows/marvin-label-triage.yml",
"chars": 8874,
"preview": "name: Marvin Label Triage\n# Automatically triage GitHub issues and PRs using Marvin\n\non:\n issues:\n types: [opened]\n "
},
{
"path": ".github/workflows/minimize-resolved-reviews.yml",
"chars": 1463,
"preview": "# Minimize resolved PR review comments to reduce noise.\n#\n# Runs automatically on review activity for same-repo PRs. For"
},
{
"path": ".github/workflows/publish.yml",
"chars": 514,
"preview": "name: Publish FastMCP to PyPI\non:\n release:\n types: [published]\n workflow_dispatch:\n\njobs:\n pypi-publish:\n name"
},
{
"path": ".github/workflows/run-static.yml",
"chars": 706,
"preview": "name: Run static analysis\n\nenv:\n PY_COLORS: 1\n\non:\n push:\n branches: [\"main\"]\n paths:\n - \"src/**\"\n - \""
},
{
"path": ".github/workflows/run-tests.yml",
"chars": 2310,
"preview": "name: Tests\n\nenv:\n PY_COLORS: 1\n\non:\n push:\n branches: [\"main\"]\n paths:\n - \"src/**\"\n - \"tests/**\"\n "
},
{
"path": ".github/workflows/run-upgrade-checks.yml",
"chars": 4712,
"preview": "name: Upgrade checks\n\nenv:\n PY_COLORS: 1\n\non:\n push:\n branches: [\"main\"]\n paths:\n - \"src/**\"\n - \"tests"
},
{
"path": ".github/workflows/update-config-schema.yml",
"chars": 2547,
"preview": "name: Update MCPServerConfig Schema\n\n# Regenerates config schema on pushes to main and opens a long-lived PR\n# with the "
},
{
"path": ".github/workflows/update-sdk-docs.yml",
"chars": 2254,
"preview": "name: Update SDK Documentation\n\n# Regenerates SDK docs on pushes to main and opens a long-lived PR\n# with the changes, s"
},
{
"path": ".gitignore",
"chars": 819,
"preview": "# Python-generated files\n__pycache__/\n*.py[cod]\n*$py.class\nbuild/\ndist/\nwheels/\n*.egg-info/\n*.egg\nMANIFEST\n.pytest_cache"
},
{
"path": ".pre-commit-config.yaml",
"chars": 1369,
"preview": "fail_fast: false\n\nrepos:\n - repo: https://github.com/abravalheri/validate-pyproject\n rev: v0.24.1\n hooks:\n -"
},
{
"path": "CLAUDE.md",
"chars": 6888,
"preview": "# FastMCP Development Guidelines\n\n> **Audience**: LLM-driven engineering agents and human developers\n\n> **Note**: `AGENT"
},
{
"path": "CODE_OF_CONDUCT.md",
"chars": 5218,
"preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make participa"
},
{
"path": "CONTRIBUTING.md",
"chars": 4429,
"preview": "# Contributing to FastMCP\n\nFastMCP is an actively maintained, high-traffic project. We welcome contributions — but the m"
},
{
"path": "LICENSE",
"chars": 11356,
"preview": " Apache License\n Version 2.0, January 2004\n "
},
{
"path": "README.md",
"chars": 5857,
"preview": "<div align=\"center\">\n\n<!-- omit in toc -->\n\n<picture>\n <source width=\"550\" media=\"(prefers-color-scheme: dark)\" srcset="
},
{
"path": "SECURITY.md",
"chars": 1344,
"preview": "# Security Policy\n\n## Supported Versions\n\n| Version | Supported |\n| ------- | ------------------ |\n| 3.x | "
},
{
"path": "docs/.ccignore",
"chars": 26,
"preview": "changelog.mdx\npython-sdk/\n"
},
{
"path": "docs/.cursor/rules/mintlify.mdc",
"chars": 10668,
"preview": "---\ndescription: \nglobs: *.mdx\nalwaysApply: false\n---\n# Mintlify technical writing assistant\n\nYou are an AI writing assi"
},
{
"path": "docs/apps/development.mdx",
"chars": 2289,
"preview": "---\ntitle: Development\nsidebarTitle: Development\ndescription: Preview and test your app tools locally without a full MCP"
},
{
"path": "docs/apps/low-level.mdx",
"chars": 10184,
"preview": "---\ntitle: Custom HTML Apps\nsidebarTitle: Custom HTML\ndescription: Build apps with your own HTML, CSS, and JavaScript us"
},
{
"path": "docs/apps/overview.mdx",
"chars": 3213,
"preview": "---\ntitle: Apps\nsidebarTitle: Overview\ndescription: Give your tools interactive UIs rendered directly in the conversatio"
},
{
"path": "docs/apps/patterns.mdx",
"chars": 16800,
"preview": "---\ntitle: Patterns\nsidebarTitle: Patterns\ndescription: Charts, tables, forms, and other common tool UIs.\nicon: grid-2-p"
},
{
"path": "docs/apps/prefab.mdx",
"chars": 8112,
"preview": "---\ntitle: Prefab Apps\nsidebarTitle: Prefab Apps\ndescription: Build interactive tool UIs in pure Python — no HTML or Jav"
},
{
"path": "docs/assets/schemas/mcp_server_config/latest.json",
"chars": 8198,
"preview": "{\n \"$defs\": {\n \"Deployment\": {\n \"description\": \"Configuration for server deployment and runtime settings.\",\n "
},
{
"path": "docs/assets/schemas/mcp_server_config/v1.json",
"chars": 8198,
"preview": "{\n \"$defs\": {\n \"Deployment\": {\n \"description\": \"Configuration for server deployment and runtime settings.\",\n "
},
{
"path": "docs/changelog.mdx",
"chars": 265405,
"preview": "---\ntitle: \"Changelog\"\nicon: \"list-check\"\nrss: true\ntag: NEW\n---\n\n<Update label=\"v3.0.2\" description=\"2026-02-22\">\n\n**[v"
},
{
"path": "docs/cli/auth.mdx",
"chars": 2549,
"preview": "---\ntitle: Auth Utilities\nsidebarTitle: Auth\ndescription: Create and validate CIMD documents for OAuth\nicon: key\n---\n\nim"
},
{
"path": "docs/cli/client.mdx",
"chars": 5667,
"preview": "---\ntitle: Client Commands\nsidebarTitle: Client\ndescription: List tools, call them, and discover configured servers\nicon"
},
{
"path": "docs/cli/generate-cli.mdx",
"chars": 4204,
"preview": "---\ntitle: Generate CLI\nsidebarTitle: Generate CLI\ndescription: Scaffold a standalone typed CLI from any MCP server\nicon"
},
{
"path": "docs/cli/inspecting.mdx",
"chars": 2298,
"preview": "---\ntitle: Inspecting Servers\nsidebarTitle: Inspecting\ndescription: View a server's components and metadata\nicon: magnif"
},
{
"path": "docs/cli/install-mcp.mdx",
"chars": 5330,
"preview": "---\ntitle: Install MCP Servers\nsidebarTitle: Install MCPs\ndescription: Install MCP servers into Claude, Cursor, Gemini, "
},
{
"path": "docs/cli/overview.mdx",
"chars": 3969,
"preview": "---\ntitle: CLI\nsidebarTitle: Overview\ndescription: The fastmcp command-line interface\nicon: terminal\n---\n\nimport { Versi"
},
{
"path": "docs/cli/running.mdx",
"chars": 7278,
"preview": "---\ntitle: Running Servers\nsidebarTitle: Running\ndescription: Start, develop, and configure servers from the command lin"
},
{
"path": "docs/clients/auth/bearer.mdx",
"chars": 2739,
"preview": "---\ntitle: Bearer Token Authentication\nsidebarTitle: Bearer Auth\ndescription: Authenticate your FastMCP client with a Be"
},
{
"path": "docs/clients/auth/cimd.mdx",
"chars": 5906,
"preview": "---\ntitle: CIMD Authentication\nsidebarTitle: CIMD\ndescription: Use Client ID Metadata Documents for verifiable, domain-b"
},
{
"path": "docs/clients/auth/oauth.mdx",
"chars": 8782,
"preview": "---\ntitle: OAuth Authentication\nsidebarTitle: OAuth\ndescription: Authenticate your FastMCP client via OAuth 2.1.\nicon: w"
},
{
"path": "docs/clients/cli.mdx",
"chars": 9673,
"preview": "---\ntitle: Client CLI\nsidebarTitle: CLI\ndescription: Query and invoke MCP server tools directly from the terminal with f"
},
{
"path": "docs/clients/client.mdx",
"chars": 8641,
"preview": "---\ntitle: The FastMCP Client\nsidebarTitle: Overview\ndescription: Programmatic client for interacting with MCP servers t"
},
{
"path": "docs/clients/elicitation.mdx",
"chars": 4510,
"preview": "---\ntitle: User Elicitation\nsidebarTitle: Elicitation\ndescription: Handle server requests for structured user input.\nico"
},
{
"path": "docs/clients/generate-cli.mdx",
"chars": 7415,
"preview": "---\ntitle: Generate CLI\nsidebarTitle: Generate CLI\ndescription: Turn any MCP server into a standalone, typed command-lin"
},
{
"path": "docs/clients/logging.mdx",
"chars": 2730,
"preview": "---\ntitle: Server Logging\nsidebarTitle: Logging\ndescription: Receive and handle log messages from MCP servers.\nicon: rec"
},
{
"path": "docs/clients/notifications.mdx",
"chars": 4843,
"preview": "---\ntitle: Notifications\nsidebarTitle: Notifications\ndescription: Handle server-sent notifications for list changes and "
},
{
"path": "docs/clients/progress.mdx",
"chars": 1585,
"preview": "---\ntitle: Progress Monitoring\nsidebarTitle: Progress\ndescription: Handle progress notifications from long-running serve"
},
{
"path": "docs/clients/prompts.mdx",
"chars": 4333,
"preview": "---\ntitle: Getting Prompts\nsidebarTitle: Prompts\ndescription: Retrieve rendered message templates with automatic argumen"
},
{
"path": "docs/clients/resources.mdx",
"chars": 3330,
"preview": "---\ntitle: Reading Resources\nsidebarTitle: Resources\ndescription: Access static and templated data sources from MCP serv"
},
{
"path": "docs/clients/roots.mdx",
"chars": 1111,
"preview": "---\ntitle: Client Roots\nsidebarTitle: Roots\ndescription: Provide local context and resource boundaries to MCP servers.\ni"
},
{
"path": "docs/clients/sampling.mdx",
"chars": 5327,
"preview": "---\ntitle: LLM Sampling\nsidebarTitle: Sampling\ndescription: Handle server-initiated LLM completion requests.\nicon: robot"
},
{
"path": "docs/clients/tasks.mdx",
"chars": 4588,
"preview": "---\ntitle: Background Tasks\nsidebarTitle: Tasks\ndescription: Execute operations asynchronously and track their progress."
},
{
"path": "docs/clients/tools.mdx",
"chars": 5541,
"preview": "---\ntitle: Calling Tools\nsidebarTitle: Tools\ndescription: Execute server-side tools and handle structured results.\nicon:"
},
{
"path": "docs/clients/transports.mdx",
"chars": 7576,
"preview": "---\ntitle: Client Transports\nsidebarTitle: Transports\ndescription: Configure how clients connect to and communicate with"
},
{
"path": "docs/community/README.md",
"chars": 563,
"preview": "# Community Section\n\nThis directory contains community-contributed content and showcases for FastMCP.\n\n## Structure\n\n- `"
},
{
"path": "docs/community/showcase.mdx",
"chars": 2227,
"preview": "---\ntitle: 'Community Showcase'\ndescription: 'High-quality projects and examples from the FastMCP community'\nicon: 'user"
},
{
"path": "docs/css/banner.css",
"chars": 1476,
"preview": "/* Banner styling -- improve readability with better contrast */\n#banner {\n background: #f1f5f9 !important;\n color: #1"
},
{
"path": "docs/css/python-sdk.css",
"chars": 46,
"preview": "a:has(svg.icon) {\n border: none !important;\n}"
},
{
"path": "docs/css/style.css",
"chars": 1276,
"preview": "html:not([data-page-mode=\"wide\"]) #content-area {\n max-width: 44rem !important;\n}\n\nimg.nav-logo {\n max-width: 200px;\n}"
},
{
"path": "docs/css/version-badge.css",
"chars": 661,
"preview": "/* Version badge -- display a badge with the current version of the documentation */\n.version-badge {\n --color-text: #f"
},
{
"path": "docs/deployment/http.mdx",
"chars": 34806,
"preview": "---\ntitle: HTTP Deployment\nsidebarTitle: HTTP Deployment\ndescription: Deploy your FastMCP server over HTTP for remote ac"
},
{
"path": "docs/deployment/prefect-horizon.mdx",
"chars": 6275,
"preview": "---\ntitle: Prefect Horizon\nsidebarTitle: Prefect Horizon\ndescription: The MCP platform from the FastMCP team\nicon: cloud"
},
{
"path": "docs/deployment/running-server.mdx",
"chars": 11619,
"preview": "---\ntitle: Running Your Server\nsidebarTitle: Running Your Server\ndescription: Learn how to run your FastMCP server local"
},
{
"path": "docs/deployment/server-configuration.mdx",
"chars": 21687,
"preview": "---\ntitle: \"Project Configuration\"\nsidebarTitle: \"Project Configuration\"\ndescription: Use fastmcp.json for portable, dec"
},
{
"path": "docs/development/contributing.mdx",
"chars": 9313,
"preview": "---\ntitle: \"Contributing\"\ndescription: \"Development workflow for FastMCP contributors\"\nicon: code-pull-request\n---\n\nCont"
},
{
"path": "docs/development/releases.mdx",
"chars": 4113,
"preview": "---\ntitle: \"Releases\"\ndescription: \"FastMCP versioning and release process\"\nicon: \"truck-fast\"\n---\n\nFastMCP releases fre"
},
{
"path": "docs/development/tests.mdx",
"chars": 13668,
"preview": "---\ntitle: \"Tests\"\ndescription: \"Testing patterns and requirements for FastMCP\"\nicon: vial\n---\n\nimport { VersionBadge } "
},
{
"path": "docs/development/v3-notes/auth-provider-env-vars.mdx",
"chars": 3299,
"preview": "---\ntitle: Auth Provider Environment Variables\n---\n\n## Decision: Remove automatic environment variable loading from auth"
},
{
"path": "docs/development/v3-notes/v3-features.mdx",
"chars": 56550,
"preview": "---\ntitle: v3.0 Feature Tracking\n---\n\nThis document tracks major features in FastMCP v3.0 for release notes preparation."
},
{
"path": "docs/docs.json",
"chars": 42913,
"preview": "{\n \"$schema\": \"https://mintlify.com/docs.json\",\n \"appearance\": {\n \"default\": \"system\",\n \"strict\": false\n },\n \""
},
{
"path": "docs/getting-started/installation.mdx",
"chars": 3147,
"preview": "---\ntitle: Installation\ndescription: Install FastMCP and verify your setup\nicon: arrow-down-to-line\n---\n## Install FastM"
},
{
"path": "docs/getting-started/quickstart.mdx",
"chars": 4658,
"preview": "---\ntitle: Quickstart\nicon: rocket-launch\n---\n\nWelcome! This guide will help you quickly set up FastMCP, run your first "
},
{
"path": "docs/getting-started/upgrading/from-fastmcp-2.mdx",
"chars": 18118,
"preview": "---\ntitle: Upgrading from FastMCP 2\nsidebarTitle: \"From FastMCP 2\"\ndescription: Migration instructions for upgrading bet"
},
{
"path": "docs/getting-started/upgrading/from-low-level-sdk.mdx",
"chars": 20500,
"preview": "---\ntitle: Upgrading from the MCP Low-Level SDK\nsidebarTitle: \"From MCP Low-Level SDK\"\ndescription: Upgrade your MCP ser"
},
{
"path": "docs/getting-started/upgrading/from-mcp-sdk.mdx",
"chars": 7512,
"preview": "---\ntitle: Upgrading from the MCP SDK\nsidebarTitle: \"From MCP SDK\"\ndescription: Upgrade from FastMCP in the MCP Python S"
},
{
"path": "docs/getting-started/welcome.mdx",
"chars": 4888,
"preview": "---\ntitle: \"Welcome to FastMCP\"\nsidebarTitle: \"Welcome!\"\ndescription: The fast, Pythonic way to build MCP servers, clien"
},
{
"path": "docs/integrations/anthropic.mdx",
"chars": 7420,
"preview": "---\ntitle: Anthropic API 🤝 FastMCP\nsidebarTitle: Anthropic API\ndescription: Connect FastMCP servers to the Anthropic API"
},
{
"path": "docs/integrations/auth0.mdx",
"chars": 7307,
"preview": "---\ntitle: Auth0 OAuth 🤝 FastMCP\nsidebarTitle: Auth0\ndescription: Secure your FastMCP server with Auth0 OAuth\nicon: shie"
},
{
"path": "docs/integrations/authkit.mdx",
"chars": 3884,
"preview": "---\ntitle: AuthKit 🤝 FastMCP\nsidebarTitle: AuthKit\ndescription: Secure your FastMCP server with AuthKit by WorkOS\nicon: "
},
{
"path": "docs/integrations/aws-cognito.mdx",
"chars": 11526,
"preview": "---\ntitle: AWS Cognito OAuth 🤝 FastMCP\nsidebarTitle: AWS Cognito\ndescription: Secure your FastMCP server with AWS Cognit"
},
{
"path": "docs/integrations/azure.mdx",
"chars": 19988,
"preview": "---\ntitle: Azure (Microsoft Entra ID) OAuth 🤝 FastMCP\nsidebarTitle: Azure (Entra ID)\ndescription: Secure your FastMCP se"
},
{
"path": "docs/integrations/chatgpt.mdx",
"chars": 4692,
"preview": "---\ntitle: ChatGPT 🤝 FastMCP\nsidebarTitle: ChatGPT\ndescription: Connect FastMCP servers to ChatGPT in Chat and Deep Rese"
},
{
"path": "docs/integrations/claude-code.mdx",
"chars": 6173,
"preview": "---\ntitle: Claude Code 🤝 FastMCP\nsidebarTitle: Claude Code\ndescription: Install and use FastMCP servers in Claude Code\ni"
},
{
"path": "docs/integrations/claude-desktop.mdx",
"chars": 10233,
"preview": "---\ntitle: Claude Desktop 🤝 FastMCP\nsidebarTitle: Claude Desktop\ndescription: Connect FastMCP servers to Claude Desktop\n"
},
{
"path": "docs/integrations/cursor.mdx",
"chars": 8749,
"preview": "---\ntitle: Cursor 🤝 FastMCP\nsidebarTitle: Cursor\ndescription: Install and use FastMCP servers in Cursor\nicon: message-sm"
},
{
"path": "docs/integrations/descope.mdx",
"chars": 3708,
"preview": "---\ntitle: Descope 🤝 FastMCP\nsidebarTitle: Descope\ndescription: Secure your FastMCP server with Descope\nicon: shield-che"
},
{
"path": "docs/integrations/discord.mdx",
"chars": 6332,
"preview": "---\ntitle: Discord OAuth 🤝 FastMCP\nsidebarTitle: Discord\ndescription: Secure your FastMCP server with Discord OAuth\nicon"
},
{
"path": "docs/integrations/eunomia-authorization.mdx",
"chars": 4592,
"preview": "---\ntitle: Eunomia Authorization 🤝 FastMCP\nsidebarTitle: Eunomia Auth\ndescription: Add policy-based authorization to you"
},
{
"path": "docs/integrations/fastapi.mdx",
"chars": 14565,
"preview": "---\ntitle: FastAPI 🤝 FastMCP\nsidebarTitle: FastAPI\ndescription: Integrate FastMCP with FastAPI applications\nicon: bolt\n-"
},
{
"path": "docs/integrations/gemini-cli.mdx",
"chars": 5746,
"preview": "---\ntitle: Gemini CLI 🤝 FastMCP\nsidebarTitle: Gemini CLI\ndescription: Install and use FastMCP servers in Gemini CLI\nicon"
},
{
"path": "docs/integrations/gemini.mdx",
"chars": 3433,
"preview": "---\ntitle: Gemini SDK 🤝 FastMCP\nsidebarTitle: Gemini SDK\ndescription: Connect FastMCP servers to the Google Gemini SDK\ni"
},
{
"path": "docs/integrations/github.mdx",
"chars": 6619,
"preview": "---\ntitle: GitHub OAuth 🤝 FastMCP\nsidebarTitle: GitHub\ndescription: Secure your FastMCP server with GitHub OAuth\nicon: g"
},
{
"path": "docs/integrations/google.mdx",
"chars": 7506,
"preview": "---\ntitle: Google OAuth 🤝 FastMCP\nsidebarTitle: Google\ndescription: Secure your FastMCP server with Google OAuth\nicon: g"
},
{
"path": "docs/integrations/goose.mdx",
"chars": 5319,
"preview": "---\ntitle: Goose 🤝 FastMCP\nsidebarTitle: Goose\ndescription: Install and use FastMCP servers in Goose\nicon: message-smile"
},
{
"path": "docs/integrations/mcp-json-configuration.mdx",
"chars": 9961,
"preview": "---\ntitle: MCP JSON Configuration 🤝 FastMCP\nsidebarTitle: MCP.json\ndescription: Generate standard MCP configuration file"
},
{
"path": "docs/integrations/oci.mdx",
"chars": 10748,
"preview": "---\ntitle: OCI IAM OAuth 🤝 FastMCP\nsidebarTitle: Oracle\ndescription: Secure your FastMCP server with OCI IAM OAuth\nicon:"
},
{
"path": "docs/integrations/openai.mdx",
"chars": 6951,
"preview": "---\ntitle: OpenAI API 🤝 FastMCP\nsidebarTitle: OpenAI API\ndescription: Connect FastMCP servers to the OpenAI API\nicon: me"
},
{
"path": "docs/integrations/openapi.mdx",
"chars": 16275,
"preview": "---\ntitle: OpenAPI 🤝 FastMCP\nsidebarTitle: OpenAPI\ndescription: Generate MCP servers from any OpenAPI specification\nicon"
},
{
"path": "docs/integrations/permit.mdx",
"chars": 13394,
"preview": "---\ntitle: Permit.io Authorization 🤝 FastMCP\nsidebarTitle: Permit.io\ndescription: Add fine-grained authorization to your"
},
{
"path": "docs/integrations/propelauth.mdx",
"chars": 6038,
"preview": "---\ntitle: PropelAuth 🤝 FastMCP\nsidebarTitle: PropelAuth\ndescription: Secure your FastMCP server with PropelAuth\nicon: s"
},
{
"path": "docs/integrations/scalekit.mdx",
"chars": 5238,
"preview": "---\ntitle: Scalekit 🤝 FastMCP\nsidebarTitle: Scalekit\ndescription: Secure your FastMCP server with Scalekit\nicon: shield-"
},
{
"path": "docs/integrations/supabase.mdx",
"chars": 4419,
"preview": "---\ntitle: Supabase 🤝 FastMCP\nsidebarTitle: Supabase\ndescription: Secure your FastMCP server with Supabase Auth\nicon: sh"
},
{
"path": "docs/integrations/workos.mdx",
"chars": 6289,
"preview": "---\ntitle: WorkOS 🤝 FastMCP\nsidebarTitle: WorkOS\ndescription: Authenticate FastMCP servers with WorkOS Connect\nicon: shi"
},
{
"path": "docs/more/settings.mdx",
"chars": 6975,
"preview": "---\ntitle: Settings\ndescription: Configure FastMCP behavior through environment variables or a .env file.\nicon: gear\n---"
},
{
"path": "docs/patterns/cli.mdx",
"chars": 33439,
"preview": "---\ntitle: FastMCP CLI\nsidebarTitle: CLI\ndescription: Learn how to use the FastMCP command-line interface\nicon: terminal"
},
{
"path": "docs/patterns/contrib.mdx",
"chars": 2058,
"preview": "---\ntitle: \"Contrib Modules\"\ndescription: \"Community-contributed modules extending FastMCP\"\nicon: \"cubes\"\n---\n\nimport { "
},
{
"path": "docs/patterns/testing.mdx",
"chars": 3530,
"preview": "---\ntitle: Testing your FastMCP Server\nsidebarTitle: Testing\ndescription: How to test your FastMCP server.\nicon: vial\n--"
},
{
"path": "docs/public/schemas/fastmcp.json/latest.json",
"chars": 8602,
"preview": "{\n \"$defs\": {\n \"Deployment\": {\n \"description\": \"Configuration for server deployment and runtime settings.\",\n "
},
{
"path": "docs/public/schemas/fastmcp.json/v1.json",
"chars": 8602,
"preview": "{\n \"$defs\": {\n \"Deployment\": {\n \"description\": \"Configuration for server deployment and runtime settings.\",\n "
},
{
"path": "docs/python-sdk/fastmcp-cli-__init__.mdx",
"chars": 87,
"preview": "---\ntitle: __init__\nsidebarTitle: __init__\n---\n\n# `fastmcp.cli`\n\n\nFastMCP CLI package.\n"
},
{
"path": "docs/python-sdk/fastmcp-cli-apps_dev.mdx",
"chars": 1636,
"preview": "---\ntitle: apps_dev\nsidebarTitle: apps_dev\n---\n\n# `fastmcp.cli.apps_dev`\n\n\nDev server for previewing FastMCPApp UIs loca"
},
{
"path": "docs/python-sdk/fastmcp-cli-auth.mdx",
"chars": 100,
"preview": "---\ntitle: auth\nsidebarTitle: auth\n---\n\n# `fastmcp.cli.auth`\n\n\nAuthentication-related CLI commands.\n"
},
{
"path": "docs/python-sdk/fastmcp-cli-cimd.mdx",
"chars": 1234,
"preview": "---\ntitle: cimd\nsidebarTitle: cimd\n---\n\n# `fastmcp.cli.cimd`\n\n\nCIMD (Client ID Metadata Document) CLI commands.\n\n## Func"
},
{
"path": "docs/python-sdk/fastmcp-cli-cli.mdx",
"chars": 5093,
"preview": "---\ntitle: cli\nsidebarTitle: cli\n---\n\n# `fastmcp.cli.cli`\n\n\nFastMCP CLI tools using Cyclopts.\n\n## Functions\n\n### `with_a"
},
{
"path": "docs/python-sdk/fastmcp-cli-client.mdx",
"chars": 4726,
"preview": "---\ntitle: client\nsidebarTitle: client\n---\n\n# `fastmcp.cli.client`\n\n\nClient-side CLI commands for querying and invoking "
},
{
"path": "docs/python-sdk/fastmcp-cli-discovery.mdx",
"chars": 2218,
"preview": "---\ntitle: discovery\nsidebarTitle: discovery\n---\n\n# `fastmcp.cli.discovery`\n\n\nDiscover MCP servers configured in editor "
},
{
"path": "docs/python-sdk/fastmcp-cli-generate.mdx",
"chars": 2369,
"preview": "---\ntitle: generate\nsidebarTitle: generate\n---\n\n# `fastmcp.cli.generate`\n\n\nGenerate a standalone CLI script and agent sk"
},
{
"path": "docs/python-sdk/fastmcp-cli-install-__init__.mdx",
"chars": 126,
"preview": "---\ntitle: __init__\nsidebarTitle: __init__\n---\n\n# `fastmcp.cli.install`\n\n\nInstall subcommands for FastMCP CLI using Cycl"
},
{
"path": "docs/python-sdk/fastmcp-cli-install-claude_code.mdx",
"chars": 2261,
"preview": "---\ntitle: claude_code\nsidebarTitle: claude_code\n---\n\n# `fastmcp.cli.install.claude_code`\n\n\nClaude Code integration for "
},
{
"path": "docs/python-sdk/fastmcp-cli-install-claude_desktop.mdx",
"chars": 2084,
"preview": "---\ntitle: claude_desktop\nsidebarTitle: claude_desktop\n---\n\n# `fastmcp.cli.install.claude_desktop`\n\n\nClaude Desktop inte"
},
{
"path": "docs/python-sdk/fastmcp-cli-install-cursor.mdx",
"chars": 3567,
"preview": "---\ntitle: cursor\nsidebarTitle: cursor\n---\n\n# `fastmcp.cli.install.cursor`\n\n\nCursor integration for FastMCP install usin"
},
{
"path": "docs/python-sdk/fastmcp-cli-install-gemini_cli.mdx",
"chars": 2117,
"preview": "---\ntitle: gemini_cli\nsidebarTitle: gemini_cli\n---\n\n# `fastmcp.cli.install.gemini_cli`\n\n\nGemini CLI integration for Fast"
},
{
"path": "docs/python-sdk/fastmcp-cli-install-goose.mdx",
"chars": 1999,
"preview": "---\ntitle: goose\nsidebarTitle: goose\n---\n\n# `fastmcp.cli.install.goose`\n\n\nGoose integration for FastMCP install using Cy"
},
{
"path": "docs/python-sdk/fastmcp-cli-install-mcp_json.mdx",
"chars": 1604,
"preview": "---\ntitle: mcp_json\nsidebarTitle: mcp_json\n---\n\n# `fastmcp.cli.install.mcp_json`\n\n\nMCP configuration JSON generation for"
},
{
"path": "docs/python-sdk/fastmcp-cli-install-shared.mdx",
"chars": 1941,
"preview": "---\ntitle: shared\nsidebarTitle: shared\n---\n\n# `fastmcp.cli.install.shared`\n\n\nShared utilities for install commands.\n\n## "
},
{
"path": "docs/python-sdk/fastmcp-cli-install-stdio.mdx",
"chars": 1593,
"preview": "---\ntitle: stdio\nsidebarTitle: stdio\n---\n\n# `fastmcp.cli.install.stdio`\n\n\nStdio command generation for FastMCP install u"
},
{
"path": "docs/python-sdk/fastmcp-cli-run.mdx",
"chars": 4581,
"preview": "---\ntitle: run\nsidebarTitle: run\n---\n\n# `fastmcp.cli.run`\n\n\nFastMCP run command implementation with enhanced type hints."
},
{
"path": "docs/python-sdk/fastmcp-cli-tasks.mdx",
"chars": 1202,
"preview": "---\ntitle: tasks\nsidebarTitle: tasks\n---\n\n# `fastmcp.cli.tasks`\n\n\nFastMCP tasks CLI for Docket task management.\n\n## Func"
},
{
"path": "docs/python-sdk/fastmcp-client-__init__.mdx",
"chars": 142,
"preview": "---\ntitle: __init__\nsidebarTitle: __init__\n---\n\n# `fastmcp.client`\n\n*This module is empty or contains only private/inter"
},
{
"path": "docs/python-sdk/fastmcp-client-auth-__init__.mdx",
"chars": 147,
"preview": "---\ntitle: __init__\nsidebarTitle: __init__\n---\n\n# `fastmcp.client.auth`\n\n*This module is empty or contains only private/"
},
{
"path": "docs/python-sdk/fastmcp-client-auth-bearer.mdx",
"chars": 545,
"preview": "---\ntitle: bearer\nsidebarTitle: bearer\n---\n\n# `fastmcp.client.auth.bearer`\n\n## Classes\n\n### `BearerAuth` <sup><a href=\"h"
},
{
"path": "docs/python-sdk/fastmcp-client-auth-oauth.mdx",
"chars": 4017,
"preview": "---\ntitle: oauth\nsidebarTitle: oauth\n---\n\n# `fastmcp.client.auth.oauth`\n\n## Functions\n\n### `check_if_auth_required` <sup"
},
{
"path": "docs/python-sdk/fastmcp-client-client.mdx",
"chars": 11107,
"preview": "---\ntitle: client\nsidebarTitle: client\n---\n\n# `fastmcp.client.client`\n\n## Classes\n\n### `ClientSessionState` <sup><a href"
},
{
"path": "docs/python-sdk/fastmcp-client-elicitation.mdx",
"chars": 636,
"preview": "---\ntitle: elicitation\nsidebarTitle: elicitation\n---\n\n# `fastmcp.client.elicitation`\n\n## Functions\n\n### `create_elicitat"
},
{
"path": "docs/python-sdk/fastmcp-client-logging.mdx",
"chars": 736,
"preview": "---\ntitle: logging\nsidebarTitle: logging\n---\n\n# `fastmcp.client.logging`\n\n## Functions\n\n### `default_log_handler` <sup><"
},
{
"path": "docs/python-sdk/fastmcp-client-messages.mdx",
"chars": 4833,
"preview": "---\ntitle: messages\nsidebarTitle: messages\n---\n\n# `fastmcp.client.messages`\n\n## Classes\n\n### `MessageHandler` <sup><a hr"
},
{
"path": "docs/python-sdk/fastmcp-client-mixins-__init__.mdx",
"chars": 103,
"preview": "---\ntitle: __init__\nsidebarTitle: __init__\n---\n\n# `fastmcp.client.mixins`\n\n\nClient mixins for FastMCP.\n"
},
{
"path": "docs/python-sdk/fastmcp-client-mixins-prompts.mdx",
"chars": 4830,
"preview": "---\ntitle: prompts\nsidebarTitle: prompts\n---\n\n# `fastmcp.client.mixins.prompts`\n\n\nPrompt-related methods for FastMCP Cli"
},
{
"path": "docs/python-sdk/fastmcp-client-mixins-resources.mdx",
"chars": 6680,
"preview": "---\ntitle: resources\nsidebarTitle: resources\n---\n\n# `fastmcp.client.mixins.resources`\n\n\nResource-related methods for Fas"
},
{
"path": "docs/python-sdk/fastmcp-client-mixins-task_management.mdx",
"chars": 3515,
"preview": "---\ntitle: task_management\nsidebarTitle: task_management\n---\n\n# `fastmcp.client.mixins.task_management`\n\n\nTask managemen"
},
{
"path": "docs/python-sdk/fastmcp-client-mixins-tools.mdx",
"chars": 6289,
"preview": "---\ntitle: tools\nsidebarTitle: tools\n---\n\n# `fastmcp.client.mixins.tools`\n\n\nTool-related methods for FastMCP Client.\n\n##"
},
{
"path": "docs/python-sdk/fastmcp-client-oauth_callback.mdx",
"chars": 2638,
"preview": "---\ntitle: oauth_callback\nsidebarTitle: oauth_callback\n---\n\n# `fastmcp.client.oauth_callback`\n\n\n\nOAuth callback server f"
},
{
"path": "docs/python-sdk/fastmcp-client-progress.mdx",
"chars": 673,
"preview": "---\ntitle: progress\nsidebarTitle: progress\n---\n\n# `fastmcp.client.progress`\n\n## Functions\n\n### `default_progress_handler"
},
{
"path": "docs/python-sdk/fastmcp-client-roots.mdx",
"chars": 656,
"preview": "---\ntitle: roots\nsidebarTitle: roots\n---\n\n# `fastmcp.client.roots`\n\n## Functions\n\n### `convert_roots_list` <sup><a href="
},
{
"path": "docs/python-sdk/fastmcp-client-sampling-__init__.mdx",
"chars": 402,
"preview": "---\ntitle: __init__\nsidebarTitle: __init__\n---\n\n# `fastmcp.client.sampling`\n\n## Functions\n\n### `create_sampling_callback"
},
{
"path": "docs/python-sdk/fastmcp-client-sampling-handlers-__init__.mdx",
"chars": 160,
"preview": "---\ntitle: __init__\nsidebarTitle: __init__\n---\n\n# `fastmcp.client.sampling.handlers`\n\n*This module is empty or contains "
},
{
"path": "docs/python-sdk/fastmcp-client-sampling-handlers-anthropic.mdx",
"chars": 432,
"preview": "---\ntitle: anthropic\nsidebarTitle: anthropic\n---\n\n# `fastmcp.client.sampling.handlers.anthropic`\n\n\nAnthropic sampling ha"
},
{
"path": "docs/python-sdk/fastmcp-client-sampling-handlers-google_genai.mdx",
"chars": 492,
"preview": "---\ntitle: google_genai\nsidebarTitle: google_genai\n---\n\n# `fastmcp.client.sampling.handlers.google_genai`\n\n\nGoogle GenAI"
},
{
"path": "docs/python-sdk/fastmcp-client-sampling-handlers-openai.mdx",
"chars": 411,
"preview": "---\ntitle: openai\nsidebarTitle: openai\n---\n\n# `fastmcp.client.sampling.handlers.openai`\n\n\nOpenAI sampling handler for Fa"
},
{
"path": "docs/python-sdk/fastmcp-client-tasks.mdx",
"chars": 7339,
"preview": "---\ntitle: tasks\nsidebarTitle: tasks\n---\n\n# `fastmcp.client.tasks`\n\n\nSEP-1686 client Task classes.\n\n## Classes\n\n### `Tas"
},
{
"path": "docs/python-sdk/fastmcp-client-telemetry.mdx",
"chars": 619,
"preview": "---\ntitle: telemetry\nsidebarTitle: telemetry\n---\n\n# `fastmcp.client.telemetry`\n\n\nClient-side telemetry helpers.\n\n## Func"
},
{
"path": "docs/python-sdk/fastmcp-client-transports-__init__.mdx",
"chars": 153,
"preview": "---\ntitle: __init__\nsidebarTitle: __init__\n---\n\n# `fastmcp.client.transports`\n\n*This module is empty or contains only pr"
},
{
"path": "docs/python-sdk/fastmcp-client-transports-base.mdx",
"chars": 2116,
"preview": "---\ntitle: base\nsidebarTitle: base\n---\n\n# `fastmcp.client.transports.base`\n\n## Classes\n\n### `SessionKwargs` <sup><a href"
},
{
"path": "docs/python-sdk/fastmcp-client-transports-config.mdx",
"chars": 2543,
"preview": "---\ntitle: config\nsidebarTitle: config\n---\n\n# `fastmcp.client.transports.config`\n\n## Classes\n\n### `MCPConfigTransport` <"
},
{
"path": "docs/python-sdk/fastmcp-client-transports-http.mdx",
"chars": 1272,
"preview": "---\ntitle: http\nsidebarTitle: http\n---\n\n# `fastmcp.client.transports.http`\n\n\nStreamable HTTP transport for FastMCP Clien"
},
{
"path": "docs/python-sdk/fastmcp-client-transports-inference.mdx",
"chars": 2149,
"preview": "---\ntitle: inference\nsidebarTitle: inference\n---\n\n# `fastmcp.client.transports.inference`\n\n## Functions\n\n### `infer_tran"
},
{
"path": "docs/python-sdk/fastmcp-client-transports-memory.mdx",
"chars": 976,
"preview": "---\ntitle: memory\nsidebarTitle: memory\n---\n\n# `fastmcp.client.transports.memory`\n\n## Classes\n\n### `FastMCPTransport` <su"
},
{
"path": "docs/python-sdk/fastmcp-client-transports-sse.mdx",
"chars": 767,
"preview": "---\ntitle: sse\nsidebarTitle: sse\n---\n\n# `fastmcp.client.transports.sse`\n\n\nServer-Sent Events (SSE) transport for FastMCP"
},
{
"path": "docs/python-sdk/fastmcp-client-transports-stdio.mdx",
"chars": 3197,
"preview": "---\ntitle: stdio\nsidebarTitle: stdio\n---\n\n# `fastmcp.client.transports.stdio`\n\n## Classes\n\n### `StdioTransport` <sup><a "
},
{
"path": "docs/python-sdk/fastmcp-decorators.mdx",
"chars": 1078,
"preview": "---\ntitle: decorators\nsidebarTitle: decorators\n---\n\n# `fastmcp.decorators`\n\n\nShared decorator utilities for FastMCP.\n\n##"
},
{
"path": "docs/python-sdk/fastmcp-dependencies.mdx",
"chars": 496,
"preview": "---\ntitle: dependencies\nsidebarTitle: dependencies\n---\n\n# `fastmcp.dependencies`\n\n\nDependency injection exports for Fast"
},
{
"path": "docs/python-sdk/fastmcp-exceptions.mdx",
"chars": 2421,
"preview": "---\ntitle: exceptions\nsidebarTitle: exceptions\n---\n\n# `fastmcp.exceptions`\n\n\nCustom exceptions for FastMCP.\n\n## Classes\n"
},
{
"path": "docs/python-sdk/fastmcp-experimental-__init__.mdx",
"chars": 148,
"preview": "---\ntitle: __init__\nsidebarTitle: __init__\n---\n\n# `fastmcp.experimental`\n\n*This module is empty or contains only private"
},
{
"path": "docs/python-sdk/fastmcp-experimental-sampling-__init__.mdx",
"chars": 157,
"preview": "---\ntitle: __init__\nsidebarTitle: __init__\n---\n\n# `fastmcp.experimental.sampling`\n\n*This module is empty or contains onl"
},
{
"path": "docs/python-sdk/fastmcp-experimental-sampling-handlers.mdx",
"chars": 166,
"preview": "---\ntitle: handlers\nsidebarTitle: handlers\n---\n\n# `fastmcp.experimental.sampling.handlers`\n\n*This module is empty or con"
},
{
"path": "docs/python-sdk/fastmcp-experimental-transforms-__init__.mdx",
"chars": 159,
"preview": "---\ntitle: __init__\nsidebarTitle: __init__\n---\n\n# `fastmcp.experimental.transforms`\n\n*This module is empty or contains o"
},
{
"path": "docs/python-sdk/fastmcp-experimental-transforms-code_mode.mdx",
"chars": 5632,
"preview": "---\ntitle: code_mode\nsidebarTitle: code_mode\n---\n\n# `fastmcp.experimental.transforms.code_mode`\n\n## Classes\n\n### `Sandbo"
},
{
"path": "docs/python-sdk/fastmcp-mcp_config.mdx",
"chars": 6571,
"preview": "---\ntitle: mcp_config\nsidebarTitle: mcp_config\n---\n\n# `fastmcp.mcp_config`\n\n\nCanonical MCP Configuration Format.\n\nThis m"
},
{
"path": "docs/python-sdk/fastmcp-prompts-__init__.mdx",
"chars": 143,
"preview": "---\ntitle: __init__\nsidebarTitle: __init__\n---\n\n# `fastmcp.prompts`\n\n*This module is empty or contains only private/inte"
},
{
"path": "docs/python-sdk/fastmcp-prompts-base.mdx",
"chars": 4863,
"preview": "---\ntitle: base\nsidebarTitle: base\n---\n\n# `fastmcp.prompts.base`\n\n\nBase classes for FastMCP prompts.\n\n## Classes\n\n### `M"
},
{
"path": "docs/python-sdk/fastmcp-prompts-function_prompt.mdx",
"chars": 3636,
"preview": "---\ntitle: function_prompt\nsidebarTitle: function_prompt\n---\n\n# `fastmcp.prompts.function_prompt`\n\n\nStandalone @prompt d"
},
{
"path": "docs/python-sdk/fastmcp-resources-__init__.mdx",
"chars": 145,
"preview": "---\ntitle: __init__\nsidebarTitle: __init__\n---\n\n# `fastmcp.resources`\n\n*This module is empty or contains only private/in"
},
{
"path": "docs/python-sdk/fastmcp-resources-base.mdx",
"chars": 6366,
"preview": "---\ntitle: base\nsidebarTitle: base\n---\n\n# `fastmcp.resources.base`\n\n\nBase classes and interfaces for FastMCP resources.\n"
}
]
// ... and 1040 more files (download for full content)
About this extraction
This page contains the full source code of the PrefectHQ/fastmcp GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 1240 files (9.4 MB), approximately 2.5M tokens, and a symbol index with 8642 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.