From 1700bc360bb37554f16168f0c6b981f84d4244a7 Mon Sep 17 00:00:00 2001
From: "marvin-context-protocol[bot]"
<225465937+marvin-context-protocol[bot]@users.noreply.github.com>
Date: Fri, 16 Jan 2026 21:28:11 -0500
Subject: [PATCH] chore: Update SDK documentation (#2834)
Co-authored-by: marvin-context-protocol[bot] <225465937+marvin-context-protocol[bot]@users.noreply.github.com>
---
docs/docs.json | 50 ++-
docs/python-sdk/fastmcp-cli-cli.mdx | 12 +-
docs/python-sdk/fastmcp-client-client.mdx | 88 ++---
docs/python-sdk/fastmcp-client-telemetry.mdx | 23 ++
docs/python-sdk/fastmcp-client-transports.mdx | 63 ++--
docs/python-sdk/fastmcp-decorators.mdx | 39 +++
docs/python-sdk/fastmcp-dependencies.mdx | 4 +
docs/python-sdk/fastmcp-exceptions.mdx | 6 +
docs/python-sdk/fastmcp-fs-__init__.mdx | 43 ---
docs/python-sdk/fastmcp-fs-decorators.mdx | 156 ---------
docs/python-sdk/fastmcp-fs-provider.mdx | 111 ------
docs/python-sdk/fastmcp-mcp_config.mdx | 32 +-
.../fastmcp-prompts-function_prompt.mdx | 106 ++++++
docs/python-sdk/fastmcp-prompts-prompt.mdx | 85 +----
.../fastmcp-resources-function_resource.mdx | 93 +++++
.../python-sdk/fastmcp-resources-resource.mdx | 75 +---
.../python-sdk/fastmcp-resources-template.mdx | 52 +--
.../fastmcp-server-auth-authorization.mdx | 139 ++++++++
...cp-server-auth-providers-introspection.mdx | 14 +-
docs/python-sdk/fastmcp-server-context.mdx | 143 +++++---
.../fastmcp-server-dependencies.mdx | 321 +++++++++++++-----
.../python-sdk/fastmcp-server-elicitation.mdx | 6 +-
docs/python-sdk/fastmcp-server-http.mdx | 18 +-
docs/python-sdk/fastmcp-server-low_level.mdx | 19 +-
...astmcp-server-middleware-authorization.mdx | 116 +++++++
.../fastmcp-server-middleware-ping.mdx | 32 ++
.../fastmcp-server-providers-aggregate.mdx | 139 ++++++++
.../fastmcp-server-providers-base.mdx | 137 ++++----
...tmcp-server-providers-fastmcp_provider.mdx | 118 ++++---
.../fastmcp-server-providers-filesystem.mdx | 128 +++++++
...server-providers-filesystem_discovery.mdx} | 29 +-
...astmcp-server-providers-local_provider.mdx | 189 ++++++-----
...tmcp-server-providers-openapi-provider.mdx | 24 +-
.../fastmcp-server-providers-proxy.mdx | 88 +++--
.../fastmcp-server-providers-transforming.mdx | 117 -------
docs/python-sdk/fastmcp-server-server.mdx | 287 +++++++++-------
.../fastmcp-server-tasks-capabilities.mdx | 15 +-
.../fastmcp-server-tasks-config.mdx | 19 +-
.../fastmcp-server-tasks-requests.mdx | 10 +-
.../fastmcp-server-tasks-subscriptions.mdx | 4 +-
docs/python-sdk/fastmcp-server-telemetry.mdx | 56 +++
.../fastmcp-server-transforms-__init__.mdx | 196 +++++++++++
.../fastmcp-server-transforms-namespace.mdx | 96 ++++++
...stmcp-server-transforms-tool_transform.mdx | 40 +++
...stmcp-server-transforms-version_filter.mdx | 85 +++++
.../fastmcp-server-transforms-visibility.mdx | 158 +++++++++
docs/python-sdk/fastmcp-telemetry.mdx | 95 ++++++
.../fastmcp-tools-function_parsing.mdx | 21 ++
.../fastmcp-tools-function_tool.mdx | 108 ++++++
docs/python-sdk/fastmcp-tools-tool.mdx | 95 +-----
.../fastmcp-tools-tool_transform.mdx | 25 +-
.../fastmcp-utilities-async_utils.mdx | 15 +-
docs/python-sdk/fastmcp-utilities-cli.mdx | 6 +-
.../fastmcp-utilities-components.mdx | 35 +-
.../fastmcp-utilities-json_schema_type.mdx | 4 +-
docs/python-sdk/fastmcp-utilities-logging.mdx | 2 +-
.../fastmcp-utilities-version_check.mdx | 40 +++
.../python-sdk/fastmcp-utilities-versions.mdx | 190 +++++++++++
.../fastmcp-utilities-visibility.mdx | 86 -----
59 files changed, 3060 insertions(+), 1443 deletions(-)
create mode 100644 docs/python-sdk/fastmcp-client-telemetry.mdx
create mode 100644 docs/python-sdk/fastmcp-decorators.mdx
delete mode 100644 docs/python-sdk/fastmcp-fs-__init__.mdx
delete mode 100644 docs/python-sdk/fastmcp-fs-decorators.mdx
delete mode 100644 docs/python-sdk/fastmcp-fs-provider.mdx
create mode 100644 docs/python-sdk/fastmcp-prompts-function_prompt.mdx
create mode 100644 docs/python-sdk/fastmcp-resources-function_resource.mdx
create mode 100644 docs/python-sdk/fastmcp-server-auth-authorization.mdx
create mode 100644 docs/python-sdk/fastmcp-server-middleware-authorization.mdx
create mode 100644 docs/python-sdk/fastmcp-server-middleware-ping.mdx
create mode 100644 docs/python-sdk/fastmcp-server-providers-aggregate.mdx
create mode 100644 docs/python-sdk/fastmcp-server-providers-filesystem.mdx
rename docs/python-sdk/{fastmcp-fs-discovery.mdx => fastmcp-server-providers-filesystem_discovery.mdx} (55%)
delete mode 100644 docs/python-sdk/fastmcp-server-providers-transforming.mdx
create mode 100644 docs/python-sdk/fastmcp-server-telemetry.mdx
create mode 100644 docs/python-sdk/fastmcp-server-transforms-__init__.mdx
create mode 100644 docs/python-sdk/fastmcp-server-transforms-namespace.mdx
create mode 100644 docs/python-sdk/fastmcp-server-transforms-tool_transform.mdx
create mode 100644 docs/python-sdk/fastmcp-server-transforms-version_filter.mdx
create mode 100644 docs/python-sdk/fastmcp-server-transforms-visibility.mdx
create mode 100644 docs/python-sdk/fastmcp-telemetry.mdx
create mode 100644 docs/python-sdk/fastmcp-tools-function_parsing.mdx
create mode 100644 docs/python-sdk/fastmcp-tools-function_tool.mdx
create mode 100644 docs/python-sdk/fastmcp-utilities-version_check.mdx
create mode 100644 docs/python-sdk/fastmcp-utilities-versions.mdx
delete mode 100644 docs/python-sdk/fastmcp-utilities-visibility.mdx
diff --git a/docs/docs.json b/docs/docs.json
index 5b1c59f23..f6b0649d1 100644
--- a/docs/docs.json
+++ b/docs/docs.json
@@ -20,7 +20,10 @@
"primary": "#2d00f7"
},
"contextual": {
- "options": ["copy", "view"]
+ "options": [
+ "copy",
+ "view"
+ ]
},
"description": "The fast, Pythonic way to build MCP servers and clients.",
"errors": {
@@ -163,7 +166,10 @@
{
"group": "Essentials",
"icon": "cube",
- "pages": ["clients/client", "clients/transports"]
+ "pages": [
+ "clients/client",
+ "clients/transports"
+ ]
},
{
"group": "Core Operations",
@@ -190,7 +196,10 @@
{
"group": "Authentication",
"icon": "user-shield",
- "pages": ["clients/auth/oauth", "clients/auth/bearer"]
+ "pages": [
+ "clients/auth/oauth",
+ "clients/auth/bearer"
+ ]
}
]
},
@@ -200,7 +209,10 @@
{
"group": "Providers",
"icon": "globe",
- "pages": ["integrations/fastapi", "integrations/openapi"]
+ "pages": [
+ "integrations/fastapi",
+ "integrations/openapi"
+ ]
},
{
"group": "Authentication",
@@ -279,10 +291,12 @@
"anchor": "Python SDK",
"icon": "python",
"pages": [
+ "python-sdk/fastmcp-decorators",
"python-sdk/fastmcp-dependencies",
"python-sdk/fastmcp-exceptions",
"python-sdk/fastmcp-mcp_config",
"python-sdk/fastmcp-settings",
+ "python-sdk/fastmcp-telemetry",
{
"group": "fastmcp.cli",
"pages": [
@@ -338,6 +352,7 @@
]
},
"python-sdk/fastmcp-client-tasks",
+ "python-sdk/fastmcp-client-telemetry",
"python-sdk/fastmcp-client-transports"
]
},
@@ -345,6 +360,7 @@
"group": "fastmcp.prompts",
"pages": [
"python-sdk/fastmcp-prompts-__init__",
+ "python-sdk/fastmcp-prompts-function_prompt",
"python-sdk/fastmcp-prompts-prompt"
]
},
@@ -352,6 +368,7 @@
"group": "fastmcp.resources",
"pages": [
"python-sdk/fastmcp-resources-__init__",
+ "python-sdk/fastmcp-resources-function_resource",
"python-sdk/fastmcp-resources-resource",
"python-sdk/fastmcp-resources-template",
"python-sdk/fastmcp-resources-types"
@@ -366,6 +383,7 @@
"pages": [
"python-sdk/fastmcp-server-auth-__init__",
"python-sdk/fastmcp-server-auth-auth",
+ "python-sdk/fastmcp-server-auth-authorization",
"python-sdk/fastmcp-server-auth-jwt_issuer",
"python-sdk/fastmcp-server-auth-middleware",
"python-sdk/fastmcp-server-auth-oauth_proxy",
@@ -405,10 +423,12 @@
"group": "middleware",
"pages": [
"python-sdk/fastmcp-server-middleware-__init__",
+ "python-sdk/fastmcp-server-middleware-authorization",
"python-sdk/fastmcp-server-middleware-caching",
"python-sdk/fastmcp-server-middleware-error_handling",
"python-sdk/fastmcp-server-middleware-logging",
"python-sdk/fastmcp-server-middleware-middleware",
+ "python-sdk/fastmcp-server-middleware-ping",
"python-sdk/fastmcp-server-middleware-rate_limiting",
"python-sdk/fastmcp-server-middleware-timing",
"python-sdk/fastmcp-server-middleware-tool_injection"
@@ -427,8 +447,11 @@
"group": "providers",
"pages": [
"python-sdk/fastmcp-server-providers-__init__",
+ "python-sdk/fastmcp-server-providers-aggregate",
"python-sdk/fastmcp-server-providers-base",
"python-sdk/fastmcp-server-providers-fastmcp_provider",
+ "python-sdk/fastmcp-server-providers-filesystem",
+ "python-sdk/fastmcp-server-providers-filesystem_discovery",
"python-sdk/fastmcp-server-providers-local_provider",
{
"group": "openapi",
@@ -439,8 +462,7 @@
"python-sdk/fastmcp-server-providers-openapi-routing"
]
},
- "python-sdk/fastmcp-server-providers-proxy",
- "python-sdk/fastmcp-server-providers-transforming"
+ "python-sdk/fastmcp-server-providers-proxy"
]
},
"python-sdk/fastmcp-server-proxy",
@@ -465,6 +487,17 @@
"python-sdk/fastmcp-server-tasks-routing",
"python-sdk/fastmcp-server-tasks-subscriptions"
]
+ },
+ "python-sdk/fastmcp-server-telemetry",
+ {
+ "group": "transforms",
+ "pages": [
+ "python-sdk/fastmcp-server-transforms-__init__",
+ "python-sdk/fastmcp-server-transforms-namespace",
+ "python-sdk/fastmcp-server-transforms-tool_transform",
+ "python-sdk/fastmcp-server-transforms-version_filter",
+ "python-sdk/fastmcp-server-transforms-visibility"
+ ]
}
]
},
@@ -472,6 +505,8 @@
"group": "fastmcp.tools",
"pages": [
"python-sdk/fastmcp-tools-__init__",
+ "python-sdk/fastmcp-tools-function_parsing",
+ "python-sdk/fastmcp-tools-function_tool",
"python-sdk/fastmcp-tools-tool",
"python-sdk/fastmcp-tools-tool_transform"
]
@@ -535,7 +570,8 @@
"python-sdk/fastmcp-utilities-tests",
"python-sdk/fastmcp-utilities-types",
"python-sdk/fastmcp-utilities-ui",
- "python-sdk/fastmcp-utilities-visibility"
+ "python-sdk/fastmcp-utilities-version_check",
+ "python-sdk/fastmcp-utilities-versions"
]
}
]
diff --git a/docs/python-sdk/fastmcp-cli-cli.mdx b/docs/python-sdk/fastmcp-cli-cli.mdx
index cb0c4be1b..759a4324d 100644
--- a/docs/python-sdk/fastmcp-cli-cli.mdx
+++ b/docs/python-sdk/fastmcp-cli-cli.mdx
@@ -10,7 +10,7 @@ FastMCP CLI tools using Cyclopts.
## Functions
-### `with_argv`
+### `with_argv`
```python
with_argv(args: list[str] | None)
@@ -27,7 +27,7 @@ Args are provided without the script name, so we preserve sys.argv[0]
and replace the rest.
-### `version`
+### `version`
```python
version()
@@ -37,7 +37,7 @@ version()
Display version information and platform details.
-### `dev`
+### `dev`
```python
dev(server_spec: str | None = None) -> None
@@ -50,7 +50,7 @@ Run an MCP server with the MCP Inspector for development.
- `server_spec`: Python file to run, optionally with \:object suffix, or None to auto-detect fastmcp.json
-### `run`
+### `run`
```python
run(server_spec: str | None = None, *server_args: str) -> None
@@ -74,7 +74,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
@@ -105,7 +105,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-client-client.mdx b/docs/python-sdk/fastmcp-client-client.mdx
index a638d3940..9bdf9108a 100644
--- a/docs/python-sdk/fastmcp-client-client.mdx
+++ b/docs/python-sdk/fastmcp-client-client.mdx
@@ -7,7 +7,7 @@ sidebarTitle: client
## Classes
-### `ClientSessionState`
+### `ClientSessionState`
Holds all session-related state for a Client instance.
@@ -16,13 +16,13 @@ This allows clean separation of configuration (which is copied) from
session state (which should be fresh for each new client instance).
-### `CallToolResult`
+### `CallToolResult`
Parsed result from a tool call.
-### `Client`
+### `Client`
MCP client that delegates connection management to a Transport instance.
@@ -85,7 +85,7 @@ async with client:
**Methods:**
-#### `session`
+#### `session`
```python
session(self) -> ClientSession
@@ -94,7 +94,7 @@ session(self) -> ClientSession
Get the current active session. Raises RuntimeError if not connected.
-#### `initialize_result`
+#### `initialize_result`
```python
initialize_result(self) -> mcp.types.InitializeResult | None
@@ -103,7 +103,7 @@ initialize_result(self) -> mcp.types.InitializeResult | None
Get the result of the initialization request.
-#### `set_roots`
+#### `set_roots`
```python
set_roots(self, roots: RootsList | RootsHandler) -> None
@@ -112,7 +112,7 @@ set_roots(self, roots: RootsList | RootsHandler) -> None
Set the roots for the client. This does not automatically call `send_roots_list_changed`.
-#### `set_sampling_callback`
+#### `set_sampling_callback`
```python
set_sampling_callback(self, sampling_callback: SamplingHandler, sampling_capabilities: mcp.types.SamplingCapability | None = None) -> None
@@ -121,7 +121,7 @@ set_sampling_callback(self, sampling_callback: SamplingHandler, sampling_capabil
Set the sampling callback for the client.
-#### `set_elicitation_callback`
+#### `set_elicitation_callback`
```python
set_elicitation_callback(self, elicitation_callback: ElicitationHandler) -> None
@@ -130,7 +130,7 @@ set_elicitation_callback(self, elicitation_callback: ElicitationHandler) -> None
Set the elicitation callback for the client.
-#### `is_connected`
+#### `is_connected`
```python
is_connected(self) -> bool
@@ -139,7 +139,7 @@ is_connected(self) -> bool
Check if the client is currently connected.
-#### `new`
+#### `new`
```python
new(self) -> Client[ClientTransportT]
@@ -155,7 +155,7 @@ share state with the original client.
- A new Client instance with the same configuration but disconnected state.
-#### `initialize`
+#### `initialize`
```python
initialize(self, timeout: datetime.timedelta | float | int | None = None) -> mcp.types.InitializeResult
@@ -183,13 +183,13 @@ capabilities, protocol version, and optional instructions.
- `RuntimeError`: If the client is not connected or initialization times out.
-#### `close`
+#### `close`
```python
close(self)
```
-#### `ping`
+#### `ping`
```python
ping(self) -> bool
@@ -198,7 +198,7 @@ ping(self) -> bool
Send a ping request.
-#### `cancel`
+#### `cancel`
```python
cancel(self, request_id: str | int, reason: str | None = None) -> None
@@ -207,7 +207,7 @@ cancel(self, request_id: str | int, reason: str | None = None) -> None
Send a cancellation notification for an in-progress request.
-#### `progress`
+#### `progress`
```python
progress(self, progress_token: str | int, progress: float, total: float | None = None, message: str | None = None) -> None
@@ -216,7 +216,7 @@ progress(self, progress_token: str | int, progress: float, total: float | None =
Send a progress notification.
-#### `set_logging_level`
+#### `set_logging_level`
```python
set_logging_level(self, level: mcp.types.LoggingLevel) -> None
@@ -225,7 +225,7 @@ set_logging_level(self, level: mcp.types.LoggingLevel) -> None
Send a logging/setLevel request.
-#### `send_roots_list_changed`
+#### `send_roots_list_changed`
```python
send_roots_list_changed(self) -> None
@@ -234,7 +234,7 @@ send_roots_list_changed(self) -> None
Send a roots/list_changed notification.
-#### `list_resources_mcp`
+#### `list_resources_mcp`
```python
list_resources_mcp(self) -> mcp.types.ListResourcesResult
@@ -251,7 +251,7 @@ containing the list of resources and any additional metadata.
- `McpError`: If the request results in a TimeoutError | JSONRPCError
-#### `list_resources`
+#### `list_resources`
```python
list_resources(self) -> list[mcp.types.Resource]
@@ -267,7 +267,7 @@ Retrieve a list of resources available on the server.
- `McpError`: If the request results in a TimeoutError | JSONRPCError
-#### `list_resource_templates_mcp`
+#### `list_resource_templates_mcp`
```python
list_resource_templates_mcp(self) -> mcp.types.ListResourceTemplatesResult
@@ -284,7 +284,7 @@ containing the list of resource templates and any additional metadata.
- `McpError`: If the request results in a TimeoutError | JSONRPCError
-#### `list_resource_templates`
+#### `list_resource_templates`
```python
list_resource_templates(self) -> list[mcp.types.ResourceTemplate]
@@ -300,7 +300,7 @@ Retrieve a list of resource templates available on the server.
- `McpError`: If the request results in a TimeoutError | JSONRPCError
-#### `read_resource_mcp`
+#### `read_resource_mcp`
```python
read_resource_mcp(self, uri: AnyUrl | str, meta: dict[str, Any] | None = None) -> mcp.types.ReadResourceResult
@@ -321,19 +321,19 @@ containing the resource contents and any additional metadata.
- `McpError`: If the request results in a TimeoutError | JSONRPCError
-#### `read_resource`
+#### `read_resource`
```python
read_resource(self, uri: AnyUrl | str) -> list[mcp.types.TextResourceContents | mcp.types.BlobResourceContents]
```
-#### `read_resource`
+#### `read_resource`
```python
read_resource(self, uri: AnyUrl | str) -> ResourceTask
```
-#### `read_resource`
+#### `read_resource`
```python
read_resource(self, uri: AnyUrl | str) -> list[mcp.types.TextResourceContents | mcp.types.BlobResourceContents] | ResourceTask
@@ -356,7 +356,7 @@ A list of content objects if task=False, or a ResourceTask object if task=True.
- `McpError`: If the request results in a TimeoutError | JSONRPCError
-#### `list_prompts_mcp`
+#### `list_prompts_mcp`
```python
list_prompts_mcp(self) -> mcp.types.ListPromptsResult
@@ -373,7 +373,7 @@ containing the list of prompts and any additional metadata.
- `McpError`: If the request results in a TimeoutError | JSONRPCError
-#### `list_prompts`
+#### `list_prompts`
```python
list_prompts(self) -> list[mcp.types.Prompt]
@@ -389,7 +389,7 @@ Retrieve a list of prompts available on the server.
- `McpError`: If the request results in a TimeoutError | JSONRPCError
-#### `get_prompt_mcp`
+#### `get_prompt_mcp`
```python
get_prompt_mcp(self, name: str, arguments: dict[str, Any] | None = None, meta: dict[str, Any] | None = None) -> mcp.types.GetPromptResult
@@ -411,19 +411,19 @@ containing the prompt messages and any additional metadata.
- `McpError`: If the request results in a TimeoutError | JSONRPCError
-#### `get_prompt`
+#### `get_prompt`
```python
get_prompt(self, name: str, arguments: dict[str, Any] | None = None) -> mcp.types.GetPromptResult
```
-#### `get_prompt`
+#### `get_prompt`
```python
get_prompt(self, name: str, arguments: dict[str, Any] | None = None) -> PromptTask
```
-#### `get_prompt`
+#### `get_prompt`
```python
get_prompt(self, name: str, arguments: dict[str, Any] | None = None) -> mcp.types.GetPromptResult | PromptTask
@@ -447,7 +447,7 @@ or a PromptTask object if task=True.
- `McpError`: If the request results in a TimeoutError | JSONRPCError
-#### `complete_mcp`
+#### `complete_mcp`
```python
complete_mcp(self, ref: mcp.types.ResourceTemplateReference | mcp.types.PromptReference, argument: dict[str, str], context_arguments: dict[str, Any] | None = None) -> mcp.types.CompleteResult
@@ -470,7 +470,7 @@ containing the completion and any additional metadata.
- `McpError`: If the request results in a TimeoutError | JSONRPCError
-#### `complete`
+#### `complete`
```python
complete(self, ref: mcp.types.ResourceTemplateReference | mcp.types.PromptReference, argument: dict[str, str], context_arguments: dict[str, Any] | None = None) -> mcp.types.Completion
@@ -492,7 +492,7 @@ include with the completion request. Defaults to None.
- `McpError`: If the request results in a TimeoutError | JSONRPCError
-#### `list_tools_mcp`
+#### `list_tools_mcp`
```python
list_tools_mcp(self) -> mcp.types.ListToolsResult
@@ -509,7 +509,7 @@ containing the list of tools and any additional metadata.
- `McpError`: If the request results in a TimeoutError | JSONRPCError
-#### `list_tools`
+#### `list_tools`
```python
list_tools(self) -> list[mcp.types.Tool]
@@ -525,7 +525,7 @@ Retrieve a list of tools available on the server.
- `McpError`: If the request results in a TimeoutError | JSONRPCError
-#### `call_tool_mcp`
+#### `call_tool_mcp`
```python
call_tool_mcp(self, name: str, arguments: dict[str, Any], progress_handler: ProgressHandler | None = None, timeout: datetime.timedelta | float | int | None = None, meta: dict[str, Any] | None = None) -> mcp.types.CallToolResult
@@ -555,19 +555,19 @@ containing the tool result and any additional metadata.
- `McpError`: If the tool call requests results in a TimeoutError | JSONRPCError
-#### `call_tool`
+#### `call_tool`
```python
call_tool(self, name: str, arguments: dict[str, Any] | None = None) -> CallToolResult
```
-#### `call_tool`
+#### `call_tool`
```python
call_tool(self, name: str, arguments: dict[str, Any] | None = None) -> ToolTask
```
-#### `call_tool`
+#### `call_tool`
```python
call_tool(self, name: str, arguments: dict[str, Any] | None = None) -> CallToolResult | ToolTask
@@ -606,7 +606,7 @@ raw result object.
- `RuntimeError`: If called while the client is not connected.
-#### `get_task_status`
+#### `get_task_status`
```python
get_task_status(self, task_id: str) -> GetTaskResult
@@ -627,7 +627,7 @@ Sends a 'tasks/get' MCP protocol request over the existing transport.
- `McpError`: If the request results in a TimeoutError | JSONRPCError
-#### `get_task_result`
+#### `get_task_result`
```python
get_task_result(self, task_id: str) -> Any
@@ -649,7 +649,7 @@ Returns the raw result - callers should parse it appropriately.
- `McpError`: If the request results in a TimeoutError | JSONRPCError
-#### `list_tasks`
+#### `list_tasks`
```python
list_tasks(self, cursor: str | None = None, limit: int = 50) -> dict[str, Any]
@@ -675,7 +675,7 @@ querying status for locally tracked task IDs.
- `McpError`: If the request results in a TimeoutError | JSONRPCError
-#### `cancel_task`
+#### `cancel_task`
```python
cancel_task(self, task_id: str) -> mcp.types.CancelTaskResult
@@ -697,7 +697,7 @@ and transition to cancelled state.
- `McpError`: If the request results in a TimeoutError | JSONRPCError
-#### `generate_name`
+#### `generate_name`
```python
generate_name(cls, name: str | None = None) -> str
diff --git a/docs/python-sdk/fastmcp-client-telemetry.mdx b/docs/python-sdk/fastmcp-client-telemetry.mdx
new file mode 100644
index 000000000..42ec72e93
--- /dev/null
+++ b/docs/python-sdk/fastmcp-client-telemetry.mdx
@@ -0,0 +1,23 @@
+---
+title: telemetry
+sidebarTitle: telemetry
+---
+
+# `fastmcp.client.telemetry`
+
+
+Client-side telemetry helpers.
+
+## Functions
+
+### `client_span`
+
+```python
+client_span(name: str, method: str, component_key: str, session_id: str | None = None, resource_uri: str | None = None) -> Generator[Span, None, None]
+```
+
+
+Create a CLIENT span with standard MCP attributes.
+
+Automatically records any exception on the span and sets error status.
+
diff --git a/docs/python-sdk/fastmcp-client-transports.mdx b/docs/python-sdk/fastmcp-client-transports.mdx
index c9f748a32..bdf965c95 100644
--- a/docs/python-sdk/fastmcp-client-transports.mdx
+++ b/docs/python-sdk/fastmcp-client-transports.mdx
@@ -7,7 +7,7 @@ sidebarTitle: transports
## Functions
-### `infer_transport`
+### `infer_transport`
```python
infer_transport(transport: ClientTransport | FastMCP | FastMCP1Server | AnyUrl | Path | MCPConfig | dict[str, Any] | str) -> ClientTransport
@@ -57,13 +57,13 @@ transport = infer_transport(config)
## Classes
-### `SessionKwargs`
+### `SessionKwargs`
Keyword arguments for the MCP ClientSession constructor.
-### `ClientTransport`
+### `ClientTransport`
Abstract base class for different MCP client transport mechanisms.
@@ -74,7 +74,7 @@ to an MCP server, and providing a ClientSession within an async context.
**Methods:**
-#### `connect_session`
+#### `connect_session`
```python
connect_session(self, **session_kwargs: Unpack[SessionKwargs]) -> AsyncIterator[ClientSession]
@@ -93,7 +93,7 @@ within this context.
constructor (e.g., callbacks, timeouts).
-#### `close`
+#### `close`
```python
close(self)
@@ -102,7 +102,16 @@ close(self)
Close the transport.
-### `SSETransport`
+#### `get_session_id`
+
+```python
+get_session_id(self) -> str | None
+```
+
+Get the session ID for this transport, if available.
+
+
+### `SSETransport`
Transport implementation that connects to an MCP server via Server-Sent Events.
@@ -110,13 +119,13 @@ 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]
```
-### `StreamableHttpTransport`
+### `StreamableHttpTransport`
Transport implementation that connects to an MCP server via Streamable HTTP Requests.
@@ -124,25 +133,25 @@ 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)
```
-### `StdioTransport`
+### `StdioTransport`
Base transport for connecting to an MCP server via subprocess with stdio.
@@ -153,67 +162,67 @@ transports like Python, Node, Uvx, etc.
**Methods:**
-#### `connect_session`
+#### `connect_session`
```python
connect_session(self, **session_kwargs: Unpack[SessionKwargs]) -> AsyncIterator[ClientSession]
```
-#### `connect`
+#### `connect`
```python
connect(self, **session_kwargs: Unpack[SessionKwargs]) -> ClientSession | None
```
-#### `disconnect`
+#### `disconnect`
```python
disconnect(self)
```
-#### `close`
+#### `close`
```python
close(self)
```
-### `PythonStdioTransport`
+### `PythonStdioTransport`
Transport for running Python scripts.
-### `FastMCPStdioTransport`
+### `FastMCPStdioTransport`
Transport for running FastMCP servers using the FastMCP CLI.
-### `NodeStdioTransport`
+### `NodeStdioTransport`
Transport for running Node.js scripts.
-### `UvStdioTransport`
+### `UvStdioTransport`
Transport for running commands via the uv tool.
-### `UvxStdioTransport`
+### `UvxStdioTransport`
Transport for running commands via the uvx tool.
-### `NpxStdioTransport`
+### `NpxStdioTransport`
Transport for running commands via the npx tool.
-### `FastMCPTransport`
+### `FastMCPTransport`
In-memory transport for FastMCP servers.
@@ -226,13 +235,13 @@ tests or scenarios where client and server run in the same runtime.
**Methods:**
-#### `connect_session`
+#### `connect_session`
```python
connect_session(self, **session_kwargs: Unpack[SessionKwargs]) -> AsyncIterator[ClientSession]
```
-### `MCPConfigTransport`
+### `MCPConfigTransport`
Transport for connecting to one or more MCP servers defined in an MCPConfig.
@@ -284,13 +293,13 @@ async with client:
**Methods:**
-#### `connect_session`
+#### `connect_session`
```python
connect_session(self, **session_kwargs: Unpack[SessionKwargs]) -> AsyncIterator[ClientSession]
```
-#### `close`
+#### `close`
```python
close(self)
diff --git a/docs/python-sdk/fastmcp-decorators.mdx b/docs/python-sdk/fastmcp-decorators.mdx
new file mode 100644
index 000000000..b57712ad6
--- /dev/null
+++ b/docs/python-sdk/fastmcp-decorators.mdx
@@ -0,0 +1,39 @@
+---
+title: decorators
+sidebarTitle: decorators
+---
+
+# `fastmcp.decorators`
+
+
+Shared decorator utilities for FastMCP.
+
+## Functions
+
+### `resolve_task_config`
+
+```python
+resolve_task_config(task: bool | TaskConfig | None) -> bool | TaskConfig
+```
+
+
+Resolve task config, defaulting None to False.
+
+
+### `get_fastmcp_meta`
+
+```python
+get_fastmcp_meta(fn: Any) -> Any | None
+```
+
+
+Extract FastMCP metadata from a function, handling bound methods and wrappers.
+
+
+## Classes
+
+### `HasFastMCPMeta`
+
+
+Protocol for callables decorated with FastMCP metadata.
+
diff --git a/docs/python-sdk/fastmcp-dependencies.mdx b/docs/python-sdk/fastmcp-dependencies.mdx
index d53c37027..e803029c3 100644
--- a/docs/python-sdk/fastmcp-dependencies.mdx
+++ b/docs/python-sdk/fastmcp-dependencies.mdx
@@ -12,3 +12,7 @@ This module re-exports dependency injection symbols from Docket and FastMCP
to provide a clean, centralized import location for all dependency-related
functionality.
+DI features (Depends, CurrentContext, CurrentFastMCP) work without pydocket
+using a vendored DI engine. Only task-related dependencies (CurrentDocket,
+CurrentWorker) and background task execution require fastmcp[tasks].
+
diff --git a/docs/python-sdk/fastmcp-exceptions.mdx b/docs/python-sdk/fastmcp-exceptions.mdx
index 26e62012a..78d2e0110 100644
--- a/docs/python-sdk/fastmcp-exceptions.mdx
+++ b/docs/python-sdk/fastmcp-exceptions.mdx
@@ -63,3 +63,9 @@ Object not found.
Object is disabled.
+
+### `AuthorizationError`
+
+
+Error when authorization check fails.
+
diff --git a/docs/python-sdk/fastmcp-fs-__init__.mdx b/docs/python-sdk/fastmcp-fs-__init__.mdx
deleted file mode 100644
index d49a61f5b..000000000
--- a/docs/python-sdk/fastmcp-fs-__init__.mdx
+++ /dev/null
@@ -1,43 +0,0 @@
----
-title: __init__
-sidebarTitle: __init__
----
-
-# `fastmcp.fs`
-
-
-Filesystem-based component discovery for FastMCP.
-
-This module provides decorators and a provider for discovering MCP components
-from the filesystem. Files are scanned for functions decorated with @tool,
-@resource, or @prompt, and automatically registered with the server.
-
-Example:
- ```python
- # server.py
- from fastmcp import FastMCP
- from fastmcp.fs import FileSystemProvider
-
- mcp = FastMCP("MyServer", providers=[FileSystemProvider("mcp/")])
- ```
-
- ```python
- # mcp/tools/greet.py
- from fastmcp.fs import tool
-
- @tool
- def greet(name: str) -> str:
- '''Greet someone by name.'''
- return f"Hello, {name}!"
- ```
-
- ```python
- # mcp/resources/config.py
- from fastmcp.fs import resource
-
- @resource("config://app")
- def get_config() -> dict:
- '''Get application configuration.'''
- return {"version": "1.0"}
- ```
-
diff --git a/docs/python-sdk/fastmcp-fs-decorators.mdx b/docs/python-sdk/fastmcp-fs-decorators.mdx
deleted file mode 100644
index 45ade0981..000000000
--- a/docs/python-sdk/fastmcp-fs-decorators.mdx
+++ /dev/null
@@ -1,156 +0,0 @@
----
-title: decorators
-sidebarTitle: decorators
----
-
-# `fastmcp.fs.decorators`
-
-
-Decorators for marking functions in filesystem-based discovery.
-
-These decorators mark functions with metadata so that FileSystemProvider
-can discover and register them. Unlike LocalProvider's decorators, these
-do NOT register components immediately - they just store metadata on the
-function for later discovery.
-
-Example:
- ```python
- # mcp/tools/greet.py
- from fastmcp.fs import tool
-
- @tool
- def greet(name: str) -> str:
- '''Greet someone by name.'''
- return f"Hello, {name}!"
-
- @tool(name="custom-greet", tags={"greeting"})
- def my_greet(name: str) -> str:
- return f"Hi, {name}!"
- ```
-
-
-## Functions
-
-### `get_fs_meta`
-
-```python
-get_fs_meta(fn: Any) -> FSMeta | None
-```
-
-
-Get filesystem metadata from a function if it has been decorated.
-
-
-### `has_fs_meta`
-
-```python
-has_fs_meta(fn: Any) -> bool
-```
-
-
-Check if a function has filesystem metadata.
-
-
-### `tool`
-
-```python
-tool(fn: AnyFunction | str | None = None) -> Any
-```
-
-
-Mark a function as a tool for filesystem-based discovery.
-
-This decorator stores metadata on the function but does NOT register it.
-FileSystemProvider discovers marked functions when scanning directories.
-
-Supports multiple calling patterns:
-- @tool (without parentheses)
-- @tool() (with empty parentheses)
-- @tool("custom_name") (with name as first argument)
-- @tool(name="custom_name") (with keyword arguments)
-
-**Args:**
-- `fn`: The function to decorate, or a name string, or None
-- `name`: Optional name for the tool (defaults to function name)
-- `title`: Optional title for display
-- `description`: Optional description (defaults to docstring)
-- `icons`: Optional icons for the tool
-- `tags`: Optional tags for categorization
-- `output_schema`: Optional JSON schema for output
-- `annotations`: Optional tool annotations
-- `meta`: Optional metadata dict
-
-
-### `resource`
-
-```python
-resource(uri: str) -> Any
-```
-
-
-Mark a function as a resource for filesystem-based discovery.
-
-This decorator stores metadata on the function but does NOT register it.
-FileSystemProvider discovers marked functions when scanning directories.
-
-Unlike @tool and @prompt, @resource REQUIRES a URI argument.
-
-**Args:**
-- `uri`: URI for the resource (e.g., "config\://app" or "users\://{user_id}")
-- `name`: Optional name for the resource
-- `title`: Optional title for display
-- `description`: Optional description (defaults to docstring)
-- `icons`: Optional icons for the resource
-- `mime_type`: Optional MIME type
-- `tags`: Optional tags for categorization
-- `annotations`: Optional resource annotations
-- `meta`: Optional metadata dict
-
-
-### `prompt`
-
-```python
-prompt(fn: AnyFunction | str | None = None) -> Any
-```
-
-
-Mark a function as a prompt for filesystem-based discovery.
-
-This decorator stores metadata on the function but does NOT register it.
-FileSystemProvider discovers marked functions when scanning directories.
-
-Supports multiple calling patterns:
-- @prompt (without parentheses)
-- @prompt() (with empty parentheses)
-- @prompt("custom_name") (with name as first argument)
-- @prompt(name="custom_name") (with keyword arguments)
-
-**Args:**
-- `fn`: The function to decorate, or a name string, or None
-- `name`: Optional name for the prompt (defaults to function name)
-- `title`: Optional title for display
-- `description`: Optional description (defaults to docstring)
-- `icons`: Optional icons for the prompt
-- `tags`: Optional tags for categorization
-- `meta`: Optional metadata dict
-
-
-## Classes
-
-### `ToolMeta`
-
-
-Metadata stored on functions decorated with @tool.
-
-
-### `ResourceMeta`
-
-
-Metadata stored on functions decorated with @resource.
-
-
-### `PromptMeta`
-
-
-Metadata stored on functions decorated with @prompt.
-
diff --git a/docs/python-sdk/fastmcp-fs-provider.mdx b/docs/python-sdk/fastmcp-fs-provider.mdx
deleted file mode 100644
index 84bb30a4c..000000000
--- a/docs/python-sdk/fastmcp-fs-provider.mdx
+++ /dev/null
@@ -1,111 +0,0 @@
----
-title: provider
-sidebarTitle: provider
----
-
-# `fastmcp.fs.provider`
-
-
-FileSystemProvider for filesystem-based component discovery.
-
-FileSystemProvider scans a directory for Python files, imports them, and
-registers any functions decorated with @tool, @resource, or @prompt.
-
-Example:
- ```python
- from fastmcp import FastMCP
- from fastmcp.fs import FileSystemProvider
-
- mcp = FastMCP("MyServer", providers=[FileSystemProvider("mcp/")])
- ```
-
-
-## Classes
-
-### `FileSystemProvider`
-
-
-Provider that discovers components from the filesystem.
-
-Scans a directory for Python files and registers functions decorated
-with @tool, @resource, or @prompt from fastmcp.fs.
-
-**Args:**
-- `root`: Root directory to scan. Defaults to current directory.
-- `reload`: If True, re-scan files on every request (dev mode).
-Defaults to False (scan once at init, cache results).
-
-
-**Methods:**
-
-#### `list_tools`
-
-```python
-list_tools(self) -> Sequence[Tool]
-```
-
-Return all tools, reloading if in reload mode.
-
-
-#### `get_tool`
-
-```python
-get_tool(self, name: str) -> Tool | None
-```
-
-Get a tool by name, reloading if in reload mode.
-
-
-#### `list_resources`
-
-```python
-list_resources(self) -> Sequence[Resource]
-```
-
-Return all resources, reloading if in reload mode.
-
-
-#### `get_resource`
-
-```python
-get_resource(self, uri: str) -> Resource | None
-```
-
-Get a resource by URI, reloading if in reload mode.
-
-
-#### `list_resource_templates`
-
-```python
-list_resource_templates(self) -> Sequence[ResourceTemplate]
-```
-
-Return all resource templates, reloading if in reload mode.
-
-
-#### `get_resource_template`
-
-```python
-get_resource_template(self, uri: str) -> ResourceTemplate | None
-```
-
-Get a resource template, reloading if in reload mode.
-
-
-#### `list_prompts`
-
-```python
-list_prompts(self) -> Sequence[Prompt]
-```
-
-Return all prompts, reloading if in reload mode.
-
-
-#### `get_prompt`
-
-```python
-get_prompt(self, name: str) -> Prompt | None
-```
-
-Get a prompt by name, reloading if in reload mode.
-
diff --git a/docs/python-sdk/fastmcp-mcp_config.mdx b/docs/python-sdk/fastmcp-mcp_config.mdx
index 9b30dad85..87ed568a0 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
@@ -57,7 +57,7 @@ worry about transforming server objects here.
## Classes
-### `StdioMCPServer`
+### `StdioMCPServer`
MCP server configuration for stdio transport.
@@ -67,19 +67,19 @@ This is the canonical configuration format for MCP servers using stdio transport
**Methods:**
-#### `to_transport`
+#### `to_transport`
```python
to_transport(self) -> StdioTransport
```
-### `TransformingStdioMCPServer`
+### `TransformingStdioMCPServer`
A Stdio server with tool transforms.
-### `RemoteMCPServer`
+### `RemoteMCPServer`
MCP server configuration for HTTP/SSE transport.
@@ -89,19 +89,19 @@ This is the canonical configuration format for MCP servers using remote transpor
**Methods:**
-#### `to_transport`
+#### `to_transport`
```python
to_transport(self) -> StreamableHttpTransport | SSETransport
```
-### `TransformingRemoteMCPServer`
+### `TransformingRemoteMCPServer`
A Remote server with tool transforms.
-### `MCPConfig`
+### `MCPConfig`
A configuration object for MCP Servers that conforms to the canonical MCP configuration format
@@ -113,7 +113,7 @@ For an MCPConfig that is strictly canonical, see the `CanonicalMCPConfig` class.
**Methods:**
-#### `wrap_servers_at_root`
+#### `wrap_servers_at_root`
```python
wrap_servers_at_root(cls, values: dict[str, Any]) -> dict[str, Any]
@@ -122,7 +122,7 @@ wrap_servers_at_root(cls, values: dict[str, Any]) -> dict[str, Any]
If there's no mcpServers key but there are server configs at root, wrap them.
-#### `add_server`
+#### `add_server`
```python
add_server(self, name: str, server: MCPServerTypes) -> None
@@ -131,7 +131,7 @@ add_server(self, name: str, server: MCPServerTypes) -> None
Add or update a server in the configuration.
-#### `from_dict`
+#### `from_dict`
```python
from_dict(cls, config: dict[str, Any]) -> Self
@@ -140,7 +140,7 @@ from_dict(cls, config: dict[str, Any]) -> Self
Parse MCP configuration from dictionary format.
-#### `to_dict`
+#### `to_dict`
```python
to_dict(self) -> dict[str, Any]
@@ -149,7 +149,7 @@ to_dict(self) -> dict[str, Any]
Convert MCPConfig to dictionary format, preserving all fields.
-#### `write_to_file`
+#### `write_to_file`
```python
write_to_file(self, file_path: Path) -> None
@@ -158,7 +158,7 @@ write_to_file(self, file_path: Path) -> None
Write configuration to JSON file.
-#### `from_file`
+#### `from_file`
```python
from_file(cls, file_path: Path) -> Self
@@ -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-prompts-function_prompt.mdx b/docs/python-sdk/fastmcp-prompts-function_prompt.mdx
new file mode 100644
index 000000000..c8e48ef9c
--- /dev/null
+++ b/docs/python-sdk/fastmcp-prompts-function_prompt.mdx
@@ -0,0 +1,106 @@
+---
+title: function_prompt
+sidebarTitle: function_prompt
+---
+
+# `fastmcp.prompts.function_prompt`
+
+
+Standalone @prompt decorator for FastMCP.
+
+## Functions
+
+### `prompt`
+
+```python
+prompt(name_or_fn: str | Callable[..., Any] | None = None) -> Any
+```
+
+
+Standalone decorator to mark a function as an MCP prompt.
+
+Returns the original function with metadata attached. Register with a server
+using mcp.add_prompt().
+
+
+## Classes
+
+### `DecoratedPrompt`
+
+
+Protocol for functions decorated with @prompt.
+
+
+### `PromptMeta`
+
+
+Metadata attached to functions by the @prompt decorator.
+
+
+### `FunctionPrompt`
+
+
+A prompt that is a function.
+
+
+**Methods:**
+
+#### `from_function`
+
+```python
+from_function(cls, fn: Callable[..., Any]) -> FunctionPrompt
+```
+
+Create a Prompt from a function.
+
+**Args:**
+- `fn`: The function to wrap
+- `metadata`: PromptMeta object with all configuration. If provided,
+individual parameters must not be passed.
+- `name, title, etc.`: Individual parameters for backwards compatibility.
+Cannot be used together with metadata parameter.
+
+The function can return:
+- str: wrapped as single user Message
+- list\[Message | str]: converted to list\[Message]
+- PromptResult: used directly
+
+
+#### `render`
+
+```python
+render(self, arguments: dict[str, Any] | None = None) -> PromptResult
+```
+
+Render the prompt with arguments.
+
+
+#### `register_with_docket`
+
+```python
+register_with_docket(self, docket: Docket) -> None
+```
+
+Register this prompt with docket for background execution.
+
+FunctionPrompt registers the underlying function, which has the user's
+Depends parameters for docket to resolve.
+
+
+#### `add_to_docket`
+
+```python
+add_to_docket(self, docket: Docket, arguments: dict[str, Any] | None, **kwargs: Any) -> Execution
+```
+
+Schedule this prompt for background execution via docket.
+
+FunctionPrompt splats the arguments dict since .fn expects **kwargs.
+
+**Args:**
+- `docket`: The Docket instance
+- `arguments`: Prompt arguments
+- `fn_key`: Function lookup key in Docket registry (defaults to self.key)
+- `task_key`: Redis storage key for the result
+- `**kwargs`: Additional kwargs passed to docket.add()
+
diff --git a/docs/python-sdk/fastmcp-prompts-prompt.mdx b/docs/python-sdk/fastmcp-prompts-prompt.mdx
index 8516742dd..f4ef6c85e 100644
--- a/docs/python-sdk/fastmcp-prompts-prompt.mdx
+++ b/docs/python-sdk/fastmcp-prompts-prompt.mdx
@@ -10,7 +10,7 @@ Base classes for FastMCP prompts.
## Classes
-### `Message`
+### `Message`
Wrapper for prompt message with auto-serialization.
@@ -21,7 +21,7 @@ Accepts any content - strings pass through, other types
**Methods:**
-#### `to_mcp_prompt_message`
+#### `to_mcp_prompt_message`
```python
to_mcp_prompt_message(self) -> PromptMessage
@@ -30,13 +30,13 @@ to_mcp_prompt_message(self) -> PromptMessage
Convert to MCP PromptMessage.
-### `PromptArgument`
+### `PromptArgument`
An argument that can be passed to a prompt.
-### `PromptResult`
+### `PromptResult`
Canonical result type for prompt rendering.
@@ -47,7 +47,7 @@ roles, and metadata at both the message and result level.
**Methods:**
-#### `to_mcp_prompt_result`
+#### `to_mcp_prompt_result`
```python
to_mcp_prompt_result(self) -> GetPromptResult
@@ -56,7 +56,7 @@ to_mcp_prompt_result(self) -> GetPromptResult
Convert to MCP GetPromptResult.
-### `Prompt`
+### `Prompt`
A prompt template that can be rendered with parameters.
@@ -64,7 +64,7 @@ A prompt template that can be rendered with parameters.
**Methods:**
-#### `to_mcp_prompt`
+#### `to_mcp_prompt`
```python
to_mcp_prompt(self, **overrides: Any) -> SDKPrompt
@@ -73,10 +73,10 @@ to_mcp_prompt(self, **overrides: Any) -> SDKPrompt
Convert the prompt to an MCP prompt.
-#### `from_function`
+#### `from_function`
```python
-from_function(fn: Callable[..., Any], name: str | None = None, title: str | None = None, description: str | None = None, icons: list[Icon] | None = None, tags: set[str] | None = None, meta: dict[str, Any] | None = None, task: bool | TaskConfig | None = None) -> FunctionPrompt
+from_function(cls, fn: Callable[..., Any]) -> FunctionPrompt
```
Create a Prompt from a function.
@@ -87,7 +87,7 @@ The function can return:
- PromptResult: used directly
-#### `render`
+#### `render`
```python
render(self, arguments: dict[str, Any] | None = None) -> str | list[Message | str] | PromptResult
@@ -101,7 +101,7 @@ Subclasses must implement this method. Return one of:
- PromptResult: Used directly
-#### `convert_result`
+#### `convert_result`
```python
convert_result(self, raw_value: Any) -> PromptResult
@@ -113,7 +113,7 @@ Convert a raw return value to PromptResult.
- `TypeError`: for unsupported types
-#### `register_with_docket`
+#### `register_with_docket`
```python
register_with_docket(self, docket: Docket) -> None
@@ -122,7 +122,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
@@ -138,63 +138,8 @@ Schedule this prompt for background execution via docket.
- `**kwargs`: Additional kwargs passed to docket.add()
-### `FunctionPrompt`
-
-
-A prompt that is a function.
-
-
-**Methods:**
-
-#### `from_function`
+#### `get_span_attributes`
```python
-from_function(cls, fn: Callable[..., Any], name: str | None = None, title: str | None = None, description: str | None = None, icons: list[Icon] | None = None, tags: set[str] | None = None, meta: dict[str, Any] | None = None, task: bool | TaskConfig | None = None) -> FunctionPrompt
+get_span_attributes(self) -> dict[str, Any]
```
-
-Create a Prompt from a function.
-
-The function can return:
-- str: wrapped as single user Message
-- list\[Message | str]: converted to list\[Message]
-- PromptResult: used directly
-
-
-#### `render`
-
-```python
-render(self, arguments: dict[str, Any] | None = None) -> PromptResult
-```
-
-Render the prompt with arguments.
-
-
-#### `register_with_docket`
-
-```python
-register_with_docket(self, docket: Docket) -> None
-```
-
-Register this prompt with docket for background execution.
-
-FunctionPrompt registers the underlying function, which has the user's
-Depends parameters for docket to resolve.
-
-
-#### `add_to_docket`
-
-```python
-add_to_docket(self, docket: Docket, arguments: dict[str, Any] | None, **kwargs: Any) -> Execution
-```
-
-Schedule this prompt for background execution via docket.
-
-FunctionPrompt splats the arguments dict since .fn expects **kwargs.
-
-**Args:**
-- `docket`: The Docket instance
-- `arguments`: Prompt arguments
-- `fn_key`: Function lookup key in Docket registry (defaults to self.key)
-- `task_key`: Redis storage key for the result
-- `**kwargs`: Additional kwargs passed to docket.add()
-
diff --git a/docs/python-sdk/fastmcp-resources-function_resource.mdx b/docs/python-sdk/fastmcp-resources-function_resource.mdx
new file mode 100644
index 000000000..ad184b53c
--- /dev/null
+++ b/docs/python-sdk/fastmcp-resources-function_resource.mdx
@@ -0,0 +1,93 @@
+---
+title: function_resource
+sidebarTitle: function_resource
+---
+
+# `fastmcp.resources.function_resource`
+
+
+Standalone @resource decorator for FastMCP.
+
+## Functions
+
+### `resource`
+
+```python
+resource(uri: str) -> Callable[[F], F]
+```
+
+
+Standalone decorator to mark a function as an MCP resource.
+
+Returns the original function with metadata attached. Register with a server
+using mcp.add_resource().
+
+
+## Classes
+
+### `DecoratedResource`
+
+
+Protocol for functions decorated with @resource.
+
+
+### `ResourceMeta`
+
+
+Metadata attached to functions by the @resource decorator.
+
+
+### `FunctionResource`
+
+
+A resource that defers data loading by wrapping a function.
+
+The function is only called when the resource is read, allowing for lazy loading
+of potentially expensive data. This is particularly useful when listing resources,
+as the function won't be called until the resource is actually accessed.
+
+The function can return:
+- str for text content (default)
+- bytes for binary content
+- other types will be converted to JSON
+
+
+**Methods:**
+
+#### `from_function`
+
+```python
+from_function(cls, fn: Callable[..., Any], uri: str | AnyUrl | None = None) -> FunctionResource
+```
+
+Create a FunctionResource from a function.
+
+**Args:**
+- `fn`: The function to wrap
+- `uri`: The URI for the resource (required if metadata not provided)
+- `metadata`: ResourceMeta object with all configuration. If provided,
+individual parameters must not be passed.
+- `name, title, etc.`: Individual parameters for backwards compatibility.
+Cannot be used together with metadata parameter.
+
+
+#### `read`
+
+```python
+read(self) -> str | bytes | ResourceResult
+```
+
+Read the resource by calling the wrapped function.
+
+
+#### `register_with_docket`
+
+```python
+register_with_docket(self, docket: Docket) -> None
+```
+
+Register this resource with docket for background execution.
+
+FunctionResource registers the underlying function, which has the user's
+Depends parameters for docket to resolve.
+
diff --git a/docs/python-sdk/fastmcp-resources-resource.mdx b/docs/python-sdk/fastmcp-resources-resource.mdx
index bbd17a04f..94c92ee31 100644
--- a/docs/python-sdk/fastmcp-resources-resource.mdx
+++ b/docs/python-sdk/fastmcp-resources-resource.mdx
@@ -10,7 +10,7 @@ Base classes and interfaces for FastMCP resources.
## Classes
-### `ResourceContent`
+### `ResourceContent`
Wrapper for resource content with optional MIME type and metadata.
@@ -21,7 +21,7 @@ other types (dict, list, BaseModel, etc.) are automatically JSON-serialized.
**Methods:**
-#### `to_mcp_resource_contents`
+#### `to_mcp_resource_contents`
```python
to_mcp_resource_contents(self, uri: AnyUrl | str) -> mcp.types.TextResourceContents | mcp.types.BlobResourceContents
@@ -36,7 +36,7 @@ Convert to MCP resource contents type.
- TextResourceContents for str content, BlobResourceContents for bytes
-### `ResourceResult`
+### `ResourceResult`
Canonical result type for resource reads.
@@ -47,7 +47,7 @@ per-item MIME types, and metadata at both the item and result level.
**Methods:**
-#### `to_mcp_result`
+#### `to_mcp_result`
```python
to_mcp_result(self, uri: AnyUrl | str) -> mcp.types.ReadResourceResult
@@ -62,7 +62,7 @@ Convert to MCP ReadResourceResult.
- MCP ReadResourceResult with converted contents
-### `Resource`
+### `Resource`
Base class for all resources.
@@ -70,13 +70,13 @@ Base class for all resources.
**Methods:**
-#### `from_function`
+#### `from_function`
```python
-from_function(fn: Callable[..., Any], uri: str | AnyUrl, name: str | None = None, title: str | None = None, description: str | None = None, icons: list[Icon] | None = None, mime_type: str | None = None, tags: set[str] | None = None, annotations: Annotations | None = None, meta: dict[str, Any] | None = None, task: bool | TaskConfig | None = None) -> FunctionResource
+from_function(cls, fn: Callable[..., Any], uri: str | AnyUrl) -> FunctionResource
```
-#### `set_default_mime_type`
+#### `set_default_mime_type`
```python
set_default_mime_type(cls, mime_type: str | None) -> str
@@ -85,7 +85,7 @@ set_default_mime_type(cls, mime_type: str | None) -> str
Set default MIME type if not provided.
-#### `set_default_name`
+#### `set_default_name`
```python
set_default_name(self) -> Self
@@ -94,7 +94,7 @@ set_default_name(self) -> Self
Set default name from URI if not provided.
-#### `read`
+#### `read`
```python
read(self) -> str | bytes | ResourceResult
@@ -108,7 +108,7 @@ Subclasses implement this to return resource data. Supported return types:
- ResourceResult: Full control over contents and result-level meta
-#### `convert_result`
+#### `convert_result`
```python
convert_result(self, raw_value: Any) -> ResourceResult
@@ -124,7 +124,7 @@ Handles ResourceResult passthrough and converts raw values using
ResourceResult's normalization.
-#### `to_mcp_resource`
+#### `to_mcp_resource`
```python
to_mcp_resource(self, **overrides: Any) -> SDKResource
@@ -133,7 +133,7 @@ to_mcp_resource(self, **overrides: Any) -> SDKResource
Convert the resource to an SDKResource.
-#### `key`
+#### `key`
```python
key(self) -> str
@@ -142,7 +142,7 @@ key(self) -> str
The globally unique lookup key for this resource.
-#### `register_with_docket`
+#### `register_with_docket`
```python
register_with_docket(self, docket: Docket) -> None
@@ -151,7 +151,7 @@ register_with_docket(self, docket: Docket) -> None
Register this resource with docket for background execution.
-#### `add_to_docket`
+#### `add_to_docket`
```python
add_to_docket(self, docket: Docket, **kwargs: Any) -> Execution
@@ -166,49 +166,8 @@ Schedule this resource for background execution via docket.
- `**kwargs`: Additional kwargs passed to docket.add()
-### `FunctionResource`
-
-
-A resource that defers data loading by wrapping a function.
-
-The function is only called when the resource is read, allowing for lazy loading
-of potentially expensive data. This is particularly useful when listing resources,
-as the function won't be called until the resource is actually accessed.
-
-The function can return:
-- str for text content (default)
-- bytes for binary content
-- other types will be converted to JSON
-
-
-**Methods:**
-
-#### `from_function`
+#### `get_span_attributes`
```python
-from_function(cls, fn: Callable[..., Any], uri: str | AnyUrl, name: str | None = None, title: str | None = None, description: str | None = None, icons: list[Icon] | None = None, mime_type: str | None = None, tags: set[str] | None = None, annotations: Annotations | None = None, meta: dict[str, Any] | None = None, task: bool | TaskConfig | None = None) -> FunctionResource
+get_span_attributes(self) -> dict[str, Any]
```
-
-Create a FunctionResource from a function.
-
-
-#### `read`
-
-```python
-read(self) -> str | bytes | ResourceResult
-```
-
-Read the resource by calling the wrapped function.
-
-
-#### `register_with_docket`
-
-```python
-register_with_docket(self, docket: Docket) -> None
-```
-
-Register this resource with docket for background execution.
-
-FunctionResource registers the underlying function, which has the user's
-Depends parameters for docket to resolve.
-
diff --git a/docs/python-sdk/fastmcp-resources-template.mdx b/docs/python-sdk/fastmcp-resources-template.mdx
index e93d9f4be..30ce6b464 100644
--- a/docs/python-sdk/fastmcp-resources-template.mdx
+++ b/docs/python-sdk/fastmcp-resources-template.mdx
@@ -10,7 +10,7 @@ Resource template functionality.
## Functions
-### `extract_query_params`
+### `extract_query_params`
```python
extract_query_params(uri_template: str) -> set[str]
@@ -20,7 +20,7 @@ extract_query_params(uri_template: str) -> set[str]
Extract query parameter names from RFC 6570 `{?param1,param2}` syntax.
-### `build_regex`
+### `build_regex`
```python
build_regex(template: str) -> re.Pattern
@@ -35,7 +35,7 @@ Supports:
- `{?var1,var2}` - query parameters (ignored in path matching)
-### `match_uri_template`
+### `match_uri_template`
```python
match_uri_template(uri: str, uri_template: str) -> dict[str, str] | None
@@ -51,7 +51,7 @@ Supports RFC 6570 URI templates:
## Classes
-### `ResourceTemplate`
+### `ResourceTemplate`
A template for dynamically creating resources.
@@ -59,13 +59,13 @@ A template for dynamically creating resources.
**Methods:**
-#### `from_function`
+#### `from_function`
```python
-from_function(fn: Callable[..., Any], uri_template: str, name: str | None = None, title: str | None = None, description: str | None = None, icons: list[Icon] | None = None, mime_type: str | None = None, tags: set[str] | None = None, annotations: Annotations | None = None, meta: dict[str, Any] | None = None, task: bool | TaskConfig | None = None) -> FunctionResourceTemplate
+from_function(fn: Callable[..., Any], uri_template: str, name: str | None = None, version: str | int | None = None, title: str | None = None, description: str | None = None, icons: list[Icon] | None = None, mime_type: str | None = None, tags: set[str] | None = None, annotations: Annotations | None = None, meta: dict[str, Any] | None = None, task: bool | TaskConfig | None = None, auth: AuthCheckCallable | list[AuthCheckCallable] | None = None) -> FunctionResourceTemplate
```
-#### `set_default_mime_type`
+#### `set_default_mime_type`
```python
set_default_mime_type(cls, mime_type: str | None) -> str
@@ -74,7 +74,7 @@ set_default_mime_type(cls, mime_type: str | None) -> str
Set default MIME type if not provided.
-#### `matches`
+#### `matches`
```python
matches(self, uri: str) -> dict[str, Any] | None
@@ -83,7 +83,7 @@ matches(self, uri: str) -> dict[str, Any] | None
Check if URI matches template and extract parameters.
-#### `read`
+#### `read`
```python
read(self, arguments: dict[str, Any]) -> str | bytes | ResourceResult
@@ -92,7 +92,7 @@ read(self, arguments: dict[str, Any]) -> str | bytes | ResourceResult
Read the resource content.
-#### `convert_result`
+#### `convert_result`
```python
convert_result(self, raw_value: Any) -> ResourceResult
@@ -108,7 +108,7 @@ Handles ResourceResult passthrough and converts raw values using
ResourceResult's normalization.
-#### `create_resource`
+#### `create_resource`
```python
create_resource(self, uri: str, params: dict[str, Any]) -> Resource
@@ -120,7 +120,7 @@ The base implementation does not support background tasks.
Use FunctionResourceTemplate for task support.
-#### `to_mcp_template`
+#### `to_mcp_template`
```python
to_mcp_template(self, **overrides: Any) -> SDKResourceTemplate
@@ -129,7 +129,7 @@ to_mcp_template(self, **overrides: Any) -> SDKResourceTemplate
Convert the resource template to an SDKResourceTemplate.
-#### `from_mcp_template`
+#### `from_mcp_template`
```python
from_mcp_template(cls, mcp_template: SDKResourceTemplate) -> ResourceTemplate
@@ -138,7 +138,7 @@ from_mcp_template(cls, mcp_template: SDKResourceTemplate) -> ResourceTemplate
Creates a FastMCP ResourceTemplate from a raw MCP ResourceTemplate object.
-#### `key`
+#### `key`
```python
key(self) -> str
@@ -147,7 +147,7 @@ key(self) -> str
The globally unique lookup key for this template.
-#### `register_with_docket`
+#### `register_with_docket`
```python
register_with_docket(self, docket: Docket) -> None
@@ -156,7 +156,7 @@ register_with_docket(self, docket: Docket) -> None
Register this template with docket for background execution.
-#### `add_to_docket`
+#### `add_to_docket`
```python
add_to_docket(self, docket: Docket, params: dict[str, Any], **kwargs: Any) -> Execution
@@ -172,7 +172,13 @@ Schedule this template for background execution via docket.
- `**kwargs`: Additional kwargs passed to docket.add()
-### `FunctionResourceTemplate`
+#### `get_span_attributes`
+
+```python
+get_span_attributes(self) -> dict[str, Any]
+```
+
+### `FunctionResourceTemplate`
A template for dynamically creating resources.
@@ -180,7 +186,7 @@ A template for dynamically creating resources.
**Methods:**
-#### `create_resource`
+#### `create_resource`
```python
create_resource(self, uri: str, params: dict[str, Any]) -> Resource
@@ -189,7 +195,7 @@ create_resource(self, uri: str, params: dict[str, Any]) -> Resource
Create a resource from the template with the given parameters.
-#### `read`
+#### `read`
```python
read(self, arguments: dict[str, Any]) -> str | bytes | ResourceResult
@@ -198,7 +204,7 @@ read(self, arguments: dict[str, Any]) -> str | bytes | ResourceResult
Read the resource content.
-#### `register_with_docket`
+#### `register_with_docket`
```python
register_with_docket(self, docket: Docket) -> None
@@ -210,7 +216,7 @@ FunctionResourceTemplate registers the underlying function, which has the
user's Depends parameters for docket to resolve.
-#### `add_to_docket`
+#### `add_to_docket`
```python
add_to_docket(self, docket: Docket, params: dict[str, Any], **kwargs: Any) -> Execution
@@ -228,10 +234,10 @@ FunctionResourceTemplate splats the params dict since .fn expects **kwargs.
- `**kwargs`: Additional kwargs passed to docket.add()
-#### `from_function`
+#### `from_function`
```python
-from_function(cls, fn: Callable[..., Any], uri_template: str, name: str | None = None, title: str | None = None, description: str | None = None, icons: list[Icon] | None = None, mime_type: str | None = None, tags: set[str] | None = None, annotations: Annotations | None = None, meta: dict[str, Any] | None = None, task: bool | TaskConfig | None = None) -> FunctionResourceTemplate
+from_function(cls, fn: Callable[..., Any], uri_template: str, name: str | None = None, version: str | int | None = None, title: str | None = None, description: str | None = None, icons: list[Icon] | None = None, mime_type: str | None = None, tags: set[str] | None = None, annotations: Annotations | None = None, meta: dict[str, Any] | None = None, task: bool | TaskConfig | None = None, auth: AuthCheckCallable | list[AuthCheckCallable] | None = None) -> FunctionResourceTemplate
```
Create a template from a function.
diff --git a/docs/python-sdk/fastmcp-server-auth-authorization.mdx b/docs/python-sdk/fastmcp-server-auth-authorization.mdx
new file mode 100644
index 000000000..d8e0611a9
--- /dev/null
+++ b/docs/python-sdk/fastmcp-server-auth-authorization.mdx
@@ -0,0 +1,139 @@
+---
+title: authorization
+sidebarTitle: authorization
+---
+
+# `fastmcp.server.auth.authorization`
+
+
+Authorization checks for FastMCP components.
+
+This module provides callable-based authorization for tools, resources, and prompts.
+Auth checks are functions that receive an AuthContext and return True to allow access
+or False to deny.
+
+Auth checks can also raise exceptions:
+- AuthorizationError: Propagates with the custom message for explicit denial
+- Other exceptions: Masked for security (logged, treated as auth failure)
+
+Example:
+ ```python
+ from fastmcp import FastMCP
+ from fastmcp.server.auth import require_auth, require_scopes
+
+ mcp = FastMCP()
+
+ @mcp.tool(auth=require_auth)
+ def protected_tool(): ...
+
+ @mcp.resource("data://secret", auth=require_scopes("read"))
+ def secret_data(): ...
+
+ @mcp.prompt(auth=require_auth)
+ def admin_prompt(): ...
+ ```
+
+
+## Functions
+
+### `require_auth`
+
+```python
+require_auth(ctx: AuthContext) -> bool
+```
+
+
+Require any valid authentication.
+
+Returns True if the request has a valid token, False otherwise.
+
+
+### `require_scopes`
+
+```python
+require_scopes(*scopes: str) -> AuthCheck
+```
+
+
+Require specific OAuth scopes.
+
+Returns an auth check that requires ALL specified scopes to be present
+in the token (AND logic).
+
+**Args:**
+- `*scopes`: One or more scope strings that must all be present.
+
+
+### `restrict_tag`
+
+```python
+restrict_tag(tag: str) -> AuthCheck
+```
+
+
+Restrict components with a specific tag to require certain scopes.
+
+If the component has the specified tag, the token must have ALL the
+required scopes. If the component doesn't have the tag, access is allowed.
+
+**Args:**
+- `tag`: The tag that triggers the scope requirement.
+- `scopes`: List of scopes required when the tag is present.
+
+
+### `run_auth_checks`
+
+```python
+run_auth_checks(checks: AuthCheck | list[AuthCheck], ctx: AuthContext) -> bool
+```
+
+
+Run auth checks with AND logic.
+
+All checks must pass for authorization to succeed.
+
+Auth checks can:
+- Return True to allow access
+- Return False to deny access
+- Raise AuthorizationError to deny with a custom message (propagates)
+- Raise other exceptions (masked for security, treated as denial)
+
+**Args:**
+- `checks`: A single check function or list of check functions.
+- `ctx`: The auth context to pass to each check.
+
+**Returns:**
+- True if all checks pass, False if any check fails.
+
+**Raises:**
+- `AuthorizationError`: If an auth check explicitly raises it.
+
+
+## Classes
+
+### `AuthContext`
+
+
+Context passed to auth check callables.
+
+This object is passed to each auth check function and provides
+access to the current authentication token and the component being accessed.
+
+**Attributes:**
+- `token`: The current access token, or None if unauthenticated.
+- `component`: The component (tool, resource, or prompt) being accessed.
+- `tool`: Backwards-compatible alias for component when it's a Tool.
+
+
+**Methods:**
+
+#### `tool`
+
+```python
+tool(self) -> Tool | None
+```
+
+Backwards-compatible access to the component as a Tool.
+
+Returns the component if it's a Tool, None otherwise.
+
diff --git a/docs/python-sdk/fastmcp-server-auth-providers-introspection.mdx b/docs/python-sdk/fastmcp-server-auth-providers-introspection.mdx
index 2a0d2e22d..32943d6b2 100644
--- a/docs/python-sdk/fastmcp-server-auth-providers-introspection.mdx
+++ b/docs/python-sdk/fastmcp-server-auth-providers-introspection.mdx
@@ -31,7 +31,7 @@ Example:
## Classes
-### `IntrospectionTokenVerifier`
+### `IntrospectionTokenVerifier`
OAuth 2.0 Token Introspection verifier (RFC 7662).
@@ -40,8 +40,11 @@ This verifier validates opaque tokens by calling an OAuth 2.0 token introspectio
endpoint. Unlike JWT verification which is stateless, token introspection requires
a network call to the authorization server for each token validation.
-The verifier authenticates to the introspection endpoint using HTTP Basic Auth
-with the provided client_id and client_secret, as specified in RFC 7662.
+The verifier authenticates to the introspection endpoint using either:
+- HTTP Basic Auth (client_secret_basic, default): credentials in Authorization header
+- POST body authentication (client_secret_post): credentials in request body
+
+Both methods are specified in RFC 6749 (OAuth 2.0) and RFC 7662 (Token Introspection).
Use this when:
- Your authorization server issues opaque (non-JWT) tokens
@@ -52,7 +55,7 @@ Use this when:
**Methods:**
-#### `verify_token`
+#### `verify_token`
```python
verify_token(self, token: str) -> AccessToken | None
@@ -61,7 +64,8 @@ verify_token(self, token: str) -> AccessToken | None
Verify a bearer token using OAuth 2.0 Token Introspection (RFC 7662).
This method makes a POST request to the introspection endpoint with the token,
-authenticated using HTTP Basic Auth with the client credentials.
+authenticated using the configured client authentication method (client_secret_basic
+or client_secret_post).
**Args:**
- `token`: The opaque token string to validate
diff --git a/docs/python-sdk/fastmcp-server-context.mdx b/docs/python-sdk/fastmcp-server-context.mdx
index 91e4c1195..822efb8c6 100644
--- a/docs/python-sdk/fastmcp-server-context.mdx
+++ b/docs/python-sdk/fastmcp-server-context.mdx
@@ -7,7 +7,27 @@ sidebarTitle: context
## Functions
-### `set_context`
+### `set_transport`
+
+```python
+set_transport(transport: TransportType) -> Token[TransportType | None]
+```
+
+
+Set the current transport type. Returns token for reset.
+
+
+### `reset_transport`
+
+```python
+reset_transport(token: Token[TransportType | None]) -> None
+```
+
+
+Reset transport to previous value.
+
+
+### `set_context`
```python
set_context(context: Context) -> Generator[Context, None, None]
@@ -15,7 +35,7 @@ set_context(context: Context) -> Generator[Context, None, None]
## Classes
-### `LogData`
+### `LogData`
Data object for passing log arguments to client-side handlers.
@@ -24,7 +44,7 @@ This provides an interface to match the Python standard library logging,
for compatibility with structured logging.
-### `Context`
+### `Context`
Context object providing access to MCP capabilities.
@@ -53,18 +73,22 @@ async def my_tool(x: int, ctx: Context) -> str:
request_id = ctx.request_id
client_id = ctx.client_id
- # Manage state across the request
- ctx.set_state("key", "value")
- value = ctx.get_state("key")
+ # Manage state across the session (persists across requests)
+ await ctx.set_state("key", "value")
+ value = await ctx.get_state("key")
return str(x)
```
State Management:
-Context objects maintain a state dictionary that can be used to store and share
-data across middleware and tool calls within a request. When a new context
-is created (nested contexts), it inherits a copy of its parent's state, ensuring
-that modifications in child contexts don't affect parent contexts.
+Context provides session-scoped state that persists across requests within
+the same MCP session. State is automatically keyed by session, ensuring
+isolation between different clients.
+
+State set during `on_initialize` middleware will persist to subsequent tool
+calls when using the same session object (STDIO, SSE, single-server HTTP).
+For distributed/serverless HTTP deployments where different machines handle
+the init and tool calls, state is isolated by the mcp-session-id header.
The context parameter name can be anything as long as it's annotated with Context.
The context is optional - tools that don't need it can omit the parameter.
@@ -72,7 +96,7 @@ The context is optional - tools that don't need it can omit the parameter.
**Methods:**
-#### `fastmcp`
+#### `fastmcp`
```python
fastmcp(self) -> FastMCP
@@ -81,7 +105,7 @@ fastmcp(self) -> FastMCP
Get the FastMCP instance.
-#### `request_context`
+#### `request_context`
```python
request_context(self) -> RequestContext[ServerSession, Any, Request] | None
@@ -110,7 +134,7 @@ async def on_request(self, context, call_next):
```
-#### `lifespan_context`
+#### `lifespan_context`
```python
lifespan_context(self) -> dict[str, Any]
@@ -133,7 +157,7 @@ def my_tool(ctx: Context) -> str:
```
-#### `report_progress`
+#### `report_progress`
```python
report_progress(self, progress: float, total: float | None = None, message: str | None = None) -> None
@@ -146,7 +170,7 @@ Report progress for the current operation.
- `total`: Optional total value e.g. 100
-#### `list_resources`
+#### `list_resources`
```python
list_resources(self) -> list[SDKResource]
@@ -158,7 +182,7 @@ List all available resources from the server.
- List of Resource objects available on the server
-#### `list_prompts`
+#### `list_prompts`
```python
list_prompts(self) -> list[SDKPrompt]
@@ -170,7 +194,7 @@ List all available prompts from the server.
- List of Prompt objects available on the server
-#### `get_prompt`
+#### `get_prompt`
```python
get_prompt(self, name: str, arguments: dict[str, Any] | None = None) -> GetPromptResult
@@ -186,7 +210,7 @@ Get a prompt by name with optional arguments.
- The prompt result
-#### `read_resource`
+#### `read_resource`
```python
read_resource(self, uri: str | AnyUrl) -> ResourceResult
@@ -201,7 +225,7 @@ Read a resource by URI.
- ResourceResult with contents
-#### `log`
+#### `log`
```python
log(self, message: str, level: LoggingLevel | None = None, logger_name: str | None = None, extra: Mapping[str, Any] | None = None) -> None
@@ -219,7 +243,19 @@ Messages sent to Clients are also logged to the `fastmcp.server.context.to_clien
- `extra`: Optional mapping for additional arguments
-#### `client_id`
+#### `transport`
+
+```python
+transport(self) -> TransportType | None
+```
+
+Get the current transport type.
+
+Returns the transport type used to run this server: "stdio", "sse",
+or "streamable-http". Returns None if called outside of a server context.
+
+
+#### `client_id`
```python
client_id(self) -> str | None
@@ -228,7 +264,7 @@ client_id(self) -> str | None
Get the client ID if available.
-#### `request_id`
+#### `request_id`
```python
request_id(self) -> str
@@ -239,7 +275,7 @@ Get the unique ID for this request.
Raises RuntimeError if MCP request context is not available.
-#### `session_id`
+#### `session_id`
```python
session_id(self) -> str
@@ -256,7 +292,7 @@ the same client session.
- for other transports.
-#### `session`
+#### `session`
```python
session(self) -> ServerSession
@@ -267,7 +303,7 @@ Access to the underlying session for advanced usage.
Raises RuntimeError if MCP request context is not available.
-#### `debug`
+#### `debug`
```python
debug(self, message: str, logger_name: str | None = None, extra: Mapping[str, Any] | None = None) -> None
@@ -278,7 +314,7 @@ Send a `DEBUG`-level message to the connected MCP Client.
Messages sent to Clients are also logged to the `fastmcp.server.context.to_client` logger with a level of `DEBUG`.
-#### `info`
+#### `info`
```python
info(self, message: str, logger_name: str | None = None, extra: Mapping[str, Any] | None = None) -> None
@@ -289,7 +325,7 @@ Send a `INFO`-level message to the connected MCP Client.
Messages sent to Clients are also logged to the `fastmcp.server.context.to_client` logger with a level of `DEBUG`.
-#### `warning`
+#### `warning`
```python
warning(self, message: str, logger_name: str | None = None, extra: Mapping[str, Any] | None = None) -> None
@@ -300,7 +336,7 @@ Send a `WARNING`-level message to the connected MCP Client.
Messages sent to Clients are also logged to the `fastmcp.server.context.to_client` logger with a level of `DEBUG`.
-#### `error`
+#### `error`
```python
error(self, message: str, logger_name: str | None = None, extra: Mapping[str, Any] | None = None) -> None
@@ -311,7 +347,7 @@ Send a `ERROR`-level message to the connected MCP Client.
Messages sent to Clients are also logged to the `fastmcp.server.context.to_client` logger with a level of `DEBUG`.
-#### `list_roots`
+#### `list_roots`
```python
list_roots(self) -> list[Root]
@@ -320,7 +356,7 @@ list_roots(self) -> list[Root]
List the roots available to the server, as indicated by the client.
-#### `send_notification`
+#### `send_notification`
```python
send_notification(self, notification: mcp.types.ServerNotificationType) -> None
@@ -336,7 +372,7 @@ for the background flusher.
- `notification`: An MCP notification instance (e.g., ToolListChangedNotification())
-#### `send_notification_sync`
+#### `send_notification_sync`
```python
send_notification_sync(self, notification: mcp.types.ServerNotificationType) -> None
@@ -351,7 +387,7 @@ sent within ~1 second by the background flusher.
- `notification`: An MCP notification instance (e.g., ToolListChangedNotification())
-#### `close_sse_stream`
+#### `close_sse_stream`
```python
close_sse_stream(self) -> None
@@ -369,7 +405,7 @@ Instead of holding a connection open for minutes, you can periodically close
and let the client reconnect.
-#### `sample_step`
+#### `sample_step`
```python
sample_step(self, messages: str | Sequence[str | SamplingMessage]) -> SampleStep
@@ -406,7 +442,7 @@ Tools can raise ToolError to bypass masking.
- - .text: The text content (if any)
-#### `sample`
+#### `sample`
```python
sample(self, messages: str | Sequence[str | SamplingMessage]) -> SamplingResult[ResultT]
@@ -415,7 +451,7 @@ sample(self, messages: str | Sequence[str | SamplingMessage]) -> SamplingResult[
Overload: With result_type, returns SamplingResult[ResultT].
-#### `sample`
+#### `sample`
```python
sample(self, messages: str | Sequence[str | SamplingMessage]) -> SamplingResult[str]
@@ -424,7 +460,7 @@ sample(self, messages: str | Sequence[str | SamplingMessage]) -> SamplingResult[
Overload: Without result_type, returns SamplingResult[str].
-#### `sample`
+#### `sample`
```python
sample(self, messages: str | Sequence[str | SamplingMessage]) -> SamplingResult[ResultT] | SamplingResult[str]
@@ -466,43 +502,43 @@ Tools can raise ToolError to bypass masking.
- - .history: All messages exchanged during sampling
-#### `elicit`
+#### `elicit`
```python
elicit(self, message: str, response_type: None) -> AcceptedElicitation[dict[str, Any]] | DeclinedElicitation | CancelledElicitation
```
-#### `elicit`
+#### `elicit`
```python
elicit(self, message: str, response_type: type[T]) -> AcceptedElicitation[T] | DeclinedElicitation | CancelledElicitation
```
-#### `elicit`
+#### `elicit`
```python
elicit(self, message: str, response_type: list[str]) -> AcceptedElicitation[str] | DeclinedElicitation | CancelledElicitation
```
-#### `elicit`
+#### `elicit`
```python
elicit(self, message: str, response_type: dict[str, dict[str, str]]) -> AcceptedElicitation[str] | DeclinedElicitation | CancelledElicitation
```
-#### `elicit`
+#### `elicit`
```python
elicit(self, message: str, response_type: list[list[str]]) -> AcceptedElicitation[list[str]] | DeclinedElicitation | CancelledElicitation
```
-#### `elicit`
+#### `elicit`
```python
elicit(self, message: str, response_type: list[dict[str, dict[str, str]]]) -> AcceptedElicitation[list[str]] | DeclinedElicitation | CancelledElicitation
```
-#### `elicit`
+#### `elicit`
```python
elicit(self, message: str, response_type: type[T] | list[str] | dict[str, dict[str, str]] | list[list[str]] | list[dict[str, dict[str, str]]] | None = None) -> AcceptedElicitation[T] | AcceptedElicitation[dict[str, Any]] | AcceptedElicitation[str] | AcceptedElicitation[list[str]] | DeclinedElicitation | CancelledElicitation
@@ -531,20 +567,35 @@ type or dataclass or BaseModel. If it is a primitive type, an
object schema with a single "value" field will be generated.
-#### `set_state`
+#### `set_state`
```python
set_state(self, key: str, value: Any) -> None
```
-Set a value in the context state.
+Set a value in the session-scoped state store.
+
+Values persist across requests within the same MCP session.
+The key is automatically prefixed with the session identifier.
+State expires after 1 day to prevent unbounded memory growth.
-#### `get_state`
+#### `get_state`
```python
get_state(self, key: str) -> Any
```
-Get a value from the context state. Returns None if the key is not found.
+Get a value from the session-scoped state store.
+
+Returns None if the key is not found.
+
+
+#### `delete_state`
+
+```python
+delete_state(self, key: str) -> None
+```
+
+Delete a value from the session-scoped state store.
diff --git a/docs/python-sdk/fastmcp-server-dependencies.mdx b/docs/python-sdk/fastmcp-server-dependencies.mdx
index 125ba2ecb..2eebf8f5d 100644
--- a/docs/python-sdk/fastmcp-server-dependencies.mdx
+++ b/docs/python-sdk/fastmcp-server-dependencies.mdx
@@ -5,9 +5,139 @@ sidebarTitle: dependencies
# `fastmcp.server.dependencies`
+
+Dependency injection for FastMCP.
+
+DI features (Depends, CurrentContext, CurrentFastMCP) work without pydocket
+using a vendored DI engine. Only task-related dependencies (CurrentDocket,
+CurrentWorker) and background task execution require fastmcp[tasks].
+
+
## Functions
-### `without_injected_parameters`
+### `is_docket_available`
+
+```python
+is_docket_available() -> bool
+```
+
+
+Check if pydocket is installed.
+
+
+### `require_docket`
+
+```python
+require_docket(feature: str) -> None
+```
+
+
+Raise ImportError with install instructions if docket not available.
+
+**Args:**
+- `feature`: Description of what requires docket (e.g., "`task=True`",
+ "CurrentDocket()"). Will be included in the error message.
+
+
+### `transform_context_annotations`
+
+```python
+transform_context_annotations(fn: Callable[..., Any]) -> Callable[..., Any]
+```
+
+
+Transform ctx: Context into ctx: Context = CurrentContext().
+
+Transforms ALL params typed as Context to use Docket's DI system,
+unless they already have a Dependency-based default (like CurrentContext()).
+
+This unifies the legacy type annotation DI with Docket's Depends() system,
+allowing both patterns to work through a single resolution path.
+
+Note: Only POSITIONAL_OR_KEYWORD parameters are reordered (params with defaults
+after those without). KEYWORD_ONLY parameters keep their position since Python
+allows them to have defaults in any order.
+
+**Args:**
+- `fn`: Function to transform
+
+**Returns:**
+- Function with modified signature (same function object, updated __signature__)
+
+
+### `get_context`
+
+```python
+get_context() -> Context
+```
+
+
+Get the current FastMCP Context instance directly.
+
+
+### `get_server`
+
+```python
+get_server() -> FastMCP
+```
+
+
+Get the current FastMCP server instance directly.
+
+**Returns:**
+- The active FastMCP server
+
+**Raises:**
+- `RuntimeError`: If no server in context
+
+
+### `get_http_request`
+
+```python
+get_http_request() -> Request
+```
+
+
+Get the current HTTP request.
+
+Tries MCP SDK's request_ctx first, then falls back to FastMCP's HTTP context.
+
+
+### `get_http_headers`
+
+```python
+get_http_headers(include_all: bool = False) -> dict[str, str]
+```
+
+
+Extract headers from the current HTTP request if available.
+
+Never raises an exception, even if there is no active HTTP request (in which case
+an empty dict is returned).
+
+By default, strips problematic headers like `content-length` that cause issues
+if forwarded to downstream clients. If `include_all` is True, all headers are returned.
+
+
+### `get_access_token`
+
+```python
+get_access_token() -> AccessToken | None
+```
+
+
+Get the FastMCP access token from the current context.
+
+This function first tries to get the token from the current HTTP request's scope,
+which is more reliable for long-lived connections where the SDK's auth_context_var
+may become stale after token refresh. Falls back to the SDK's context var if no
+request is available.
+
+**Returns:**
+- The access token if an authenticated user is available, None otherwise.
+
+
+### `without_injected_parameters`
```python
without_injected_parameters(fn: Callable[..., Any]) -> Callable[..., Any]
@@ -21,6 +151,10 @@ making it safe to use with Pydantic TypeAdapter for schema generation and
validation. The wrapper internally handles all dependency resolution and
Context injection when called.
+Handles:
+- Legacy Context injection (always works)
+- Depends() injection (always works - uses docket or vendored DI engine)
+
**Args:**
- `fn`: Original function with Context and/or dependencies
@@ -28,37 +162,33 @@ Context injection when called.
- 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]
```
-Resolve dependencies and inject Context for a FastMCP function.
+Resolve dependencies for a FastMCP function.
This function:
1. Filters out any dependency parameter names from user arguments (security)
-2. Resolves Docket dependencies
-3. Injects Context if needed
-4. Merges everything together
+2. Resolves Depends() parameters via the DI system
The filtering prevents external callers from overriding injected parameters by
providing values for dependency parameter names. This is a security feature.
+Note: Context injection is handled via transform_context_annotations() which
+converts `ctx: Context` to `ctx: Context = Depends(get_context)` at registration
+time, so all injection goes through the unified DI system.
+
**Args:**
- `fn`: The function to resolve dependencies for
- `arguments`: User arguments (may contain keys that match dependency names,
which will be filtered out)
-### `get_context`
-
-```python
-get_context() -> Context
-```
-
-### `CurrentContext`
+### `CurrentContext`
```python
CurrentContext() -> Context
@@ -77,7 +207,7 @@ current MCP operation (tool/resource/prompt call).
- `RuntimeError`: If no active context found (during resolution)
-### `CurrentDocket`
+### `CurrentDocket`
```python
CurrentDocket() -> Docket
@@ -94,9 +224,10 @@ automatically creates for background task scheduling.
**Raises:**
- `RuntimeError`: If not within a FastMCP server context
+- `ImportError`: If fastmcp[tasks] not installed
-### `CurrentWorker`
+### `CurrentWorker`
```python
CurrentWorker() -> Worker
@@ -113,12 +244,13 @@ automatically creates for background task processing.
**Raises:**
- `RuntimeError`: If not within a FastMCP server context
+- `ImportError`: If fastmcp[tasks] not installed
-### `CurrentFastMCP`
+### `CurrentFastMCP`
```python
-CurrentFastMCP()
+CurrentFastMCP() -> FastMCP
```
@@ -133,95 +265,47 @@ This dependency provides access to the active FastMCP server.
- `RuntimeError`: If no server in context (during resolution)
-### `get_server`
-
-```python
-get_server()
-```
-
-
-Get the current FastMCP server instance directly.
-
-**Returns:**
-- The active FastMCP server
-
-**Raises:**
-- `RuntimeError`: If no server in context
-
-
-### `get_http_request`
-
-```python
-get_http_request() -> Request
-```
-
-### `get_http_headers`
-
-```python
-get_http_headers(include_all: bool = False) -> dict[str, str]
-```
-
-
-Extract headers from the current HTTP request if available.
-
-Never raises an exception, even if there is no active HTTP request (in which case
-an empty dict is returned).
-
-By default, strips problematic headers like `content-length` that cause issues if forwarded to downstream clients.
-If `include_all` is True, all headers are returned.
-
-
-### `get_access_token`
-
-```python
-get_access_token() -> AccessToken | None
-```
-
-
-Get the FastMCP access token from the current context.
-
-This function first tries to get the token from the current HTTP request's scope,
-which is more reliable for long-lived connections where the SDK's auth_context_var
-may become stale after token refresh. Falls back to the SDK's context var if no
-request is available.
-
-**Returns:**
-- The access token if an authenticated user is available, None otherwise.
-
-
## Classes
-### `InMemoryProgress`
+### `ProgressLike`
-In-memory progress tracker for immediate tool execution.
+Protocol for progress tracking interface.
-Provides the same interface as Progress but stores state in memory
-instead of Redis. Useful for testing and immediate execution where
-progress doesn't need to be observable across processes.
+Defines the common interface between InMemoryProgress (server context)
+and Docket's Progress (worker context).
**Methods:**
-#### `current`
+#### `current`
```python
current(self) -> int | None
```
-#### `total`
+Current progress value.
+
+
+#### `total`
```python
total(self) -> int
```
-#### `message`
+Total/target progress value.
+
+
+#### `message`
```python
message(self) -> str | None
```
-#### `set_total`
+Current progress message.
+
+
+#### `set_total`
```python
set_total(self, total: int) -> None
@@ -230,7 +314,7 @@ set_total(self, total: int) -> None
Set the total/target value for progress tracking.
-#### `increment`
+#### `increment`
```python
increment(self, amount: int = 1) -> None
@@ -239,7 +323,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
@@ -248,15 +332,74 @@ set_message(self, message: str | None) -> None
Update the progress status message.
-### `Progress`
+### `InMemoryProgress`
+
+
+In-memory progress tracker for immediate tool execution.
+
+Provides the same interface as Docket's Progress but stores state in memory
+instead of Redis. Useful for testing and immediate execution where
+progress doesn't need to be observable across processes.
+
+
+**Methods:**
+
+#### `current`
+
+```python
+current(self) -> int | None
+```
+
+#### `total`
+
+```python
+total(self) -> int
+```
+
+#### `message`
+
+```python
+message(self) -> str | None
+```
+
+#### `set_total`
+
+```python
+set_total(self, total: int) -> None
+```
+
+Set the total/target value for progress tracking.
+
+
+#### `increment`
+
+```python
+increment(self, amount: int = 1) -> None
+```
+
+Atomically increment the current progress value.
+
+
+#### `set_message`
+
+```python
+set_message(self, message: str | None) -> None
+```
+
+Update the progress status message.
+
+
+### `Progress`
FastMCP Progress dependency that works in both server and worker contexts.
-Extends Docket's Progress to handle two execution modes:
-- In Docket worker: Uses the execution's progress (standard Docket behavior)
-- In FastMCP server: Uses in-memory progress (not observable remotely)
+Handles three execution modes:
+- In Docket worker: Uses the execution's progress (observable via Redis)
+- In FastMCP server with Docket: Falls back to in-memory progress
+- In FastMCP server without Docket: Uses in-memory progress
This allows tools to use Progress() regardless of whether they're called
-immediately or as background tasks.
+immediately or as background tasks, and regardless of whether pydocket
+is installed.
diff --git a/docs/python-sdk/fastmcp-server-elicitation.mdx b/docs/python-sdk/fastmcp-server-elicitation.mdx
index c8c3267d0..47b1d0c4c 100644
--- a/docs/python-sdk/fastmcp-server-elicitation.mdx
+++ b/docs/python-sdk/fastmcp-server-elicitation.mdx
@@ -28,7 +28,7 @@ Supports multiple syntaxes:
- Other types (dataclass, BaseModel): use directly
-### `handle_elicit_accept`
+### `handle_elicit_accept`
```python
handle_elicit_accept(config: ElicitConfig, content: Any) -> AcceptedElicitation[Any]
@@ -45,7 +45,7 @@ Handle an accepted elicitation response.
- AcceptedElicitation with the extracted/validated data
-### `get_elicitation_schema`
+### `get_elicitation_schema`
```python
get_elicitation_schema(response_type: type[T]) -> dict[str, Any]
@@ -58,7 +58,7 @@ Get the schema for an elicitation response.
- `response_type`: The type of the response
-### `validate_elicitation_json_schema`
+### `validate_elicitation_json_schema`
```python
validate_elicitation_json_schema(schema: dict[str, Any]) -> None
diff --git a/docs/python-sdk/fastmcp-server-http.mdx b/docs/python-sdk/fastmcp-server-http.mdx
index 8aaf2c934..64e82d57d 100644
--- a/docs/python-sdk/fastmcp-server-http.mdx
+++ b/docs/python-sdk/fastmcp-server-http.mdx
@@ -7,13 +7,13 @@ sidebarTitle: http
## Functions
-### `set_http_request`
+### `set_http_request`
```python
set_http_request(request: Request) -> Generator[Request, None, None]
```
-### `create_base_app`
+### `create_base_app`
```python
create_base_app(routes: list[BaseRoute], middleware: list[Middleware], debug: bool = False, lifespan: Callable | None = None) -> StarletteWithLifespan
@@ -32,7 +32,7 @@ Create a base Starlette app with common middleware and routes.
- A Starlette application
-### `create_sse_app`
+### `create_sse_app`
```python
create_sse_app(server: FastMCP[LifespanResultT], message_path: str, sse_path: str, auth: AuthProvider | None = None, debug: bool = False, routes: list[BaseRoute] | None = None, middleware: list[Middleware] | None = None) -> StarletteWithLifespan
@@ -54,7 +54,7 @@ Returns:
A Starlette application with RequestContextMiddleware
-### `create_streamable_http_app`
+### `create_streamable_http_app`
```python
create_streamable_http_app(server: FastMCP[LifespanResultT], streamable_http_path: str, event_store: EventStore | None = None, retry_interval: int | None = None, auth: AuthProvider | None = None, json_response: bool = False, stateless_http: bool = False, debug: bool = False, routes: list[BaseRoute] | None = None, middleware: list[Middleware] | None = None) -> StarletteWithLifespan
@@ -83,24 +83,24 @@ disconnections. Requires event_store to be set. Defaults to SDK default.
## Classes
-### `StreamableHTTPASGIApp`
+### `StreamableHTTPASGIApp`
ASGI application wrapper for Streamable HTTP server transport.
-### `StarletteWithLifespan`
+### `StarletteWithLifespan`
**Methods:**
-#### `lifespan`
+#### `lifespan`
```python
lifespan(self) -> Lifespan[Starlette]
```
-### `RequestContextMiddleware`
+### `RequestContextMiddleware`
-Middleware that stores each request in a ContextVar
+Middleware that stores each request in a ContextVar and sets transport type.
diff --git a/docs/python-sdk/fastmcp-server-low_level.mdx b/docs/python-sdk/fastmcp-server-low_level.mdx
index 40ef65ff1..4a2212305 100644
--- a/docs/python-sdk/fastmcp-server-low_level.mdx
+++ b/docs/python-sdk/fastmcp-server-low_level.mdx
@@ -43,7 +43,20 @@ Get the FastMCP instance.
create_initialization_options(self, notification_options: NotificationOptions | None = None, experimental_capabilities: dict[str, dict[str, Any]] | None = None, **kwargs: Any) -> InitializationOptions
```
-#### `run`
+#### `get_capabilities`
+
+```python
+get_capabilities(self, notification_options: NotificationOptions, experimental_capabilities: dict[str, dict[str, Any]]) -> mcp.types.ServerCapabilities
+```
+
+Override to set capabilities.tasks as a first-class field per SEP-1686.
+
+This ensures task capabilities appear in capabilities.tasks instead of
+capabilities.experimental.tasks, which is required by the MCP spec and
+enables proper task detection by clients like VS Code Copilot 1.107+.
+
+
+#### `run`
```python
run(self, read_stream: MemoryObjectReceiveStream[SessionMessage | Exception], write_stream: MemoryObjectSendStream[SessionMessage], initialization_options: InitializationOptions, raise_exceptions: bool = False, stateless: bool = False)
@@ -52,7 +65,7 @@ run(self, read_stream: MemoryObjectReceiveStream[SessionMessage | Exception], wr
Overrides the run method to use the MiddlewareServerSession.
-#### `read_resource`
+#### `read_resource`
```python
read_resource(self) -> Callable[[Callable[[AnyUrl], Awaitable[mcp.types.ReadResourceResult | mcp.types.CreateTaskResult]]], Callable[[AnyUrl], Awaitable[mcp.types.ReadResourceResult | mcp.types.CreateTaskResult]]]
@@ -67,7 +80,7 @@ This decorator can be removed once the MCP SDK adds native CreateTaskResult supp
for resources.
-#### `get_prompt`
+#### `get_prompt`
```python
get_prompt(self) -> Callable[[Callable[[str, dict[str, Any] | None], Awaitable[mcp.types.GetPromptResult | mcp.types.CreateTaskResult]]], Callable[[str, dict[str, Any] | None], Awaitable[mcp.types.GetPromptResult | mcp.types.CreateTaskResult]]]
diff --git a/docs/python-sdk/fastmcp-server-middleware-authorization.mdx b/docs/python-sdk/fastmcp-server-middleware-authorization.mdx
new file mode 100644
index 000000000..f5a41afdc
--- /dev/null
+++ b/docs/python-sdk/fastmcp-server-middleware-authorization.mdx
@@ -0,0 +1,116 @@
+---
+title: authorization
+sidebarTitle: authorization
+---
+
+# `fastmcp.server.middleware.authorization`
+
+
+Authorization middleware for FastMCP.
+
+This module provides middleware-based authorization using callable auth checks.
+AuthMiddleware applies auth checks globally to all components on the server.
+
+Example:
+ ```python
+ from fastmcp import FastMCP
+ from fastmcp.server.auth import require_auth, require_scopes, restrict_tag
+ from fastmcp.server.middleware import AuthMiddleware
+
+ # Require auth for all components
+ mcp = FastMCP(middleware=[
+ AuthMiddleware(auth=require_auth)
+ ])
+
+ # Tag-based: components tagged "admin" require "admin" scope
+ mcp = FastMCP(middleware=[
+ AuthMiddleware(auth=restrict_tag("admin", scopes=["admin"]))
+ ])
+ ```
+
+
+## Classes
+
+### `AuthMiddleware`
+
+
+Global authorization middleware using callable checks.
+
+This middleware applies auth checks to all components (tools, resources,
+prompts) on the server. It uses the same callable API as component-level
+auth checks.
+
+The middleware:
+- Filters tools/resources/prompts from list responses based on auth checks
+- Checks auth before tool execution, resource read, and prompt render
+- Skips all auth checks for STDIO transport (no OAuth concept)
+
+**Args:**
+- `auth`: A single auth check function or list of check functions.
+All checks must pass for authorization to succeed (AND logic).
+
+
+**Methods:**
+
+#### `on_list_tools`
+
+```python
+on_list_tools(self, context: MiddlewareContext[mt.ListToolsRequest], call_next: CallNext[mt.ListToolsRequest, Sequence[Tool]]) -> Sequence[Tool]
+```
+
+Filter tools/list response based on auth checks.
+
+
+#### `on_call_tool`
+
+```python
+on_call_tool(self, context: MiddlewareContext[mt.CallToolRequestParams], call_next: CallNext[mt.CallToolRequestParams, ToolResult]) -> ToolResult
+```
+
+Check auth before tool execution.
+
+
+#### `on_list_resources`
+
+```python
+on_list_resources(self, context: MiddlewareContext[mt.ListResourcesRequest], call_next: CallNext[mt.ListResourcesRequest, Sequence[Resource]]) -> Sequence[Resource]
+```
+
+Filter resources/list response based on auth checks.
+
+
+#### `on_read_resource`
+
+```python
+on_read_resource(self, context: MiddlewareContext[mt.ReadResourceRequestParams], call_next: CallNext[mt.ReadResourceRequestParams, ResourceResult]) -> ResourceResult
+```
+
+Check auth before resource read.
+
+
+#### `on_list_resource_templates`
+
+```python
+on_list_resource_templates(self, context: MiddlewareContext[mt.ListResourceTemplatesRequest], call_next: CallNext[mt.ListResourceTemplatesRequest, Sequence[ResourceTemplate]]) -> Sequence[ResourceTemplate]
+```
+
+Filter resource templates/list response based on auth checks.
+
+
+#### `on_list_prompts`
+
+```python
+on_list_prompts(self, context: MiddlewareContext[mt.ListPromptsRequest], call_next: CallNext[mt.ListPromptsRequest, Sequence[Prompt]]) -> Sequence[Prompt]
+```
+
+Filter prompts/list response based on auth checks.
+
+
+#### `on_get_prompt`
+
+```python
+on_get_prompt(self, context: MiddlewareContext[mt.GetPromptRequestParams], call_next: CallNext[mt.GetPromptRequestParams, PromptResult]) -> PromptResult
+```
+
+Check auth before prompt render.
+
diff --git a/docs/python-sdk/fastmcp-server-middleware-ping.mdx b/docs/python-sdk/fastmcp-server-middleware-ping.mdx
new file mode 100644
index 000000000..fe81c216d
--- /dev/null
+++ b/docs/python-sdk/fastmcp-server-middleware-ping.mdx
@@ -0,0 +1,32 @@
+---
+title: ping
+sidebarTitle: ping
+---
+
+# `fastmcp.server.middleware.ping`
+
+
+Ping middleware for keeping client connections alive.
+
+## Classes
+
+### `PingMiddleware`
+
+
+Middleware that sends periodic pings to keep client connections alive.
+
+Starts a background ping task on first message from each session. The task
+sends server-to-client pings at the configured interval until the session
+ends.
+
+
+**Methods:**
+
+#### `on_message`
+
+```python
+on_message(self, context: MiddlewareContext, call_next: CallNext) -> Any
+```
+
+Start ping task on first message from a session.
+
diff --git a/docs/python-sdk/fastmcp-server-providers-aggregate.mdx b/docs/python-sdk/fastmcp-server-providers-aggregate.mdx
new file mode 100644
index 000000000..61b90c87f
--- /dev/null
+++ b/docs/python-sdk/fastmcp-server-providers-aggregate.mdx
@@ -0,0 +1,139 @@
+---
+title: aggregate
+sidebarTitle: aggregate
+---
+
+# `fastmcp.server.providers.aggregate`
+
+
+AggregateProvider for combining multiple providers into one.
+
+This module provides `AggregateProvider` which presents multiple providers
+as a single unified provider. Used internally by FastMCP for aggregating
+components from all providers.
+
+
+## Classes
+
+### `AggregateProvider`
+
+
+Presents multiple providers as a single provider.
+
+Components are aggregated from all providers. For get_* operations,
+providers are queried in parallel and the highest version is returned.
+
+Errors from individual providers are logged and skipped (graceful degradation).
+
+
+**Methods:**
+
+#### `list_tools`
+
+```python
+list_tools(self) -> Sequence[Tool]
+```
+
+List all tools from all providers (with transforms applied).
+
+
+#### `get_tool`
+
+```python
+get_tool(self, name: str, version: VersionSpec | None = None) -> Tool | None
+```
+
+Get tool by name.
+
+**Args:**
+- `name`: The tool name.
+- `version`: If None, returns highest version across all providers.
+If specified, returns highest version matching the spec from any provider.
+
+
+#### `list_resources`
+
+```python
+list_resources(self) -> Sequence[Resource]
+```
+
+List all resources from all providers (with transforms applied).
+
+
+#### `get_resource`
+
+```python
+get_resource(self, uri: str, version: VersionSpec | None = None) -> Resource | None
+```
+
+Get resource by URI.
+
+**Args:**
+- `uri`: The resource URI.
+- `version`: If None, returns highest version across all providers.
+If specified, returns highest version matching the spec from any provider.
+
+
+#### `list_resource_templates`
+
+```python
+list_resource_templates(self) -> Sequence[ResourceTemplate]
+```
+
+List all resource templates from all providers (with transforms applied).
+
+
+#### `get_resource_template`
+
+```python
+get_resource_template(self, uri: str, version: VersionSpec | None = None) -> ResourceTemplate | None
+```
+
+Get resource template by URI.
+
+**Args:**
+- `uri`: The template URI to match.
+- `version`: If None, returns highest version across all providers.
+If specified, returns highest version matching the spec from any provider.
+
+
+#### `list_prompts`
+
+```python
+list_prompts(self) -> Sequence[Prompt]
+```
+
+List all prompts from all providers (with transforms applied).
+
+
+#### `get_prompt`
+
+```python
+get_prompt(self, name: str, version: VersionSpec | None = None) -> Prompt | None
+```
+
+Get prompt by name.
+
+**Args:**
+- `name`: The prompt name.
+- `version`: If None, returns highest version across all providers.
+If specified, returns highest version matching the spec from any provider.
+
+
+#### `get_tasks`
+
+```python
+get_tasks(self) -> Sequence[FastMCPComponent]
+```
+
+Get all task-eligible components from all providers.
+
+
+#### `lifespan`
+
+```python
+lifespan(self) -> AsyncIterator[None]
+```
+
+Combine lifespans of all providers.
+
diff --git a/docs/python-sdk/fastmcp-server-providers-base.mdx b/docs/python-sdk/fastmcp-server-providers-base.mdx
index 12c036a08..623c24e21 100644
--- a/docs/python-sdk/fastmcp-server-providers-base.mdx
+++ b/docs/python-sdk/fastmcp-server-providers-base.mdx
@@ -36,7 +36,7 @@ Example:
## Classes
-### `Provider`
+### `Provider`
Base class for dynamic component providers.
@@ -48,44 +48,22 @@ supports.
**Methods:**
-#### `with_transforms`
+#### `add_transform`
```python
-with_transforms(self) -> Provider
+add_transform(self, transform: Transform) -> None
```
-Apply transformations to this provider's components.
+Add a transform to this provider.
-Returns a TransformingProvider that wraps this provider and applies
-the specified transformations. Can be chained - each call creates a
-new wrapper that composes with the previous.
+Transforms modify components (tools, resources, prompts) as they flow
+through the provider. They're applied in order - first added is innermost.
**Args:**
-- `namespace`: Prefix for tools/prompts ("namespace_name"), path segment
-for resources ("protocol\://namespace/path").
-- `tool_renames`: Map of original_name → final_name. Tools in this map
-use the specified name instead of namespace prefixing.
-
-**Returns:**
-- A TransformingProvider wrapping this provider.
+- `transform`: The transform to add.
-#### `with_namespace`
-
-```python
-with_namespace(self, namespace: str) -> Provider
-```
-
-Shorthand for with_transforms(namespace=...).
-
-**Args:**
-- `namespace`: The namespace to apply.
-
-**Returns:**
-- A TransformingProvider wrapping this provider.
-
-
-#### `list_tools`
+#### `list_tools`
```python
list_tools(self) -> Sequence[Tool]
@@ -93,25 +71,31 @@ list_tools(self) -> Sequence[Tool]
Return all available tools.
-Override to provide tools dynamically.
+Override to provide tools dynamically. Returns ALL versions of all tools.
+The server handles deduplication to show one tool per name.
-#### `get_tool`
+#### `get_tool`
```python
-get_tool(self, name: str) -> Tool | None
+get_tool(self, name: str, version: VersionSpec | None = None) -> Tool | None
```
Get a specific tool by name.
-Default implementation lists all tools and finds by name.
-Override for more efficient single-tool lookup.
+Default implementation filters list_tools() and picks the highest version
+that matches the spec.
+
+**Args:**
+- `name`: The tool name.
+- `version`: Optional version filter. If None, returns highest version.
+ If specified, returns highest version matching the spec.
**Returns:**
- The Tool if found, or None to continue searching other providers.
-#### `list_resources`
+#### `list_resources`
```python
list_resources(self) -> Sequence[Resource]
@@ -119,25 +103,30 @@ list_resources(self) -> Sequence[Resource]
Return all available resources.
-Override to provide resources dynamically.
+Override to provide resources dynamically. Returns ALL versions of all resources.
+The server handles deduplication to show one resource per URI.
-#### `get_resource`
+#### `get_resource`
```python
-get_resource(self, uri: str) -> Resource | None
+get_resource(self, uri: str, version: VersionSpec | None = None) -> Resource | None
```
Get a specific resource by URI.
-Default implementation lists all resources and finds by URI.
-Override for more efficient single-resource lookup.
+Default implementation filters list_resources() and returns highest
+version matching the spec.
+
+**Args:**
+- `uri`: The resource URI.
+- `version`: Optional version filter. If None, returns highest version.
**Returns:**
- The Resource if found, or None to continue searching other providers.
-#### `list_resource_templates`
+#### `list_resource_templates`
```python
list_resource_templates(self) -> Sequence[ResourceTemplate]
@@ -145,26 +134,30 @@ list_resource_templates(self) -> Sequence[ResourceTemplate]
Return all available resource templates.
-Override to provide resource templates dynamically.
+Override to provide resource templates dynamically. Returns ALL versions.
+The server handles deduplication.
-#### `get_resource_template`
+#### `get_resource_template`
```python
-get_resource_template(self, uri: str) -> ResourceTemplate | None
+get_resource_template(self, uri: str, version: VersionSpec | None = None) -> ResourceTemplate | None
```
Get a resource template that matches the given URI.
-Default implementation lists all templates and finds one whose pattern
-matches the URI.
-Override for more efficient lookup.
+Default implementation lists all templates, finds those whose pattern
+matches the URI, and returns the highest version matching the spec.
+
+**Args:**
+- `uri`: The URI to match against templates.
+- `version`: Optional version filter. If None, returns highest version.
**Returns:**
- The ResourceTemplate if a matching one is found, or None to continue searching.
-#### `list_prompts`
+#### `list_prompts`
```python
list_prompts(self) -> Sequence[Prompt]
@@ -172,40 +165,30 @@ list_prompts(self) -> Sequence[Prompt]
Return all available prompts.
-Override to provide prompts dynamically.
+Override to provide prompts dynamically. Returns ALL versions of all prompts.
+The server handles deduplication to show one prompt per name.
-#### `get_prompt`
+#### `get_prompt`
```python
-get_prompt(self, name: str) -> Prompt | None
+get_prompt(self, name: str, version: VersionSpec | None = None) -> Prompt | None
```
Get a specific prompt by name.
-Default implementation lists all prompts and finds by name.
-Override for more efficient single-prompt lookup.
+Default implementation filters list_prompts() and picks the highest version
+matching the spec.
+
+**Args:**
+- `name`: The prompt name.
+- `version`: Optional version filter. If None, returns highest version.
**Returns:**
- The Prompt if found, or None to continue searching other providers.
-#### `get_component`
-
-```python
-get_component(self, key: str) -> Tool | Resource | ResourceTemplate | Prompt | None
-```
-
-Get a component by its prefixed key.
-
-**Args:**
-- `key`: The prefixed key (e.g., "tool\:name", "resource\:uri", "template\:uri").
-
-**Returns:**
-- The component if found, or None to continue searching other providers.
-
-
-#### `get_tasks`
+#### `get_tasks`
```python
get_tasks(self) -> Sequence[FastMCPComponent]
@@ -214,13 +197,13 @@ get_tasks(self) -> Sequence[FastMCPComponent]
Return components that should be registered as background tasks.
Override to customize which components are task-eligible.
-Default calls list_* methods and filters for components
-with task_config.mode != 'forbidden'.
+Default calls list_* methods, applies provider transforms, and filters
+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]
@@ -236,7 +219,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) -> None
@@ -245,12 +228,12 @@ enable(self) -> None
Enable components by removing from blocklist, or set allowlist with only=True.
**Args:**
-- `keys`: Keys to enable (e.g., "tool\:my_tool").
+- `keys`: Keys to enable (e.g., "tool\:my_tool@" for unversioned, "tool\:my_tool@1.0" for versioned).
- `tags`: Tags to enable - components with these tags will be enabled.
- `only`: If True, switches to allowlist mode - ONLY show these keys/tags.
-#### `disable`
+#### `disable`
```python
disable(self) -> None
@@ -259,6 +242,6 @@ disable(self) -> None
Disable components by adding to the blocklist.
**Args:**
-- `keys`: Keys to disable (e.g., "tool\:my_tool").
+- `keys`: Keys to disable (e.g., "tool\:my_tool@" for unversioned, "tool\:my_tool@1.0" for versioned).
- `tags`: Tags to disable - components with these tags will be disabled.
diff --git a/docs/python-sdk/fastmcp-server-providers-fastmcp_provider.mdx b/docs/python-sdk/fastmcp-server-providers-fastmcp_provider.mdx
index 32f940c04..b12db1ca1 100644
--- a/docs/python-sdk/fastmcp-server-providers-fastmcp_provider.mdx
+++ b/docs/python-sdk/fastmcp-server-providers-fastmcp_provider.mdx
@@ -18,7 +18,7 @@ executed.
## Classes
-### `FastMCPProviderTool`
+### `FastMCPProviderTool`
Tool that delegates execution to a wrapped server's middleware.
@@ -30,7 +30,7 @@ chain is executed.
**Methods:**
-#### `wrap`
+#### `wrap`
```python
wrap(cls, server: Any, tool: Tool) -> FastMCPProviderTool
@@ -39,19 +39,25 @@ wrap(cls, server: Any, tool: Tool) -> FastMCPProviderTool
Wrap a Tool to delegate execution to the server's middleware.
-#### `run`
+#### `run`
```python
-run(self, arguments: dict[str, Any]) -> ToolResult | mcp.types.CreateTaskResult
+run(self, arguments: dict[str, Any]) -> ToolResult
```
-Not implemented - use _run() which delegates to child server.
+Delegate to child server's call_tool() without task_meta.
-FastMCPProviderTool._run() handles all execution by delegating
-to the child server's call_tool() with task_meta.
+This is called when the tool is used within a TransformedTool
+forwarding function or other contexts where task_meta is not available.
-### `FastMCPProviderResource`
+#### `get_span_attributes`
+
+```python
+get_span_attributes(self) -> dict[str, Any]
+```
+
+### `FastMCPProviderResource`
Resource that delegates reading to a wrapped server's read_resource().
@@ -62,7 +68,7 @@ When `read()` is called, this resource invokes the wrapped server's
**Methods:**
-#### `wrap`
+#### `wrap`
```python
wrap(cls, server: Any, resource: Resource) -> FastMCPProviderResource
@@ -71,7 +77,13 @@ wrap(cls, server: Any, resource: Resource) -> FastMCPProviderResource
Wrap a Resource to delegate reading to the server's middleware.
-### `FastMCPProviderPrompt`
+#### `get_span_attributes`
+
+```python
+get_span_attributes(self) -> dict[str, Any]
+```
+
+### `FastMCPProviderPrompt`
Prompt that delegates rendering to a wrapped server's render_prompt().
@@ -82,7 +94,7 @@ When `render()` is called, this prompt invokes the wrapped server's
**Methods:**
-#### `wrap`
+#### `wrap`
```python
wrap(cls, server: Any, prompt: Prompt) -> FastMCPProviderPrompt
@@ -91,19 +103,25 @@ wrap(cls, server: Any, prompt: Prompt) -> FastMCPProviderPrompt
Wrap a Prompt to delegate rendering to the server's middleware.
-#### `render`
+#### `render`
```python
-render(self, arguments: dict[str, Any] | None = None) -> PromptResult | mcp.types.CreateTaskResult
+render(self, arguments: dict[str, Any] | None = None) -> PromptResult
```
-Not implemented - use _render() which delegates to child server.
+Delegate to child server's render_prompt() without task_meta.
-FastMCPProviderPrompt._render() handles all execution by delegating
-to the child server's render_prompt() with task_meta.
+This is called when the prompt is used within a transformed context
+or other contexts where task_meta is not available.
-### `FastMCPProviderResourceTemplate`
+#### `get_span_attributes`
+
+```python
+get_span_attributes(self) -> dict[str, Any]
+```
+
+### `FastMCPProviderResourceTemplate`
Resource template that creates FastMCPProviderResources.
@@ -115,7 +133,7 @@ when read.
**Methods:**
-#### `wrap`
+#### `wrap`
```python
wrap(cls, server: Any, template: ResourceTemplate) -> FastMCPProviderResourceTemplate
@@ -124,7 +142,7 @@ wrap(cls, server: Any, template: ResourceTemplate) -> FastMCPProviderResourceTem
Wrap a ResourceTemplate to create FastMCPProviderResources.
-#### `create_resource`
+#### `create_resource`
```python
create_resource(self, uri: str, params: dict[str, Any]) -> Resource
@@ -137,7 +155,7 @@ We use `_original_uri_template` with `params` to construct the internal
URI that the nested server understands.
-#### `read`
+#### `read`
```python
read(self, arguments: dict[str, Any]) -> str | bytes | ResourceResult
@@ -149,7 +167,7 @@ Reads the resource via the wrapped server and returns the ResourceResult.
This method is called by Docket during background task execution.
-#### `register_with_docket`
+#### `register_with_docket`
```python
register_with_docket(self, docket: Docket) -> None
@@ -158,7 +176,7 @@ register_with_docket(self, docket: Docket) -> None
No-op: the child's actual template is registered via get_tasks().
-#### `add_to_docket`
+#### `add_to_docket`
```python
add_to_docket(self, docket: Docket, params: dict[str, Any], **kwargs: Any) -> Execution
@@ -170,7 +188,13 @@ The child's FunctionResourceTemplate.fn is registered (via get_tasks),
and it expects splatted **kwargs, so we splat params here.
-### `FastMCPProvider`
+#### `get_span_attributes`
+
+```python
+get_span_attributes(self) -> dict[str, Any]
+```
+
+### `FastMCPProvider`
Provider that wraps a FastMCP server.
@@ -186,7 +210,7 @@ This ensures middleware runs when components are executed.
**Methods:**
-#### `list_tools`
+#### `list_tools`
```python
list_tools(self) -> Sequence[Tool]
@@ -199,16 +223,19 @@ each tool as a FastMCPProviderTool that delegates execution to the
nested server's middleware.
-#### `get_tool`
+#### `get_tool`
```python
-get_tool(self, name: str) -> Tool | None
+get_tool(self, name: str, version: VersionSpec | None = None) -> Tool | None
```
Get a tool by name as a FastMCPProviderTool.
+Passes the full VersionSpec to the nested server, which handles both
+exact version matching and range filtering.
-#### `list_resources`
+
+#### `list_resources`
```python
list_resources(self) -> Sequence[Resource]
@@ -221,16 +248,19 @@ each resource as a FastMCPProviderResource that delegates reading to the
nested server's middleware.
-#### `get_resource`
+#### `get_resource`
```python
-get_resource(self, uri: str) -> Resource | None
+get_resource(self, uri: str, version: VersionSpec | None = None) -> Resource | None
```
Get a concrete resource by URI as a FastMCPProviderResource.
+Passes the full VersionSpec to the nested server, which handles both
+exact version matching and range filtering.
-#### `list_resource_templates`
+
+#### `list_resource_templates`
```python
list_resource_templates(self) -> Sequence[ResourceTemplate]
@@ -242,16 +272,19 @@ Returns FastMCPProviderResourceTemplate instances that create
FastMCPProviderResources when materialized.
-#### `get_resource_template`
+#### `get_resource_template`
```python
-get_resource_template(self, uri: str) -> ResourceTemplate | None
+get_resource_template(self, uri: str, version: VersionSpec | None = None) -> ResourceTemplate | None
```
Get a resource template that matches the given URI.
+Passes the full VersionSpec to the nested server, which handles both
+exact version matching and range filtering.
-#### `list_prompts`
+
+#### `list_prompts`
```python
list_prompts(self) -> Sequence[Prompt]
@@ -263,16 +296,19 @@ Returns FastMCPProviderPrompt instances that delegate rendering to the
wrapped server's middleware.
-#### `get_prompt`
+#### `get_prompt`
```python
-get_prompt(self, name: str) -> Prompt | None
+get_prompt(self, name: str, version: VersionSpec | None = None) -> Prompt | None
```
Get a prompt by name as a FastMCPProviderPrompt.
+Passes the full VersionSpec to the nested server, which handles both
+exact version matching and range filtering.
-#### `get_tasks`
+
+#### `get_tasks`
```python
get_tasks(self) -> Sequence[FastMCPComponent]
@@ -281,14 +317,12 @@ get_tasks(self) -> Sequence[FastMCPComponent]
Return task-eligible components from the mounted server.
Returns the child's ACTUAL components (not wrapped) so their actual
-functions get registered with Docket. TransformingProvider.get_tasks()
-handles namespace transformation of keys.
-
-Iterates through all providers in the wrapped server (including its
-LocalProvider) to collect task-eligible components.
+functions get registered with Docket. Uses _source_get_tasks() to get
+components with child 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-filesystem.mdx b/docs/python-sdk/fastmcp-server-providers-filesystem.mdx
new file mode 100644
index 000000000..55e9b342c
--- /dev/null
+++ b/docs/python-sdk/fastmcp-server-providers-filesystem.mdx
@@ -0,0 +1,128 @@
+---
+title: filesystem
+sidebarTitle: filesystem
+---
+
+# `fastmcp.server.providers.filesystem`
+
+
+FileSystemProvider for filesystem-based component discovery.
+
+FileSystemProvider scans a directory for Python files, imports them, and
+registers any Tool, Resource, ResourceTemplate, or Prompt objects found.
+
+Components are created using the standalone decorators from fastmcp.tools,
+fastmcp.resources, and fastmcp.prompts:
+
+Example:
+ ```python
+ # In mcp/tools.py
+ from fastmcp.tools import tool
+
+ @tool
+ def greet(name: str) -> str:
+ return f"Hello, {name}!"
+
+ # In main.py
+ from pathlib import Path
+
+ from fastmcp import FastMCP
+ from fastmcp.server.providers import FileSystemProvider
+
+ mcp = FastMCP("MyServer", providers=[FileSystemProvider(Path(__file__).parent / "mcp")])
+ ```
+
+
+## Classes
+
+### `FileSystemProvider`
+
+
+Provider that discovers components from the filesystem.
+
+Scans a directory for Python files and registers any Tool, Resource,
+ResourceTemplate, or Prompt objects found. Components are created using
+the standalone decorators:
+- @tool from fastmcp.tools
+- @resource from fastmcp.resources
+- @prompt from fastmcp.prompts
+
+**Args:**
+- `root`: Root directory to scan. Defaults to current directory.
+- `reload`: If True, re-scan files on every request (dev mode).
+Defaults to False (scan once at init, cache results).
+
+
+**Methods:**
+
+#### `list_tools`
+
+```python
+list_tools(self) -> Sequence[Tool]
+```
+
+Return all tools, reloading if in reload mode.
+
+
+#### `get_tool`
+
+```python
+get_tool(self, name: str, version: VersionSpec | None = None) -> Tool | None
+```
+
+Get a tool by name, reloading if in reload mode.
+
+
+#### `list_resources`
+
+```python
+list_resources(self) -> Sequence[Resource]
+```
+
+Return all resources, reloading if in reload mode.
+
+
+#### `get_resource`
+
+```python
+get_resource(self, uri: str, version: VersionSpec | None = None) -> Resource | None
+```
+
+Get a resource by URI, reloading if in reload mode.
+
+
+#### `list_resource_templates`
+
+```python
+list_resource_templates(self) -> Sequence[ResourceTemplate]
+```
+
+Return all resource templates, reloading if in reload mode.
+
+
+#### `get_resource_template`
+
+```python
+get_resource_template(self, uri: str, version: VersionSpec | None = None) -> ResourceTemplate | None
+```
+
+Get a resource template, reloading if in reload mode.
+
+
+#### `list_prompts`
+
+```python
+list_prompts(self) -> Sequence[Prompt]
+```
+
+Return all prompts, reloading if in reload mode.
+
+
+#### `get_prompt`
+
+```python
+get_prompt(self, name: str, version: VersionSpec | None = None) -> Prompt | None
+```
+
+Get a prompt by name, reloading if in reload mode.
+
diff --git a/docs/python-sdk/fastmcp-fs-discovery.mdx b/docs/python-sdk/fastmcp-server-providers-filesystem_discovery.mdx
similarity index 55%
rename from docs/python-sdk/fastmcp-fs-discovery.mdx
rename to docs/python-sdk/fastmcp-server-providers-filesystem_discovery.mdx
index 4d6720be4..0a02129c9 100644
--- a/docs/python-sdk/fastmcp-fs-discovery.mdx
+++ b/docs/python-sdk/fastmcp-server-providers-filesystem_discovery.mdx
@@ -1,9 +1,9 @@
---
-title: discovery
-sidebarTitle: discovery
+title: filesystem_discovery
+sidebarTitle: filesystem_discovery
---
-# `fastmcp.fs.discovery`
+# `fastmcp.server.providers.filesystem_discovery`
File discovery and module import utilities for filesystem-based routing.
@@ -11,12 +11,12 @@ File discovery and module import utilities for filesystem-based routing.
This module provides functions to:
1. Discover Python files in a directory tree
2. Import modules (as packages if __init__.py exists, else directly)
-3. Extract decorated functions from imported modules
+3. Extract decorated components (Tool, Resource, Prompt objects) from imported modules
## Functions
-### `discover_files`
+### `discover_files`
```python
discover_files(root: Path) -> list[Path]
@@ -34,7 +34,7 @@ Excludes __init__.py files (they're for package structure, not components).
- List of .py file paths, sorted for deterministic order.
-### `import_module_from_file`
+### `import_module_from_file`
```python
import_module_from_file(file_path: Path) -> ModuleType
@@ -57,26 +57,27 @@ imports directly using spec_from_file_location.
- `ImportError`: If the module cannot be imported.
-### `extract_components`
+### `extract_components`
```python
-extract_components(module: ModuleType) -> list[tuple[Any, FSMeta]]
+extract_components(module: ModuleType) -> list[FastMCPComponent]
```
-Extract all decorated functions from a module.
+Extract all MCP components from a module.
-Scans all module attributes for functions that have been decorated
-with @tool, @resource, or @prompt.
+Scans all module attributes for instances of Tool, Resource,
+ResourceTemplate, or Prompt objects created by standalone decorators,
+or functions decorated with @tool/@resource/@prompt that have __fastmcp__ metadata.
**Args:**
- `module`: The imported module to scan.
**Returns:**
-- List of (function, metadata) tuples for each decorated function.
+- List of component objects (Tool, Resource, ResourceTemplate, Prompt).
-### `discover_and_import`
+### `discover_and_import`
```python
discover_and_import(root: Path) -> DiscoveryResult
@@ -96,7 +97,7 @@ This is the main entry point for filesystem-based discovery.
## Classes
-### `DiscoveryResult`
+### `DiscoveryResult`
Result of filesystem discovery.
diff --git a/docs/python-sdk/fastmcp-server-providers-local_provider.mdx b/docs/python-sdk/fastmcp-server-providers-local_provider.mdx
index f002b48b1..247d9e1ba 100644
--- a/docs/python-sdk/fastmcp-server-providers-local_provider.mdx
+++ b/docs/python-sdk/fastmcp-server-providers-local_provider.mdx
@@ -47,43 +47,61 @@ like `_tool_serializer` and `_support_tasks_by_default` are injected.
**Methods:**
-#### `add_tool`
+#### `add_tool`
```python
-add_tool(self, tool: Tool) -> Tool
+add_tool(self, tool: Tool | Callable[..., Any]) -> Tool
```
Add a tool to this provider's storage.
+Accepts either a Tool object or a decorated function with __fastmcp__ metadata.
-#### `remove_tool`
+
+#### `remove_tool`
```python
-remove_tool(self, name: str) -> None
+remove_tool(self, name: str, version: str | None = None) -> None
```
-Remove a tool from this provider's storage.
+Remove tool(s) from this provider's storage.
+
+**Args:**
+- `name`: The tool name.
+- `version`: If None, removes ALL versions. If specified, removes only that version.
+
+**Raises:**
+- `KeyError`: If no matching tool is found.
-#### `add_resource`
+#### `add_resource`
```python
-add_resource(self, resource: Resource) -> Resource
+add_resource(self, resource: Resource | ResourceTemplate | Callable[..., Any]) -> Resource | ResourceTemplate
```
Add a resource to this provider's storage.
+Accepts either a Resource/ResourceTemplate object or a decorated function with __fastmcp__ metadata.
-#### `remove_resource`
+
+#### `remove_resource`
```python
-remove_resource(self, uri: str) -> None
+remove_resource(self, uri: str, version: str | None = None) -> None
```
-Remove a resource from this provider's storage.
+Remove resource(s) from this provider's storage.
+
+**Args:**
+- `uri`: The resource URI.
+- `version`: If None, removes ALL versions. If specified, removes only that version.
+
+**Raises:**
+- `KeyError`: If no matching resource is found.
-#### `add_template`
+#### `add_template`
```python
add_template(self, template: ResourceTemplate) -> ResourceTemplate
@@ -92,92 +110,72 @@ add_template(self, template: ResourceTemplate) -> ResourceTemplate
Add a resource template to this provider's storage.
-#### `remove_template`
+#### `remove_template`
```python
-remove_template(self, uri_template: str) -> None
+remove_template(self, uri_template: str, version: str | None = None) -> None
```
-Remove a resource template from this provider's storage.
+Remove resource template(s) from this provider's storage.
+
+**Args:**
+- `uri_template`: The template URI pattern.
+- `version`: If None, removes ALL versions. If specified, removes only that version.
+
+**Raises:**
+- `KeyError`: If no matching template is found.
-#### `add_prompt`
+#### `add_prompt`
```python
-add_prompt(self, prompt: Prompt) -> Prompt
+add_prompt(self, prompt: Prompt | Callable[..., Any]) -> Prompt
```
Add a prompt to this provider's storage.
+Accepts either a Prompt object or a decorated function with __fastmcp__ metadata.
-#### `remove_prompt`
+
+#### `remove_prompt`
```python
-remove_prompt(self, name: str) -> None
+remove_prompt(self, name: str, version: str | None = None) -> None
```
-Remove a prompt from this provider's storage.
-
-
-#### `add_tool_transformation`
-
-```python
-add_tool_transformation(self, tool_name: str, transformation: ToolTransformConfig) -> None
-```
-
-Add a tool transformation.
+Remove prompt(s) from this provider's storage.
**Args:**
-- `tool_name`: The name of the tool to transform.
-- `transformation`: The transformation configuration.
+- `name`: The prompt name.
+- `version`: If None, removes ALL versions. If specified, removes only that version.
+
+**Raises:**
+- `KeyError`: If no matching prompt is found.
-#### `get_tool_transformation`
-
-```python
-get_tool_transformation(self, tool_name: str) -> ToolTransformConfig | None
-```
-
-Get a tool transformation.
-
-**Args:**
-- `tool_name`: The name of the tool.
-
-**Returns:**
-- The transformation config, or None if not found.
-
-
-#### `remove_tool_transformation`
-
-```python
-remove_tool_transformation(self, tool_name: str) -> None
-```
-
-Remove a tool transformation.
-
-**Args:**
-- `tool_name`: The name of the tool.
-
-
-#### `list_tools`
+#### `list_tools`
```python
list_tools(self) -> Sequence[Tool]
```
-Return all visible tools with transformations applied.
+Return all visible tools.
-#### `get_tool`
+#### `get_tool`
```python
-get_tool(self, name: str) -> Tool | None
+get_tool(self, name: str, version: VersionSpec | None = None) -> Tool | None
```
-Get a tool by name, with transformations applied.
+Get a tool by name.
+
+**Args:**
+- `name`: The tool name.
+- `version`: Optional version filter. If None, returns highest version.
-#### `list_resources`
+#### `list_resources`
```python
list_resources(self) -> Sequence[Resource]
@@ -186,16 +184,20 @@ list_resources(self) -> Sequence[Resource]
Return all visible resources.
-#### `get_resource`
+#### `get_resource`
```python
-get_resource(self, uri: str) -> Resource | None
+get_resource(self, uri: str, version: VersionSpec | None = None) -> Resource | None
```
-Get a resource by URI if visible.
+Get a resource by URI.
+
+**Args:**
+- `uri`: The resource URI.
+- `version`: Optional version filter. If None, returns highest version.
-#### `list_resource_templates`
+#### `list_resource_templates`
```python
list_resource_templates(self) -> Sequence[ResourceTemplate]
@@ -204,16 +206,20 @@ list_resource_templates(self) -> Sequence[ResourceTemplate]
Return all visible resource templates.
-#### `get_resource_template`
+#### `get_resource_template`
```python
-get_resource_template(self, uri: str) -> ResourceTemplate | None
+get_resource_template(self, uri: str, version: VersionSpec | None = None) -> ResourceTemplate | None
```
-Get a resource template that matches the given URI if visible.
+Get a resource template that matches the given URI.
+
+**Args:**
+- `uri`: The URI to match against templates.
+- `version`: Optional version filter. If None, returns highest version.
-#### `list_prompts`
+#### `list_prompts`
```python
list_prompts(self) -> Sequence[Prompt]
@@ -222,27 +228,20 @@ list_prompts(self) -> Sequence[Prompt]
Return all visible prompts.
-#### `get_prompt`
+#### `get_prompt`
```python
-get_prompt(self, name: str) -> Prompt | None
+get_prompt(self, name: str, version: VersionSpec | None = None) -> Prompt | None
```
-Get a prompt by name if visible.
+Get a prompt by name.
+
+**Args:**
+- `name`: The prompt name.
+- `version`: Optional version filter. If None, returns highest version.
-#### `get_component`
-
-```python
-get_component(self, key: str) -> Tool | Resource | ResourceTemplate | Prompt | None
-```
-
-Get a component by its prefixed key.
-
-Efficient O(1) lookup in the unified components dict.
-
-
-#### `get_tasks`
+#### `get_tasks`
```python
get_tasks(self) -> Sequence[FastMCPComponent]
@@ -255,19 +254,19 @@ This includes both FunctionTool/Resource/Prompt instances created via
decorators and custom Tool/Resource/Prompt subclasses.
-#### `tool`
+#### `tool`
```python
tool(self, name_or_fn: AnyFunction) -> FunctionTool
```
-#### `tool`
+#### `tool`
```python
tool(self, name_or_fn: str | None = None) -> Callable[[AnyFunction], FunctionTool]
```
-#### `tool`
+#### `tool`
```python
tool(self, name_or_fn: str | AnyFunction | None = None) -> Callable[[AnyFunction], FunctionTool] | FunctionTool | partial[Callable[[AnyFunction], FunctionTool] | FunctionTool]
@@ -301,10 +300,10 @@ This decorator supports multiple calling patterns:
- The registered FunctionTool or a decorator function.
-#### `resource`
+#### `resource`
```python
-resource(self, uri: str) -> Callable[[AnyFunction], Resource | ResourceTemplate]
+resource(self, uri: str) -> Callable[[AnyFunction], Resource | ResourceTemplate | AnyFunction]
```
Decorator to register a function as a resource.
@@ -324,24 +323,25 @@ has parameters, it will be registered as a template resource.
- `annotations`: Optional annotations about the resource's behavior
- `meta`: Optional meta information about the resource
- `task`: Optional task configuration for background execution
+- `auth`: Optional authorization checks for the resource
**Returns:**
- A decorator function.
-#### `prompt`
+#### `prompt`
```python
prompt(self, name_or_fn: AnyFunction) -> FunctionPrompt
```
-#### `prompt`
+#### `prompt`
```python
prompt(self, name_or_fn: str | None = None) -> Callable[[AnyFunction], FunctionPrompt]
```
-#### `prompt`
+#### `prompt`
```python
prompt(self, name_or_fn: str | AnyFunction | None = None) -> Callable[[AnyFunction], FunctionPrompt] | FunctionPrompt | partial[Callable[[AnyFunction], FunctionPrompt] | FunctionPrompt]
@@ -366,6 +366,7 @@ This decorator supports multiple calling patterns:
- `enabled`: Whether the prompt is enabled (default True). If False, adds to blocklist.
- `meta`: Optional meta information about the prompt
- `task`: Optional task configuration for background execution
+- `auth`: Optional authorization checks for the prompt
**Returns:**
- The registered FunctionPrompt or a decorator function.
diff --git a/docs/python-sdk/fastmcp-server-providers-openapi-provider.mdx b/docs/python-sdk/fastmcp-server-providers-openapi-provider.mdx
index 2df5a6449..2e262c525 100644
--- a/docs/python-sdk/fastmcp-server-providers-openapi-provider.mdx
+++ b/docs/python-sdk/fastmcp-server-providers-openapi-provider.mdx
@@ -10,7 +10,7 @@ OpenAPIProvider for creating MCP components from OpenAPI specifications.
## Classes
-### `OpenAPIProvider`
+### `OpenAPIProvider`
Provider that creates MCP components from an OpenAPI specification.
@@ -21,7 +21,7 @@ spec. Each component makes HTTP calls to the described API endpoints.
**Methods:**
-#### `list_tools`
+#### `list_tools`
```python
list_tools(self) -> Sequence[Tool]
@@ -30,16 +30,16 @@ list_tools(self) -> Sequence[Tool]
Return all tools created from the OpenAPI spec.
-#### `get_tool`
+#### `get_tool`
```python
-get_tool(self, name: str) -> Tool | None
+get_tool(self, name: str, version: VersionSpec | None = None) -> Tool | None
```
Get a tool by name.
-#### `list_resources`
+#### `list_resources`
```python
list_resources(self) -> Sequence[Resource]
@@ -48,16 +48,16 @@ list_resources(self) -> Sequence[Resource]
Return all resources created from the OpenAPI spec.
-#### `get_resource`
+#### `get_resource`
```python
-get_resource(self, uri: str) -> Resource | None
+get_resource(self, uri: str, version: VersionSpec | None = None) -> Resource | None
```
Get a resource by URI.
-#### `list_resource_templates`
+#### `list_resource_templates`
```python
list_resource_templates(self) -> Sequence[ResourceTemplate]
@@ -66,16 +66,16 @@ list_resource_templates(self) -> Sequence[ResourceTemplate]
Return all resource templates created from the OpenAPI spec.
-#### `get_resource_template`
+#### `get_resource_template`
```python
-get_resource_template(self, uri: str) -> ResourceTemplate | None
+get_resource_template(self, uri: str, version: VersionSpec | None = None) -> ResourceTemplate | None
```
Get a resource template that matches the given URI.
-#### `list_prompts`
+#### `list_prompts`
```python
list_prompts(self) -> Sequence[Prompt]
@@ -84,7 +84,7 @@ list_prompts(self) -> Sequence[Prompt]
Return empty list - OpenAPI doesn't create prompts.
-#### `get_tasks`
+#### `get_tasks`
```python
get_tasks(self) -> Sequence[FastMCPComponent]
diff --git a/docs/python-sdk/fastmcp-server-providers-proxy.mdx b/docs/python-sdk/fastmcp-server-providers-proxy.mdx
index 90e779647..55aca8243 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
@@ -67,7 +67,7 @@ Forward progress notification from remote server to proxy's connected clients.
## Classes
-### `ProxyTool`
+### `ProxyTool`
A Tool that represents and executes a tool on a remote server.
@@ -75,7 +75,7 @@ A Tool that represents and executes a tool on a remote server.
**Methods:**
-#### `model_copy`
+#### `model_copy`
```python
model_copy(self, **kwargs: Any) -> ProxyTool
@@ -84,7 +84,7 @@ model_copy(self, **kwargs: Any) -> ProxyTool
Override to preserve _backend_name when name changes.
-#### `from_mcp_tool`
+#### `from_mcp_tool`
```python
from_mcp_tool(cls, client_factory: ClientFactoryT, mcp_tool: mcp.types.Tool) -> ProxyTool
@@ -93,7 +93,7 @@ from_mcp_tool(cls, client_factory: ClientFactoryT, mcp_tool: mcp.types.Tool) ->
Factory method to create a ProxyTool from a raw MCP tool schema.
-#### `run`
+#### `run`
```python
run(self, arguments: dict[str, Any], context: Context | None = None) -> ToolResult
@@ -102,7 +102,13 @@ run(self, arguments: dict[str, Any], context: Context | None = None) -> ToolResu
Executes the tool by making a call through the client.
-### `ProxyResource`
+#### `get_span_attributes`
+
+```python
+get_span_attributes(self) -> dict[str, Any]
+```
+
+### `ProxyResource`
A Resource that represents and reads a resource from a remote server.
@@ -110,7 +116,7 @@ A Resource that represents and reads a resource from a remote server.
**Methods:**
-#### `model_copy`
+#### `model_copy`
```python
model_copy(self, **kwargs: Any) -> ProxyResource
@@ -119,7 +125,7 @@ model_copy(self, **kwargs: Any) -> ProxyResource
Override to preserve _backend_uri when uri changes.
-#### `from_mcp_resource`
+#### `from_mcp_resource`
```python
from_mcp_resource(cls, client_factory: ClientFactoryT, mcp_resource: mcp.types.Resource) -> ProxyResource
@@ -128,7 +134,7 @@ from_mcp_resource(cls, client_factory: ClientFactoryT, mcp_resource: mcp.types.R
Factory method to create a ProxyResource from a raw MCP resource schema.
-#### `read`
+#### `read`
```python
read(self) -> ResourceResult
@@ -137,7 +143,13 @@ read(self) -> ResourceResult
Read the resource content from the remote server.
-### `ProxyTemplate`
+#### `get_span_attributes`
+
+```python
+get_span_attributes(self) -> dict[str, Any]
+```
+
+### `ProxyTemplate`
A ResourceTemplate that represents and creates resources from a remote server template.
@@ -145,7 +157,7 @@ A ResourceTemplate that represents and creates resources from a remote server te
**Methods:**
-#### `model_copy`
+#### `model_copy`
```python
model_copy(self, **kwargs: Any) -> ProxyTemplate
@@ -154,7 +166,7 @@ model_copy(self, **kwargs: Any) -> ProxyTemplate
Override to preserve _backend_uri_template when uri_template changes.
-#### `from_mcp_template`
+#### `from_mcp_template`
```python
from_mcp_template(cls, client_factory: ClientFactoryT, mcp_template: mcp.types.ResourceTemplate) -> ProxyTemplate
@@ -163,7 +175,7 @@ from_mcp_template(cls, client_factory: ClientFactoryT, mcp_template: mcp.types.R
Factory method to create a ProxyTemplate from a raw MCP template schema.
-#### `create_resource`
+#### `create_resource`
```python
create_resource(self, uri: str, params: dict[str, Any], context: Context | None = None) -> ProxyResource
@@ -172,7 +184,13 @@ create_resource(self, uri: str, params: dict[str, Any], context: Context | None
Create a resource from the template by calling the remote server.
-### `ProxyPrompt`
+#### `get_span_attributes`
+
+```python
+get_span_attributes(self) -> dict[str, Any]
+```
+
+### `ProxyPrompt`
A Prompt that represents and renders a prompt from a remote server.
@@ -180,7 +198,7 @@ A Prompt that represents and renders a prompt from a remote server.
**Methods:**
-#### `model_copy`
+#### `model_copy`
```python
model_copy(self, **kwargs: Any) -> ProxyPrompt
@@ -189,7 +207,7 @@ model_copy(self, **kwargs: Any) -> ProxyPrompt
Override to preserve _backend_name when name changes.
-#### `from_mcp_prompt`
+#### `from_mcp_prompt`
```python
from_mcp_prompt(cls, client_factory: ClientFactoryT, mcp_prompt: mcp.types.Prompt) -> ProxyPrompt
@@ -198,7 +216,7 @@ from_mcp_prompt(cls, client_factory: ClientFactoryT, mcp_prompt: mcp.types.Promp
Factory method to create a ProxyPrompt from a raw MCP prompt schema.
-#### `render`
+#### `render`
```python
render(self, arguments: dict[str, Any]) -> PromptResult
@@ -207,7 +225,13 @@ render(self, arguments: dict[str, Any]) -> PromptResult
Render the prompt by making a call through the client.
-### `ProxyProvider`
+#### `get_span_attributes`
+
+```python
+get_span_attributes(self) -> dict[str, Any]
+```
+
+### `ProxyProvider`
Provider that proxies to a remote MCP server via a client factory.
@@ -221,7 +245,7 @@ because tasks cannot be executed through a proxy.
**Methods:**
-#### `list_tools`
+#### `list_tools`
```python
list_tools(self) -> Sequence[Tool]
@@ -230,7 +254,7 @@ list_tools(self) -> Sequence[Tool]
List all tools from the remote server.
-#### `list_resources`
+#### `list_resources`
```python
list_resources(self) -> Sequence[Resource]
@@ -239,7 +263,7 @@ list_resources(self) -> Sequence[Resource]
List all resources from the remote server.
-#### `list_resource_templates`
+#### `list_resource_templates`
```python
list_resource_templates(self) -> Sequence[ResourceTemplate]
@@ -248,7 +272,7 @@ list_resource_templates(self) -> Sequence[ResourceTemplate]
List all resource templates from the remote server.
-#### `list_prompts`
+#### `list_prompts`
```python
list_prompts(self) -> Sequence[Prompt]
@@ -257,7 +281,7 @@ list_prompts(self) -> Sequence[Prompt]
List all prompts from the remote server.
-#### `get_tasks`
+#### `get_tasks`
```python
get_tasks(self) -> Sequence[FastMCPComponent]
@@ -270,7 +294,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.
@@ -279,7 +303,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.
@@ -287,7 +311,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.
@@ -301,7 +325,7 @@ Note that it is essential to ensure that the proxy server itself is also statefu
**Methods:**
-#### `clear`
+#### `clear`
```python
clear(self)
@@ -310,7 +334,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-providers-transforming.mdx b/docs/python-sdk/fastmcp-server-providers-transforming.mdx
deleted file mode 100644
index 94952eac2..000000000
--- a/docs/python-sdk/fastmcp-server-providers-transforming.mdx
+++ /dev/null
@@ -1,117 +0,0 @@
----
-title: transforming
-sidebarTitle: transforming
----
-
-# `fastmcp.server.providers.transforming`
-
-
-TransformingProvider for applying component transformations.
-
-This module provides the `TransformingProvider` class that wraps any Provider
-and applies transformations like namespace prefixes and tool renames.
-
-
-## Classes
-
-### `TransformingProvider`
-
-
-Wraps any provider and applies component transformations.
-
-Users typically use `provider.with_transforms()` rather than instantiating
-this class directly. Multiple `.with_transforms()` calls stack - each
-creates a new wrapper that composes with the previous.
-
-
-**Methods:**
-
-#### `list_tools`
-
-```python
-list_tools(self) -> Sequence[Tool]
-```
-
-List tools with transformations applied.
-
-
-#### `get_tool`
-
-```python
-get_tool(self, name: str) -> Tool | None
-```
-
-Get tool by transformed name.
-
-
-#### `list_resources`
-
-```python
-list_resources(self) -> Sequence[Resource]
-```
-
-List resources with URI transformations applied.
-
-
-#### `get_resource`
-
-```python
-get_resource(self, uri: str) -> Resource | None
-```
-
-Get resource by transformed URI.
-
-
-#### `list_resource_templates`
-
-```python
-list_resource_templates(self) -> Sequence[ResourceTemplate]
-```
-
-List resource templates with URI transformations applied.
-
-
-#### `get_resource_template`
-
-```python
-get_resource_template(self, uri: str) -> ResourceTemplate | None
-```
-
-Get resource template by transformed URI.
-
-
-#### `list_prompts`
-
-```python
-list_prompts(self) -> Sequence[Prompt]
-```
-
-List prompts with transformations applied.
-
-
-#### `get_prompt`
-
-```python
-get_prompt(self, name: str) -> Prompt | None
-```
-
-Get prompt by transformed name.
-
-
-#### `get_tasks`
-
-```python
-get_tasks(self) -> Sequence[FastMCPComponent]
-```
-
-Get tasks with transformations applied to all components.
-
-
-#### `lifespan`
-
-```python
-lifespan(self) -> AsyncIterator[None]
-```
-
-Delegate lifespan to wrapped provider.
-
diff --git a/docs/python-sdk/fastmcp-server-server.mdx b/docs/python-sdk/fastmcp-server-server.mdx
index da73702c3..0268f02b6 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,59 @@ use `FastMCPProxy` or `ProxyProvider` directly from `fastmcp.server.providers.pr
## Classes
-### `FastMCP`
+### `StateValue`
+
+
+Wrapper for stored context state values.
+
+
+### `FastMCP`
**Methods:**
-#### `settings`
+#### `settings`
```python
settings(self) -> Settings
```
-#### `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]
```
-#### `docket`
+#### `docket`
```python
docket(self) -> Docket | None
@@ -111,7 +117,7 @@ Get the Docket instance if Docket support is enabled.
Returns None if Docket is not enabled or server hasn't been started yet.
-#### `run_async`
+#### `run_async`
```python
run_async(self, transport: Transport | None = None, show_banner: bool | None = None, **transport_kwargs: Any) -> None
@@ -125,7 +131,7 @@ Run the FastMCP server asynchronously.
FASTMCP_SHOW_SERVER_BANNER setting (default\: True).
-#### `run`
+#### `run`
```python
run(self, transport: Transport | None = None, show_banner: bool | None = None, **transport_kwargs: Any) -> None
@@ -139,13 +145,13 @@ Run the FastMCP server. Note this is a synchronous function.
FASTMCP_SHOW_SERVER_BANNER setting (default\: True).
-#### `add_middleware`
+#### `add_middleware`
```python
add_middleware(self, middleware: Middleware) -> None
```
-#### `add_provider`
+#### `add_provider`
```python
add_provider(self, provider: Provider) -> None
@@ -161,7 +167,46 @@ always take precedence over providers.
- `provider`: A Provider instance that will provide components dynamically.
-#### `enable`
+#### `add_transform`
+
+```python
+add_transform(self, transform: Transform) -> None
+```
+
+Add a server-level transform.
+
+Server-level transforms are applied after all providers are aggregated.
+They transform tools, resources, and prompts from ALL providers.
+
+**Args:**
+- `transform`: The transform to add.
+
+
+#### `add_tool_transformation`
+
+```python
+add_tool_transformation(self, tool_name: str, transformation: ToolTransformConfig) -> None
+```
+
+Add a tool transformation.
+
+.. deprecated::
+ Use ``add_transform(ToolTransform({...}))`` instead.
+
+
+#### `remove_tool_transformation`
+
+```python
+remove_tool_transformation(self, _tool_name: str) -> None
+```
+
+Remove a tool transformation.
+
+.. deprecated::
+ Tool transformations are now immutable. Use visibility controls instead.
+
+
+#### `enable`
```python
enable(self) -> None
@@ -170,13 +215,13 @@ enable(self) -> None
Enable components by removing from blocklist, or set allowlist with only=True.
**Args:**
-- `keys`: Keys to enable (e.g., ``"tool\:my_tool"``).
+- `keys`: Keys to enable (e.g., ``"tool\:my_tool@"`` for unversioned, ``"tool\:my_tool@1.0"`` for versioned).
- `tags`: Tags to enable - components with these tags will be enabled.
- `only`: If True, switches to allowlist mode - ONLY show these keys/tags.
This clears existing allowlists and sets default visibility to False.
-#### `disable`
+#### `disable`
```python
disable(self) -> None
@@ -185,11 +230,11 @@ disable(self) -> None
Disable components by adding to the blocklist.
**Args:**
-- `keys`: Keys to disable (e.g., ``"tool\:my_tool"``).
+- `keys`: Keys to disable (e.g., ``"tool\:my_tool@"`` for unversioned, ``"tool\:my_tool@1.0"`` for versioned).
- `tags`: Tags to disable - components with these tags will be disabled.
-#### `get_tools`
+#### `get_tools`
```python
get_tools(self) -> list[Tool]
@@ -197,27 +242,34 @@ get_tools(self) -> list[Tool]
Get all enabled tools from providers.
-Queries all providers in parallel and collects tools.
-First provider wins for duplicate keys. Filters by server blocklist.
+Queries all providers via the root provider (which applies provider transforms,
+server transforms, and visibility filtering). First provider wins for duplicate keys.
**Args:**
- `run_middleware`: If True, apply the middleware chain before
returning results. Used by MCP handlers and mounted servers.
-#### `get_tool`
+#### `get_tool`
```python
-get_tool(self, name: str) -> Tool
+get_tool(self, name: str, version: VersionSpec | str | None = None) -> Tool
```
Get an enabled tool by name.
-Queries all providers in parallel to find the tool.
-First provider wins. Returns only if enabled.
+Queries providers with full transform chain (provider transforms + server transforms + visibility).
+Returns only if enabled and authorized.
+
+**Args:**
+- `name`: The tool name.
+- `version`: Version filter. Can be\:
+- None\: returns highest version
+- str\: returns exact version match
+- VersionSpec\: returns best match within spec (highest matching)
-#### `get_resources`
+#### `get_resources`
```python
get_resources(self) -> list[Resource]
@@ -225,27 +277,34 @@ get_resources(self) -> list[Resource]
Get all enabled resources from providers.
-Queries all providers in parallel and collects resources.
-First provider wins for duplicate keys. Filters by server blocklist.
+Queries all providers via the root provider (which applies provider transforms,
+server transforms, and visibility filtering). First provider wins for duplicate keys.
**Args:**
- `run_middleware`: If True, apply the middleware chain before
returning results. Used by MCP handlers and mounted servers.
-#### `get_resource`
+#### `get_resource`
```python
-get_resource(self, uri: str) -> Resource
+get_resource(self, uri: str, version: VersionSpec | str | None = None) -> Resource
```
Get an enabled resource by URI.
-Queries all providers in parallel to find the resource.
-First provider wins. Returns only if enabled.
+Queries providers with full transform chain (provider transforms + server transforms + visibility).
+Returns only if enabled and authorized.
+
+**Args:**
+- `uri`: The resource URI.
+- `version`: Version filter. Can be\:
+- None\: returns highest version
+- str\: returns exact version match
+- VersionSpec\: returns best match within spec (highest matching)
-#### `get_resource_templates`
+#### `get_resource_templates`
```python
get_resource_templates(self) -> list[ResourceTemplate]
@@ -253,27 +312,34 @@ get_resource_templates(self) -> list[ResourceTemplate]
Get all enabled resource templates from providers.
-Queries all providers in parallel and collects templates.
-First provider wins for duplicate keys. Filters by server blocklist.
+Queries all providers via the root provider (which applies provider transforms,
+server transforms, and visibility filtering). First provider wins for duplicate keys.
**Args:**
- `run_middleware`: If True, apply the middleware chain before
returning results. Used by MCP handlers and mounted servers.
-#### `get_resource_template`
+#### `get_resource_template`
```python
-get_resource_template(self, uri: str) -> ResourceTemplate
+get_resource_template(self, uri: str, version: VersionSpec | str | None = None) -> ResourceTemplate
```
Get an enabled resource template that matches the given URI.
-Queries all providers in parallel to find the template.
-First provider wins. Returns only if enabled.
+Queries providers with full transform chain (provider transforms + server transforms + visibility).
+Returns only if enabled and authorized.
+
+**Args:**
+- `uri`: The template URI to match.
+- `version`: Version filter. Can be\:
+- None\: returns highest version
+- str\: returns exact version match
+- VersionSpec\: returns best match within spec (highest matching)
-#### `get_prompts`
+#### `get_prompts`
```python
get_prompts(self) -> list[Prompt]
@@ -281,60 +347,46 @@ get_prompts(self) -> list[Prompt]
Get all enabled prompts from providers.
-Queries all providers in parallel and collects prompts.
-First provider wins for duplicate keys. Filters by server blocklist.
+Queries all providers via the root provider (which applies provider transforms,
+server transforms, and visibility filtering). First provider wins for duplicate keys.
**Args:**
- `run_middleware`: If True, apply the middleware chain before
returning results. Used by MCP handlers and mounted servers.
-#### `get_prompt`
+#### `get_prompt`
```python
-get_prompt(self, name: str) -> Prompt
+get_prompt(self, name: str, version: VersionSpec | str | None = None) -> Prompt
```
Get an enabled prompt by name.
-Queries all providers in parallel to find the prompt.
-First provider wins. Returns only if enabled.
-
-
-#### `get_component`
-
-```python
-get_component(self, key: str) -> Tool | Resource | ResourceTemplate | Prompt
-```
-
-Get a component by its prefixed key.
-
-Queries all providers in parallel to find the component.
-First provider wins.
+Queries providers with full transform chain (provider transforms + server transforms + visibility).
+Returns only if enabled and authorized.
**Args:**
-- `key`: The prefixed key (e.g., "tool\:name", "resource\:uri", "template\:uri").
-
-**Returns:**
-- The component if found.
-
-**Raises:**
-- `NotFoundError`: If no component is found with the given key.
+- `name`: The prompt name.
+- `version`: Version filter. Can be\:
+- None\: returns highest version
+- str\: returns exact version match
+- VersionSpec\: returns best match within spec (highest matching)
-#### `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
@@ -363,19 +415,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
@@ -403,19 +455,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
@@ -444,7 +496,7 @@ return PromptResult.
- `PromptError`: If prompt rendering fails
-#### `custom_route`
+#### `custom_route`
```python
custom_route(self, path: str, methods: list[str], name: str | None = None, include_in_schema: bool = True) -> Callable[[Callable[[Request], Awaitable[Response]]], Callable[[Request], Awaitable[Response]]]
@@ -465,10 +517,10 @@ Starlette's reverse URL lookup feature)
- `include_in_schema`: Whether to include in OpenAPI schema, defaults to True
-#### `add_tool`
+#### `add_tool`
```python
-add_tool(self, tool: Tool) -> Tool
+add_tool(self, tool: Tool | Callable[..., Any]) -> Tool
```
Add a tool to the server.
@@ -477,58 +529,41 @@ The tool function can optionally request a Context object by adding a parameter
with the Context type annotation. See the @tool decorator for examples.
**Args:**
-- `tool`: The Tool instance to register
+- `tool`: The Tool instance or @tool-decorated function to register
**Returns:**
- The tool instance that was added to the server.
-#### `remove_tool`
+#### `remove_tool`
```python
-remove_tool(self, name: str) -> None
+remove_tool(self, name: str, version: str | None = None) -> None
```
-Remove a tool from the server.
+Remove tool(s) from the server.
**Args:**
-- `name`: The name of the tool to remove
+- `name`: The name of the tool to remove.
+- `version`: If None, removes ALL versions. If specified, removes only that version.
**Raises:**
-- `NotFoundError`: If the tool is not found
+- `NotFoundError`: If no matching tool is found.
-#### `add_tool_transformation`
-
-```python
-add_tool_transformation(self, tool_name: str, transformation: ToolTransformConfig) -> None
-```
-
-Add a tool transformation.
-
-
-#### `remove_tool_transformation`
-
-```python
-remove_tool_transformation(self, tool_name: str) -> None
-```
-
-Remove a tool transformation.
-
-
-#### `tool`
+#### `tool`
```python
tool(self, name_or_fn: AnyFunction) -> FunctionTool
```
-#### `tool`
+#### `tool`
```python
tool(self, name_or_fn: str | None = None) -> Callable[[AnyFunction], FunctionTool]
```
-#### `tool`
+#### `tool`
```python
tool(self, name_or_fn: str | AnyFunction | None = None) -> Callable[[AnyFunction], FunctionTool] | FunctionTool | partial[Callable[[AnyFunction], FunctionTool] | FunctionTool]
@@ -584,22 +619,22 @@ server.tool(my_function, name="custom_name")
```
-#### `add_resource`
+#### `add_resource`
```python
-add_resource(self, resource: Resource) -> Resource
+add_resource(self, resource: Resource | Callable[..., Any]) -> Resource | ResourceTemplate
```
Add a resource to the server.
**Args:**
-- `resource`: A Resource instance to add
+- `resource`: A Resource instance or @resource-decorated function to add
**Returns:**
- The resource instance that was added to the server.
-#### `add_template`
+#### `add_template`
```python
add_template(self, template: ResourceTemplate) -> ResourceTemplate
@@ -614,10 +649,10 @@ Add a resource template to the server.
- The template instance that was added to the server.
-#### `resource`
+#### `resource`
```python
-resource(self, uri: str) -> Callable[[AnyFunction], Resource | ResourceTemplate]
+resource(self, uri: str) -> Callable[[AnyFunction], Resource | ResourceTemplate | AnyFunction]
```
Decorator to register a function as a resource.
@@ -673,34 +708,34 @@ async def get_weather(city: str) -> str:
```
-#### `add_prompt`
+#### `add_prompt`
```python
-add_prompt(self, prompt: Prompt) -> Prompt
+add_prompt(self, prompt: Prompt | Callable[..., Any]) -> Prompt
```
Add a prompt to the server.
**Args:**
-- `prompt`: A Prompt instance to add
+- `prompt`: A Prompt instance or @prompt-decorated function to add
**Returns:**
- The prompt instance that was added to the server.
-#### `prompt`
+#### `prompt`
```python
prompt(self, name_or_fn: AnyFunction) -> FunctionPrompt
```
-#### `prompt`
+#### `prompt`
```python
prompt(self, name_or_fn: str | None = None) -> Callable[[AnyFunction], FunctionPrompt]
```
-#### `prompt`
+#### `prompt`
```python
prompt(self, name_or_fn: str | AnyFunction | None = None) -> Callable[[AnyFunction], FunctionPrompt] | FunctionPrompt | partial[Callable[[AnyFunction], FunctionPrompt] | FunctionPrompt]
@@ -777,7 +812,7 @@ Decorator to register a prompt.
```
-#### `run_stdio_async`
+#### `run_stdio_async`
```python
run_stdio_async(self, show_banner: bool = True, log_level: str | None = None, stateless: bool = False) -> None
@@ -791,7 +826,7 @@ Run the server using stdio transport.
- `stateless`: Whether to run in stateless mode (no session initialization)
-#### `run_http_async`
+#### `run_http_async`
```python
run_http_async(self, show_banner: bool = True, transport: Literal['http', 'streamable-http', 'sse'] = 'http', host: str | None = None, port: int | None = None, log_level: str | None = None, path: str | None = None, uvicorn_config: dict[str, Any] | None = None, middleware: list[ASGIMiddleware] | None = None, json_response: bool | None = None, stateless_http: bool | None = None, stateless: bool | None = None) -> None
@@ -812,7 +847,7 @@ Run the server using HTTP transport.
- `stateless`: Alias for stateless_http for CLI consistency
-#### `http_app`
+#### `http_app`
```python
http_app(self, 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
@@ -838,7 +873,7 @@ streamable-http transport.
- A Starlette application configured with the specified transport
-#### `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
@@ -885,7 +920,7 @@ mounted server.
- `prefix`: Deprecated. Use namespace instead.
-#### `import_server`
+#### `import_server`
```python
import_server(self, server: FastMCP[LifespanResultT], prefix: str | None = None) -> None
@@ -926,7 +961,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, 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, timeout: float | None = None, **settings: Any) -> Self
@@ -950,7 +985,7 @@ Create a FastMCP server from an OpenAPI specification.
- 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, timeout: float | None = None, **settings: Any) -> Self
@@ -974,7 +1009,7 @@ Create a FastMCP server from a FastAPI application.
- 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
@@ -992,7 +1027,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 6b8c78e3e..77c1467d3 100644
--- a/docs/python-sdk/fastmcp-server-tasks-capabilities.mdx
+++ b/docs/python-sdk/fastmcp-server-tasks-capabilities.mdx
@@ -10,15 +10,20 @@ SEP-1686 task capabilities declaration.
## Functions
-### `get_task_capabilities`
+### `get_task_capabilities`
```python
-get_task_capabilities() -> dict[str, Any]
+get_task_capabilities() -> ServerTasksCapability | None
```
-Return the SEP-1686 task capabilities structure.
+Return the SEP-1686 task capabilities.
-This is the standard capabilities map advertised to clients,
-declaring support for list, cancel, and request operations.
+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).
+
+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-server-tasks-config.mdx b/docs/python-sdk/fastmcp-server-tasks-config.mdx
index 129fe896c..2dbbc63dd 100644
--- a/docs/python-sdk/fastmcp-server-tasks-config.mdx
+++ b/docs/python-sdk/fastmcp-server-tasks-config.mdx
@@ -14,7 +14,7 @@ handle task-augmented execution as specified in SEP-1686.
## Classes
-### `TaskMeta`
+### `TaskMeta`
Metadata for task-augmented execution requests.
@@ -27,7 +27,7 @@ the operation should be submitted as a background task.
- `fn_key`: Docket routing key. Auto-derived from component name if None.
-### `TaskConfig`
+### `TaskConfig`
Configuration for MCP background task execution (SEP-1686).
@@ -44,7 +44,7 @@ Controls how a component handles task-augmented requests:
**Methods:**
-#### `from_bool`
+#### `from_bool`
```python
from_bool(cls, value: bool) -> TaskConfig
@@ -59,7 +59,7 @@ Convert boolean task flag to TaskConfig.
- TaskConfig with appropriate mode.
-#### `supports_tasks`
+#### `supports_tasks`
```python
supports_tasks(self) -> bool
@@ -71,7 +71,7 @@ Check if this component supports task execution.
- True if mode is "optional" or "required", False if "forbidden".
-#### `validate_function`
+#### `validate_function`
```python
validate_function(self, fn: Callable[..., Any], name: str) -> None
@@ -79,13 +79,18 @@ validate_function(self, fn: Callable[..., Any], name: str) -> None
Validate that function is compatible with this task config.
-Task execution requires async functions. Raises ValueError if mode
-is "optional" or "required" but function is synchronous.
+Task execution requires:
+1. fastmcp[tasks] to be installed (pydocket)
+2. Async functions
+
+Raises ImportError if mode is "optional" or "required" but pydocket
+is not installed. Raises ValueError if function is synchronous.
**Args:**
- `fn`: The function to validate (handles callable classes and staticmethods).
- `name`: Name for error messages.
**Raises:**
+- `ImportError`: If task execution is enabled but pydocket not installed.
- `ValueError`: If task execution is enabled but function is sync.
diff --git a/docs/python-sdk/fastmcp-server-tasks-requests.mdx b/docs/python-sdk/fastmcp-server-tasks-requests.mdx
index 75fe1ca67..50f77596a 100644
--- a/docs/python-sdk/fastmcp-server-tasks-requests.mdx
+++ b/docs/python-sdk/fastmcp-server-tasks-requests.mdx
@@ -11,10 +11,12 @@ SEP-1686 task request handlers.
Handles MCP task protocol requests: tasks/get, tasks/result, tasks/list, tasks/cancel.
These handlers query and manage existing tasks (contrast with handlers.py which creates tasks).
+This module requires fastmcp[tasks] (pydocket). It is only imported when docket is available.
+
## Functions
-### `tasks_get_handler`
+### `tasks_get_handler`
```python
tasks_get_handler(server: FastMCP, params: dict[str, Any]) -> GetTaskResult
@@ -31,7 +33,7 @@ Handle MCP 'tasks/get' request (SEP-1686).
- Task status response with spec-compliant fields
-### `tasks_result_handler`
+### `tasks_result_handler`
```python
tasks_result_handler(server: FastMCP, params: dict[str, Any]) -> Any
@@ -50,7 +52,7 @@ Converts raw task return values to MCP types based on task type.
- MCP result (CallToolResult, GetPromptResult, or ReadResourceResult)
-### `tasks_list_handler`
+### `tasks_list_handler`
```python
tasks_list_handler(server: FastMCP, params: dict[str, Any]) -> ListTasksResult
@@ -69,7 +71,7 @@ Note: With client-side tracking, this returns minimal info.
- Response with tasks list and pagination
-### `tasks_cancel_handler`
+### `tasks_cancel_handler`
```python
tasks_cancel_handler(server: FastMCP, params: dict[str, Any]) -> CancelTaskResult
diff --git a/docs/python-sdk/fastmcp-server-tasks-subscriptions.mdx b/docs/python-sdk/fastmcp-server-tasks-subscriptions.mdx
index 1b4331212..1b611ea9c 100644
--- a/docs/python-sdk/fastmcp-server-tasks-subscriptions.mdx
+++ b/docs/python-sdk/fastmcp-server-tasks-subscriptions.mdx
@@ -11,10 +11,12 @@ Task subscription helpers for sending MCP notifications (SEP-1686).
Subscribes to Docket execution state changes and sends notifications/tasks/status
to clients when their tasks change state.
+This module requires fastmcp[tasks] (pydocket). It is only imported when docket is available.
+
## Functions
-### `subscribe_to_task_updates`
+### `subscribe_to_task_updates`
```python
subscribe_to_task_updates(task_id: str, task_key: str, session: ServerSession, docket: Docket, poll_interval_ms: int = 5000) -> None
diff --git a/docs/python-sdk/fastmcp-server-telemetry.mdx b/docs/python-sdk/fastmcp-server-telemetry.mdx
new file mode 100644
index 000000000..a842c468d
--- /dev/null
+++ b/docs/python-sdk/fastmcp-server-telemetry.mdx
@@ -0,0 +1,56 @@
+---
+title: telemetry
+sidebarTitle: telemetry
+---
+
+# `fastmcp.server.telemetry`
+
+
+Server-side telemetry helpers.
+
+## Functions
+
+### `get_auth_span_attributes`
+
+```python
+get_auth_span_attributes() -> dict[str, str]
+```
+
+
+Get auth attributes for the current request, if authenticated.
+
+
+### `get_session_span_attributes`
+
+```python
+get_session_span_attributes() -> dict[str, str]
+```
+
+
+Get session attributes for the current request.
+
+
+### `server_span`
+
+```python
+server_span(name: str, method: str, server_name: str, component_type: str, component_key: str, resource_uri: str | None = None) -> Generator[Span, None, None]
+```
+
+
+Create a SERVER span with standard MCP attributes and auth context.
+
+Automatically records any exception on the span and sets error status.
+
+
+### `delegate_span`
+
+```python
+delegate_span(name: str, provider_type: str, component_key: str) -> Generator[Span, None, None]
+```
+
+
+Create an INTERNAL span for provider delegation.
+
+Used by FastMCPProvider when delegating to mounted servers.
+Automatically records any exception on the span and sets error status.
+
diff --git a/docs/python-sdk/fastmcp-server-transforms-__init__.mdx b/docs/python-sdk/fastmcp-server-transforms-__init__.mdx
new file mode 100644
index 000000000..6b7e5db17
--- /dev/null
+++ b/docs/python-sdk/fastmcp-server-transforms-__init__.mdx
@@ -0,0 +1,196 @@
+---
+title: __init__
+sidebarTitle: __init__
+---
+
+# `fastmcp.server.transforms`
+
+
+Transform system for component transformations.
+
+Transforms modify components (tools, resources, prompts) using a middleware pattern.
+Each transform wraps the next in the chain via `call_next`, allowing transforms to
+intercept, modify, or replace component queries.
+
+Unlike middleware (which operates on requests), transforms are observable by the
+system for task registration, tag filtering, and component introspection.
+
+Example:
+ ```python
+ from fastmcp import FastMCP
+ from fastmcp.server.transforms import Namespace
+
+ server = FastMCP("Server")
+ mount = server.mount(other_server)
+ mount.add_transform(Namespace("api")) # Tools become api_toolname
+ ```
+
+
+## Classes
+
+### `GetToolNext`
+
+
+Protocol for get_tool call_next functions.
+
+
+### `GetResourceNext`
+
+
+Protocol for get_resource call_next functions.
+
+
+### `GetResourceTemplateNext`
+
+
+Protocol for get_resource_template call_next functions.
+
+
+### `GetPromptNext`
+
+
+Protocol for get_prompt call_next functions.
+
+
+### `Transform`
+
+
+Base class for component transformations.
+
+Transforms use a middleware pattern with `call_next` to chain operations.
+Each transform can intercept, modify, or pass through component queries.
+
+For list operations, call `call_next()` to get components from downstream,
+then transform the result. For get operations, optionally transform the
+name/uri before calling `call_next`, then transform the result.
+
+
+**Methods:**
+
+#### `list_tools`
+
+```python
+list_tools(self, call_next: ListToolsNext) -> Sequence[Tool]
+```
+
+List tools with transformation applied.
+
+**Args:**
+- `call_next`: Callable to get tools from downstream transforms/provider.
+
+**Returns:**
+- Transformed sequence of tools.
+
+
+#### `get_tool`
+
+```python
+get_tool(self, name: str, call_next: GetToolNext) -> Tool | None
+```
+
+Get a tool by name.
+
+**Args:**
+- `name`: The requested tool name (may be transformed).
+- `call_next`: Callable to get tool from downstream.
+- `version`: Optional version filter to apply.
+
+**Returns:**
+- The tool if found, None otherwise.
+
+
+#### `list_resources`
+
+```python
+list_resources(self, call_next: ListResourcesNext) -> Sequence[Resource]
+```
+
+List resources with transformation applied.
+
+**Args:**
+- `call_next`: Callable to get resources from downstream transforms/provider.
+
+**Returns:**
+- Transformed sequence of resources.
+
+
+#### `get_resource`
+
+```python
+get_resource(self, uri: str, call_next: GetResourceNext) -> Resource | None
+```
+
+Get a resource by URI.
+
+**Args:**
+- `uri`: The requested resource URI (may be transformed).
+- `call_next`: Callable to get resource from downstream.
+- `version`: Optional version filter to apply.
+
+**Returns:**
+- The resource if found, None otherwise.
+
+
+#### `list_resource_templates`
+
+```python
+list_resource_templates(self, call_next: ListResourceTemplatesNext) -> Sequence[ResourceTemplate]
+```
+
+List resource templates with transformation applied.
+
+**Args:**
+- `call_next`: Callable to get templates from downstream transforms/provider.
+
+**Returns:**
+- Transformed sequence of resource templates.
+
+
+#### `get_resource_template`
+
+```python
+get_resource_template(self, uri: str, call_next: GetResourceTemplateNext) -> ResourceTemplate | None
+```
+
+Get a resource template by URI.
+
+**Args:**
+- `uri`: The requested template URI (may be transformed).
+- `call_next`: Callable to get template from downstream.
+- `version`: Optional version filter to apply.
+
+**Returns:**
+- The resource template if found, None otherwise.
+
+
+#### `list_prompts`
+
+```python
+list_prompts(self, call_next: ListPromptsNext) -> Sequence[Prompt]
+```
+
+List prompts with transformation applied.
+
+**Args:**
+- `call_next`: Callable to get prompts from downstream transforms/provider.
+
+**Returns:**
+- Transformed sequence of prompts.
+
+
+#### `get_prompt`
+
+```python
+get_prompt(self, name: str, call_next: GetPromptNext) -> Prompt | None
+```
+
+Get a prompt by name.
+
+**Args:**
+- `name`: The requested prompt name (may be transformed).
+- `call_next`: Callable to get prompt from downstream.
+- `version`: Optional version filter to apply.
+
+**Returns:**
+- The prompt if found, None otherwise.
+
diff --git a/docs/python-sdk/fastmcp-server-transforms-namespace.mdx b/docs/python-sdk/fastmcp-server-transforms-namespace.mdx
new file mode 100644
index 000000000..0260e3a2e
--- /dev/null
+++ b/docs/python-sdk/fastmcp-server-transforms-namespace.mdx
@@ -0,0 +1,96 @@
+---
+title: namespace
+sidebarTitle: namespace
+---
+
+# `fastmcp.server.transforms.namespace`
+
+
+Namespace transform for prefixing component names.
+
+## Classes
+
+### `Namespace`
+
+
+Prefixes component names with a namespace.
+
+- Tools: name → namespace_name
+- Prompts: name → namespace_name
+- Resources: protocol://path → protocol://namespace/path
+- Resource Templates: same as resources
+
+
+**Methods:**
+
+#### `list_tools`
+
+```python
+list_tools(self, call_next: ListToolsNext) -> Sequence[Tool]
+```
+
+Prefix tool names with namespace.
+
+
+#### `get_tool`
+
+```python
+get_tool(self, name: str, call_next: GetToolNext) -> Tool | None
+```
+
+Get tool by namespaced name.
+
+
+#### `list_resources`
+
+```python
+list_resources(self, call_next: ListResourcesNext) -> Sequence[Resource]
+```
+
+Add namespace path segment to resource URIs.
+
+
+#### `get_resource`
+
+```python
+get_resource(self, uri: str, call_next: GetResourceNext) -> Resource | None
+```
+
+Get resource by namespaced URI.
+
+
+#### `list_resource_templates`
+
+```python
+list_resource_templates(self, call_next: ListResourceTemplatesNext) -> Sequence[ResourceTemplate]
+```
+
+Add namespace path segment to template URIs.
+
+
+#### `get_resource_template`
+
+```python
+get_resource_template(self, uri: str, call_next: GetResourceTemplateNext) -> ResourceTemplate | None
+```
+
+Get resource template by namespaced URI.
+
+
+#### `list_prompts`
+
+```python
+list_prompts(self, call_next: ListPromptsNext) -> Sequence[Prompt]
+```
+
+Prefix prompt names with namespace.
+
+
+#### `get_prompt`
+
+```python
+get_prompt(self, name: str, call_next: GetPromptNext) -> Prompt | None
+```
+
+Get prompt by namespaced name.
+
diff --git a/docs/python-sdk/fastmcp-server-transforms-tool_transform.mdx b/docs/python-sdk/fastmcp-server-transforms-tool_transform.mdx
new file mode 100644
index 000000000..417e18f77
--- /dev/null
+++ b/docs/python-sdk/fastmcp-server-transforms-tool_transform.mdx
@@ -0,0 +1,40 @@
+---
+title: tool_transform
+sidebarTitle: tool_transform
+---
+
+# `fastmcp.server.transforms.tool_transform`
+
+
+Transform for applying tool transformations.
+
+## Classes
+
+### `ToolTransform`
+
+
+Applies tool transformations to modify tool schemas.
+
+Wraps ToolTransformConfig to apply argument renames, schema changes,
+hidden arguments, and other transformations at the transform level.
+
+
+**Methods:**
+
+#### `list_tools`
+
+```python
+list_tools(self, call_next: ListToolsNext) -> Sequence[Tool]
+```
+
+Apply transforms to matching tools.
+
+
+#### `get_tool`
+
+```python
+get_tool(self, name: str, call_next: GetToolNext) -> Tool | None
+```
+
+Get tool by transformed name.
+
diff --git a/docs/python-sdk/fastmcp-server-transforms-version_filter.mdx b/docs/python-sdk/fastmcp-server-transforms-version_filter.mdx
new file mode 100644
index 000000000..7a2e43431
--- /dev/null
+++ b/docs/python-sdk/fastmcp-server-transforms-version_filter.mdx
@@ -0,0 +1,85 @@
+---
+title: version_filter
+sidebarTitle: version_filter
+---
+
+# `fastmcp.server.transforms.version_filter`
+
+
+Version filter transform for filtering components by version range.
+
+## Classes
+
+### `VersionFilter`
+
+
+Filters components by version range.
+
+When applied to a provider or server, only components within the version
+range are visible. Within that filtered set, the highest version of each
+component is exposed to clients (standard deduplication behavior).
+
+Parameters mirror comparison operators for clarity:
+
+ # Versions < 3.0 (v1 and v2)
+ server.add_transform(VersionFilter(version_lt="3.0"))
+
+ # Versions >= 2.0 and < 3.0 (only v2.x)
+ server.add_transform(VersionFilter(version_gte="2.0", version_lt="3.0"))
+
+Works with any version string - PEP 440 (1.0, 2.0) or dates (2025-01-01).
+
+**Args:**
+- `version_gte`: Versions >= this value pass through.
+- `version_lt`: Versions < this value pass through.
+
+
+**Methods:**
+
+#### `list_tools`
+
+```python
+list_tools(self, call_next: ListToolsNext) -> Sequence[Tool]
+```
+
+#### `get_tool`
+
+```python
+get_tool(self, name: str, call_next: GetToolNext) -> Tool | None
+```
+
+#### `list_resources`
+
+```python
+list_resources(self, call_next: ListResourcesNext) -> Sequence[Resource]
+```
+
+#### `get_resource`
+
+```python
+get_resource(self, uri: str, call_next: GetResourceNext) -> Resource | None
+```
+
+#### `list_resource_templates`
+
+```python
+list_resource_templates(self, call_next: ListResourceTemplatesNext) -> Sequence[ResourceTemplate]
+```
+
+#### `get_resource_template`
+
+```python
+get_resource_template(self, uri: str, call_next: GetResourceTemplateNext) -> ResourceTemplate | None
+```
+
+#### `list_prompts`
+
+```python
+list_prompts(self, call_next: ListPromptsNext) -> Sequence[Prompt]
+```
+
+#### `get_prompt`
+
+```python
+get_prompt(self, name: str, call_next: GetPromptNext) -> Prompt | None
+```
diff --git a/docs/python-sdk/fastmcp-server-transforms-visibility.mdx b/docs/python-sdk/fastmcp-server-transforms-visibility.mdx
new file mode 100644
index 000000000..25ef0478d
--- /dev/null
+++ b/docs/python-sdk/fastmcp-server-transforms-visibility.mdx
@@ -0,0 +1,158 @@
+---
+title: visibility
+sidebarTitle: visibility
+---
+
+# `fastmcp.server.transforms.visibility`
+
+
+Visibility transform for filtering components based on enable/disable settings.
+
+This module provides the `Visibility` class which manages component visibility
+with blocklist and allowlist support. Components can be hidden by key or tag,
+and the visibility state is mutable - changes take effect on subsequent queries.
+
+
+## Classes
+
+### `Visibility`
+
+
+Filters components based on visibility settings.
+
+Manages blocklist and allowlist logic for controlling component visibility.
+Both servers and providers use this class. Visibility is hierarchical: if a
+component is hidden at any level (provider or server), it's hidden to the client.
+
+Filtering logic (blocklist wins over allowlist):
+1. If component key is in _disabled_keys → HIDDEN
+2. If any component tag is in _disabled_tags → HIDDEN
+3. If _default_enabled is False and component not in allowlist → HIDDEN
+4. Otherwise → VISIBLE
+
+The `only=True` flag on enable() switches to allowlist mode:
+- Sets _default_enabled = False
+- Clears existing allowlists
+- Adds specified keys/tags to allowlist
+
+
+**Methods:**
+
+#### `disable`
+
+```python
+disable(self) -> None
+```
+
+Add to blocklist (hide components).
+
+**Args:**
+- `keys`: Component keys to hide (e.g., "tool\:my_tool@", "resource\:file\://x@")
+- `tags`: Tags to hide - any component with these tags will be hidden
+
+
+#### `enable`
+
+```python
+enable(self) -> None
+```
+
+Remove from blocklist, or set allowlist with only=True.
+
+**Args:**
+- `keys`: Component keys to show
+- `tags`: Tags to show
+- `only`: If True, switches to allowlist mode - ONLY show these keys/tags.
+This sets default visibility to False, clears existing allowlists,
+and adds the specified keys/tags to the allowlist.
+
+
+#### `reset`
+
+```python
+reset(self) -> None
+```
+
+Reset to default state (everything enabled, no filters).
+
+
+#### `is_enabled`
+
+```python
+is_enabled(self, component: FastMCPComponent) -> bool
+```
+
+Check if component is enabled. Blocklist wins over allowlist.
+
+
+#### `list_tools`
+
+```python
+list_tools(self, call_next: ListToolsNext) -> Sequence[Tool]
+```
+
+Filter tools by visibility.
+
+
+#### `get_tool`
+
+```python
+get_tool(self, name: str, call_next: GetToolNext) -> Tool | None
+```
+
+Get tool if enabled, None otherwise.
+
+
+#### `list_resources`
+
+```python
+list_resources(self, call_next: ListResourcesNext) -> Sequence[Resource]
+```
+
+Filter resources by visibility.
+
+
+#### `get_resource`
+
+```python
+get_resource(self, uri: str, call_next: GetResourceNext) -> Resource | None
+```
+
+Get resource if enabled, None otherwise.
+
+
+#### `list_resource_templates`
+
+```python
+list_resource_templates(self, call_next: ListResourceTemplatesNext) -> Sequence[ResourceTemplate]
+```
+
+Filter resource templates by visibility.
+
+
+#### `get_resource_template`
+
+```python
+get_resource_template(self, uri: str, call_next: GetResourceTemplateNext) -> ResourceTemplate | None
+```
+
+Get resource template if enabled, None otherwise.
+
+
+#### `list_prompts`
+
+```python
+list_prompts(self, call_next: ListPromptsNext) -> Sequence[Prompt]
+```
+
+Filter prompts by visibility.
+
+
+#### `get_prompt`
+
+```python
+get_prompt(self, name: str, call_next: GetPromptNext) -> Prompt | None
+```
+
+Get prompt if enabled, None otherwise.
+
diff --git a/docs/python-sdk/fastmcp-telemetry.mdx b/docs/python-sdk/fastmcp-telemetry.mdx
new file mode 100644
index 000000000..805e9940d
--- /dev/null
+++ b/docs/python-sdk/fastmcp-telemetry.mdx
@@ -0,0 +1,95 @@
+---
+title: telemetry
+sidebarTitle: telemetry
+---
+
+# `fastmcp.telemetry`
+
+
+OpenTelemetry instrumentation for FastMCP.
+
+This module provides native OpenTelemetry integration for FastMCP servers and clients.
+It uses only the opentelemetry-api package, so telemetry is a no-op unless the user
+installs an OpenTelemetry SDK and configures exporters.
+
+Example usage with SDK:
+ ```python
+ from opentelemetry import trace
+ from opentelemetry.sdk.trace import TracerProvider
+ from opentelemetry.sdk.trace.export import ConsoleSpanExporter, SimpleSpanProcessor
+
+ # Configure the SDK (user responsibility)
+ provider = TracerProvider()
+ provider.add_span_processor(SimpleSpanProcessor(ConsoleSpanExporter()))
+ trace.set_tracer_provider(provider)
+
+ # Now FastMCP will emit traces
+ from fastmcp import FastMCP
+ mcp = FastMCP("my-server")
+ ```
+
+
+## Functions
+
+### `get_tracer`
+
+```python
+get_tracer(version: str | None = None) -> Tracer
+```
+
+
+Get the FastMCP tracer for creating spans.
+
+**Args:**
+- `version`: Optional version string for the instrumentation
+
+**Returns:**
+- A tracer instance. Returns a no-op tracer if no SDK is configured.
+
+
+### `inject_trace_context`
+
+```python
+inject_trace_context(meta: dict[str, Any] | None = None) -> dict[str, Any] | None
+```
+
+
+Inject current trace context into a meta dict for MCP request propagation.
+
+**Args:**
+- `meta`: Optional existing meta dict to merge with trace context
+
+**Returns:**
+- A new dict containing the original meta (if any) plus trace context keys,
+- or None if no trace context to inject and meta was None
+
+
+### `record_span_error`
+
+```python
+record_span_error(span: Span, exception: BaseException) -> None
+```
+
+
+Record an exception on a span and set error status.
+
+
+### `extract_trace_context`
+
+```python
+extract_trace_context(meta: dict[str, Any] | None) -> Context
+```
+
+
+Extract trace context from an MCP request meta dict.
+
+If already in a valid trace (e.g., from HTTP propagation), the existing
+trace context is preserved and meta is not used.
+
+**Args:**
+- `meta`: The meta dict from an MCP request (ctx.request_context.meta)
+
+**Returns:**
+- An OpenTelemetry Context with the extracted trace context,
+- or the current context if no trace context found or already in a trace
+
diff --git a/docs/python-sdk/fastmcp-tools-function_parsing.mdx b/docs/python-sdk/fastmcp-tools-function_parsing.mdx
new file mode 100644
index 000000000..2f69d1548
--- /dev/null
+++ b/docs/python-sdk/fastmcp-tools-function_parsing.mdx
@@ -0,0 +1,21 @@
+---
+title: function_parsing
+sidebarTitle: function_parsing
+---
+
+# `fastmcp.tools.function_parsing`
+
+
+Function introspection and schema generation for FastMCP tools.
+
+## Classes
+
+### `ParsedFunction`
+
+**Methods:**
+
+#### `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
new file mode 100644
index 000000000..6196d8484
--- /dev/null
+++ b/docs/python-sdk/fastmcp-tools-function_tool.mdx
@@ -0,0 +1,108 @@
+---
+title: function_tool
+sidebarTitle: function_tool
+---
+
+# `fastmcp.tools.function_tool`
+
+
+Standalone @tool decorator for FastMCP.
+
+## Functions
+
+### `tool`
+
+```python
+tool(name_or_fn: str | Callable[..., Any] | None = None) -> Any
+```
+
+
+Standalone decorator to mark a function as an MCP tool.
+
+Returns the original function with metadata attached. Register with a server
+using mcp.add_tool().
+
+
+## Classes
+
+### `DecoratedTool`
+
+
+Protocol for functions decorated with @tool.
+
+
+### `ToolMeta`
+
+
+Metadata attached to functions by the @tool decorator.
+
+
+### `FunctionTool`
+
+**Methods:**
+
+#### `to_mcp_tool`
+
+```python
+to_mcp_tool(self, **overrides: Any) -> mcp.types.Tool
+```
+
+Convert the FastMCP tool to an MCP tool.
+
+Extends the base implementation to add task execution mode if enabled.
+
+
+#### `from_function`
+
+```python
+from_function(cls, fn: Callable[..., Any]) -> FunctionTool
+```
+
+Create a FunctionTool from a function.
+
+**Args:**
+- `fn`: The function to wrap
+- `metadata`: ToolMeta object with all configuration. If provided,
+individual parameters must not be passed.
+- `name, title, etc.`: Individual parameters for backwards compatibility.
+Cannot be used together with metadata parameter.
+
+
+#### `run`
+
+```python
+run(self, arguments: dict[str, Any]) -> ToolResult
+```
+
+Run the tool with arguments.
+
+
+#### `register_with_docket`
+
+```python
+register_with_docket(self, docket: Docket) -> None
+```
+
+Register this tool with docket for background execution.
+
+FunctionTool registers the underlying function, which has the user's
+Depends parameters for docket to resolve.
+
+
+#### `add_to_docket`
+
+```python
+add_to_docket(self, docket: Docket, arguments: dict[str, Any], **kwargs: Any) -> Execution
+```
+
+Schedule this tool for background execution via docket.
+
+FunctionTool splats the arguments dict since .fn expects **kwargs.
+
+**Args:**
+- `docket`: The Docket instance
+- `arguments`: Tool arguments
+- `fn_key`: Function lookup key in Docket registry (defaults to self.key)
+- `task_key`: Redis storage key for the result
+- `**kwargs`: Additional kwargs passed to docket.add()
+
diff --git a/docs/python-sdk/fastmcp-tools-tool.mdx b/docs/python-sdk/fastmcp-tools-tool.mdx
index c5e5e1c3a..c347cd480 100644
--- a/docs/python-sdk/fastmcp-tools-tool.mdx
+++ b/docs/python-sdk/fastmcp-tools-tool.mdx
@@ -7,7 +7,7 @@ sidebarTitle: tool
## Functions
-### `default_serializer`
+### `default_serializer`
```python
default_serializer(data: Any) -> str
@@ -15,17 +15,17 @@ default_serializer(data: Any) -> str
## Classes
-### `ToolResult`
+### `ToolResult`
**Methods:**
-#### `to_mcp_result`
+#### `to_mcp_result`
```python
to_mcp_result(self) -> list[ContentBlock] | tuple[list[ContentBlock], dict[str, Any]] | CallToolResult
```
-### `Tool`
+### `Tool`
Internal tool registration info.
@@ -33,7 +33,7 @@ Internal tool registration info.
**Methods:**
-#### `to_mcp_tool`
+#### `to_mcp_tool`
```python
to_mcp_tool(self, **overrides: Any) -> MCPTool
@@ -42,16 +42,16 @@ to_mcp_tool(self, **overrides: Any) -> MCPTool
Convert the FastMCP tool to an MCP tool.
-#### `from_function`
+#### `from_function`
```python
-from_function(fn: Callable[..., Any], name: str | None = None, title: str | None = None, description: str | None = None, icons: list[Icon] | None = None, tags: set[str] | None = None, annotations: ToolAnnotations | None = None, exclude_args: list[str] | None = None, output_schema: dict[str, Any] | NotSetT | None = NotSet, serializer: ToolResultSerializerType | None = None, meta: dict[str, Any] | None = None, task: bool | TaskConfig | None = None) -> FunctionTool
+from_function(cls, fn: Callable[..., Any]) -> FunctionTool
```
Create a Tool from a function.
-#### `run`
+#### `run`
```python
run(self, arguments: dict[str, Any]) -> ToolResult
@@ -66,7 +66,7 @@ implemented by subclasses.
(list of ContentBlocks, dict of structured output).
-#### `convert_result`
+#### `convert_result`
```python
convert_result(self, raw_value: Any) -> ToolResult
@@ -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,81 +103,14 @@ 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) -> TransformedTool
```
-### `FunctionTool`
-
-**Methods:**
-
-#### `to_mcp_tool`
+#### `get_span_attributes`
```python
-to_mcp_tool(self, **overrides: Any) -> MCPTool
-```
-
-Convert the FastMCP tool to an MCP tool.
-
-Extends the base implementation to add task execution mode if enabled.
-
-
-#### `from_function`
-
-```python
-from_function(cls, fn: Callable[..., Any], name: str | None = None, title: str | None = None, description: str | None = None, icons: list[Icon] | None = None, tags: set[str] | None = None, annotations: ToolAnnotations | None = None, exclude_args: list[str] | None = None, output_schema: dict[str, Any] | NotSetT | None = NotSet, serializer: ToolResultSerializerType | None = None, meta: dict[str, Any] | None = None, task: bool | TaskConfig | None = None) -> FunctionTool
-```
-
-Create a Tool from a function.
-
-
-#### `run`
-
-```python
-run(self, arguments: dict[str, Any]) -> ToolResult
-```
-
-Run the tool with arguments.
-
-
-#### `register_with_docket`
-
-```python
-register_with_docket(self, docket: Docket) -> None
-```
-
-Register this tool with docket for background execution.
-
-FunctionTool registers the underlying function, which has the user's
-Depends parameters for docket to resolve.
-
-
-#### `add_to_docket`
-
-```python
-add_to_docket(self, docket: Docket, arguments: dict[str, Any], **kwargs: Any) -> Execution
-```
-
-Schedule this tool for background execution via docket.
-
-FunctionTool splats the arguments dict since .fn expects **kwargs.
-
-**Args:**
-- `docket`: The Docket instance
-- `arguments`: Tool arguments
-- `fn_key`: Function lookup key in Docket registry (defaults to self.key)
-- `task_key`: Redis storage key for the result
-- `**kwargs`: Additional kwargs passed to docket.add()
-
-
-### `ParsedFunction`
-
-**Methods:**
-
-#### `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
+get_span_attributes(self) -> dict[str, Any]
```
diff --git a/docs/python-sdk/fastmcp-tools-tool_transform.mdx b/docs/python-sdk/fastmcp-tools-tool_transform.mdx
index 0288596ac..052ab7192 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,10 +210,10 @@ functions.
- ToolResult object containing content and optional structured output.
-#### `from_tool`
+#### `from_tool`
```python
-from_tool(cls, tool: Tool, name: str | None = None, 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
+from_tool(cls, tool: Tool, 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
```
Create a transformed tool from a parent tool.
@@ -224,6 +224,7 @@ Create a transformed tool from a parent tool.
to call the parent tool. Functions with **kwargs receive transformed
argument names.
- `name`: New name for the tool. Defaults to parent tool's name.
+- `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\:
@@ -292,7 +293,7 @@ async def custom_output(**kwargs) -> ToolResult:
```
-### `ToolTransformConfig`
+### `ToolTransformConfig`
Provides a way to transform a tool.
@@ -300,7 +301,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-async_utils.mdx b/docs/python-sdk/fastmcp-utilities-async_utils.mdx
index 7a44351b6..f5f24019f 100644
--- a/docs/python-sdk/fastmcp-utilities-async_utils.mdx
+++ b/docs/python-sdk/fastmcp-utilities-async_utils.mdx
@@ -10,7 +10,20 @@ Async utilities for FastMCP.
## Functions
-### `gather`
+### `call_sync_fn_in_threadpool`
+
+```python
+call_sync_fn_in_threadpool(fn: Callable[..., Any], *args: Any, **kwargs: Any) -> Any
+```
+
+
+Call a sync function in a threadpool to avoid blocking the event loop.
+
+Uses anyio.to_thread.run_sync which properly propagates contextvars,
+making this safe for functions that depend on context (like dependency injection).
+
+
+### `gather`
```python
gather(*awaitables: Awaitable[T]) -> list[T] | list[T | BaseException]
diff --git a/docs/python-sdk/fastmcp-utilities-cli.mdx b/docs/python-sdk/fastmcp-utilities-cli.mdx
index 2eb792220..455655637 100644
--- a/docs/python-sdk/fastmcp-utilities-cli.mdx
+++ b/docs/python-sdk/fastmcp-utilities-cli.mdx
@@ -7,7 +7,7 @@ sidebarTitle: cli
## Functions
-### `is_already_in_uv_subprocess`
+### `is_already_in_uv_subprocess`
```python
is_already_in_uv_subprocess() -> bool
@@ -17,7 +17,7 @@ is_already_in_uv_subprocess() -> bool
Check if we're already running in a FastMCP uv subprocess.
-### `load_and_merge_config`
+### `load_and_merge_config`
```python
load_and_merge_config(server_spec: str | None, **cli_overrides) -> tuple[MCPServerConfig, str]
@@ -37,7 +37,7 @@ run, inspect, and dev commands.
- Tuple of (MCPServerConfig, resolved_server_spec)
-### `log_server_banner`
+### `log_server_banner`
```python
log_server_banner(server: FastMCP[Any]) -> None
diff --git a/docs/python-sdk/fastmcp-utilities-components.mdx b/docs/python-sdk/fastmcp-utilities-components.mdx
index 08879acdf..cc2b90446 100644
--- a/docs/python-sdk/fastmcp-utilities-components.mdx
+++ b/docs/python-sdk/fastmcp-utilities-components.mdx
@@ -9,7 +9,7 @@ sidebarTitle: components
### `FastMCPMeta`
-### `FastMCPComponent`
+### `FastMCPComponent`
Base class for FastMCP tools, prompts, resources, and resource templates.
@@ -17,7 +17,7 @@ Base class for FastMCP tools, prompts, resources, and resource templates.
**Methods:**
-#### `make_key`
+#### `make_key`
```python
make_key(cls, identifier: str) -> str
@@ -32,7 +32,7 @@ Construct the lookup key for this component type.
- A prefixed key like "tool:name" or "resource:uri"
-#### `key`
+#### `key`
```python
key(self) -> str
@@ -40,13 +40,17 @@ key(self) -> str
The globally unique lookup key for this component.
-Format: "{key_prefix}:{identifier}" e.g. "tool:my_tool", "resource:file://x.txt"
+Format: "{key_prefix}:{identifier}@{version}" or "{key_prefix}:{identifier}@"
+e.g. "tool:my_tool@v2", "tool:my_tool@", "resource:file://x.txt@"
+
+The @ suffix is ALWAYS present to enable unambiguous parsing of keys
+(URIs may contain @ characters, so we always include the delimiter).
Subclasses should override this to use their specific identifier.
Base implementation uses name.
-#### `get_meta`
+#### `get_meta`
```python
get_meta(self, include_fastmcp_meta: bool | None = None) -> dict[str, Any] | None
@@ -58,7 +62,7 @@ If include_fastmcp_meta is True, a `_fastmcp` key will be added to the
meta, containing a `tags` field with the tags of the component.
-#### `enable`
+#### `enable`
```python
enable(self) -> None
@@ -67,7 +71,7 @@ enable(self) -> None
Removed in 3.0. Use server.enable(keys=[...]) instead.
-#### `disable`
+#### `disable`
```python
disable(self) -> None
@@ -76,7 +80,7 @@ disable(self) -> None
Removed in 3.0. Use server.disable(keys=[...]) instead.
-#### `copy`
+#### `copy`
```python
copy(self) -> Self
@@ -85,7 +89,7 @@ copy(self) -> Self
Create a copy of the component.
-#### `register_with_docket`
+#### `register_with_docket`
```python
register_with_docket(self, docket: Docket) -> None
@@ -97,7 +101,7 @@ No-ops if task_config.mode is "forbidden". Subclasses override to
register their callable (self.run, self.read, self.render, or self.fn).
-#### `add_to_docket`
+#### `add_to_docket`
```python
add_to_docket(self, docket: Docket, *args: Any, **kwargs: Any) -> Execution
@@ -113,3 +117,14 @@ Subclasses override this to handle their specific calling conventions:
The **kwargs are passed through to docket.add() (e.g., key=task_key).
+
+#### `get_span_attributes`
+
+```python
+get_span_attributes(self) -> dict[str, Any]
+```
+
+Return span attributes for telemetry.
+
+Subclasses should call super() and merge their specific attributes.
+
diff --git a/docs/python-sdk/fastmcp-utilities-json_schema_type.mdx b/docs/python-sdk/fastmcp-utilities-json_schema_type.mdx
index 50fba7654..59b66f2ec 100644
--- a/docs/python-sdk/fastmcp-utilities-json_schema_type.mdx
+++ b/docs/python-sdk/fastmcp-utilities-json_schema_type.mdx
@@ -42,7 +42,7 @@ Example:
## Functions
-### `json_schema_to_type`
+### `json_schema_to_type`
```python
json_schema_to_type(schema: Mapping[str, Any], name: str | None = None) -> type
@@ -107,4 +107,4 @@ class Name:
## Classes
-### `JSONSchema`
+### `JSONSchema`
diff --git a/docs/python-sdk/fastmcp-utilities-logging.mdx b/docs/python-sdk/fastmcp-utilities-logging.mdx
index ef3264dbb..1fffe465c 100644
--- a/docs/python-sdk/fastmcp-utilities-logging.mdx
+++ b/docs/python-sdk/fastmcp-utilities-logging.mdx
@@ -41,7 +41,7 @@ Configure logging for FastMCP.
- `rich_kwargs`: the parameters to use for creating RichHandler
-### `temporary_log_level`
+### `temporary_log_level`
```python
temporary_log_level(level: str | None, logger: logging.Logger | None = None, enable_rich_tracebacks: bool | None = None, **rich_kwargs: Any)
diff --git a/docs/python-sdk/fastmcp-utilities-version_check.mdx b/docs/python-sdk/fastmcp-utilities-version_check.mdx
new file mode 100644
index 000000000..a88805fb2
--- /dev/null
+++ b/docs/python-sdk/fastmcp-utilities-version_check.mdx
@@ -0,0 +1,40 @@
+---
+title: version_check
+sidebarTitle: version_check
+---
+
+# `fastmcp.utilities.version_check`
+
+
+Version checking utilities for FastMCP.
+
+## Functions
+
+### `get_latest_version`
+
+```python
+get_latest_version(include_prereleases: bool = False) -> str | None
+```
+
+
+Get the latest version of FastMCP from PyPI, using cache when available.
+
+**Args:**
+- `include_prereleases`: If True, include pre-release versions.
+
+**Returns:**
+- The latest version string, or None if unavailable.
+
+
+### `check_for_newer_version`
+
+```python
+check_for_newer_version() -> str | None
+```
+
+
+Check if a newer version of FastMCP is available.
+
+**Returns:**
+- The latest version string if newer than current, None otherwise.
+
diff --git a/docs/python-sdk/fastmcp-utilities-versions.mdx b/docs/python-sdk/fastmcp-utilities-versions.mdx
new file mode 100644
index 000000000..9adb00b50
--- /dev/null
+++ b/docs/python-sdk/fastmcp-utilities-versions.mdx
@@ -0,0 +1,190 @@
+---
+title: versions
+sidebarTitle: versions
+---
+
+# `fastmcp.utilities.versions`
+
+
+Version comparison utilities for component versioning.
+
+This module provides utilities for comparing component versions. Versions are
+strings that are first attempted to be parsed as PEP 440 versions (using the
+`packaging` library), falling back to lexicographic string comparison.
+
+Examples:
+ - "1", "2", "10" → parsed as PEP 440, compared semantically (1 < 2 < 10)
+ - "1.0", "2.0" → parsed as PEP 440
+ - "v1.0" → 'v' prefix stripped, parsed as "1.0"
+ - "2025-01-15" → not valid PEP 440, compared as strings
+ - None → sorts lowest (unversioned components)
+
+
+## Functions
+
+### `parse_version_key`
+
+```python
+parse_version_key(version: str | None) -> VersionKey
+```
+
+
+Parse a version string into a sortable key.
+
+**Args:**
+- `version`: The version string, or None for unversioned.
+
+**Returns:**
+- A VersionKey suitable for sorting.
+
+
+### `version_sort_key`
+
+```python
+version_sort_key(component: FastMCPComponent) -> VersionKey
+```
+
+
+Get a sort key for a component based on its version.
+
+Use with sorted() or max() to order components by version.
+
+**Args:**
+- `component`: The component to get a sort key for.
+
+**Returns:**
+- A sortable VersionKey.
+
+
+### `compare_versions`
+
+```python
+compare_versions(a: str | None, b: str | None) -> int
+```
+
+
+Compare two version strings.
+
+**Args:**
+- `a`: First version string (or None).
+- `b`: Second version string (or None).
+
+**Returns:**
+- -1 if a < b, 0 if a == b, 1 if a > b.
+
+
+### `is_version_greater`
+
+```python
+is_version_greater(a: str | None, b: str | None) -> bool
+```
+
+
+Check if version a is greater than version b.
+
+**Args:**
+- `a`: First version string (or None).
+- `b`: Second version string (or None).
+
+**Returns:**
+- True if a > b, False otherwise.
+
+
+### `max_version`
+
+```python
+max_version(a: str | None, b: str | None) -> str | None
+```
+
+
+Return the greater of two versions.
+
+**Args:**
+- `a`: First version string (or None).
+- `b`: Second version string (or None).
+
+**Returns:**
+- The greater version, or None if both are None.
+
+
+### `min_version`
+
+```python
+min_version(a: str | None, b: str | None) -> str | None
+```
+
+
+Return the lesser of two versions.
+
+**Args:**
+- `a`: First version string (or None).
+- `b`: Second version string (or None).
+
+**Returns:**
+- The lesser version, or None if both are None.
+
+
+## Classes
+
+### `VersionSpec`
+
+
+Specification for filtering components by version.
+
+Used by transforms and providers to filter components to a specific
+version or version range. Unversioned components (version=None) always
+match any spec.
+
+**Args:**
+- `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).
+
+
+**Methods:**
+
+#### `matches`
+
+```python
+matches(self, version: str | None) -> bool
+```
+
+Check if a version matches this spec.
+
+**Args:**
+- `version`: The version to check, or None for unversioned.
+
+**Returns:**
+- True if the version matches the spec.
+
+
+#### `intersect`
+
+```python
+intersect(self, other: VersionSpec | None) -> VersionSpec
+```
+
+Return a spec that satisfies both this spec and other.
+
+Used by transforms to combine caller constraints with filter constraints.
+For example, if a VersionFilter has lt="3.0" and caller requests eq="1.0",
+the intersection validates "1.0" is in range and returns the exact spec.
+
+**Args:**
+- `other`: Another spec to intersect with, or None.
+
+**Returns:**
+- A VersionSpec that matches only versions satisfying both specs.
+
+
+### `VersionKey`
+
+
+A comparable version key that handles None, PEP 440 versions, and strings.
+
+Comparison order:
+1. None (unversioned) sorts lowest
+2. PEP 440 versions sort by semantic version order
+3. Invalid versions (strings) sort lexicographically
+4. When comparing PEP 440 vs string, PEP 440 comes first
+
diff --git a/docs/python-sdk/fastmcp-utilities-visibility.mdx b/docs/python-sdk/fastmcp-utilities-visibility.mdx
deleted file mode 100644
index ade14110e..000000000
--- a/docs/python-sdk/fastmcp-utilities-visibility.mdx
+++ /dev/null
@@ -1,86 +0,0 @@
----
-title: visibility
-sidebarTitle: visibility
----
-
-# `fastmcp.utilities.visibility`
-
-
-Visibility filtering for FastMCP components.
-
-This module provides the VisibilityFilter class which handles blocklist and
-allowlist logic for controlling component visibility at both the provider
-and server levels.
-
-
-## Classes
-
-### `VisibilityFilter`
-
-
-Manages component visibility with blocklist and allowlist support.
-
-Both servers and providers use this class to control which components
-are visible. Visibility is hierarchical: if a component is hidden at
-any level (provider or server), it's hidden to the client.
-
-Filtering logic (blocklist wins over allowlist):
-1. If component key is in _disabled_keys → HIDDEN
-2. If any component tag is in _disabled_tags → HIDDEN
-3. If _default_enabled is False and component not in allowlist → HIDDEN
-4. Otherwise → VISIBLE
-
-The `only=True` flag on enable() switches to allowlist mode:
-- Sets _default_enabled = False
-- Clears existing allowlists
-- Adds specified keys/tags to allowlist
-
-
-**Methods:**
-
-#### `disable`
-
-```python
-disable(self) -> None
-```
-
-Add to blocklist (hide components).
-
-**Args:**
-- `keys`: Component keys to hide (e.g., "tool\:my_tool", "resource\:file\://x")
-- `tags`: Tags to hide - any component with these tags will be hidden
-
-
-#### `enable`
-
-```python
-enable(self) -> None
-```
-
-Remove from blocklist, or set allowlist with only=True.
-
-**Args:**
-- `keys`: Component keys to show
-- `tags`: Tags to show
-- `only`: If True, switches to allowlist mode - ONLY show these keys/tags.
-This sets default visibility to False, clears existing allowlists,
-and adds the specified keys/tags to the allowlist.
-
-
-#### `reset`
-
-```python
-reset(self) -> None
-```
-
-Reset to default state (everything enabled, no filters).
-
-
-#### `is_enabled`
-
-```python
-is_enabled(self, component: FastMCPComponent) -> bool
-```
-
-Check if component is enabled. Blocklist wins over allowlist.
-