diff --git a/docs/python-sdk-pages.json b/docs/python-sdk-pages.json
index 704b28e4f9..b16a3c2abf 100644
--- a/docs/python-sdk-pages.json
+++ b/docs/python-sdk-pages.json
@@ -1,5 +1,4 @@
[
- "python-sdk/fastmcp-apps",
"python-sdk/fastmcp-cli",
"python-sdk/fastmcp-client",
"python-sdk/fastmcp-decorators",
@@ -13,6 +12,19 @@
"python-sdk/fastmcp-telemetry",
"python-sdk/fastmcp-tools",
"python-sdk/fastmcp-types",
+ {
+ "group": "fastmcp.apps",
+ "pages": [
+ "python-sdk/fastmcp-apps-__init__",
+ "python-sdk/fastmcp-apps-app",
+ "python-sdk/fastmcp-apps-approval",
+ "python-sdk/fastmcp-apps-choice",
+ "python-sdk/fastmcp-apps-config",
+ "python-sdk/fastmcp-apps-file_upload",
+ "python-sdk/fastmcp-apps-form",
+ "python-sdk/fastmcp-apps-generative"
+ ]
+ },
{
"group": "fastmcp.experimental",
"pages": [
@@ -39,6 +51,7 @@
"python-sdk/fastmcp-utilities-__init__",
"python-sdk/fastmcp-utilities-async_utils",
"python-sdk/fastmcp-utilities-auth",
+ "python-sdk/fastmcp-utilities-authorization",
"python-sdk/fastmcp-utilities-cli",
"python-sdk/fastmcp-utilities-components",
"python-sdk/fastmcp-utilities-docstring_parsing",
@@ -82,6 +95,7 @@
"python-sdk/fastmcp-utilities-openapi",
"python-sdk/fastmcp-utilities-pagination",
"python-sdk/fastmcp-utilities-skills",
+ "python-sdk/fastmcp-utilities-tasks",
"python-sdk/fastmcp-utilities-tests",
"python-sdk/fastmcp-utilities-timeout",
"python-sdk/fastmcp-utilities-token_cache",
diff --git a/docs/python-sdk/fastmcp-apps.mdx b/docs/python-sdk/fastmcp-apps-__init__.mdx
similarity index 89%
rename from docs/python-sdk/fastmcp-apps.mdx
rename to docs/python-sdk/fastmcp-apps-__init__.mdx
index 58bd246561..5f69a4b594 100644
--- a/docs/python-sdk/fastmcp-apps.mdx
+++ b/docs/python-sdk/fastmcp-apps-__init__.mdx
@@ -1,6 +1,6 @@
---
-title: apps
-sidebarTitle: apps
+title: __init__
+sidebarTitle: __init__
---
# `fastmcp.apps`
diff --git a/docs/python-sdk/fastmcp-apps-app.mdx b/docs/python-sdk/fastmcp-apps-app.mdx
new file mode 100644
index 0000000000..4b10923094
--- /dev/null
+++ b/docs/python-sdk/fastmcp-apps-app.mdx
@@ -0,0 +1,146 @@
+---
+title: app
+sidebarTitle: app
+---
+
+# `fastmcp.apps.app`
+
+
+FastMCPApp — a Provider that represents a composable MCP application.
+
+FastMCPApp binds entry-point tools (model calls these) together with backend
+tools (the UI calls these via CallTool). Backend tools are tagged with
+``meta["fastmcp"]["app"]`` so they can be found through the provider chain
+even when transforms (namespace, visibility, etc.) have renamed or hidden
+them — the server sets a context var that tells ``Provider.get_tool`` to
+fall back to a direct lookup for app-visible tools.
+
+Usage::
+
+ from fastmcp import FastMCP, FastMCPApp
+
+ app = FastMCPApp("Dashboard")
+
+ @app.ui()
+ def show_dashboard() -> Component:
+ return Column(...)
+
+ @app.tool()
+ def save_contact(name: str, email: str) -> str:
+ return name
+
+ server = FastMCP("Platform")
+ server.add_provider(app)
+
+
+## Classes
+
+### `FastMCPApp`
+
+
+A Provider that represents an MCP application.
+
+Binds together entry-point tools (``@app.ui``), backend tools
+(``@app.tool``), and the Prefab renderer resource. Backend tools
+are tagged with ``meta["fastmcp"]["app"]`` so ``Provider.get_tool``
+can find them by original name even when transforms have been applied.
+
+
+**Methods:**
+
+#### `tool`
+
+```python
+tool(self, name_or_fn: F) -> F
+```
+
+#### `tool`
+
+```python
+tool(self, name_or_fn: str | None = None) -> Callable[[F], F]
+```
+
+#### `tool`
+
+```python
+tool(self, name_or_fn: str | AnyFunction | None = None) -> Any
+```
+
+Register a backend tool that the UI calls via CallTool.
+
+Backend tools default to ``visibility=["app"]``. Pass ``model=True``
+to also expose the tool to the model (``visibility=["app", "model"]``).
+
+Supports multiple calling patterns::
+
+ @app.tool
+ def save(name: str): ...
+
+ @app.tool()
+ def save(name: str): ...
+
+ @app.tool("custom_name")
+ def save(name: str): ...
+
+
+#### `ui`
+
+```python
+ui(self, name_or_fn: F) -> F
+```
+
+#### `ui`
+
+```python
+ui(self, name_or_fn: str | None = None) -> Callable[[F], F]
+```
+
+#### `ui`
+
+```python
+ui(self, name_or_fn: str | AnyFunction | None = None) -> Any
+```
+
+Register a UI entry-point tool that the model calls.
+
+Entry-point tools default to ``visibility=["model"]`` and auto-wire
+the Prefab renderer resource and CSP. They are tagged with the app
+name so structured content includes ``_meta.fastmcp.app``.
+
+Supports multiple calling patterns::
+
+ @app.ui
+ def dashboard() -> Component: ...
+
+ @app.ui()
+ def dashboard() -> Component: ...
+
+ @app.ui("my_dashboard")
+ def dashboard() -> Component: ...
+
+
+#### `add_tool`
+
+```python
+add_tool(self, tool: Tool | Callable[..., Any]) -> Tool
+```
+
+Add a tool to this app programmatically.
+
+The tool is tagged with this app's name for routing.
+
+
+#### `lifespan`
+
+```python
+lifespan(self) -> AsyncIterator[None]
+```
+
+#### `run`
+
+```python
+run(self, transport: Literal['stdio', 'http', 'sse', 'streamable-http'] | None = None, **kwargs: Any) -> None
+```
+
+Create a temporary FastMCP server and run this app standalone.
+
diff --git a/docs/python-sdk/fastmcp-apps-approval.mdx b/docs/python-sdk/fastmcp-apps-approval.mdx
new file mode 100644
index 0000000000..81285a76d7
--- /dev/null
+++ b/docs/python-sdk/fastmcp-apps-approval.mdx
@@ -0,0 +1,58 @@
+---
+title: approval
+sidebarTitle: approval
+---
+
+# `fastmcp.apps.approval`
+
+
+Approval — a Provider that adds human-in-the-loop approval to any server.
+
+The LLM presents a summary of what it's about to do, and the user
+approves or rejects via buttons. The result is sent back into the
+conversation as a message, prompting the LLM's next turn.
+
+Requires ``fastmcp[apps]`` (prefab-ui).
+
+Usage::
+
+ from fastmcp import FastMCP
+ from fastmcp.apps.approval import Approval
+
+ mcp = FastMCP("My Server")
+ mcp.add_provider(Approval())
+
+
+## Classes
+
+### `Approval`
+
+
+A Provider that adds human-in-the-loop approval to a server.
+
+The LLM calls the ``request_approval`` tool with a summary and
+optional details. The user sees an approval card with Approve and
+Reject buttons. Clicking either sends a message back into the
+conversation (via ``SendMessage``), triggering the LLM's next turn.
+
+The message appears as if the user sent it, so the LLM sees
+something like ``'"Deploy v3.2 to production" is APPROVED'``.
+
+Example::
+
+ from fastmcp import FastMCP
+ from fastmcp.apps.approval import Approval
+
+ mcp = FastMCP("My Server")
+ mcp.add_provider(Approval())
+
+Customized::
+
+ Approval(
+ title="Deploy Gate",
+ approve_text="Ship it",
+ approve_variant="default",
+ reject_text="Abort",
+ reject_variant="destructive",
+ )
+
diff --git a/docs/python-sdk/fastmcp-apps-choice.mdx b/docs/python-sdk/fastmcp-apps-choice.mdx
new file mode 100644
index 0000000000..8b7572622d
--- /dev/null
+++ b/docs/python-sdk/fastmcp-apps-choice.mdx
@@ -0,0 +1,44 @@
+---
+title: choice
+sidebarTitle: choice
+---
+
+# `fastmcp.apps.choice`
+
+
+Choice — a Provider that lets the user pick from a set of options.
+
+The LLM presents options, the user clicks one, and the selection
+flows back into the conversation as a message.
+
+Requires ``fastmcp[apps]`` (prefab-ui).
+
+Usage::
+
+ from fastmcp import FastMCP
+ from fastmcp.apps.choice import Choice
+
+ mcp = FastMCP("My Server")
+ mcp.add_provider(Choice())
+
+
+## Classes
+
+### `Choice`
+
+
+A Provider that lets the user choose from a set of options.
+
+The LLM calls ``choose`` with a prompt and a list of options.
+The user sees a card with one button per option. Clicking a button
+sends the selection back into the conversation via ``SendMessage``,
+triggering the LLM's next turn.
+
+Example::
+
+ from fastmcp import FastMCP
+ from fastmcp.apps.choice import Choice
+
+ mcp = FastMCP("My Server")
+ mcp.add_provider(Choice())
+
diff --git a/docs/python-sdk/fastmcp-apps-config.mdx b/docs/python-sdk/fastmcp-apps-config.mdx
new file mode 100644
index 0000000000..74828bbdd5
--- /dev/null
+++ b/docs/python-sdk/fastmcp-apps-config.mdx
@@ -0,0 +1,90 @@
+---
+title: config
+sidebarTitle: config
+---
+
+# `fastmcp.apps.config`
+
+
+MCP Apps support — extension negotiation and typed UI metadata models.
+
+Provides constants and Pydantic models for the MCP Apps extension
+(io.modelcontextprotocol/ui), enabling tools and resources to carry
+UI metadata for clients that support interactive app rendering.
+
+
+## Functions
+
+### `app_config_to_meta_dict`
+
+```python
+app_config_to_meta_dict(app: AppConfig | dict[str, Any]) -> dict[str, Any]
+```
+
+
+Convert an AppConfig or dict to the wire-format dict for ``meta["ui"]``.
+
+
+## Classes
+
+### `ResourceCSP`
+
+
+Content Security Policy for MCP App resources.
+
+Declares which external origins the app is allowed to connect to or
+load resources from. Hosts use these declarations to build the
+``Content-Security-Policy`` header for the sandboxed iframe.
+
+
+### `ResourcePermissions`
+
+
+Iframe sandbox permissions for MCP App resources.
+
+Each field, when set (typically to ``{}``), requests that the host
+grant the corresponding Permission Policy feature to the sandboxed
+iframe. Hosts MAY honour these; apps should use JS feature detection
+as a fallback.
+
+
+### `AppConfig`
+
+
+Configuration for MCP App tools and resources.
+
+Controls how a tool or resource participates in the MCP Apps extension.
+On tools, ``resource_uri`` and ``visibility`` specify which UI resource
+to render and where the tool appears. On resources, those fields must
+be left unset (the resource itself is the UI).
+
+All fields use ``exclude_none`` serialization so only explicitly-set
+values appear on the wire. Aliases match the MCP Apps wire format
+(camelCase).
+
+
+### `PrefabAppConfig`
+
+
+App configuration for Prefab tools with sensible defaults.
+
+Like ``app=True`` but customizable. Auto-wires the Prefab renderer
+URI and merges the renderer's CSP with any additional domains you
+specify. The renderer resource is registered automatically.
+
+Example::
+
+ @mcp.tool(app=PrefabAppConfig()) # same as app=True
+
+ @mcp.tool(app=PrefabAppConfig(
+ csp=ResourceCSP(frame_domains=["https://example.com"]),
+ ))
+
+
+**Methods:**
+
+#### `model_post_init`
+
+```python
+model_post_init(self, __context: Any) -> None
+```
diff --git a/docs/python-sdk/fastmcp-apps-file_upload.mdx b/docs/python-sdk/fastmcp-apps-file_upload.mdx
new file mode 100644
index 0000000000..878cbae32b
--- /dev/null
+++ b/docs/python-sdk/fastmcp-apps-file_upload.mdx
@@ -0,0 +1,144 @@
+---
+title: file_upload
+sidebarTitle: file_upload
+---
+
+# `fastmcp.apps.file_upload`
+
+
+FileUpload — a Provider that adds drag-and-drop file upload to any server.
+
+Lets users upload files directly to the server through an interactive UI,
+bypassing the LLM context window entirely. The LLM can then read and work
+with uploaded files through model-visible tools.
+
+Requires ``fastmcp[apps]`` (prefab-ui).
+
+Usage::
+
+ from fastmcp import FastMCP
+ from fastmcp.apps import FileUpload
+
+ mcp = FastMCP("My Server")
+ mcp.add_provider(FileUpload())
+
+For custom persistence, override the storage methods::
+
+ class S3Upload(FileUpload):
+ def on_store(self, files, ctx):
+ # write to S3, return summaries
+ ...
+
+ def on_list(self, ctx):
+ # list from S3
+ ...
+
+ def on_read(self, name, ctx):
+ # read from S3
+ ...
+
+
+## Classes
+
+### `FileUpload`
+
+
+A Provider that adds file upload capabilities to a server.
+
+Registers a drag-and-drop UI tool, a backend storage tool, and
+model-visible tools for listing and reading uploaded files.
+
+Files are scoped by MCP session and stored in memory by default.
+Override ``on_store``, ``on_list``, and ``on_read`` for custom
+persistence (filesystem, S3, database, etc.). Each method receives
+the current ``Context``, giving access to session ID, auth tokens,
+and request metadata for partitioning and authorization.
+
+**Session scoping:** The default storage uses ``ctx.session_id`` to
+isolate files by session. This works with stdio, SSE, and stateful
+HTTP transports. In **stateless HTTP** mode, each request creates a
+new session, so files won't persist across requests. For stateless
+deployments, override the storage methods to partition by a stable
+identifier from the auth context::
+
+ class UserScopedUpload(FileUpload):
+ def on_store(self, files, ctx):
+ user_id = ctx.access_token["sub"]
+ ...
+
+Example::
+
+ from fastmcp import FastMCP
+ from fastmcp.apps.file_upload import FileUpload
+
+ mcp = FastMCP("My Server")
+ mcp.add_provider(FileUpload())
+
+
+**Methods:**
+
+#### `on_store`
+
+```python
+on_store(self, files: list[dict[str, Any]], ctx: Context) -> list[dict[str, Any]]
+```
+
+Store uploaded files and return summaries.
+
+**Args:**
+- `files`: List of file dicts, each with ``name``, ``size``,
+``type``, and ``data`` (base64-encoded content).
+- `ctx`: The current request context. Use for session ID,
+auth tokens, or any metadata needed for partitioning.
+
+Override this method for custom persistence. The default
+implementation stores files in memory, scoped by
+``_get_scope_key(ctx)``.
+
+**Returns:**
+- List of file summary dicts (``name``, ``type``, ``size``,
+- ``size_display``, ``uploaded_at``).
+
+
+#### `on_list`
+
+```python
+on_list(self, ctx: Context) -> list[dict[str, Any]]
+```
+
+List all stored files.
+
+**Args:**
+- `ctx`: The current request context.
+
+Override this method for custom persistence. The default
+implementation returns files from the current scope.
+
+**Returns:**
+- List of file summary dicts.
+
+
+#### `on_read`
+
+```python
+on_read(self, name: str, ctx: Context) -> dict[str, Any]
+```
+
+Read a file's contents by name.
+
+**Args:**
+- `name`: The filename to read.
+- `ctx`: The current request context.
+
+Override this method for custom persistence. The default
+implementation reads from the current scope's in-memory store.
+Text files are decoded from base64; binary files return a
+truncated base64 preview.
+
+**Returns:**
+- Dict with file metadata and ``content`` (text) or
+- ``content_base64`` (binary preview).
+
+**Raises:**
+- `ValueError`: If the file is not found.
+
diff --git a/docs/python-sdk/fastmcp-apps-form.mdx b/docs/python-sdk/fastmcp-apps-form.mdx
new file mode 100644
index 0000000000..c99110c7b1
--- /dev/null
+++ b/docs/python-sdk/fastmcp-apps-form.mdx
@@ -0,0 +1,69 @@
+---
+title: form
+sidebarTitle: form
+---
+
+# `fastmcp.apps.form`
+
+
+FormInput — a Provider that collects structured input from the user.
+
+Define a Pydantic model for the data you need, and ``FormInput``
+generates a form UI. The user fills it out, the submission is
+validated, and an optional callback processes the result.
+
+Requires ``fastmcp[apps]`` (prefab-ui).
+
+Usage::
+
+ from pydantic import BaseModel
+ from fastmcp import FastMCP
+ from fastmcp.apps.form import FormInput
+
+ class ShippingAddress(BaseModel):
+ street: str
+ city: str
+ state: str
+ zip_code: str
+
+ mcp = FastMCP("My Server")
+ mcp.add_provider(FormInput(model=ShippingAddress))
+
+
+## Classes
+
+### `FormInput`
+
+
+A Provider that collects structured input via a Pydantic model.
+
+Define a model for the data you need, and ``FormInput`` generates
+a form from it using ``Form.from_model()``. Field types, labels,
+descriptions, and validation are all derived from the model.
+
+Optionally provide an ``on_submit`` callback to process the
+validated data. The callback receives a model instance and returns
+a string that goes back to the LLM. Without a callback, the
+validated JSON is sent directly.
+
+Example::
+
+ from pydantic import BaseModel
+ from fastmcp import FastMCP
+ from fastmcp.apps.form import FormInput
+
+ class Contact(BaseModel):
+ name: str
+ email: str
+
+ mcp = FastMCP("My Server")
+ mcp.add_provider(FormInput(model=Contact))
+
+With a callback::
+
+ def save_contact(contact: Contact) -> str:
+ db.insert(contact.model_dump())
+ return f"Saved {contact.name}"
+
+ mcp.add_provider(FormInput(model=Contact, on_submit=save_contact))
+
diff --git a/docs/python-sdk/fastmcp-apps-generative.mdx b/docs/python-sdk/fastmcp-apps-generative.mdx
new file mode 100644
index 0000000000..bb5756b966
--- /dev/null
+++ b/docs/python-sdk/fastmcp-apps-generative.mdx
@@ -0,0 +1,56 @@
+---
+title: generative
+sidebarTitle: generative
+---
+
+# `fastmcp.apps.generative`
+
+
+GenerativeUI — a Provider that adds LLM-generated UI capabilities.
+
+Registers tools and resources from ``prefab_ui.generative`` so that an
+LLM can write Prefab Python code, execute it in a sandbox, and render
+the result as a streaming interactive UI.
+
+Requires ``fastmcp[apps]`` (prefab-ui).
+
+Usage::
+
+ from fastmcp import FastMCP
+ from fastmcp.apps.generative import GenerativeUI
+
+ mcp = FastMCP("My Server")
+ mcp.add_provider(GenerativeUI())
+
+
+## Classes
+
+### `GenerativeUI`
+
+
+A Provider that adds generative UI capabilities to a server.
+
+Registers:
+
+- A ``generate_ui`` tool that accepts Prefab Python code, executes
+ it in a Pyodide sandbox, and returns the rendered PrefabApp.
+ Supports streaming via ``ontoolinputpartial``.
+- A ``components`` tool that searches the Prefab component library.
+- The generative renderer resource with CSP for Pyodide CDN access.
+
+Example::
+
+ from fastmcp import FastMCP
+ from fastmcp.apps.generative import GenerativeUI
+
+ mcp = FastMCP("My Server")
+ mcp.add_provider(GenerativeUI())
+
+
+**Methods:**
+
+#### `lifespan`
+
+```python
+lifespan(self) -> AsyncIterator[None]
+```
diff --git a/docs/python-sdk/fastmcp-experimental-transforms-code_mode.mdx b/docs/python-sdk/fastmcp-experimental-transforms-code_mode.mdx
index ae98a1a4da..6d634b6ea1 100644
--- a/docs/python-sdk/fastmcp-experimental-transforms-code_mode.mdx
+++ b/docs/python-sdk/fastmcp-experimental-transforms-code_mode.mdx
@@ -7,7 +7,7 @@ sidebarTitle: code_mode
## Classes
-### `SandboxProvider`
+### `SandboxProvider`
Interface for executing LLM-generated Python code in a sandbox.
@@ -20,13 +20,13 @@ sandbox — never with plain ``exec()``. Use ``MontySandboxProvider``
**Methods:**
-#### `run`
+#### `run`
```python
run(self, code: str) -> Any
```
-### `MontySandboxProvider`
+### `MontySandboxProvider`
Sandbox provider backed by `pydantic-monty`.
@@ -38,16 +38,22 @@ Sandbox provider backed by `pydantic-monty`.
``gc_interval`` (int). All are optional; omit a key to
leave that limit uncapped.
+When the argument is omitted entirely, a conservative baseline
+is applied (``max_duration_secs=30``, ``max_memory=100 MB``) so
+the out-of-box configuration is not unbounded. Pass
+``limits=None`` to explicitly run without any limits, or a dict
+to set your own.
+
**Methods:**
-#### `run`
+#### `run`
```python
run(self, code: str) -> Any
```
-### `Search`
+### `Search`
Discovery tool factory that searches the catalog by query.
@@ -64,7 +70,7 @@ Defaults to BM25 ranking.
The LLM can override this per call. ``None`` means no limit.
-### `GetSchemas`
+### `GetSchemas`
Discovery tool factory that returns schemas for tools by name.
@@ -78,7 +84,7 @@ types, and required markers.
``"full"`` returns the complete JSON schema.
-### `GetTags`
+### `GetTags`
Discovery tool factory that lists tool tags from the catalog.
@@ -93,7 +99,7 @@ without tags appear under ``"untagged"``.
``"full"`` lists all tools under each tag.
-### `ListTools`
+### `ListTools`
Discovery tool factory that lists all tools in the catalog.
@@ -106,7 +112,7 @@ Discovery tool factory that lists all tools in the catalog.
``"full"`` returns the complete JSON schema.
-### `CodeMode`
+### `CodeMode`
Transform that collapses all tools into discovery + execute meta-tools.
@@ -123,13 +129,13 @@ environment with ``call_tool(name, params)`` in scope.
**Methods:**
-#### `transform_tools`
+#### `transform_tools`
```python
transform_tools(self, tools: Sequence[Tool]) -> Sequence[Tool]
```
-#### `get_tool`
+#### `get_tool`
```python
get_tool(self, name: str, call_next: GetToolNext) -> Tool | None
diff --git a/docs/python-sdk/fastmcp-mcp_config.mdx b/docs/python-sdk/fastmcp-mcp_config.mdx
index 8d0c4a83e8..0302d92707 100644
--- a/docs/python-sdk/fastmcp-mcp_config.mdx
+++ b/docs/python-sdk/fastmcp-mcp_config.mdx
@@ -42,7 +42,7 @@ infer_transport_type_from_url(url: str | AnyUrl) -> Literal['http', 'sse']
Infer the appropriate transport type from the given URL.
-### `update_config_file`
+### `update_config_file`
```python
update_config_file(file_path: Path, server_name: str, server_config: CanonicalMCPServerTypes) -> None
@@ -167,7 +167,7 @@ from_file(cls, file_path: Path) -> Self
Load configuration from JSON file.
-### `CanonicalMCPConfig`
+### `CanonicalMCPConfig`
Canonical MCP configuration format.
@@ -178,7 +178,7 @@ The format is designed to be client-agnostic and extensible for future use cases
**Methods:**
-#### `add_server`
+#### `add_server`
```python
add_server(self, name: str, server: CanonicalMCPServerTypes) -> None
diff --git a/docs/python-sdk/fastmcp-utilities-authorization.mdx b/docs/python-sdk/fastmcp-utilities-authorization.mdx
new file mode 100644
index 0000000000..f70c442831
--- /dev/null
+++ b/docs/python-sdk/fastmcp-utilities-authorization.mdx
@@ -0,0 +1,70 @@
+---
+title: authorization
+sidebarTitle: authorization
+---
+
+# `fastmcp.utilities.authorization`
+
+
+Authorization checks for FastMCP components.
+
+Auth checks are callables that receive an ``AuthContext`` and return True to
+allow access or False to deny it. They can also raise ``AuthorizationError`` to
+deny with a custom message; other exceptions are masked and treated as denial.
+
+
+## Functions
+
+### `require_scopes`
+
+```python
+require_scopes(*scopes: str) -> AuthCheck
+```
+
+
+Require all of the given OAuth scopes.
+
+
+### `restrict_tag`
+
+```python
+restrict_tag(tag: str) -> AuthCheck
+```
+
+
+Require scopes when the accessed component has a specific tag.
+
+
+### `run_auth_checks`
+
+```python
+run_auth_checks(checks: AuthCheck | list[AuthCheck], ctx: AuthContext) -> bool
+```
+
+
+Run auth checks with AND logic.
+
+
+## Classes
+
+### `AuthContext`
+
+
+Context passed to auth check callables.
+
+**Attributes:**
+- `token`: The current access token, or None if unauthenticated.
+- `component`: The tool, resource, resource template, or prompt being accessed.
+- `tool`: Backwards-compatible alias for component when it is a Tool.
+
+
+**Methods:**
+
+#### `tool`
+
+```python
+tool(self) -> Tool | None
+```
+
+Backwards-compatible access to the component as a Tool.
+
diff --git a/docs/python-sdk/fastmcp-utilities-json_schema.mdx b/docs/python-sdk/fastmcp-utilities-json_schema.mdx
index 53655abd49..ca24bc283c 100644
--- a/docs/python-sdk/fastmcp-utilities-json_schema.mdx
+++ b/docs/python-sdk/fastmcp-utilities-json_schema.mdx
@@ -62,7 +62,7 @@ the referenced definition while preserving $defs for nested references.
- if no resolution is needed
-### `compress_schema`
+### `compress_schema`
```python
compress_schema(schema: dict[str, Any], prune_params: list[str] | None = None, prune_additional_properties: bool = False, prune_titles: bool = False, dereference: bool = False) -> dict[str, Any]
diff --git a/docs/python-sdk/fastmcp-utilities-tasks.mdx b/docs/python-sdk/fastmcp-utilities-tasks.mdx
new file mode 100644
index 0000000000..ed455626eb
--- /dev/null
+++ b/docs/python-sdk/fastmcp-utilities-tasks.mdx
@@ -0,0 +1,62 @@
+---
+title: tasks
+sidebarTitle: tasks
+---
+
+# `fastmcp.utilities.tasks`
+
+
+Task configuration primitives for FastMCP components.
+
+## Classes
+
+### `TaskMeta`
+
+
+Metadata for task-augmented execution requests.
+
+**Attributes:**
+- `ttl`: Client-requested TTL in milliseconds. If None, uses server default.
+- `fn_key`: Docket routing key. Auto-derived from component name if None.
+
+
+### `TaskConfig`
+
+
+Configuration for MCP background task execution.
+
+Controls how a component handles task-augmented requests:
+
+- ``forbidden``: Component does not support task execution.
+- ``optional``: Component supports both synchronous and task execution.
+- ``required``: Component requires task execution.
+
+
+**Methods:**
+
+#### `from_bool`
+
+```python
+from_bool(cls, value: bool) -> TaskConfig
+```
+
+Convert a boolean task flag to a TaskConfig.
+
+
+#### `supports_tasks`
+
+```python
+supports_tasks(self) -> bool
+```
+
+Check if this component supports task execution.
+
+
+#### `validate_function`
+
+```python
+validate_function(self, fn: Callable[..., Any], name: str) -> None
+```
+
+Validate that a function is compatible with this task config.
+
diff --git a/docs/python-sdk/fastmcp-utilities-versions.mdx b/docs/python-sdk/fastmcp-utilities-versions.mdx
index 0e390aef90..1eaa6391ac 100644
--- a/docs/python-sdk/fastmcp-utilities-versions.mdx
+++ b/docs/python-sdk/fastmcp-utilities-versions.mdx
@@ -22,7 +22,7 @@ Examples:
## Functions
-### `parse_version_key`
+### `parse_version_key`
```python
parse_version_key(version: str | None) -> VersionKey
@@ -38,10 +38,10 @@ Parse a version string into a sortable key.
- A VersionKey suitable for sorting.
-### `version_sort_key`
+### `version_sort_key`
```python
-version_sort_key(component: FastMCPComponent) -> VersionKey
+version_sort_key(component: FastMCPComponent) -> tuple[VersionKey, str]
```
@@ -49,14 +49,22 @@ Get a sort key for a component based on its version.
Use with sorted() or max() to order components by version.
+The key is a `(VersionKey, raw)` tuple. The `VersionKey` orders by PEP 440
+semantics (or lexicographically for non-PEP 440 strings); the raw version
+string is a deterministic tie-breaker so that two components whose versions
+are PEP 440-equivalent but spelled differently (e.g. `"1"` and `"1.0"`) are
+ordered reproducibly instead of by registration order. The raw tie-breaker
+only affects equivalent-version ties and never the primary version order,
+so range/equality matching (which uses `VersionKey` directly) is unchanged.
+
**Args:**
- `component`: The component to get a sort key for.
**Returns:**
-- A sortable VersionKey.
+- A deterministic, sortable `(VersionKey, raw)` tuple.
-### `compare_versions`
+### `compare_versions`
```python
compare_versions(a: str | None, b: str | None) -> int
@@ -73,7 +81,7 @@ Compare two version strings.
- -1 if a < b, 0 if a == b, 1 if a > b.
-### `is_version_greater`
+### `is_version_greater`
```python
is_version_greater(a: str | None, b: str | None) -> bool
@@ -90,7 +98,7 @@ Check if version a is greater than version b.
- True if a > b, False otherwise.
-### `max_version`
+### `max_version`
```python
max_version(a: str | None, b: str | None) -> str | None
@@ -107,7 +115,7 @@ Return the greater of two versions.
- The greater version, or None if both are None.
-### `min_version`
+### `min_version`
```python
min_version(a: str | None, b: str | None) -> str | None
@@ -124,7 +132,7 @@ Return the lesser of two versions.
- The lesser version, or None if both are None.
-### `dedupe_with_versions`
+### `dedupe_with_versions`
```python
dedupe_with_versions(components: Sequence[C], key_fn: Callable[[C], str]) -> list[C]
@@ -159,11 +167,18 @@ match any spec.
- `gte`: If set, only versions >= this value match.
- `lt`: If set, only versions < this value match.
- `eq`: If set, only this exact version matches (gte/lt ignored).
+Matching is PEP 440-normalized and `v`-prefix insensitive, so
+`eq="v1.0"` matches a component versioned `"1.0"`, and `eq="1.0"`
+matches `"1"` (PEP 440 treats `1` and `1.0` as the same version).
+If a server registers two PEP 440-equivalent spellings of the
+same component (e.g. both `"1"` and `"1.0"`), they are the same
+version under this spec; selection among them is deterministic
+(see `version_sort_key`), not registration-order dependent.
**Methods:**
-#### `matches`
+#### `matches`
```python
matches(self, version: str | None) -> bool
@@ -182,7 +197,7 @@ from version-specific rules.
- True if the version matches the spec.
-#### `intersect`
+#### `intersect`
```python
intersect(self, other: VersionSpec | None) -> VersionSpec
@@ -201,7 +216,7 @@ the intersection validates "1.0" is in range and returns the exact spec.
- A VersionSpec that matches only versions satisfying both specs.
-### `VersionKey`
+### `VersionKey`
A comparable version key that handles None, PEP 440 versions, and strings.