From 56456cb188efc9deb0185747ca603fb561ad7fec Mon Sep 17 00:00:00 2001 From: "marvin-context-protocol[bot]" <225465937+marvin-context-protocol[bot]@users.noreply.github.com> Date: Sun, 12 Apr 2026 13:53:38 -0400 Subject: [PATCH] chore: Update SDK documentation (#3808) Co-authored-by: marvin-context-protocol[bot] <225465937+marvin-context-protocol[bot]@users.noreply.github.com> --- docs/python-sdk-pages.json | 10 ++ docs/python-sdk/fastmcp-apps-app.mdx | 20 ++-- docs/python-sdk/fastmcp-apps-file_upload.mdx | 8 +- docs/python-sdk/fastmcp-cli-cli.mdx | 4 +- docs/python-sdk/fastmcp-cli-run.mdx | 16 +-- .../fastmcp-client-transports-http.mdx | 6 +- .../fastmcp-client-transports-sse.mdx | 2 +- .../fastmcp-prompts-function_prompt.mdx | 16 +-- .../fastmcp-resources-function_resource.mdx | 6 +- .../fastmcp-server-auth-handlers-__init__.mdx | 8 ++ ...fastmcp-server-auth-handlers-authorize.mdx | 83 +++++++++++++ .../fastmcp-server-dependencies.mdx | 113 ++++++++++-------- .../fastmcp-server-mixins-transport.mdx | 2 +- .../fastmcp-server-providers-addressing.mdx | 81 +++++++++++++ .../fastmcp-server-providers-aggregate.mdx | 17 ++- .../fastmcp-server-providers-base.mdx | 33 +++-- ...tmcp-server-providers-fastmcp_provider.mdx | 13 +- ...viders-local_provider-decorators-tools.mdx | 10 +- ...tmcp-server-providers-prefab_synthesis.mdx | 58 +++++++++ .../fastmcp-server-providers-proxy.mdx | 20 ++-- .../fastmcp-server-sampling-run.mdx | 28 ++--- docs/python-sdk/fastmcp-server-server.mdx | 104 ++++++++-------- .../fastmcp-server-tasks-capabilities.mdx | 8 +- docs/python-sdk/fastmcp-tools-base.mdx | 8 +- .../fastmcp-tools-function_parsing.mdx | 4 +- .../fastmcp-tools-function_tool.mdx | 8 +- .../fastmcp-tools-tool_transform.mdx | 29 ++--- .../fastmcp-utilities-docstring_parsing.mdx | 39 ++++++ .../fastmcp-utilities-json_schema_type.mdx | 9 +- .../fastmcp-utilities-openapi-schemas.mdx | 2 +- 30 files changed, 544 insertions(+), 221 deletions(-) create mode 100644 docs/python-sdk/fastmcp-server-auth-handlers-__init__.mdx create mode 100644 docs/python-sdk/fastmcp-server-auth-handlers-authorize.mdx create mode 100644 docs/python-sdk/fastmcp-server-providers-addressing.mdx create mode 100644 docs/python-sdk/fastmcp-server-providers-prefab_synthesis.mdx create mode 100644 docs/python-sdk/fastmcp-utilities-docstring_parsing.mdx diff --git a/docs/python-sdk-pages.json b/docs/python-sdk-pages.json index 209f75633..e55c709df 100644 --- a/docs/python-sdk-pages.json +++ b/docs/python-sdk-pages.json @@ -160,6 +160,13 @@ "python-sdk/fastmcp-server-auth-auth", "python-sdk/fastmcp-server-auth-authorization", "python-sdk/fastmcp-server-auth-cimd", + { + "group": "handlers", + "pages": [ + "python-sdk/fastmcp-server-auth-handlers-__init__", + "python-sdk/fastmcp-server-auth-handlers-authorize" + ] + }, "python-sdk/fastmcp-server-auth-jwt_issuer", "python-sdk/fastmcp-server-auth-middleware", { @@ -246,6 +253,7 @@ "group": "providers", "pages": [ "python-sdk/fastmcp-server-providers-__init__", + "python-sdk/fastmcp-server-providers-addressing", "python-sdk/fastmcp-server-providers-aggregate", "python-sdk/fastmcp-server-providers-base", "python-sdk/fastmcp-server-providers-fastmcp_provider", @@ -276,6 +284,7 @@ "python-sdk/fastmcp-server-providers-openapi-routing" ] }, + "python-sdk/fastmcp-server-providers-prefab_synthesis", "python-sdk/fastmcp-server-providers-proxy", { "group": "skills", @@ -358,6 +367,7 @@ "python-sdk/fastmcp-utilities-auth", "python-sdk/fastmcp-utilities-cli", "python-sdk/fastmcp-utilities-components", + "python-sdk/fastmcp-utilities-docstring_parsing", "python-sdk/fastmcp-utilities-exceptions", "python-sdk/fastmcp-utilities-http", "python-sdk/fastmcp-utilities-inspect", diff --git a/docs/python-sdk/fastmcp-apps-app.mdx b/docs/python-sdk/fastmcp-apps-app.mdx index b4a6bbf70..e6053277e 100644 --- a/docs/python-sdk/fastmcp-apps-app.mdx +++ b/docs/python-sdk/fastmcp-apps-app.mdx @@ -35,7 +35,7 @@ Usage:: ## Classes -### `FastMCPApp` +### `FastMCPApp` A Provider that represents an MCP application. @@ -48,19 +48,19 @@ can find them by original name even when transforms have been applied. **Methods:** -#### `tool` +#### `tool` ```python tool(self, name_or_fn: F) -> F ``` -#### `tool` +#### `tool` ```python tool(self, name_or_fn: str | None = None) -> Callable[[F], F] ``` -#### `tool` +#### `tool` ```python tool(self, name_or_fn: str | AnyFunction | None = None) -> Any @@ -83,19 +83,19 @@ Supports multiple calling patterns:: def save(name: str): ... -#### `ui` +#### `ui` ```python ui(self, name_or_fn: F) -> F ``` -#### `ui` +#### `ui` ```python ui(self, name_or_fn: str | None = None) -> Callable[[F], F] ``` -#### `ui` +#### `ui` ```python ui(self, name_or_fn: str | AnyFunction | None = None) -> Any @@ -119,7 +119,7 @@ Supports multiple calling patterns:: def dashboard() -> Component: ... -#### `add_tool` +#### `add_tool` ```python add_tool(self, tool: Tool | Callable[..., Any]) -> Tool @@ -130,13 +130,13 @@ Add a tool to this app programmatically. The tool is tagged with this app's name for routing. -#### `lifespan` +#### `lifespan` ```python lifespan(self) -> AsyncIterator[None] ``` -#### `run` +#### `run` ```python run(self, transport: Literal['stdio', 'http', 'sse', 'streamable-http'] | None = None, **kwargs: Any) -> None diff --git a/docs/python-sdk/fastmcp-apps-file_upload.mdx b/docs/python-sdk/fastmcp-apps-file_upload.mdx index 9705e335b..a77d9fa6a 100644 --- a/docs/python-sdk/fastmcp-apps-file_upload.mdx +++ b/docs/python-sdk/fastmcp-apps-file_upload.mdx @@ -40,7 +40,7 @@ For custom persistence, override the storage methods:: ## Classes -### `FileUpload` +### `FileUpload` A Provider that adds file upload capabilities to a server. @@ -77,7 +77,7 @@ Example:: **Methods:** -#### `on_store` +#### `on_store` ```python on_store(self, files: list[dict[str, Any]], ctx: Context) -> list[dict[str, Any]] @@ -100,7 +100,7 @@ implementation stores files in memory, scoped by - ``size_display``, ``uploaded_at``). -#### `on_list` +#### `on_list` ```python on_list(self, ctx: Context) -> list[dict[str, Any]] @@ -118,7 +118,7 @@ implementation returns files from the current scope. - List of file summary dicts. -#### `on_read` +#### `on_read` ```python on_read(self, name: str, ctx: Context) -> dict[str, Any] diff --git a/docs/python-sdk/fastmcp-cli-cli.mdx b/docs/python-sdk/fastmcp-cli-cli.mdx index b8bf7e0de..d396af571 100644 --- a/docs/python-sdk/fastmcp-cli-cli.mdx +++ b/docs/python-sdk/fastmcp-cli-cli.mdx @@ -91,7 +91,7 @@ fastmcp run server.py -- --config config.json --debug - `server_spec`: Python file, object specification (file\:obj), config file, URL, or None to auto-detect -### `inspect` +### `inspect` ```python inspect(server_spec: str | None = None) -> None @@ -122,7 +122,7 @@ fastmcp inspect # auto-detect fastmcp.json - `server_spec`: Python file to inspect, optionally with \:object suffix, or fastmcp.json -### `prepare` +### `prepare` ```python prepare(config_path: Annotated[str | None, cyclopts.Parameter(help='Path to fastmcp.json configuration file')] = None, output_dir: Annotated[str | None, cyclopts.Parameter(help='Directory to create the persistent environment in')] = None, skip_source: Annotated[bool, cyclopts.Parameter(help='Skip source preparation (e.g., git clone)')] = False) -> None diff --git a/docs/python-sdk/fastmcp-cli-run.mdx b/docs/python-sdk/fastmcp-cli-run.mdx index 0b341c459..1b7af37a5 100644 --- a/docs/python-sdk/fastmcp-cli-run.mdx +++ b/docs/python-sdk/fastmcp-cli-run.mdx @@ -10,7 +10,7 @@ FastMCP run command implementation with enhanced type hints. ## Functions -### `is_url` +### `is_url` ```python is_url(path: str) -> bool @@ -20,7 +20,7 @@ is_url(path: str) -> bool Check if a string is a URL. -### `create_client_server` +### `create_client_server` ```python create_client_server(url: str) -> Any @@ -36,7 +36,7 @@ Create a FastMCP server from a client URL. - A FastMCP server instance -### `create_mcp_config_server` +### `create_mcp_config_server` ```python create_mcp_config_server(mcp_config_path: Path) -> FastMCP[None] @@ -46,7 +46,7 @@ create_mcp_config_server(mcp_config_path: Path) -> FastMCP[None] Create a FastMCP server from a MCPConfig. -### `load_mcp_server_config` +### `load_mcp_server_config` ```python load_mcp_server_config(config_path: Path) -> MCPServerConfig @@ -62,7 +62,7 @@ Load a FastMCP configuration from a fastmcp.json file. - MCPServerConfig object -### `run_command` +### `run_command` ```python run_command(server_spec: str, transport: TransportType | None = None, host: str | None = None, port: int | None = None, path: str | None = None, log_level: LogLevelType | None = None, server_args: list[str] | None = None, show_banner: bool = True, use_direct_import: bool = False, skip_source: bool = False, stateless: bool = False) -> None @@ -85,7 +85,7 @@ Run a MCP server or connect to a remote one. - `stateless`: Whether to run in stateless mode (no session) -### `run_module_command` +### `run_module_command` ```python run_module_command(module_name: str) -> None @@ -104,7 +104,7 @@ with environment setup (e.g. ``UVEnvironment.build_command``). - `extra_args`: Extra arguments forwarded after the module name. -### `run_v1_server_async` +### `run_v1_server_async` ```python run_v1_server_async(server: FastMCP1x, host: str | None = None, port: int | None = None, transport: TransportType | None = None) -> None @@ -120,7 +120,7 @@ Run a FastMCP 1.x server using async methods. - `transport`: Transport protocol to use -### `run_with_reload` +### `run_with_reload` ```python run_with_reload(cmd: list[str], reload_dirs: list[Path] | None = None, is_stdio: bool = False) -> None diff --git a/docs/python-sdk/fastmcp-client-transports-http.mdx b/docs/python-sdk/fastmcp-client-transports-http.mdx index a0db1401d..48a9559e3 100644 --- a/docs/python-sdk/fastmcp-client-transports-http.mdx +++ b/docs/python-sdk/fastmcp-client-transports-http.mdx @@ -18,19 +18,19 @@ Transport implementation that connects to an MCP server via Streamable HTTP Requ **Methods:** -#### `connect_session` +#### `connect_session` ```python connect_session(self, **session_kwargs: Unpack[SessionKwargs]) -> AsyncIterator[ClientSession] ``` -#### `get_session_id` +#### `get_session_id` ```python get_session_id(self) -> str | None ``` -#### `close` +#### `close` ```python close(self) diff --git a/docs/python-sdk/fastmcp-client-transports-sse.mdx b/docs/python-sdk/fastmcp-client-transports-sse.mdx index a65dace46..6a78d9325 100644 --- a/docs/python-sdk/fastmcp-client-transports-sse.mdx +++ b/docs/python-sdk/fastmcp-client-transports-sse.mdx @@ -18,7 +18,7 @@ Transport implementation that connects to an MCP server via Server-Sent Events. **Methods:** -#### `connect_session` +#### `connect_session` ```python connect_session(self, **session_kwargs: Unpack[SessionKwargs]) -> AsyncIterator[ClientSession] diff --git a/docs/python-sdk/fastmcp-prompts-function_prompt.mdx b/docs/python-sdk/fastmcp-prompts-function_prompt.mdx index 191e36816..82b55e6dd 100644 --- a/docs/python-sdk/fastmcp-prompts-function_prompt.mdx +++ b/docs/python-sdk/fastmcp-prompts-function_prompt.mdx @@ -10,7 +10,7 @@ Standalone @prompt decorator for FastMCP. ## Functions -### `prompt` +### `prompt` ```python prompt(name_or_fn: str | Callable[..., Any] | None = None) -> Any @@ -25,19 +25,19 @@ using mcp.add_prompt(). ## Classes -### `DecoratedPrompt` +### `DecoratedPrompt` Protocol for functions decorated with @prompt. -### `PromptMeta` +### `PromptMeta` Metadata attached to functions by the @prompt decorator. -### `FunctionPrompt` +### `FunctionPrompt` A prompt that is a function. @@ -45,7 +45,7 @@ A prompt that is a function. **Methods:** -#### `from_function` +#### `from_function` ```python from_function(cls, fn: Callable[..., Any]) -> FunctionPrompt @@ -66,7 +66,7 @@ The function can return: - PromptResult: used directly -#### `render` +#### `render` ```python render(self, arguments: dict[str, Any] | None = None) -> PromptResult @@ -75,7 +75,7 @@ render(self, arguments: dict[str, Any] | None = None) -> PromptResult Render the prompt with arguments. -#### `register_with_docket` +#### `register_with_docket` ```python register_with_docket(self, docket: Docket) -> None @@ -84,7 +84,7 @@ register_with_docket(self, docket: Docket) -> None Register this prompt with docket for background execution. -#### `add_to_docket` +#### `add_to_docket` ```python add_to_docket(self, docket: Docket, arguments: dict[str, Any] | None, **kwargs: Any) -> Execution diff --git a/docs/python-sdk/fastmcp-resources-function_resource.mdx b/docs/python-sdk/fastmcp-resources-function_resource.mdx index 28f08a580..24aa2052c 100644 --- a/docs/python-sdk/fastmcp-resources-function_resource.mdx +++ b/docs/python-sdk/fastmcp-resources-function_resource.mdx @@ -10,7 +10,7 @@ Standalone @resource decorator for FastMCP. ## Functions -### `resource` +### `resource` ```python resource(uri: str) -> Callable[[F], F] @@ -71,7 +71,7 @@ individual parameters must not be passed. Cannot be used together with metadata parameter. -#### `read` +#### `read` ```python read(self) -> str | bytes | ResourceResult @@ -80,7 +80,7 @@ read(self) -> str | bytes | ResourceResult Read the resource by calling the wrapped function. -#### `register_with_docket` +#### `register_with_docket` ```python register_with_docket(self, docket: Docket) -> None diff --git a/docs/python-sdk/fastmcp-server-auth-handlers-__init__.mdx b/docs/python-sdk/fastmcp-server-auth-handlers-__init__.mdx new file mode 100644 index 000000000..7593775fb --- /dev/null +++ b/docs/python-sdk/fastmcp-server-auth-handlers-__init__.mdx @@ -0,0 +1,8 @@ +--- +title: __init__ +sidebarTitle: __init__ +--- + +# `fastmcp.server.auth.handlers` + +*This module is empty or contains only private/internal implementations.* diff --git a/docs/python-sdk/fastmcp-server-auth-handlers-authorize.mdx b/docs/python-sdk/fastmcp-server-auth-handlers-authorize.mdx new file mode 100644 index 000000000..f3f583027 --- /dev/null +++ b/docs/python-sdk/fastmcp-server-auth-handlers-authorize.mdx @@ -0,0 +1,83 @@ +--- +title: authorize +sidebarTitle: authorize +--- + +# `fastmcp.server.auth.handlers.authorize` + + +Enhanced authorization handler with improved error responses. + +This module provides an enhanced authorization handler that wraps the MCP SDK's +AuthorizationHandler to provide better error messages when clients attempt to +authorize with unregistered client IDs. + +The enhancement adds: +- Content negotiation: HTML for browsers, JSON for API clients +- Enhanced JSON responses with registration endpoint hints +- Styled HTML error pages with registration links/forms +- Link headers pointing to registration endpoints + + +## Functions + +### `create_unregistered_client_html` + +```python +create_unregistered_client_html(client_id: str, registration_endpoint: str, discovery_endpoint: str, server_name: str | None = None, server_icon_url: str | None = None, title: str = 'Client Not Registered') -> str +``` + + +Create styled HTML error page for unregistered client attempts. + +**Args:** +- `client_id`: The unregistered client ID that was provided +- `registration_endpoint`: URL of the registration endpoint +- `discovery_endpoint`: URL of the OAuth metadata discovery endpoint +- `server_name`: Optional server name for branding +- `server_icon_url`: Optional server icon URL +- `title`: Page title + +**Returns:** +- HTML string for the error page + + +## Classes + +### `AuthorizationHandler` + + +Authorization handler with enhanced error responses for unregistered clients. + +This handler extends the MCP SDK's AuthorizationHandler to provide better UX +when clients attempt to authorize without being registered. It implements +content negotiation to return: + +- HTML error pages for browser requests +- Enhanced JSON with registration hints for API clients +- Link headers pointing to registration endpoints + +This maintains OAuth 2.1 compliance (returns 400 for invalid client_id) +while providing actionable guidance to fix the error. + + +**Methods:** + +#### `handle` + +```python +handle(self, request: Request) -> Response +``` + +Handle authorization request with enhanced error responses. + +This method extends the SDK's authorization handler and intercepts +errors for unregistered clients to provide better error responses +based on the client's Accept header. + +**Args:** +- `request`: The authorization request + +**Returns:** +- Response (redirect on success, error response on failure) + diff --git a/docs/python-sdk/fastmcp-server-dependencies.mdx b/docs/python-sdk/fastmcp-server-dependencies.mdx index 1085b23da..64186a6cd 100644 --- a/docs/python-sdk/fastmcp-server-dependencies.mdx +++ b/docs/python-sdk/fastmcp-server-dependencies.mdx @@ -15,7 +15,7 @@ CurrentWorker) and background task execution require fastmcp[tasks]. ## Functions -### `get_task_context` +### `get_task_context` ```python get_task_context() -> TaskContextInfo | None @@ -31,7 +31,7 @@ Returns None if not running in a task context (e.g., foreground execution). - TaskContextInfo with task_id and session_id, or None if not in a task. -### `register_task_session` +### `register_task_session` ```python register_task_session(session_id: str, session: ServerSession) -> None @@ -49,7 +49,7 @@ client disconnects. - `session`: The ServerSession instance -### `get_task_session` +### `get_task_session` ```python get_task_session(session_id: str) -> ServerSession | None @@ -65,7 +65,7 @@ Get a registered session by ID if still alive. - The ServerSession if found and alive, None otherwise -### `register_task_server` +### `register_task_server` ```python register_task_server(task_id: str, server: FastMCP) -> None @@ -82,17 +82,28 @@ The map is bounded to avoid unbounded growth in long-lived servers. Evicted entries fall back to the ContextVar (parent server). -### `is_docket_available` +### `is_docket_available` ```python is_docket_available() -> bool ``` -Check if pydocket is installed. +Check if a compatible pydocket (>= 0.19.0) is installed and importable. + +Three things have to be true for fastmcp's task features to work: + 1. pydocket distribution metadata is discoverable + 2. its version is at least ``_MIN_DOCKET_VERSION`` (older versions are + missing symbols like ``docket.dependencies.current_execution``, + which fastmcp imports on the request hot path) + 3. the package actually imports — guards against broken/partial + installs where metadata exists but ``import docket`` blows up + +Any of those failing means we treat docket as unavailable and fall back +to the no-tasks code paths instead of crashing deep inside a request. -### `require_docket` +### `require_docket` ```python require_docket(feature: str) -> None @@ -106,7 +117,7 @@ Raise ImportError with install instructions if docket not available. "CurrentDocket()"). Will be included in the error message. -### `transform_context_annotations` +### `transform_context_annotations` ```python transform_context_annotations(fn: Callable[..., Any]) -> Callable[..., Any] @@ -132,7 +143,7 @@ allows them to have defaults in any order. - Function with modified signature (same function object, updated __signature__) -### `get_context` +### `get_context` ```python get_context() -> Context @@ -142,7 +153,7 @@ get_context() -> Context Get the current FastMCP Context instance directly. -### `get_server` +### `get_server` ```python get_server() -> FastMCP @@ -162,7 +173,7 @@ started the worker). - `RuntimeError`: If no server in context -### `get_http_request` +### `get_http_request` ```python get_http_request() -> Request @@ -176,7 +187,7 @@ In background tasks, returns a synthetic request populated with the snapshotted headers from the originating HTTP request. -### `get_http_headers` +### `get_http_headers` ```python get_http_headers(include_all: bool = False, include: set[str] | None = None) -> dict[str, str] @@ -197,7 +208,7 @@ normally be excluded. This is useful for proxy transports that need to forward authorization headers to upstream MCP servers. -### `get_access_token` +### `get_access_token` ```python get_access_token() -> AccessToken | None @@ -216,7 +227,7 @@ token snapshot stored in Redis at task submission time. - The access token if an authenticated user is available, None otherwise. -### `without_injected_parameters` +### `without_injected_parameters` ```python without_injected_parameters(fn: Callable[..., Any]) -> Callable[..., Any] @@ -241,7 +252,7 @@ Handles: - Async wrapper function without injected parameters -### `resolve_dependencies` +### `resolve_dependencies` ```python resolve_dependencies(fn: Callable[..., Any], arguments: dict[str, Any]) -> AsyncGenerator[dict[str, Any], None] @@ -267,7 +278,7 @@ time, so all injection goes through the unified DI system. which will be filtered out) -### `CurrentContext` +### `CurrentContext` ```python CurrentContext() -> Context @@ -286,7 +297,7 @@ current MCP operation (tool/resource/prompt call). - `RuntimeError`: If no active context found (during resolution) -### `OptionalCurrentContext` +### `OptionalCurrentContext` ```python OptionalCurrentContext() -> Context | None @@ -296,7 +307,7 @@ OptionalCurrentContext() -> Context | None Get the current FastMCP Context, or None when no context is active. -### `CurrentDocket` +### `CurrentDocket` ```python CurrentDocket() -> Docket @@ -316,7 +327,7 @@ automatically creates for background task scheduling. - `ImportError`: If fastmcp[tasks] not installed -### `CurrentWorker` +### `CurrentWorker` ```python CurrentWorker() -> Worker @@ -336,7 +347,7 @@ automatically creates for background task processing. - `ImportError`: If fastmcp[tasks] not installed -### `CurrentFastMCP` +### `CurrentFastMCP` ```python CurrentFastMCP() -> FastMCP @@ -354,7 +365,7 @@ This dependency provides access to the active FastMCP server. - `RuntimeError`: If no server in context (during resolution) -### `CurrentRequest` +### `CurrentRequest` ```python CurrentRequest() -> Request @@ -374,7 +385,7 @@ current HTTP request. Only available when running over HTTP transports - `RuntimeError`: If no HTTP request in context (e.g., STDIO transport) -### `CurrentHeaders` +### `CurrentHeaders` ```python CurrentHeaders() -> dict[str, str] @@ -392,7 +403,7 @@ transport. - A dependency that resolves to a dictionary of header name -> value -### `CurrentAccessToken` +### `CurrentAccessToken` ```python CurrentAccessToken() -> AccessToken @@ -411,7 +422,7 @@ authenticated request. Raises an error if no authentication is present. - `RuntimeError`: If no authenticated user (use get_access_token() for optional) -### `TokenClaim` +### `TokenClaim` ```python TokenClaim(name: str) -> str @@ -436,7 +447,7 @@ without needing the full token object. ## Classes -### `TaskContextInfo` +### `TaskContextInfo` Information about the current background task context. @@ -445,7 +456,7 @@ Returned by ``get_task_context()`` when running inside a Docket worker. Contains identifiers needed to communicate with the MCP session. -### `TaskContextSnapshot` +### `TaskContextSnapshot` All context data snapshotted at task-submission time. @@ -455,7 +466,7 @@ Stored as a single Redis key per task, restored once in the worker. **Methods:** -#### `capture` +#### `capture` ```python capture(cls) -> TaskContextSnapshot @@ -464,7 +475,7 @@ capture(cls) -> TaskContextSnapshot Capture current context for background task execution. -#### `from_json` +#### `from_json` ```python from_json(cls, raw: str | bytes) -> TaskContextSnapshot @@ -473,7 +484,7 @@ from_json(cls, raw: str | bytes) -> TaskContextSnapshot Deserialize from JSON stored in Redis. -#### `to_json` +#### `to_json` ```python to_json(self) -> str @@ -482,7 +493,7 @@ to_json(self) -> str Serialize to JSON for Redis storage. -#### `save` +#### `save` ```python save(self, docket: Docket, session_id: str, task_id: str, ttl_seconds: int) -> None @@ -491,7 +502,7 @@ save(self, docket: Docket, session_id: str, task_id: str, ttl_seconds: int) -> N Store this snapshot as a single Redis key. -### `ProgressLike` +### `ProgressLike` Protocol for progress tracking interface. @@ -502,7 +513,7 @@ and Docket's Progress (worker context). **Methods:** -#### `current` +#### `current` ```python current(self) -> int | None @@ -511,7 +522,7 @@ current(self) -> int | None Current progress value. -#### `total` +#### `total` ```python total(self) -> int @@ -520,7 +531,7 @@ total(self) -> int Total/target progress value. -#### `message` +#### `message` ```python message(self) -> str | None @@ -529,7 +540,7 @@ message(self) -> str | None Current progress message. -#### `set_total` +#### `set_total` ```python set_total(self, total: int) -> None @@ -538,7 +549,7 @@ set_total(self, total: int) -> None Set the total/target value for progress tracking. -#### `increment` +#### `increment` ```python increment(self, amount: int = 1) -> None @@ -547,7 +558,7 @@ increment(self, amount: int = 1) -> None Atomically increment the current progress value. -#### `set_message` +#### `set_message` ```python set_message(self, message: str | None) -> None @@ -556,7 +567,7 @@ set_message(self, message: str | None) -> None Update the progress status message. -### `InMemoryProgress` +### `InMemoryProgress` In-memory progress tracker for immediate tool execution. @@ -568,25 +579,25 @@ progress doesn't need to be observable across processes. **Methods:** -#### `current` +#### `current` ```python current(self) -> int | None ``` -#### `total` +#### `total` ```python total(self) -> int ``` -#### `message` +#### `message` ```python message(self) -> str | None ``` -#### `set_total` +#### `set_total` ```python set_total(self, total: int) -> None @@ -595,7 +606,7 @@ set_total(self, total: int) -> None Set the total/target value for progress tracking. -#### `increment` +#### `increment` ```python increment(self, amount: int = 1) -> None @@ -604,7 +615,7 @@ increment(self, amount: int = 1) -> None Atomically increment the current progress value. -#### `set_message` +#### `set_message` ```python set_message(self, message: str | None) -> None @@ -613,7 +624,7 @@ set_message(self, message: str | None) -> None Update the progress status message. -### `Progress` +### `Progress` Progress dependency that works in both server and worker contexts. @@ -628,7 +639,7 @@ share mutable state. **Methods:** -#### `current` +#### `current` ```python current(self) -> int | None @@ -637,7 +648,7 @@ current(self) -> int | None Current progress value. -#### `total` +#### `total` ```python total(self) -> int @@ -646,7 +657,7 @@ total(self) -> int Total/target progress value. -#### `message` +#### `message` ```python message(self) -> str | None @@ -655,7 +666,7 @@ message(self) -> str | None Current progress message. -#### `set_total` +#### `set_total` ```python set_total(self, total: int) -> None @@ -664,7 +675,7 @@ set_total(self, total: int) -> None Set the total/target value for progress tracking. -#### `increment` +#### `increment` ```python increment(self, amount: int = 1) -> None @@ -673,7 +684,7 @@ increment(self, amount: int = 1) -> None Atomically increment the current progress value. -#### `set_message` +#### `set_message` ```python set_message(self, message: str | None) -> None diff --git a/docs/python-sdk/fastmcp-server-mixins-transport.mdx b/docs/python-sdk/fastmcp-server-mixins-transport.mdx index ad4e0b60e..0d29ed280 100644 --- a/docs/python-sdk/fastmcp-server-mixins-transport.mdx +++ b/docs/python-sdk/fastmcp-server-mixins-transport.mdx @@ -104,7 +104,7 @@ Run the server using HTTP transport. - `stateless`: Alias for stateless_http for CLI consistency -#### `http_app` +#### `http_app` ```python http_app(self: FastMCP, path: str | None = None, middleware: list[ASGIMiddleware] | None = None, json_response: bool | None = None, stateless_http: bool | None = None, transport: Literal['http', 'streamable-http', 'sse'] = 'http', event_store: EventStore | None = None, retry_interval: int | None = None) -> StarletteWithLifespan diff --git a/docs/python-sdk/fastmcp-server-providers-addressing.mdx b/docs/python-sdk/fastmcp-server-providers-addressing.mdx new file mode 100644 index 000000000..48b953e87 --- /dev/null +++ b/docs/python-sdk/fastmcp-server-providers-addressing.mdx @@ -0,0 +1,81 @@ +--- +title: addressing +sidebarTitle: addressing +--- + +# `fastmcp.server.providers.addressing` + + +Deterministic tool hashing for backend-tool routing and per-tool resources. + +Each FastMCPApp backend tool gets a deterministic hash computed from its +app name + tool name. The hash serves two purposes: + +1. **Backend-tool routing.** Tools with ``"app"`` in their visibility are + callable via ``_``. The dispatcher parses the prefix, + then walks providers recursively (same pattern as the old ``get_app_tool``) + to find a tool whose stored hash matches. + +2. **Per-tool Prefab renderer URIs.** Each prefab tool gets a unique renderer + resource at ``ui://prefab/tool//renderer.html``. ``list_resources`` + and ``read_resource`` synthesize these on demand from the tool's meta. + +The hash is computed at registration time from ``(app_name, tool_name)`` — +both known at that moment — and stored in ``meta["fastmcp"]["_tool_hash"]``. +Deterministic across replicas (same code → same hash), no registry walk +needed. + + +## Functions + +### `hash_tool` + +```python +hash_tool(app_name: str, tool_name: str) -> str +``` + + +Deterministic hex hash for a tool in an app. + +Same inputs on every replica produce the same output. + + +### `hashed_backend_name` + +```python +hashed_backend_name(app_name: str, tool_name: str) -> str +``` + + +Format the universal name for a backend tool: ``_``. + + +### `parse_hashed_backend_name` + +```python +parse_hashed_backend_name(name: str) -> tuple[str, str] | None +``` + + +Parse ``_`` → ``(hash, local_tool_name)`` or None. + + +### `hashed_resource_uri` + +```python +hashed_resource_uri(app_name: str, tool_name: str) -> str +``` + + +Per-tool Prefab renderer resource URI. + + +### `parse_hashed_resource_uri` + +```python +parse_hashed_resource_uri(uri: str) -> str | None +``` + + +Extract the hash from a Prefab renderer URI, or None. + diff --git a/docs/python-sdk/fastmcp-server-providers-aggregate.mdx b/docs/python-sdk/fastmcp-server-providers-aggregate.mdx index ffc3d8dbb..f016f89d1 100644 --- a/docs/python-sdk/fastmcp-server-providers-aggregate.mdx +++ b/docs/python-sdk/fastmcp-server-providers-aggregate.mdx @@ -45,7 +45,7 @@ Errors from individual providers are logged and skipped (graceful degradation). **Methods:** -#### `add_provider` +#### `add_provider` ```python add_provider(self, provider: Provider) -> None @@ -64,7 +64,7 @@ FastMCPProvider to ensure middleware is invoked correctly. - Prompts become "namespace_promptname" -#### `get_app_tool` +#### `get_app_tool` ```python get_app_tool(self, app_name: str, tool_name: str) -> Tool | None @@ -73,7 +73,16 @@ get_app_tool(self, app_name: str, tool_name: str) -> Tool | None Query all child providers for an app tool. -#### `get_tasks` +#### `get_tool_by_hash` + +```python +get_tool_by_hash(self, tool_hash: str, tool_name: str) -> Tool | None +``` + +Query all child providers for a tool matching a hash. + + +#### `get_tasks` ```python get_tasks(self) -> Sequence[FastMCPComponent] @@ -82,7 +91,7 @@ get_tasks(self) -> Sequence[FastMCPComponent] Get all task-eligible components from all providers. -#### `lifespan` +#### `lifespan` ```python lifespan(self) -> AsyncIterator[None] diff --git a/docs/python-sdk/fastmcp-server-providers-base.mdx b/docs/python-sdk/fastmcp-server-providers-base.mdx index 715f52a0c..6d4774977 100644 --- a/docs/python-sdk/fastmcp-server-providers-base.mdx +++ b/docs/python-sdk/fastmcp-server-providers-base.mdx @@ -147,7 +147,20 @@ name. Skips the transform chain entirely. - The tool if found and tagged with the given app name, else None. -#### `list_resources` +#### `get_tool_by_hash` + +```python +get_tool_by_hash(self, tool_hash: str, tool_name: str) -> Tool | None +``` + +Look up an app-visible tool by its deterministic hash. + +Same recursive-walk semantics as ``get_app_tool`` but matches on +``meta["fastmcp"]["_tool_hash"]`` instead of the app name tag. +Used by the dispatcher when receiving hashed backend-tool calls. + + +#### `list_resources` ```python list_resources(self) -> Sequence[Resource] @@ -158,7 +171,7 @@ List resources with all transforms applied. Components may be marked as disabled but are NOT filtered here. -#### `get_resource` +#### `get_resource` ```python get_resource(self, uri: str, version: VersionSpec | None = None) -> Resource | None @@ -177,7 +190,7 @@ Note: This method does NOT filter disabled components. The Server - The resource if found (may be marked disabled), None if not found. -#### `list_resource_templates` +#### `list_resource_templates` ```python list_resource_templates(self) -> Sequence[ResourceTemplate] @@ -188,7 +201,7 @@ List resource templates with all transforms applied. Components may be marked as disabled but are NOT filtered here. -#### `get_resource_template` +#### `get_resource_template` ```python get_resource_template(self, uri: str, version: VersionSpec | None = None) -> ResourceTemplate | None @@ -207,7 +220,7 @@ Note: This method does NOT filter disabled components. The Server - The template if found (may be marked disabled), None if not found. -#### `list_prompts` +#### `list_prompts` ```python list_prompts(self) -> Sequence[Prompt] @@ -218,7 +231,7 @@ List prompts with all transforms applied. Components may be marked as disabled but are NOT filtered here. -#### `get_prompt` +#### `get_prompt` ```python get_prompt(self, name: str, version: VersionSpec | None = None) -> Prompt | None @@ -237,7 +250,7 @@ Note: This method does NOT filter disabled components. The Server - The prompt if found (may be marked disabled), None if not found. -#### `get_tasks` +#### `get_tasks` ```python get_tasks(self) -> Sequence[FastMCPComponent] @@ -252,7 +265,7 @@ for components with task_config.mode != 'forbidden'. Used by the server during startup to register functions with Docket. -#### `lifespan` +#### `lifespan` ```python lifespan(self) -> AsyncIterator[None] @@ -268,7 +281,7 @@ The lifespan scope matches the server's lifespan - code before yield runs at startup, code after yield runs at shutdown. -#### `enable` +#### `enable` ```python enable(self) -> Self @@ -296,7 +309,7 @@ VersionSpec(gte="v2")). Unversioned components will not match. - Self for method chaining. -#### `disable` +#### `disable` ```python disable(self) -> Self diff --git a/docs/python-sdk/fastmcp-server-providers-fastmcp_provider.mdx b/docs/python-sdk/fastmcp-server-providers-fastmcp_provider.mdx index ec5333e78..0602510ce 100644 --- a/docs/python-sdk/fastmcp-server-providers-fastmcp_provider.mdx +++ b/docs/python-sdk/fastmcp-server-providers-fastmcp_provider.mdx @@ -219,7 +219,16 @@ get_app_tool(self, app_name: str, tool_name: str) -> Tool | None Delegate to nested server's get_app_tool, wrapping for middleware. -#### `get_tasks` +#### `get_tool_by_hash` + +```python +get_tool_by_hash(self, tool_hash: str, tool_name: str) -> Tool | None +``` + +Delegate to nested server's get_tool_by_hash, wrapping for middleware. + + +#### `get_tasks` ```python get_tasks(self) -> Sequence[FastMCPComponent] @@ -233,7 +242,7 @@ server's transforms applied, then applies this provider's transforms for correct registration keys. -#### `lifespan` +#### `lifespan` ```python lifespan(self) -> AsyncIterator[None] diff --git a/docs/python-sdk/fastmcp-server-providers-local_provider-decorators-tools.mdx b/docs/python-sdk/fastmcp-server-providers-local_provider-decorators-tools.mdx index 83ae9fe49..afb6541d9 100644 --- a/docs/python-sdk/fastmcp-server-providers-local_provider-decorators-tools.mdx +++ b/docs/python-sdk/fastmcp-server-providers-local_provider-decorators-tools.mdx @@ -14,7 +14,7 @@ registration functionality to LocalProvider. ## Classes -### `ToolDecoratorMixin` +### `ToolDecoratorMixin` Mixin class providing tool decorator functionality for LocalProvider. @@ -26,7 +26,7 @@ This mixin contains all methods related to: **Methods:** -#### `add_tool` +#### `add_tool` ```python add_tool(self: LocalProvider, tool: Tool | Callable[..., Any]) -> Tool @@ -37,19 +37,19 @@ Add a tool to this provider's storage. Accepts either a Tool object or a decorated function with __fastmcp__ metadata. -#### `tool` +#### `tool` ```python tool(self: LocalProvider, name_or_fn: F) -> F ``` -#### `tool` +#### `tool` ```python tool(self: LocalProvider, name_or_fn: str | None = None) -> Callable[[F], F] ``` -#### `tool` +#### `tool` ```python tool(self: LocalProvider, name_or_fn: str | AnyFunction | None = None) -> Callable[[AnyFunction], FunctionTool] | FunctionTool | partial[Callable[[AnyFunction], FunctionTool] | FunctionTool] diff --git a/docs/python-sdk/fastmcp-server-providers-prefab_synthesis.mdx b/docs/python-sdk/fastmcp-server-providers-prefab_synthesis.mdx new file mode 100644 index 000000000..b3b2c9734 --- /dev/null +++ b/docs/python-sdk/fastmcp-server-providers-prefab_synthesis.mdx @@ -0,0 +1,58 @@ +--- +title: prefab_synthesis +sidebarTitle: prefab_synthesis +--- + +# `fastmcp.server.providers.prefab_synthesis` + + +On-demand Prefab renderer resource synthesis. + +Tools marked as Prefab (via ``app=True``, ``PrefabAppConfig``, etc.) carry +a placeholder ``meta.ui.resourceUri`` and optionally a hash in +``meta.fastmcp._tool_hash``. This module synthesizes per-tool renderer +resources on demand at ``list_resources`` and ``read_resource`` time +without storing or materializing anything. + +Each tool's resource URI is ``ui://prefab/tool//renderer.html`` +where the hash comes from the tool's own meta (set at registration from +the app name + tool name). CSP on the resource is the tool's +``meta.ui.csp`` merged with the renderer defaults across all four +``*_domains`` fields. + + +## Functions + +### `synthesize_prefab_resources` + +```python +synthesize_prefab_resources(server: FastMCP) -> list[Resource] +``` + + +Return fresh synthetic Prefab resources for all prefab tools. Pure. + + +### `synthesize_prefab_resource_by_uri` + +```python +synthesize_prefab_resource_by_uri(server: FastMCP, uri: str) -> Resource | None +``` + + +Intercept a Prefab renderer URI and synthesize on demand. + + +### `rewrite_tool_meta_for_wire` + +```python +rewrite_tool_meta_for_wire(tool: Tool) -> Tool +``` + + +Return a model_copy with the per-tool URI and CSP stripped. + +Reads the hash from the tool's own meta. If no hash is found, +returns the tool unchanged. Produces a fresh copy — the original +Tool object is untouched. + diff --git a/docs/python-sdk/fastmcp-server-providers-proxy.mdx b/docs/python-sdk/fastmcp-server-providers-proxy.mdx index 2df6ad1e3..b53bf4de7 100644 --- a/docs/python-sdk/fastmcp-server-providers-proxy.mdx +++ b/docs/python-sdk/fastmcp-server-providers-proxy.mdx @@ -15,7 +15,7 @@ classes that forward execution to remote servers. ## Functions -### `default_proxy_roots_handler` +### `default_proxy_roots_handler` ```python default_proxy_roots_handler(context: RequestContext[ClientSession, LifespanContextT]) -> RootsList @@ -25,7 +25,7 @@ default_proxy_roots_handler(context: RequestContext[ClientSession, LifespanConte Forward list roots request from remote server to proxy's connected clients. -### `default_proxy_sampling_handler` +### `default_proxy_sampling_handler` ```python default_proxy_sampling_handler(messages: list[mcp.types.SamplingMessage], params: mcp.types.CreateMessageRequestParams, context: RequestContext[ClientSession, LifespanContextT]) -> mcp.types.CreateMessageResult @@ -35,7 +35,7 @@ default_proxy_sampling_handler(messages: list[mcp.types.SamplingMessage], params Forward sampling request from remote server to proxy's connected clients. -### `default_proxy_elicitation_handler` +### `default_proxy_elicitation_handler` ```python default_proxy_elicitation_handler(message: str, response_type: type, params: mcp.types.ElicitRequestParams, context: RequestContext[ClientSession, LifespanContextT]) -> ElicitResult @@ -45,7 +45,7 @@ default_proxy_elicitation_handler(message: str, response_type: type, params: mcp Forward elicitation request from remote server to proxy's connected clients. -### `default_proxy_log_handler` +### `default_proxy_log_handler` ```python default_proxy_log_handler(message: LogMessage) -> None @@ -55,7 +55,7 @@ default_proxy_log_handler(message: LogMessage) -> None Forward log notification from remote server to proxy's connected clients. -### `default_proxy_progress_handler` +### `default_proxy_progress_handler` ```python default_proxy_progress_handler(progress: float, total: float | None, message: str | None) -> None @@ -268,7 +268,7 @@ server lifespan initialization, which would open the client before any context is set. All Proxy* components have task_config.mode="forbidden". -### `FastMCPProxy` +### `FastMCPProxy` A FastMCP server that acts as a proxy to a remote MCP-compliant server. @@ -277,7 +277,7 @@ This is a convenience wrapper that creates a FastMCP server with a ProxyProvider. For more control, use FastMCP with add_provider(ProxyProvider(...)). -### `ProxyClient` +### `ProxyClient` A proxy client that forwards advanced interactions between a remote MCP server and the proxy's connected clients. @@ -285,7 +285,7 @@ A proxy client that forwards advanced interactions between a remote MCP server a Supports forwarding roots, sampling, elicitation, logging, and progress. -### `StatefulProxyClient` +### `StatefulProxyClient` A proxy client that provides a stateful client factory for the proxy server. @@ -306,7 +306,7 @@ it to detect (and correct) staleness. **Methods:** -#### `clear` +#### `clear` ```python clear(self) @@ -315,7 +315,7 @@ clear(self) Clear all cached clients and force disconnect them. -#### `new_stateful` +#### `new_stateful` ```python new_stateful(self) -> Client[ClientTransportT] diff --git a/docs/python-sdk/fastmcp-server-sampling-run.mdx b/docs/python-sdk/fastmcp-server-sampling-run.mdx index ea6d46104..5e145c099 100644 --- a/docs/python-sdk/fastmcp-server-sampling-run.mdx +++ b/docs/python-sdk/fastmcp-server-sampling-run.mdx @@ -10,7 +10,7 @@ Sampling types and helper functions for FastMCP servers. ## Functions -### `determine_handler_mode` +### `determine_handler_mode` ```python determine_handler_mode(context: Context, needs_tools: bool) -> bool @@ -30,7 +30,7 @@ Determine whether to use fallback handler or client for sampling. - `ValueError`: If client lacks required capability and no fallback configured. -### `call_sampling_handler` +### `call_sampling_handler` ```python call_sampling_handler(context: Context, messages: list[SamplingMessage]) -> CreateMessageResult | CreateMessageResultWithTools @@ -44,7 +44,7 @@ sampling_handler is set via determine_handler_mode(). The checks below are safeguards against internal misuse. -### `execute_tools` +### `execute_tools` ```python execute_tools(tool_calls: list[ToolUseContent], tool_map: dict[str, SamplingTool], mask_error_details: bool = False, tool_concurrency: int | None = None) -> list[ToolResultContent] @@ -71,7 +71,7 @@ regardless of this setting. - List of tool result content blocks in the same order as tool_calls. -### `prepare_messages` +### `prepare_messages` ```python prepare_messages(messages: str | Sequence[str | SamplingMessage]) -> list[SamplingMessage] @@ -81,7 +81,7 @@ prepare_messages(messages: str | Sequence[str | SamplingMessage]) -> list[Sampli Convert various message formats to a list of SamplingMessage objects. -### `prepare_tools` +### `prepare_tools` ```python prepare_tools(tools: Sequence[SamplingTool | FunctionTool | TransformedTool | Callable[..., Any]] | None) -> list[SamplingTool] | None @@ -102,7 +102,7 @@ TransformedTool, or plain callable functions. - List of SamplingTool instances, or None if tools is None. -### `extract_tool_calls` +### `extract_tool_calls` ```python extract_tool_calls(response: CreateMessageResult | CreateMessageResultWithTools) -> list[ToolUseContent] @@ -112,7 +112,7 @@ extract_tool_calls(response: CreateMessageResult | CreateMessageResultWithTools) Extract tool calls from a response. -### `create_final_response_tool` +### `create_final_response_tool` ```python create_final_response_tool(result_type: type) -> SamplingTool @@ -125,7 +125,7 @@ This tool is used to capture structured responses from the LLM. The tool's schema is derived from the result_type. -### `sample_step_impl` +### `sample_step_impl` ```python sample_step_impl(context: Context, messages: str | Sequence[str | SamplingMessage]) -> SampleStep @@ -138,7 +138,7 @@ Make a single LLM sampling call. This is a stateless function that makes exactly one LLM call and optionally executes any requested tools. -### `sample_impl` +### `sample_impl` ```python sample_impl(context: Context, messages: str | Sequence[str | SamplingMessage]) -> SamplingResult[ResultT] @@ -154,7 +154,7 @@ provides a final text response. ## Classes -### `SamplingResult` +### `SamplingResult` Result of a sampling operation. @@ -165,7 +165,7 @@ Result of a sampling operation. - `history`: All messages exchanged during sampling. -### `SampleStep` +### `SampleStep` Result of a single sampling call. @@ -175,7 +175,7 @@ Represents what the LLM returned in this step plus the message history. **Methods:** -#### `is_tool_use` +#### `is_tool_use` ```python is_tool_use(self) -> bool @@ -184,7 +184,7 @@ is_tool_use(self) -> bool True if the LLM is requesting tool execution. -#### `text` +#### `text` ```python text(self) -> str | None @@ -193,7 +193,7 @@ text(self) -> str | None Extract text from the response, if available. -#### `tool_calls` +#### `tool_calls` ```python tool_calls(self) -> list[ToolUseContent] diff --git a/docs/python-sdk/fastmcp-server-server.mdx b/docs/python-sdk/fastmcp-server-server.mdx index 14fcf04ca..f68b94d3e 100644 --- a/docs/python-sdk/fastmcp-server-server.mdx +++ b/docs/python-sdk/fastmcp-server-server.mdx @@ -10,7 +10,7 @@ FastMCP - A more ergonomic interface for MCP servers. ## Functions -### `default_lifespan` +### `default_lifespan` ```python default_lifespan(server: FastMCP[LifespanResultT]) -> AsyncIterator[Any] @@ -26,7 +26,7 @@ Default lifespan context manager that does nothing. - An empty dictionary as the lifespan result. -### `create_proxy` +### `create_proxy` ```python create_proxy(target: Client[ClientTransportT] | ClientTransport | FastMCP[Any] | FastMCP1Server | AnyUrl | Path | MCPConfig | dict[str, Any] | str, **settings: Any) -> FastMCPProxy @@ -54,53 +54,53 @@ use `FastMCPProxy` or `ProxyProvider` directly from `fastmcp.server.providers.pr ## Classes -### `StateValue` +### `StateValue` Wrapper for stored context state values. -### `FastMCP` +### `FastMCP` **Methods:** -#### `name` +#### `name` ```python name(self) -> str ``` -#### `instructions` +#### `instructions` ```python instructions(self) -> str | None ``` -#### `instructions` +#### `instructions` ```python instructions(self, value: str | None) -> None ``` -#### `version` +#### `version` ```python version(self) -> str | None ``` -#### `website_url` +#### `website_url` ```python website_url(self) -> str | None ``` -#### `icons` +#### `icons` ```python icons(self) -> list[mcp.types.Icon] ``` -#### `local_provider` +#### `local_provider` ```python local_provider(self) -> LocalProvider @@ -115,13 +115,13 @@ Use this to remove components: mcp.local_provider.remove_prompt("my_prompt") -#### `add_middleware` +#### `add_middleware` ```python add_middleware(self, middleware: Middleware) -> None ``` -#### `add_provider` +#### `add_provider` ```python add_provider(self, provider: Provider) -> None @@ -141,7 +141,7 @@ always take precedence over providers. - Prompts become "namespace_promptname" -#### `get_tasks` +#### `get_tasks` ```python get_tasks(self) -> Sequence[FastMCPComponent] @@ -153,7 +153,7 @@ Overrides AggregateProvider.get_tasks() to apply server-level transforms after aggregation. AggregateProvider handles provider-level namespacing. -#### `add_transform` +#### `add_transform` ```python add_transform(self, transform: Transform) -> None @@ -168,7 +168,7 @@ They transform tools, resources, and prompts from ALL providers. - `transform`: The transform to add. -#### `add_tool_transformation` +#### `add_tool_transformation` ```python add_tool_transformation(self, tool_name: str, transformation: ToolTransformConfig) -> None @@ -180,7 +180,7 @@ Add a tool transformation. Use ``add_transform(ToolTransform({...}))`` instead. -#### `remove_tool_transformation` +#### `remove_tool_transformation` ```python remove_tool_transformation(self, _tool_name: str) -> None @@ -192,7 +192,7 @@ Remove a tool transformation. Tool transformations are now immutable. Use enable/disable controls instead. -#### `list_tools` +#### `list_tools` ```python list_tools(self) -> Sequence[Tool] @@ -205,7 +205,7 @@ and middleware execution. Returns all versions (no deduplication). Protocol handlers deduplicate for MCP wire format. -#### `get_tool` +#### `get_tool` ```python get_tool(self, name: str, version: VersionSpec | None = None) -> Tool | None @@ -228,7 +228,7 @@ requested, falls back to the next-highest enabled version. - The tool if found and enabled, None otherwise. -#### `list_resources` +#### `list_resources` ```python list_resources(self) -> Sequence[Resource] @@ -241,7 +241,7 @@ and middleware execution. Returns all versions (no deduplication). Protocol handlers deduplicate for MCP wire format. -#### `get_resource` +#### `get_resource` ```python get_resource(self, uri: str, version: VersionSpec | None = None) -> Resource | None @@ -263,7 +263,7 @@ requested, falls back to the next-highest enabled version. - The resource if found and enabled, None otherwise. -#### `list_resource_templates` +#### `list_resource_templates` ```python list_resource_templates(self) -> Sequence[ResourceTemplate] @@ -276,7 +276,7 @@ auth filtering, and middleware execution. Returns all versions (no deduplication Protocol handlers deduplicate for MCP wire format. -#### `get_resource_template` +#### `get_resource_template` ```python get_resource_template(self, uri: str, version: VersionSpec | None = None) -> ResourceTemplate | None @@ -298,7 +298,7 @@ requested, falls back to the next-highest enabled version. - The template if found and enabled, None otherwise. -#### `list_prompts` +#### `list_prompts` ```python list_prompts(self) -> Sequence[Prompt] @@ -311,7 +311,7 @@ and middleware execution. Returns all versions (no deduplication). Protocol handlers deduplicate for MCP wire format. -#### `get_prompt` +#### `get_prompt` ```python get_prompt(self, name: str, version: VersionSpec | None = None) -> Prompt | None @@ -333,19 +333,19 @@ requested, falls back to the next-highest enabled version. - The prompt if found and enabled, None otherwise. -#### `call_tool` +#### `call_tool` ```python call_tool(self, name: str, arguments: dict[str, Any] | None = None) -> ToolResult ``` -#### `call_tool` +#### `call_tool` ```python call_tool(self, name: str, arguments: dict[str, Any] | None = None) -> mcp.types.CreateTaskResult ``` -#### `call_tool` +#### `call_tool` ```python call_tool(self, name: str, arguments: dict[str, Any] | None = None) -> ToolResult | mcp.types.CreateTaskResult @@ -375,19 +375,19 @@ return ToolResult. - `ValidationError`: If arguments fail validation -#### `read_resource` +#### `read_resource` ```python read_resource(self, uri: str) -> ResourceResult ``` -#### `read_resource` +#### `read_resource` ```python read_resource(self, uri: str) -> mcp.types.CreateTaskResult ``` -#### `read_resource` +#### `read_resource` ```python read_resource(self, uri: str) -> ResourceResult | mcp.types.CreateTaskResult @@ -416,19 +416,19 @@ return ResourceResult. - `ResourceError`: If resource read fails -#### `render_prompt` +#### `render_prompt` ```python render_prompt(self, name: str, arguments: dict[str, Any] | None = None) -> PromptResult ``` -#### `render_prompt` +#### `render_prompt` ```python render_prompt(self, name: str, arguments: dict[str, Any] | None = None) -> mcp.types.CreateTaskResult ``` -#### `render_prompt` +#### `render_prompt` ```python render_prompt(self, name: str, arguments: dict[str, Any] | None = None) -> PromptResult | mcp.types.CreateTaskResult @@ -458,7 +458,7 @@ return PromptResult. - `PromptError`: If prompt rendering fails -#### `add_tool` +#### `add_tool` ```python add_tool(self, tool: Tool | Callable[..., Any]) -> Tool @@ -476,7 +476,7 @@ with the Context type annotation. See the @tool decorator for examples. - The tool instance that was added to the server. -#### `remove_tool` +#### `remove_tool` ```python remove_tool(self, name: str, version: str | None = None) -> None @@ -495,19 +495,19 @@ Remove tool(s) from the server. - `NotFoundError`: If no matching tool is found. -#### `tool` +#### `tool` ```python tool(self, name_or_fn: F) -> F ``` -#### `tool` +#### `tool` ```python tool(self, name_or_fn: str | None = None) -> Callable[[F], F] ``` -#### `tool` +#### `tool` ```python tool(self, name_or_fn: str | AnyFunction | None = None) -> Callable[[AnyFunction], FunctionTool] | FunctionTool | partial[Callable[[AnyFunction], FunctionTool] | FunctionTool] @@ -563,7 +563,7 @@ server.tool(my_function, name="custom_name") ``` -#### `add_resource` +#### `add_resource` ```python add_resource(self, resource: Resource | Callable[..., Any]) -> Resource | ResourceTemplate @@ -578,7 +578,7 @@ Add a resource to the server. - The resource instance that was added to the server. -#### `add_template` +#### `add_template` ```python add_template(self, template: ResourceTemplate) -> ResourceTemplate @@ -593,7 +593,7 @@ Add a resource template to the server. - The template instance that was added to the server. -#### `resource` +#### `resource` ```python resource(self, uri: str) -> Callable[[F], F] @@ -652,7 +652,7 @@ async def get_weather(city: str) -> str: ``` -#### `add_prompt` +#### `add_prompt` ```python add_prompt(self, prompt: Prompt | Callable[..., Any]) -> Prompt @@ -667,19 +667,19 @@ Add a prompt to the server. - The prompt instance that was added to the server. -#### `prompt` +#### `prompt` ```python prompt(self, name_or_fn: F) -> F ``` -#### `prompt` +#### `prompt` ```python prompt(self, name_or_fn: str | None = None) -> Callable[[F], F] ``` -#### `prompt` +#### `prompt` ```python prompt(self, name_or_fn: str | AnyFunction | None = None) -> Callable[[AnyFunction], FunctionPrompt] | FunctionPrompt | partial[Callable[[AnyFunction], FunctionPrompt] | FunctionPrompt] @@ -756,7 +756,7 @@ Decorator to register a prompt. ``` -#### `mount` +#### `mount` ```python mount(self, server: FastMCP[LifespanResultT], namespace: str | None = None, as_proxy: bool | None = None, tool_names: dict[str, str] | None = None, prefix: str | None = None) -> None @@ -803,7 +803,7 @@ mounted server. - `prefix`: Deprecated. Use namespace instead. -#### `import_server` +#### `import_server` ```python import_server(self, server: FastMCP[LifespanResultT], prefix: str | None = None) -> None @@ -844,7 +844,7 @@ templates, and prompts are imported with their original names. objects are imported with their original names. -#### `from_openapi` +#### `from_openapi` ```python from_openapi(cls, openapi_spec: dict[str, Any], client: httpx.AsyncClient | None = None, name: str = 'OpenAPI Server', route_maps: list[RouteMap] | None = None, route_map_fn: OpenAPIRouteMapFn | None = None, mcp_component_fn: OpenAPIComponentFn | None = None, mcp_names: dict[str, str] | None = None, tags: set[str] | None = None, validate_output: bool = True, **settings: Any) -> Self @@ -873,7 +873,7 @@ response structure while still returning structured JSON. - A FastMCP server with an OpenAPIProvider attached. -#### `from_fastapi` +#### `from_fastapi` ```python from_fastapi(cls, app: Any, name: str | None = None, route_maps: list[RouteMap] | None = None, route_map_fn: OpenAPIRouteMapFn | None = None, mcp_component_fn: OpenAPIComponentFn | None = None, mcp_names: dict[str, str] | None = None, httpx_client_kwargs: dict[str, Any] | None = None, tags: set[str] | None = None, **settings: Any) -> Self @@ -897,7 +897,7 @@ Use this to configure timeout and other client settings. - A FastMCP server with an OpenAPIProvider attached. -#### `as_proxy` +#### `as_proxy` ```python as_proxy(cls, backend: Client[ClientTransportT] | ClientTransport | FastMCP[Any] | FastMCP1Server | AnyUrl | Path | MCPConfig | dict[str, Any] | str, **settings: Any) -> FastMCPProxy @@ -915,7 +915,7 @@ instance or any value accepted as the `transport` argument of `fastmcp.client.Client` constructor. -#### `generate_name` +#### `generate_name` ```python generate_name(cls, name: str | None = None) -> str diff --git a/docs/python-sdk/fastmcp-server-tasks-capabilities.mdx b/docs/python-sdk/fastmcp-server-tasks-capabilities.mdx index 03b1102dd..8e6ada03a 100644 --- a/docs/python-sdk/fastmcp-server-tasks-capabilities.mdx +++ b/docs/python-sdk/fastmcp-server-tasks-capabilities.mdx @@ -10,7 +10,7 @@ SEP-1686 task capabilities declaration. ## Functions -### `get_task_capabilities` +### `get_task_capabilities` ```python get_task_capabilities() -> ServerTasksCapability | None @@ -22,7 +22,11 @@ Return the SEP-1686 task capabilities. Returns task capabilities as a first-class ServerCapabilities field, declaring support for list, cancel, and request operations per SEP-1686. -Returns None if pydocket is not installed (no task support). +Returns None if a compatible pydocket is not installed (no task support). +Uses the canonical ``is_docket_available()`` check so that capability +advertisement and handler registration stay in sync — otherwise a server +with an old transitive pydocket would advertise task support and then +return "method not found" when clients invoked it. Note: prompts/resources are passed via extra_data since the SDK types don't include them yet (FastMCP supports them ahead of the spec). diff --git a/docs/python-sdk/fastmcp-tools-base.mdx b/docs/python-sdk/fastmcp-tools-base.mdx index 4f8d362ea..e7bc30f5d 100644 --- a/docs/python-sdk/fastmcp-tools-base.mdx +++ b/docs/python-sdk/fastmcp-tools-base.mdx @@ -78,7 +78,7 @@ Handles ToolResult passthrough and converts raw values using the tool's attributes (serializer, output_schema) for proper conversion. -#### `register_with_docket` +#### `register_with_docket` ```python register_with_docket(self, docket: Docket) -> None @@ -87,7 +87,7 @@ register_with_docket(self, docket: Docket) -> None Register this tool with docket for background execution. -#### `add_to_docket` +#### `add_to_docket` ```python add_to_docket(self, docket: Docket, arguments: dict[str, Any], **kwargs: Any) -> Execution @@ -103,13 +103,13 @@ Schedule this tool for background execution via docket. - `**kwargs`: Additional kwargs passed to docket.add() -#### `from_tool` +#### `from_tool` ```python from_tool(cls, tool: Tool | Callable[..., Any]) -> TransformedTool ``` -#### `get_span_attributes` +#### `get_span_attributes` ```python get_span_attributes(self) -> dict[str, Any] diff --git a/docs/python-sdk/fastmcp-tools-function_parsing.mdx b/docs/python-sdk/fastmcp-tools-function_parsing.mdx index 6264ef5d3..bfe78f10e 100644 --- a/docs/python-sdk/fastmcp-tools-function_parsing.mdx +++ b/docs/python-sdk/fastmcp-tools-function_parsing.mdx @@ -10,11 +10,11 @@ Function introspection and schema generation for FastMCP tools. ## Classes -### `ParsedFunction` +### `ParsedFunction` **Methods:** -#### `from_function` +#### `from_function` ```python from_function(cls, fn: Callable[..., Any], exclude_args: list[str] | None = None, validate: bool = True, wrap_non_object_output_schema: bool = True) -> ParsedFunction diff --git a/docs/python-sdk/fastmcp-tools-function_tool.mdx b/docs/python-sdk/fastmcp-tools-function_tool.mdx index b2b7a73cc..5d16699b1 100644 --- a/docs/python-sdk/fastmcp-tools-function_tool.mdx +++ b/docs/python-sdk/fastmcp-tools-function_tool.mdx @@ -10,7 +10,7 @@ Standalone @tool decorator for FastMCP. ## Functions -### `tool` +### `tool` ```python tool(name_or_fn: str | Callable[..., Any] | None = None) -> Any @@ -57,7 +57,7 @@ individual parameters must not be passed. Cannot be used together with metadata parameter. -#### `run` +#### `run` ```python run(self, arguments: dict[str, Any]) -> ToolResult @@ -66,7 +66,7 @@ run(self, arguments: dict[str, Any]) -> ToolResult Run the tool with arguments. -#### `register_with_docket` +#### `register_with_docket` ```python register_with_docket(self, docket: Docket) -> None @@ -79,7 +79,7 @@ dependencies — both FastMCP's (CurrentContext, Progress) and Docket-native ones (Retry, Timeout, ConcurrencyLimit). -#### `add_to_docket` +#### `add_to_docket` ```python add_to_docket(self, docket: Docket, arguments: dict[str, Any], **kwargs: Any) -> Execution diff --git a/docs/python-sdk/fastmcp-tools-tool_transform.mdx b/docs/python-sdk/fastmcp-tools-tool_transform.mdx index 24f6270aa..9ba17c0e6 100644 --- a/docs/python-sdk/fastmcp-tools-tool_transform.mdx +++ b/docs/python-sdk/fastmcp-tools-tool_transform.mdx @@ -7,7 +7,7 @@ sidebarTitle: tool_transform ## Functions -### `forward` +### `forward` ```python forward(**kwargs: Any) -> ToolResult @@ -36,7 +36,7 @@ tool has args `a` and `b`, and an `transform_args` was provided that maps `x` to - `TypeError`: If provided arguments don't match the transformed schema. -### `forward_raw` +### `forward_raw` ```python forward_raw(**kwargs: Any) -> ToolResult @@ -62,7 +62,7 @@ y=2)` will call the parent tool with `x=1` and `y=2`. - `RuntimeError`: If called outside a transformed tool context. -### `apply_transformations_to_tools` +### `apply_transformations_to_tools` ```python apply_transformations_to_tools(tools: dict[str, Tool], transformations: dict[str, ToolTransformConfig]) -> dict[str, Tool] @@ -78,7 +78,7 @@ but transformations are keyed by tool name (e.g., "my_tool"). ## Classes -### `ArgTransform` +### `ArgTransform` Configuration for transforming a parent tool's argument. @@ -150,7 +150,7 @@ ArgTransform(name="new_name", description="New desc", default=None, type=int) ``` -### `ArgTransformConfig` +### `ArgTransformConfig` A model for requesting a single argument transform. @@ -158,7 +158,7 @@ A model for requesting a single argument transform. **Methods:** -#### `to_arg_transform` +#### `to_arg_transform` ```python to_arg_transform(self) -> ArgTransform @@ -167,7 +167,7 @@ to_arg_transform(self) -> ArgTransform Convert the argument transform to a FastMCP argument transform. -### `TransformedTool` +### `TransformedTool` A tool that is transformed from another tool. @@ -191,7 +191,7 @@ validation when forward() is called from custom functions. **Methods:** -#### `run` +#### `run` ```python run(self, arguments: dict[str, Any]) -> ToolResult @@ -210,7 +210,7 @@ functions. - ToolResult object containing content and optional structured output. -#### `from_tool` +#### `from_tool` ```python from_tool(cls, tool: Tool | Callable[..., Any], name: str | None = None, version: str | NotSetT | None = NotSet, title: str | NotSetT | None = NotSet, description: str | NotSetT | None = NotSet, tags: set[str] | None = None, transform_fn: Callable[..., Any] | None = None, transform_args: dict[str, ArgTransform] | None = None, annotations: ToolAnnotations | NotSetT | None = NotSet, output_schema: dict[str, Any] | NotSetT | None = NotSet, serializer: Callable[[Any], str] | NotSetT | None = NotSet, meta: dict[str, Any] | NotSetT | None = NotSet) -> TransformedTool @@ -227,17 +227,14 @@ argument names. - `version`: New version for the tool. Defaults to parent tool's version. - `title`: New title for the tool. Defaults to parent tool's title. - `transform_args`: Optional transformations for parent tool arguments. -Only specified arguments are transformed, others pass through unchanged\: -- Simple rename (str) -- Complex transformation (rename/description/default/drop) (ArgTransform) -- Drop the argument (None) +Only specified arguments are transformed, others pass through unchanged. +Use ArgTransform for rename, description, default, or hide operations. - `description`: New description. Defaults to parent's description. - `tags`: New tags. Defaults to parent's tags. - `annotations`: New annotations. Defaults to parent's annotations. - `output_schema`: Control output schema for structured outputs\: - None (default)\: Inherit from transform_fn if available, then parent tool - dict\: Use custom output schema -- False\: Disable output schema and structured outputs - `serializer`: Deprecated. Return ToolResult from your tools for full control over serialization. - `meta`: Control meta information\: - NotSet (default)\: Inherit from parent tool @@ -293,7 +290,7 @@ async def custom_output(**kwargs) -> ToolResult: ``` -### `ToolTransformConfig` +### `ToolTransformConfig` Provides a way to transform a tool. @@ -301,7 +298,7 @@ Provides a way to transform a tool. **Methods:** -#### `apply` +#### `apply` ```python apply(self, tool: Tool) -> TransformedTool diff --git a/docs/python-sdk/fastmcp-utilities-docstring_parsing.mdx b/docs/python-sdk/fastmcp-utilities-docstring_parsing.mdx new file mode 100644 index 000000000..c3fff9eea --- /dev/null +++ b/docs/python-sdk/fastmcp-utilities-docstring_parsing.mdx @@ -0,0 +1,39 @@ +--- +title: docstring_parsing +sidebarTitle: docstring_parsing +--- + +# `fastmcp.utilities.docstring_parsing` + + +Extract descriptions from function docstrings. + +Uses griffelib to parse Google, NumPy, and Sphinx-style docstrings. The +interface is intentionally narrow — a single function returning a +`ParsedDocstring` — so the implementation can be swapped without touching +callers. + + +## Functions + +### `parse_docstring` + +```python +parse_docstring(fn: Callable[..., Any]) -> ParsedDocstring +``` + + +Parse a function's docstring into a summary and parameter descriptions. + +Tries Google, NumPy, and Sphinx parsers in order, using the first one that +successfully extracts parameter descriptions. If none do, returns the full +docstring as the description with no parameter descriptions. + + +## Classes + +### `ParsedDocstring` + + +The extracted description and per-parameter descriptions from a docstring. + diff --git a/docs/python-sdk/fastmcp-utilities-json_schema_type.mdx b/docs/python-sdk/fastmcp-utilities-json_schema_type.mdx index 44fb295e5..ca7e64853 100644 --- a/docs/python-sdk/fastmcp-utilities-json_schema_type.mdx +++ b/docs/python-sdk/fastmcp-utilities-json_schema_type.mdx @@ -42,17 +42,18 @@ Example: ## Functions -### `json_schema_to_type` +### `json_schema_to_type` ```python -json_schema_to_type(schema: Mapping[str, Any], name: str | None = None) -> type +json_schema_to_type(schema: Mapping[str, Any] | bool, name: str | None = None) -> type ``` Convert JSON schema to appropriate Python type with validation. **Args:** -- `schema`: A JSON Schema dictionary defining the type structure and validation rules +- `schema`: A JSON Schema dictionary defining the type structure and validation rules. +Boolean schemas are also accepted (``True`` = any type, ``False`` = unsatisfiable). - `name`: Optional name for object schemas. Only allowed when schema type is "object". If not provided for objects, name will be inferred from schema's "title" property or default to "Root". @@ -107,4 +108,4 @@ class Name: ## Classes -### `JSONSchema` +### `JSONSchema` diff --git a/docs/python-sdk/fastmcp-utilities-openapi-schemas.mdx b/docs/python-sdk/fastmcp-utilities-openapi-schemas.mdx index b69791d74..47ee1e699 100644 --- a/docs/python-sdk/fastmcp-utilities-openapi-schemas.mdx +++ b/docs/python-sdk/fastmcp-utilities-openapi-schemas.mdx @@ -20,7 +20,7 @@ clean_schema_for_display(schema: JsonSchema | None) -> JsonSchema | None Clean up a schema dictionary for display by removing internal/complex fields. -### `extract_output_schema_from_responses` +### `extract_output_schema_from_responses` ```python extract_output_schema_from_responses(responses: dict[str, ResponseInfo], schema_definitions: dict[str, Any] | None = None, openapi_version: str | None = None) -> dict[str, Any] | None