From d35b867b10b2e4b74d9b682c9ebd6b68ddaa5cca Mon Sep 17 00:00:00 2001 From: "marvin-context-protocol[bot]" <225465937+marvin-context-protocol[bot]@users.noreply.github.com> Date: Tue, 9 Dec 2025 21:07:20 -0500 Subject: [PATCH] chore: Update SDK documentation (#2517) Co-authored-by: marvin-context-protocol[bot] <225465937+marvin-context-protocol[bot]@users.noreply.github.com> --- docs/docs.json | 21 +- docs/python-sdk/fastmcp-cli-cli.mdx | 12 +- docs/python-sdk/fastmcp-cli-tasks.mdx | 41 +++ docs/python-sdk/fastmcp-client-auth-oauth.mdx | 18 +- docs/python-sdk/fastmcp-client-client.mdx | 238 ++++++++++++++---- .../python-sdk/fastmcp-client-elicitation.mdx | 2 +- docs/python-sdk/fastmcp-client-messages.mdx | 28 +-- docs/python-sdk/fastmcp-client-tasks.mdx | 219 ++++++++++++++++ docs/python-sdk/fastmcp-client-transports.mdx | 66 +++-- docs/python-sdk/fastmcp-dependencies.mdx | 14 ++ docs/python-sdk/fastmcp-prompts-prompt.mdx | 12 +- .../python-sdk/fastmcp-resources-resource.mdx | 26 +- .../python-sdk/fastmcp-resources-template.mdx | 42 ++-- docs/python-sdk/fastmcp-server-auth-auth.mdx | 80 ++++-- .../fastmcp-server-auth-oauth_proxy.mdx | 72 ++---- docs/python-sdk/fastmcp-server-context.mdx | 80 +++--- .../fastmcp-server-dependencies.mdx | 216 +++++++++++++++- .../python-sdk/fastmcp-server-elicitation.mdx | 75 +++++- .../python-sdk/fastmcp-server-event_store.mdx | 78 ++++++ docs/python-sdk/fastmcp-server-http.mdx | 23 +- docs/python-sdk/fastmcp-server-low_level.mdx | 10 +- .../fastmcp-server-middleware-middleware.mdx | 2 +- docs/python-sdk/fastmcp-server-proxy.mdx | 74 +++--- docs/python-sdk/fastmcp-server-server.mdx | 129 +++++----- .../fastmcp-server-tasks-__init__.mdx | 12 + .../fastmcp-server-tasks-capabilities.mdx | 24 ++ .../fastmcp-server-tasks-config.mdx | 66 +++++ .../fastmcp-server-tasks-converters.mdx | 77 ++++++ .../fastmcp-server-tasks-handlers.mdx | 78 ++++++ docs/python-sdk/fastmcp-server-tasks-keys.mdx | 91 +++++++ .../fastmcp-server-tasks-protocol.mdx | 88 +++++++ .../fastmcp-server-tasks-subscriptions.mdx | 35 +++ docs/python-sdk/fastmcp-settings.mdx | 28 +-- docs/python-sdk/fastmcp-tools-tool.mdx | 45 ++-- docs/python-sdk/fastmcp-utilities-tests.mdx | 16 +- docs/python-sdk/fastmcp-utilities-types.mdx | 18 +- 36 files changed, 1740 insertions(+), 416 deletions(-) create mode 100644 docs/python-sdk/fastmcp-cli-tasks.mdx create mode 100644 docs/python-sdk/fastmcp-client-tasks.mdx create mode 100644 docs/python-sdk/fastmcp-dependencies.mdx create mode 100644 docs/python-sdk/fastmcp-server-event_store.mdx create mode 100644 docs/python-sdk/fastmcp-server-tasks-__init__.mdx create mode 100644 docs/python-sdk/fastmcp-server-tasks-capabilities.mdx create mode 100644 docs/python-sdk/fastmcp-server-tasks-config.mdx create mode 100644 docs/python-sdk/fastmcp-server-tasks-converters.mdx create mode 100644 docs/python-sdk/fastmcp-server-tasks-handlers.mdx create mode 100644 docs/python-sdk/fastmcp-server-tasks-keys.mdx create mode 100644 docs/python-sdk/fastmcp-server-tasks-protocol.mdx create mode 100644 docs/python-sdk/fastmcp-server-tasks-subscriptions.mdx diff --git a/docs/docs.json b/docs/docs.json index 8c9cbebbd..889e8f37b 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -276,6 +276,7 @@ "anchor": "Python SDK", "icon": "python", "pages": [ + "python-sdk/fastmcp-dependencies", "python-sdk/fastmcp-exceptions", "python-sdk/fastmcp-mcp_config", "python-sdk/fastmcp-settings", @@ -296,7 +297,8 @@ "python-sdk/fastmcp-cli-install-shared" ] }, - "python-sdk/fastmcp-cli-run" + "python-sdk/fastmcp-cli-run", + "python-sdk/fastmcp-cli-tasks" ] }, { @@ -319,6 +321,7 @@ "python-sdk/fastmcp-client-progress", "python-sdk/fastmcp-client-roots", "python-sdk/fastmcp-client-sampling", + "python-sdk/fastmcp-client-tasks", "python-sdk/fastmcp-client-transports" ] }, @@ -380,6 +383,7 @@ "python-sdk/fastmcp-server-context", "python-sdk/fastmcp-server-dependencies", "python-sdk/fastmcp-server-elicitation", + "python-sdk/fastmcp-server-event_store", "python-sdk/fastmcp-server-http", "python-sdk/fastmcp-server-low_level", { @@ -405,7 +409,20 @@ ] }, "python-sdk/fastmcp-server-proxy", - "python-sdk/fastmcp-server-server" + "python-sdk/fastmcp-server-server", + { + "group": "tasks", + "pages": [ + "python-sdk/fastmcp-server-tasks-__init__", + "python-sdk/fastmcp-server-tasks-capabilities", + "python-sdk/fastmcp-server-tasks-config", + "python-sdk/fastmcp-server-tasks-converters", + "python-sdk/fastmcp-server-tasks-handlers", + "python-sdk/fastmcp-server-tasks-keys", + "python-sdk/fastmcp-server-tasks-protocol", + "python-sdk/fastmcp-server-tasks-subscriptions" + ] + } ] }, { diff --git a/docs/python-sdk/fastmcp-cli-cli.mdx b/docs/python-sdk/fastmcp-cli-cli.mdx index 79cb794db..6dbb1a74b 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-cli-tasks.mdx b/docs/python-sdk/fastmcp-cli-tasks.mdx new file mode 100644 index 000000000..b1ac931aa --- /dev/null +++ b/docs/python-sdk/fastmcp-cli-tasks.mdx @@ -0,0 +1,41 @@ +--- +title: tasks +sidebarTitle: tasks +--- + +# `fastmcp.cli.tasks` + + +FastMCP tasks CLI for Docket task management. + +## Functions + +### `check_distributed_backend` + +```python +check_distributed_backend() -> None +``` + + +Check if Docket is configured with a distributed backend. + +The CLI worker runs as a separate process, so it needs Redis/Valkey +to coordinate with the main server process. + +**Raises:** +- `SystemExit`: If using memory\:// URL + + +### `worker` + +```python +worker(server_spec: Annotated[str | None, cyclopts.Parameter(help='Python file to run, optionally with :object suffix, or None to auto-detect fastmcp.json')] = None) -> None +``` + + +Start an additional worker to process background tasks. + +Connects to your Docket backend and processes tasks in parallel with +any other running workers. Configure via environment variables +(FASTMCP_DOCKET_*). + diff --git a/docs/python-sdk/fastmcp-client-auth-oauth.mdx b/docs/python-sdk/fastmcp-client-auth-oauth.mdx index 40d890ddf..aca8c2e25 100644 --- a/docs/python-sdk/fastmcp-client-auth-oauth.mdx +++ b/docs/python-sdk/fastmcp-client-auth-oauth.mdx @@ -7,7 +7,7 @@ sidebarTitle: oauth ## Functions -### `check_if_auth_required` +### `check_if_auth_required` ```python check_if_auth_required(mcp_url: str, httpx_kwargs: dict[str, Any] | None = None) -> bool @@ -22,47 +22,47 @@ Check if the MCP endpoint requires authentication by making a test request. ## Classes -### `ClientNotFoundError` +### `ClientNotFoundError` Raised when OAuth client credentials are not found on the server. -### `TokenStorageAdapter` +### `TokenStorageAdapter` **Methods:** -#### `clear` +#### `clear` ```python clear(self) -> None ``` -#### `get_tokens` +#### `get_tokens` ```python get_tokens(self) -> OAuthToken | None ``` -#### `set_tokens` +#### `set_tokens` ```python set_tokens(self, tokens: OAuthToken) -> None ``` -#### `get_client_info` +#### `get_client_info` ```python get_client_info(self) -> OAuthClientInformationFull | None ``` -#### `set_client_info` +#### `set_client_info` ```python set_client_info(self, client_info: OAuthClientInformationFull) -> None ``` -### `OAuth` +### `OAuth` OAuth client provider for MCP servers with browser-based authentication. diff --git a/docs/python-sdk/fastmcp-client-client.mdx b/docs/python-sdk/fastmcp-client-client.mdx index cbb1599f9..2f2a5fdc9 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,7 +16,13 @@ This allows clean separation of configuration (which is copied) from session state (which should be fresh for each new client instance). -### `Client` +### `CallToolResult` + + +Parsed result from a tool call. + + +### `Client` MCP client that delegates connection management to a Transport instance. @@ -79,7 +85,7 @@ async with client: **Methods:** -#### `session` +#### `session` ```python session(self) -> ClientSession @@ -88,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 @@ -97,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 @@ -106,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: ClientSamplingHandler) -> None @@ -115,7 +121,7 @@ set_sampling_callback(self, sampling_callback: ClientSamplingHandler) -> None Set the sampling callback for the client. -#### `set_elicitation_callback` +#### `set_elicitation_callback` ```python set_elicitation_callback(self, elicitation_callback: ElicitationHandler) -> None @@ -124,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 @@ -133,7 +139,7 @@ is_connected(self) -> bool Check if the client is currently connected. -#### `new` +#### `new` ```python new(self) -> Client[ClientTransportT] @@ -149,13 +155,7 @@ share state with the original client. - A new Client instance with the same configuration but disconnected state. -#### `close` - -```python -close(self) -``` - -#### `initialize` +#### `initialize` ```python initialize(self, timeout: datetime.timedelta | float | int | None = None) -> mcp.types.InitializeResult @@ -183,7 +183,13 @@ capabilities, protocol version, and optional instructions. - `RuntimeError`: If the client is not connected or initialization times out. -#### `ping` +#### `close` + +```python +close(self) +``` + +#### `ping` ```python ping(self) -> bool @@ -192,7 +198,7 @@ ping(self) -> bool Send a ping request. -#### `cancel` +#### `cancel` ```python cancel(self, request_id: str | int, reason: str | None = None) -> None @@ -201,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 @@ -210,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 @@ -219,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 @@ -228,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 @@ -244,7 +250,7 @@ containing the list of resources and any additional metadata. - `RuntimeError`: If called while the client is not connected. -#### `list_resources` +#### `list_resources` ```python list_resources(self) -> list[mcp.types.Resource] @@ -259,7 +265,7 @@ Retrieve a list of resources available on the server. - `RuntimeError`: If called while the client is not connected. -#### `list_resource_templates_mcp` +#### `list_resource_templates_mcp` ```python list_resource_templates_mcp(self) -> mcp.types.ListResourceTemplatesResult @@ -275,7 +281,7 @@ containing the list of resource templates and any additional metadata. - `RuntimeError`: If called while the client is not connected. -#### `list_resource_templates` +#### `list_resource_templates` ```python list_resource_templates(self) -> list[mcp.types.ResourceTemplate] @@ -290,16 +296,17 @@ Retrieve a list of resource templates available on the server. - `RuntimeError`: If called while the client is not connected. -#### `read_resource_mcp` +#### `read_resource_mcp` ```python -read_resource_mcp(self, uri: AnyUrl | str) -> mcp.types.ReadResourceResult +read_resource_mcp(self, uri: AnyUrl | str, meta: dict[str, Any] | None = None) -> mcp.types.ReadResourceResult ``` Send a resources/read request and return the complete MCP protocol result. **Args:** - `uri`: The URI of the resource to read. Can be a string or an AnyUrl object. +- `meta`: Request metadata (e.g., for SEP-1686 tasks). Defaults to None. **Returns:** - mcp.types.ReadResourceResult: The complete response object from the protocol, @@ -309,26 +316,41 @@ containing the resource contents and any additional metadata. - `RuntimeError`: If called while the client is not connected. -#### `read_resource` +#### `read_resource` ```python read_resource(self, uri: AnyUrl | str) -> list[mcp.types.TextResourceContents | mcp.types.BlobResourceContents] ``` +#### `read_resource` + +```python +read_resource(self, uri: AnyUrl | str) -> ResourceTask +``` + +#### `read_resource` + +```python +read_resource(self, uri: AnyUrl | str) -> list[mcp.types.TextResourceContents | mcp.types.BlobResourceContents] | ResourceTask +``` + Read the contents of a resource or resolved template. **Args:** - `uri`: The URI of the resource to read. Can be a string or an AnyUrl object. +- `task`: If True, execute as background task (SEP-1686). Defaults to False. +- `task_id`: Optional client-provided task ID (auto-generated if not provided). +- `ttl`: Time to keep results available in milliseconds (default 60s). **Returns:** -- list\[mcp.types.TextResourceContents | mcp.types.BlobResourceContents]: A list of content -objects, typically containing either text or binary data. +- list\[mcp.types.TextResourceContents | mcp.types.BlobResourceContents] | ResourceTask: +A list of content objects if task=False, or a ResourceTask object if task=True. **Raises:** - `RuntimeError`: If called while the client is not connected. -#### `list_prompts_mcp` +#### `list_prompts_mcp` ```python list_prompts_mcp(self) -> mcp.types.ListPromptsResult @@ -344,7 +366,7 @@ containing the list of prompts and any additional metadata. - `RuntimeError`: If called while the client is not connected. -#### `list_prompts` +#### `list_prompts` ```python list_prompts(self) -> list[mcp.types.Prompt] @@ -359,10 +381,10 @@ Retrieve a list of prompts available on the server. - `RuntimeError`: If called while the client is not connected. -#### `get_prompt_mcp` +#### `get_prompt_mcp` ```python -get_prompt_mcp(self, name: str, arguments: dict[str, Any] | None = None) -> mcp.types.GetPromptResult +get_prompt_mcp(self, name: str, arguments: dict[str, Any] | None = None, meta: dict[str, Any] | None = None) -> mcp.types.GetPromptResult ``` Send a prompts/get request and return the complete MCP protocol result. @@ -370,6 +392,7 @@ Send a prompts/get request and return the complete MCP protocol result. **Args:** - `name`: The name of the prompt to retrieve. - `arguments`: Arguments to pass to the prompt. Defaults to None. +- `meta`: Request metadata (e.g., for SEP-1686 tasks). Defaults to None. **Returns:** - mcp.types.GetPromptResult: The complete response object from the protocol, @@ -379,27 +402,42 @@ containing the prompt messages and any additional metadata. - `RuntimeError`: If called while the client is not connected. -#### `get_prompt` +#### `get_prompt` ```python get_prompt(self, name: str, arguments: dict[str, Any] | None = None) -> mcp.types.GetPromptResult ``` +#### `get_prompt` + +```python +get_prompt(self, name: str, arguments: dict[str, Any] | None = None) -> PromptTask +``` + +#### `get_prompt` + +```python +get_prompt(self, name: str, arguments: dict[str, Any] | None = None) -> mcp.types.GetPromptResult | PromptTask +``` + Retrieve a rendered prompt message list from the server. **Args:** - `name`: The name of the prompt to retrieve. - `arguments`: Arguments to pass to the prompt. Defaults to None. +- `task`: If True, execute as background task (SEP-1686). Defaults to False. +- `task_id`: Optional client-provided task ID (auto-generated if not provided). +- `ttl`: Time to keep results available in milliseconds (default 60s). **Returns:** -- mcp.types.GetPromptResult: The complete response object from the protocol, -containing the prompt messages and any additional metadata. +- mcp.types.GetPromptResult | PromptTask: The complete response object if task=False, +or a PromptTask object if task=True. **Raises:** - `RuntimeError`: If called while the client is not connected. -#### `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 @@ -421,7 +459,7 @@ containing the completion and any additional metadata. - `RuntimeError`: If called while the client is not connected. -#### `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 @@ -442,7 +480,7 @@ include with the completion request. Defaults to None. - `RuntimeError`: If called while the client is not connected. -#### `list_tools_mcp` +#### `list_tools_mcp` ```python list_tools_mcp(self) -> mcp.types.ListToolsResult @@ -458,7 +496,7 @@ containing the list of tools and any additional metadata. - `RuntimeError`: If called while the client is not connected. -#### `list_tools` +#### `list_tools` ```python list_tools(self) -> list[mcp.types.Tool] @@ -473,7 +511,7 @@ Retrieve a list of tools available on the server. - `RuntimeError`: If called while the client is not connected. -#### `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 @@ -502,10 +540,22 @@ containing the tool result and any additional metadata. - `RuntimeError`: If called while the client is not connected. -#### `call_tool` +#### `call_tool` ```python -call_tool(self, name: str, arguments: dict[str, Any] | None = None, timeout: datetime.timedelta | float | int | None = None, progress_handler: ProgressHandler | None = None, raise_on_error: bool = True, meta: dict[str, Any] | None = None) -> CallToolResult +call_tool(self, name: str, arguments: dict[str, Any] | None = None) -> CallToolResult +``` + +#### `call_tool` + +```python +call_tool(self, name: str, arguments: dict[str, Any] | None = None) -> ToolTask +``` + +#### `call_tool` + +```python +call_tool(self, name: str, arguments: dict[str, Any] | None = None) -> CallToolResult | ToolTask ``` Call a tool on the server. @@ -517,15 +567,18 @@ Unlike call_tool_mcp, this method raises a ToolError if the tool call results in - `arguments`: Arguments to pass to the tool. Defaults to None. - `timeout`: The timeout for the tool call. Defaults to None. - `progress_handler`: The progress handler to use for the tool call. Defaults to None. -- `raise_on_error`: Whether to raise a ToolError if the tool call results in an error. Defaults to True. +- `raise_on_error`: Whether to raise an exception if the tool call results in an error. Defaults to True. - `meta`: Additional metadata to include with the request. This is useful for passing contextual information (like user IDs, trace IDs, or preferences) that shouldn't be tool arguments but may influence server-side processing. The server can access this via `context.request_context.meta`. Defaults to None. +- `task`: If True, execute as background task (SEP-1686). Defaults to False. +- `task_id`: Optional client-provided task ID (auto-generated if not provided). +- `ttl`: Time to keep results available in milliseconds (default 60s). **Returns:** -- -The content returned by the tool. If the tool returns structured +- CallToolResult | ToolTask: The content returned by the tool if task=False, +or a ToolTask object if task=True. If the tool returns structured outputs, they are returned as a dataclass (if an output schema is available) or a dictionary; otherwise, a list of content blocks is returned. Note: to receive both structured and @@ -537,10 +590,95 @@ raw result object. - `RuntimeError`: If called while the client is not connected. -#### `generate_name` +#### `get_task_status` + +```python +get_task_status(self, task_id: str) -> GetTaskResult +``` + +Query the status of a background task. + +Sends a 'tasks/get' MCP protocol request over the existing transport. + +**Args:** +- `task_id`: The task ID returned from call_tool_as_task + +**Returns:** +- Status information including taskId, status, pollInterval, etc. + +**Raises:** +- `RuntimeError`: If client not connected + + +#### `get_task_result` + +```python +get_task_result(self, task_id: str) -> Any +``` + +Retrieve the raw result of a completed background task. + +Sends a 'tasks/result' MCP protocol request over the existing transport. +Returns the raw result - callers should parse it appropriately. + +**Args:** +- `task_id`: The task ID returned from call_tool_as_task + +**Returns:** +- The raw result (could be tool, prompt, or resource result) + +**Raises:** +- `RuntimeError`: If client not connected, task not found, or task failed + + +#### `list_tasks` + +```python +list_tasks(self, cursor: str | None = None, limit: int = 50) -> dict[str, Any] +``` + +List background tasks. + +Sends a 'tasks/list' MCP protocol request to the server. If the server +returns an empty list (indicating client-side tracking), falls back to +querying status for locally tracked task IDs. + +**Args:** +- `cursor`: Optional pagination cursor +- `limit`: Maximum number of tasks to return (default 50) + +**Returns:** +- Response with structure: +- tasks: List of task status dicts with taskId, status, etc. +- nextCursor: Optional cursor for next page + +**Raises:** +- `RuntimeError`: If client not connected + + +#### `cancel_task` + +```python +cancel_task(self, task_id: str) -> mcp.types.CancelTaskResult +``` + +Cancel a task, transitioning it to cancelled state. + +Sends a 'tasks/cancel' MCP protocol request. Task will halt execution +and transition to cancelled state. + +**Args:** +- `task_id`: The task ID to cancel + +**Returns:** +- The task status showing cancelled state + +**Raises:** +- `RuntimeError`: If task doesn't exist + + +#### `generate_name` ```python generate_name(cls, name: str | None = None) -> str ``` - -### `CallToolResult` diff --git a/docs/python-sdk/fastmcp-client-elicitation.mdx b/docs/python-sdk/fastmcp-client-elicitation.mdx index 838f6314d..ccd3ac700 100644 --- a/docs/python-sdk/fastmcp-client-elicitation.mdx +++ b/docs/python-sdk/fastmcp-client-elicitation.mdx @@ -7,7 +7,7 @@ sidebarTitle: elicitation ## Functions -### `create_elicitation_callback` +### `create_elicitation_callback` ```python create_elicitation_callback(elicitation_handler: ElicitationHandler) -> ElicitationFnT diff --git a/docs/python-sdk/fastmcp-client-messages.mdx b/docs/python-sdk/fastmcp-client-messages.mdx index ef1b87436..78c5ebd6d 100644 --- a/docs/python-sdk/fastmcp-client-messages.mdx +++ b/docs/python-sdk/fastmcp-client-messages.mdx @@ -22,85 +22,85 @@ requests, notifications, and exceptions. Users can override any of the hooks dispatch(self, message: Message) -> None ``` -#### `on_message` +#### `on_message` ```python on_message(self, message: Message) -> None ``` -#### `on_request` +#### `on_request` ```python on_request(self, message: RequestResponder[mcp.types.ServerRequest, mcp.types.ClientResult]) -> None ``` -#### `on_ping` +#### `on_ping` ```python on_ping(self, message: mcp.types.PingRequest) -> None ``` -#### `on_list_roots` +#### `on_list_roots` ```python on_list_roots(self, message: mcp.types.ListRootsRequest) -> None ``` -#### `on_create_message` +#### `on_create_message` ```python on_create_message(self, message: mcp.types.CreateMessageRequest) -> None ``` -#### `on_notification` +#### `on_notification` ```python on_notification(self, message: mcp.types.ServerNotification) -> None ``` -#### `on_exception` +#### `on_exception` ```python on_exception(self, message: Exception) -> None ``` -#### `on_progress` +#### `on_progress` ```python on_progress(self, message: mcp.types.ProgressNotification) -> None ``` -#### `on_logging_message` +#### `on_logging_message` ```python on_logging_message(self, message: mcp.types.LoggingMessageNotification) -> None ``` -#### `on_tool_list_changed` +#### `on_tool_list_changed` ```python on_tool_list_changed(self, message: mcp.types.ToolListChangedNotification) -> None ``` -#### `on_resource_list_changed` +#### `on_resource_list_changed` ```python on_resource_list_changed(self, message: mcp.types.ResourceListChangedNotification) -> None ``` -#### `on_prompt_list_changed` +#### `on_prompt_list_changed` ```python on_prompt_list_changed(self, message: mcp.types.PromptListChangedNotification) -> None ``` -#### `on_resource_updated` +#### `on_resource_updated` ```python on_resource_updated(self, message: mcp.types.ResourceUpdatedNotification) -> None ``` -#### `on_cancelled` +#### `on_cancelled` ```python on_cancelled(self, message: mcp.types.CancelledNotification) -> None diff --git a/docs/python-sdk/fastmcp-client-tasks.mdx b/docs/python-sdk/fastmcp-client-tasks.mdx new file mode 100644 index 000000000..8e8e60578 --- /dev/null +++ b/docs/python-sdk/fastmcp-client-tasks.mdx @@ -0,0 +1,219 @@ +--- +title: tasks +sidebarTitle: tasks +--- + +# `fastmcp.client.tasks` + + +SEP-1686 client Task classes. + +## Classes + +### `TaskNotificationHandler` + + +MessageHandler that routes task status notifications to Task objects. + + +**Methods:** + +#### `dispatch` + +```python +dispatch(self, message: Message) -> None +``` + +Dispatch messages, including task status notifications. + + +### `Task` + + +Abstract base class for MCP background tasks (SEP-1686). + +Provides a uniform API whether the server accepts background execution +or executes synchronously (graceful degradation per SEP-1686). + + +**Methods:** + +#### `task_id` + +```python +task_id(self) -> str +``` + +Get the task ID. + + +#### `returned_immediately` + +```python +returned_immediately(self) -> bool +``` + +Check if server executed the task immediately. + +**Returns:** +- True if server executed synchronously (graceful degradation or no task support) +- False if server accepted background execution + + +#### `on_status_change` + +```python +on_status_change(self, callback: Callable[[GetTaskResult], None | Awaitable[None]]) -> None +``` + +Register callback for status change notifications. + +The callback will be invoked when a notifications/tasks/status is received +for this task (optional server feature per SEP-1686 lines 436-444). + +Supports both sync and async callbacks (auto-detected). + +**Args:** +- `callback`: Function to call with GetTaskResult when status changes. + Can return None (sync) or Awaitable[None] (async). + + +#### `status` + +```python +status(self) -> GetTaskResult +``` + +Get current task status. + +If server executed immediately, returns synthetic completed status. +Otherwise queries the server for current status. + + +#### `result` + +```python +result(self) -> TaskResultT +``` + +Wait for and return the task result. + +Must be implemented by subclasses to return the appropriate result type. + + +#### `wait` + +```python +wait(self) -> GetTaskResult +``` + +Wait for task to reach a specific state or complete. + +Uses event-based waiting when notifications are available (fast), +with fallback to polling (reliable). Optimally wakes up immediately +on status changes when server sends notifications/tasks/status. + +**Args:** +- `state`: Desired state ('submitted', 'working', 'completed', 'failed'). + If None, waits for any terminal state (completed/failed) +- `timeout`: Maximum time to wait in seconds + +**Returns:** +- Final task status + +**Raises:** +- `TimeoutError`: If desired state not reached within timeout + + +#### `cancel` + +```python +cancel(self) -> None +``` + +Cancel this task, transitioning it to cancelled state. + +Sends a tasks/cancel protocol request. The server will attempt to halt +execution and move the task to cancelled state. + +Note: If server executed immediately (graceful degradation), this is a no-op +as there's no server-side task to cancel. + + +### `ToolTask` + + +Represents a tool call that may execute in background or immediately. + +Provides a uniform API whether the server accepts background execution +or executes synchronously (graceful degradation per SEP-1686). + + +**Methods:** + +#### `result` + +```python +result(self) -> CallToolResult +``` + +Wait for and return the tool result. + +If server executed immediately, returns the immediate result. +Otherwise waits for background task to complete and retrieves result. + +**Returns:** +- The parsed tool result (same as call_tool returns) + + +### `PromptTask` + + +Represents a prompt call that may execute in background or immediately. + +Provides a uniform API whether the server accepts background execution +or executes synchronously (graceful degradation per SEP-1686). + + +**Methods:** + +#### `result` + +```python +result(self) -> mcp.types.GetPromptResult +``` + +Wait for and return the prompt result. + +If server executed immediately, returns the immediate result. +Otherwise waits for background task to complete and retrieves result. + +**Returns:** +- The prompt result with messages and description + + +### `ResourceTask` + + +Represents a resource read that may execute in background or immediately. + +Provides a uniform API whether the server accepts background execution +or executes synchronously (graceful degradation per SEP-1686). + + +**Methods:** + +#### `result` + +```python +result(self) -> list[mcp.types.TextResourceContents | mcp.types.BlobResourceContents] +``` + +Wait for and return the resource contents. + +If server executed immediately, returns the immediate result. +Otherwise waits for background task to complete and retrieves result. + +**Returns:** +- list\[ReadResourceContents]: The resource contents + diff --git a/docs/python-sdk/fastmcp-client-transports.mdx b/docs/python-sdk/fastmcp-client-transports.mdx index acc5aca73..8246d767c 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,7 @@ close(self) Close the transport. -### `WSTransport` +### `WSTransport` Transport implementation that connects to an MCP server via WebSockets. @@ -110,13 +110,13 @@ Transport implementation that connects to an MCP server via WebSockets. **Methods:** -#### `connect_session` +#### `connect_session` ```python connect_session(self, **session_kwargs: Unpack[SessionKwargs]) -> AsyncIterator[ClientSession] ``` -### `SSETransport` +### `SSETransport` Transport implementation that connects to an MCP server via Server-Sent Events. @@ -124,13 +124,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. @@ -138,13 +138,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] ``` -### `StdioTransport` +#### `get_session_id` + +```python +get_session_id(self) -> str | None +``` + +#### `close` + +```python +close(self) +``` + +### `StdioTransport` Base transport for connecting to an MCP server via subprocess with stdio. @@ -155,67 +167,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. @@ -228,13 +240,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. @@ -287,13 +299,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-dependencies.mdx b/docs/python-sdk/fastmcp-dependencies.mdx new file mode 100644 index 000000000..d53c37027 --- /dev/null +++ b/docs/python-sdk/fastmcp-dependencies.mdx @@ -0,0 +1,14 @@ +--- +title: dependencies +sidebarTitle: dependencies +--- + +# `fastmcp.dependencies` + + +Dependency injection exports for FastMCP. + +This module re-exports dependency injection symbols from Docket and FastMCP +to provide a clean, centralized import location for all dependency-related +functionality. + diff --git a/docs/python-sdk/fastmcp-prompts-prompt.mdx b/docs/python-sdk/fastmcp-prompts-prompt.mdx index b93053e5d..fbcd6ff5a 100644 --- a/docs/python-sdk/fastmcp-prompts-prompt.mdx +++ b/docs/python-sdk/fastmcp-prompts-prompt.mdx @@ -60,7 +60,7 @@ Convert the prompt to an MCP prompt. #### `from_function` ```python -from_function(fn: Callable[..., PromptResult | Awaitable[PromptResult]], name: str | None = None, title: str | None = None, description: str | None = None, icons: list[Icon] | None = None, tags: set[str] | None = None, enabled: bool | None = None, meta: dict[str, Any] | None = None) -> FunctionPrompt +from_function(fn: Callable[..., PromptResult | Awaitable[PromptResult]], name: str | None = None, title: str | None = None, description: str | None = None, icons: list[Icon] | None = None, tags: set[str] | None = None, enabled: bool | None = None, meta: dict[str, Any] | None = None, task: bool | TaskConfig | None = None) -> FunctionPrompt ``` Create a Prompt from a function. @@ -72,7 +72,7 @@ The function can return: - A sequence of any of the above -#### `render` +#### `render` ```python render(self, arguments: dict[str, Any] | None = None) -> list[PromptMessage] @@ -84,7 +84,7 @@ This method is not implemented in the base Prompt class and must be implemented by subclasses. -### `FunctionPrompt` +### `FunctionPrompt` A prompt that is a function. @@ -92,10 +92,10 @@ A prompt that is a function. **Methods:** -#### `from_function` +#### `from_function` ```python -from_function(cls, fn: Callable[..., PromptResult | Awaitable[PromptResult]], name: str | None = None, title: str | None = None, description: str | None = None, icons: list[Icon] | None = None, tags: set[str] | None = None, enabled: bool | None = None, meta: dict[str, Any] | None = None) -> FunctionPrompt +from_function(cls, fn: Callable[..., PromptResult | Awaitable[PromptResult]], name: str | None = None, title: str | None = None, description: str | None = None, icons: list[Icon] | None = None, tags: set[str] | None = None, enabled: bool | None = None, meta: dict[str, Any] | None = None, task: bool | TaskConfig | None = None) -> FunctionPrompt ``` Create a Prompt from a function. @@ -107,7 +107,7 @@ The function can return: - A sequence of any of the above -#### `render` +#### `render` ```python render(self, arguments: dict[str, Any] | None = None) -> list[PromptMessage] diff --git a/docs/python-sdk/fastmcp-resources-resource.mdx b/docs/python-sdk/fastmcp-resources-resource.mdx index 3018841d4..7ed4f805d 100644 --- a/docs/python-sdk/fastmcp-resources-resource.mdx +++ b/docs/python-sdk/fastmcp-resources-resource.mdx @@ -18,25 +18,25 @@ Base class for all resources. **Methods:** -#### `enable` +#### `enable` ```python enable(self) -> None ``` -#### `disable` +#### `disable` ```python disable(self) -> None ``` -#### `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, enabled: bool | None = None, annotations: Annotations | None = None, meta: dict[str, Any] | None = None) -> FunctionResource +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, enabled: bool | None = None, annotations: Annotations | None = None, meta: dict[str, Any] | None = None, task: bool | TaskConfig | None = None) -> FunctionResource ``` -#### `set_default_mime_type` +#### `set_default_mime_type` ```python set_default_mime_type(cls, mime_type: str | None) -> str @@ -45,7 +45,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 @@ -54,7 +54,7 @@ set_default_name(self) -> Self Set default name from URI if not provided. -#### `read` +#### `read` ```python read(self) -> str | bytes @@ -66,7 +66,7 @@ This method is not implemented in the base Resource class and must be implemented by subclasses. -#### `to_mcp_resource` +#### `to_mcp_resource` ```python to_mcp_resource(self, **overrides: Any) -> MCPResource @@ -75,7 +75,7 @@ to_mcp_resource(self, **overrides: Any) -> MCPResource Convert the resource to an MCPResource. -#### `key` +#### `key` ```python key(self) -> str @@ -87,7 +87,7 @@ keys having a certain value, as the same tool loaded from different hierarchies of servers may have different keys. -### `FunctionResource` +### `FunctionResource` A resource that defers data loading by wrapping a function. @@ -104,16 +104,16 @@ The function can return: **Methods:** -#### `from_function` +#### `from_function` ```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, enabled: bool | None = None, annotations: Annotations | None = None, meta: dict[str, Any] | None = None) -> FunctionResource +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, enabled: bool | None = None, annotations: Annotations | None = None, meta: dict[str, Any] | None = None, task: bool | TaskConfig | None = None) -> FunctionResource ``` Create a FunctionResource from a function. -#### `read` +#### `read` ```python read(self) -> str | bytes diff --git a/docs/python-sdk/fastmcp-resources-template.mdx b/docs/python-sdk/fastmcp-resources-template.mdx index 8ff3ff26a..1effd3bc6 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,22 +59,22 @@ A template for dynamically creating resources. **Methods:** -#### `enable` +#### `enable` ```python enable(self) -> None ``` -#### `disable` +#### `disable` ```python disable(self) -> None ``` -#### `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, enabled: bool | None = None, annotations: Annotations | None = None, meta: dict[str, Any] | None = None) -> FunctionResourceTemplate +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, enabled: bool | None = None, annotations: Annotations | None = None, meta: dict[str, Any] | None = None, task: bool | TaskConfig | None = None) -> FunctionResourceTemplate ``` #### `set_default_mime_type` @@ -112,8 +112,11 @@ create_resource(self, uri: str, params: dict[str, Any]) -> Resource Create a resource from the template with the given parameters. +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) -> MCPResourceTemplate @@ -122,7 +125,7 @@ to_mcp_template(self, **overrides: Any) -> MCPResourceTemplate Convert the resource template to an MCPResourceTemplate. -#### `from_mcp_template` +#### `from_mcp_template` ```python from_mcp_template(cls, mcp_template: MCPResourceTemplate) -> ResourceTemplate @@ -131,7 +134,7 @@ from_mcp_template(cls, mcp_template: MCPResourceTemplate) -> ResourceTemplate Creates a FastMCP ResourceTemplate from a raw MCP ResourceTemplate object. -#### `key` +#### `key` ```python key(self) -> str @@ -143,7 +146,7 @@ keys having a certain value, as the same tool loaded from different hierarchies of servers may have different keys. -### `FunctionResourceTemplate` +### `FunctionResourceTemplate` A template for dynamically creating resources. @@ -151,7 +154,16 @@ A template for dynamically creating resources. **Methods:** -#### `read` +#### `create_resource` + +```python +create_resource(self, uri: str, params: dict[str, Any]) -> Resource +``` + +Create a resource from the template with the given parameters. + + +#### `read` ```python read(self, arguments: dict[str, Any]) -> str | bytes @@ -160,10 +172,10 @@ read(self, arguments: dict[str, Any]) -> str | bytes Read the resource content. -#### `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, enabled: bool | None = None, annotations: Annotations | None = None, meta: dict[str, Any] | None = None) -> FunctionResourceTemplate +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, enabled: bool | None = None, annotations: Annotations | None = None, meta: dict[str, Any] | None = None, task: bool | TaskConfig | None = None) -> FunctionResourceTemplate ``` Create a template from a function. diff --git a/docs/python-sdk/fastmcp-server-auth-auth.mdx b/docs/python-sdk/fastmcp-server-auth-auth.mdx index b5002a805..fab057df0 100644 --- a/docs/python-sdk/fastmcp-server-auth-auth.mdx +++ b/docs/python-sdk/fastmcp-server-auth-auth.mdx @@ -7,13 +7,42 @@ sidebarTitle: auth ## Classes -### `AccessToken` +### `AccessToken` AccessToken that includes all JWT claims. -### `AuthProvider` +### `TokenHandler` + + +TokenHandler that returns OAuth 2.1 compliant error responses. + +The MCP SDK returns `unauthorized_client` for client authentication failures. +However, per RFC 6749 Section 5.2, authentication failures should return +`invalid_client` with HTTP 401, not `unauthorized_client`. + +This distinction matters: `unauthorized_client` means "client exists but +can't do this", while `invalid_client` means "client doesn't exist or +credentials are wrong". Claude's OAuth client uses this to decide whether +to re-register. + +This handler transforms 401 responses with `unauthorized_client` to use +`invalid_client` instead, making the error semantics correct per OAuth spec. + + +**Methods:** + +#### `handle` + +```python +handle(self, request: Any) +``` + +Wrap SDK handle() and transform auth error responses. + + +### `AuthProvider` Base class for all FastMCP authentication providers. @@ -26,7 +55,7 @@ custom authentication routes. **Methods:** -#### `verify_token` +#### `verify_token` ```python verify_token(self, token: str) -> AccessToken | None @@ -43,7 +72,7 @@ All auth providers must implement token verification. - AccessToken object if valid, None if invalid or expired -#### `get_routes` +#### `get_routes` ```python get_routes(self, mcp_path: str | None = None) -> list[Route] @@ -67,7 +96,7 @@ provider does not create the actual MCP endpoint route. - List of all routes for this provider (excluding the MCP endpoint itself) -#### `get_well_known_routes` +#### `get_well_known_routes` ```python get_well_known_routes(self, mcp_path: str | None = None) -> list[Route] @@ -95,7 +124,7 @@ This is used to construct path-scoped well-known URLs. - List of well-known discovery routes (typically mounted at root level) -#### `get_middleware` +#### `get_middleware` ```python get_middleware(self) -> list @@ -107,7 +136,7 @@ Get HTTP application-level middleware for this auth provider. - List of Starlette Middleware instances to apply to the HTTP app -### `TokenVerifier` +### `TokenVerifier` Base class for token verifiers (Resource Servers). @@ -118,7 +147,7 @@ Token verifiers typically don't provide authentication routes by default. **Methods:** -#### `verify_token` +#### `verify_token` ```python verify_token(self, token: str) -> AccessToken | None @@ -127,7 +156,7 @@ verify_token(self, token: str) -> AccessToken | None Verify a bearer token and return access info if valid. -### `RemoteAuthProvider` +### `RemoteAuthProvider` Authentication provider for resource servers that verify tokens from known authorization servers. @@ -144,7 +173,7 @@ the authorization servers that issue valid tokens. **Methods:** -#### `verify_token` +#### `verify_token` ```python verify_token(self, token: str) -> AccessToken | None @@ -153,7 +182,7 @@ verify_token(self, token: str) -> AccessToken | None Verify token using the configured token verifier. -#### `get_routes` +#### `get_routes` ```python get_routes(self, mcp_path: str | None = None) -> list[Route] @@ -164,7 +193,7 @@ Get routes for this provider. Creates protected resource metadata routes (RFC 9728). -### `OAuthProvider` +### `OAuthProvider` OAuth Authorization Server provider. @@ -175,7 +204,7 @@ authorization flows, token issuance, and token verification. **Methods:** -#### `verify_token` +#### `verify_token` ```python verify_token(self, token: str) -> AccessToken | None @@ -193,7 +222,7 @@ to our existing load_access_token method. - AccessToken object if valid, None if invalid or expired -#### `get_routes` +#### `get_routes` ```python get_routes(self, mcp_path: str | None = None) -> list[Route] @@ -208,3 +237,26 @@ This method creates the full set of OAuth routes including: **Returns:** - List of OAuth routes + +#### `get_well_known_routes` + +```python +get_well_known_routes(self, mcp_path: str | None = None) -> list[Route] +``` + +Get well-known discovery routes with RFC 8414 path-aware support. + +Overrides the base implementation to support path-aware authorization +server metadata discovery per RFC 8414. If issuer_url has a path component, +the authorization server metadata route is adjusted to include that path. + +For example, if issuer_url is "http://example.com/api", the discovery +endpoint will be at "/.well-known/oauth-authorization-server/api" instead +of just "/.well-known/oauth-authorization-server". + +**Args:** +- `mcp_path`: The path where the MCP endpoint is mounted (e.g., "/mcp") + +**Returns:** +- List of well-known discovery routes + diff --git a/docs/python-sdk/fastmcp-server-auth-oauth_proxy.mdx b/docs/python-sdk/fastmcp-server-auth-oauth_proxy.mdx index 2ce8efee2..c8de4bb4e 100644 --- a/docs/python-sdk/fastmcp-server-auth-oauth_proxy.mdx +++ b/docs/python-sdk/fastmcp-server-auth-oauth_proxy.mdx @@ -26,7 +26,7 @@ production use with enterprise identity providers. ## Functions -### `create_consent_html` +### `create_consent_html` ```python create_consent_html(client_id: str, redirect_uri: str, scopes: list[str], txn_id: str, csrf_token: str, client_name: str | None = None, title: str = 'Application Access Request', server_name: str | None = None, server_icon_url: str | None = None, server_website_url: str | None = None, client_website_url: str | None = None, csp_policy: str | None = None) -> str @@ -42,7 +42,7 @@ If empty string "", disables CSP entirely (no meta tag is rendered). If a non-empty string, uses that as the CSP policy value. -### `create_error_html` +### `create_error_html` ```python create_error_html(error_title: str, error_message: str, error_details: dict[str, str] | None = None, server_name: str | None = None, server_icon_url: str | None = None) -> str @@ -64,7 +64,7 @@ Create a styled HTML error page for OAuth errors. ## Classes -### `OAuthTransaction` +### `OAuthTransaction` OAuth transaction state for consent flow. @@ -73,7 +73,7 @@ Stored server-side to track active authorization flows with client context. Includes CSRF tokens for consent protection per MCP security best practices. -### `ClientCode` +### `ClientCode` Client authorization code with PKCE and upstream tokens. @@ -82,7 +82,7 @@ Stored server-side after upstream IdP callback. Contains the upstream tokens bound to the client's PKCE challenge for secure token exchange. -### `UpstreamTokenSet` +### `UpstreamTokenSet` Stored upstream OAuth tokens from identity provider. @@ -92,7 +92,7 @@ and stored in plaintext within this model. Encryption is handled transparently at the storage layer via FernetEncryptionWrapper. Tokens are never exposed to MCP clients. -### `JTIMapping` +### `JTIMapping` Maps FastMCP token JTI to upstream token ID. @@ -101,7 +101,7 @@ This allows stateless JWT validation while still being able to look up the corresponding upstream token when tools need to access upstream APIs. -### `RefreshTokenMetadata` +### `RefreshTokenMetadata` Metadata for a refresh token, stored keyed by token hash. @@ -110,7 +110,7 @@ We store only metadata (not the token itself) for security - if storage is compromised, attackers get hashes they can't reverse into usable tokens. -### `ProxyDCRClient` +### `ProxyDCRClient` Client for DCR proxy with configurable redirect URI validation. @@ -140,7 +140,7 @@ arise from accepting arbitrary redirect URIs. **Methods:** -#### `validate_redirect_uri` +#### `validate_redirect_uri` ```python validate_redirect_uri(self, redirect_uri: AnyUrl | None) -> AnyUrl @@ -154,39 +154,7 @@ This is essential for cached token scenarios where the client may reconnect with a different port. -### `TokenHandler` - - -TokenHandler that returns OAuth 2.1 compliant error responses. - -The MCP SDK always returns HTTP 400 for all client authentication issues. -However, OAuth 2.1 Section 5.3 and the MCP specification require that -invalid or expired tokens MUST receive a HTTP 401 response. - -This handler extends the base MCP SDK TokenHandler to transform client -authentication failures into OAuth 2.1 compliant responses: -- Changes 'unauthorized_client' to 'invalid_client' error code -- Returns HTTP 401 status code instead of 400 for client auth failures - -Per OAuth 2.1 Section 5.3: "The authorization server MAY return an HTTP 401 -(Unauthorized) status code to indicate which HTTP authentication schemes -are supported." - -Per MCP spec: "Invalid or expired tokens MUST receive a HTTP 401 response." - - -**Methods:** - -#### `response` - -```python -response(self, obj: TokenSuccessResponse | TokenErrorResponse) -``` - -Override response method to provide OAuth 2.1 compliant error handling. - - -### `OAuthProxy` +### `OAuthProxy` OAuth provider that presents a DCR-compliant interface while proxying to non-DCR IDPs. @@ -300,7 +268,7 @@ Handles provider-specific requirements: **Methods:** -#### `get_client` +#### `get_client` ```python get_client(self, client_id: str) -> OAuthClientInformationFull | None @@ -312,7 +280,7 @@ provided to the DCR client during registration, not the upstream client ID. For unregistered clients, returns None (which will raise an error in the SDK). -#### `register_client` +#### `register_client` ```python register_client(self, client_info: OAuthClientInformationFull) -> None @@ -326,7 +294,7 @@ redirect URI will likely be localhost or unknown to the proxied IDP. The proxied IDP only knows about this server's fixed redirect URI. -#### `authorize` +#### `authorize` ```python authorize(self, client: OAuthClientInformationFull, params: AuthorizationParams) -> str @@ -343,7 +311,7 @@ If consent is disabled (require_authorization_consent=False), skip the consent s and redirect directly to the upstream IdP. -#### `load_authorization_code` +#### `load_authorization_code` ```python load_authorization_code(self, client: OAuthClientInformationFull, authorization_code: str) -> AuthorizationCode | None @@ -355,7 +323,7 @@ Look up our client code and return authorization code object with PKCE challenge for validation. -#### `exchange_authorization_code` +#### `exchange_authorization_code` ```python exchange_authorization_code(self, client: OAuthClientInformationFull, authorization_code: AuthorizationCode) -> OAuthToken @@ -373,7 +341,7 @@ Implements the token factory pattern: PKCE validation is handled by the MCP framework before this method is called. -#### `load_refresh_token` +#### `load_refresh_token` ```python load_refresh_token(self, client: OAuthClientInformationFull, refresh_token: str) -> RefreshToken | None @@ -385,7 +353,7 @@ Looks up by token hash and reconstructs the RefreshToken object. Validates that the token belongs to the requesting client. -#### `exchange_refresh_token` +#### `exchange_refresh_token` ```python exchange_refresh_token(self, client: OAuthClientInformationFull, refresh_token: RefreshToken, scopes: list[str]) -> OAuthToken @@ -402,7 +370,7 @@ Implements two-tier refresh: 6. Keep same FastMCP refresh token (unless upstream rotates) -#### `load_access_token` +#### `load_access_token` ```python load_access_token(self, token: str) -> AccessToken | None @@ -421,7 +389,7 @@ The FastMCP JWT is a reference token - all authorization data comes from validating the upstream token via the TokenVerifier. -#### `revoke_token` +#### `revoke_token` ```python revoke_token(self, token: AccessToken | RefreshToken) -> None @@ -434,7 +402,7 @@ For all tokens, attempts upstream revocation if endpoint is configured. Access token JTI mappings expire via TTL. -#### `get_routes` +#### `get_routes` ```python get_routes(self, mcp_path: str | None = None) -> list[Route] diff --git a/docs/python-sdk/fastmcp-server-context.mdx b/docs/python-sdk/fastmcp-server-context.mdx index ee9772830..fa3a35f2f 100644 --- a/docs/python-sdk/fastmcp-server-context.mdx +++ b/docs/python-sdk/fastmcp-server-context.mdx @@ -7,7 +7,7 @@ sidebarTitle: context ## Functions -### `set_context` +### `set_context` ```python set_context(context: Context) -> Generator[Context, None, None] @@ -15,7 +15,7 @@ set_context(context: Context) -> Generator[Context, None, None] ## Classes -### `LogData` +### `LogData` Data object for passing log arguments to client-side handlers. @@ -24,7 +24,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. @@ -72,7 +72,7 @@ The context is optional - tools that don't need it can omit the parameter. **Methods:** -#### `fastmcp` +#### `fastmcp` ```python fastmcp(self) -> FastMCP @@ -81,7 +81,7 @@ fastmcp(self) -> FastMCP Get the FastMCP instance. -#### `request_context` +#### `request_context` ```python request_context(self) -> RequestContext[ServerSession, Any, Request] | None @@ -110,7 +110,7 @@ async def on_request(self, context, call_next): ``` -#### `report_progress` +#### `report_progress` ```python report_progress(self, progress: float, total: float | None = None, message: str | None = None) -> None @@ -123,7 +123,7 @@ Report progress for the current operation. - `total`: Optional total value e.g. 100 -#### `list_resources` +#### `list_resources` ```python list_resources(self) -> list[MCPResource] @@ -135,7 +135,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[MCPPrompt] @@ -147,7 +147,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 @@ -163,7 +163,7 @@ Get a prompt by name with optional arguments. - The prompt result -#### `read_resource` +#### `read_resource` ```python read_resource(self, uri: str | AnyUrl) -> list[ReadResourceContents] @@ -178,7 +178,7 @@ Read a resource by URI. - The resource content as either text or bytes -#### `log` +#### `log` ```python log(self, message: str, level: LoggingLevel | None = None, logger_name: str | None = None, extra: Mapping[str, Any] | None = None) -> None @@ -196,7 +196,7 @@ Messages sent to Clients are also logged to the `fastmcp.server.context.to_clien - `extra`: Optional mapping for additional arguments -#### `client_id` +#### `client_id` ```python client_id(self) -> str | None @@ -205,7 +205,7 @@ client_id(self) -> str | None Get the client ID if available. -#### `request_id` +#### `request_id` ```python request_id(self) -> str @@ -216,7 +216,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 @@ -233,7 +233,7 @@ the same client session. - for other transports. -#### `session` +#### `session` ```python session(self) -> ServerSession @@ -244,7 +244,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 @@ -255,7 +255,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 @@ -266,7 +266,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 @@ -277,7 +277,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 @@ -288,7 +288,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] @@ -297,7 +297,7 @@ list_roots(self) -> list[Root] List the roots available to the server, as indicated by the client. -#### `send_tool_list_changed` +#### `send_tool_list_changed` ```python send_tool_list_changed(self) -> None @@ -306,7 +306,7 @@ send_tool_list_changed(self) -> None Send a tool list changed notification to the client. -#### `send_resource_list_changed` +#### `send_resource_list_changed` ```python send_resource_list_changed(self) -> None @@ -315,7 +315,7 @@ send_resource_list_changed(self) -> None Send a resource list changed notification to the client. -#### `send_prompt_list_changed` +#### `send_prompt_list_changed` ```python send_prompt_list_changed(self) -> None @@ -324,10 +324,28 @@ send_prompt_list_changed(self) -> None Send a prompt list changed notification to the client. -#### `sample` +#### `close_sse_stream` ```python -sample(self, messages: str | Sequence[str | SamplingMessage], system_prompt: str | None = None, include_context: IncludeContext | None = None, temperature: float | None = None, max_tokens: int | None = None, model_preferences: ModelPreferences | str | list[str] | None = None) -> TextContent | ImageContent | AudioContent +close_sse_stream(self) -> None +``` + +Close the current response stream to trigger client reconnection. + +When using StreamableHTTP transport with an EventStore configured, this +method gracefully closes the HTTP connection for the current request. +The client will automatically reconnect (after `retry_interval` milliseconds) +and resume receiving events from where it left off via the EventStore. + +This is useful for long-running operations to avoid load balancer timeouts. +Instead of holding a connection open for minutes, you can periodically close +and let the client reconnect. + + +#### `sample` + +```python +sample(self, messages: str | Sequence[str | SamplingMessage], system_prompt: str | None = None, include_context: IncludeContext | None = None, temperature: float | None = None, max_tokens: int | None = None, model_preferences: ModelPreferences | str | list[str] | None = None) -> SamplingMessageContentBlock | list[SamplingMessageContentBlock] ``` Send a sampling request to the client and await the response. @@ -337,25 +355,25 @@ completion from the client. The client must be appropriately configured, or the request will error. -#### `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: type[T] | list[str] | None = None) -> AcceptedElicitation[T] | AcceptedElicitation[dict[str, Any]] | AcceptedElicitation[str] | DeclinedElicitation | CancelledElicitation @@ -384,7 +402,7 @@ 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 @@ -393,7 +411,7 @@ set_state(self, key: str, value: Any) -> None Set a value in the context state. -#### `get_state` +#### `get_state` ```python get_state(self, key: str) -> Any diff --git a/docs/python-sdk/fastmcp-server-dependencies.mdx b/docs/python-sdk/fastmcp-server-dependencies.mdx index 9092633d9..19636c2ce 100644 --- a/docs/python-sdk/fastmcp-server-dependencies.mdx +++ b/docs/python-sdk/fastmcp-server-dependencies.mdx @@ -7,19 +7,155 @@ sidebarTitle: dependencies ## Functions -### `get_context` +### `without_injected_parameters` + +```python +without_injected_parameters(fn: Callable[..., Any]) -> Callable[..., Any] +``` + + +Create a wrapper function without injected parameters. + +Returns a wrapper that excludes Context and Docket dependency parameters, +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. + +**Args:** +- `fn`: Original function with Context and/or dependencies + +**Returns:** +- Async wrapper function without injected parameters + + +### `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. + +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 + +The filtering prevents external callers from overriding injected parameters by +providing values for dependency parameter names. This is a security feature. + +**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 ``` -### `get_http_request` +### `CurrentContext` + +```python +CurrentContext() -> Context +``` + + +Get the current FastMCP Context instance. + +This dependency provides access to the active FastMCP Context for the +current MCP operation (tool/resource/prompt call). + +**Returns:** +- A dependency that resolves to the active Context instance + +**Raises:** +- `RuntimeError`: If no active context found (during resolution) + + +### `CurrentDocket` + +```python +CurrentDocket() -> Docket +``` + + +Get the current Docket instance managed by FastMCP. + +This dependency provides access to the Docket instance that FastMCP +automatically creates for background task scheduling. + +**Returns:** +- A dependency that resolves to the active Docket instance + +**Raises:** +- `RuntimeError`: If not within a FastMCP server context + + +### `CurrentWorker` + +```python +CurrentWorker() -> Worker +``` + + +Get the current Docket Worker instance managed by FastMCP. + +This dependency provides access to the Worker instance that FastMCP +automatically creates for background task processing. + +**Returns:** +- A dependency that resolves to the active Worker instance + +**Raises:** +- `RuntimeError`: If not within a FastMCP server context + + +### `CurrentFastMCP` + +```python +CurrentFastMCP() +``` + + +Get the current FastMCP server instance. + +This dependency provides access to the active FastMCP server. + +**Returns:** +- A dependency that resolves to the active FastMCP server + +**Raises:** +- `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` +### `get_http_headers` ```python get_http_headers(include_all: bool = False) -> dict[str, str] @@ -35,7 +171,7 @@ By default, strips problematic headers like `content-length` that cause issues i If `include_all` is True, all headers are returned. -### `get_access_token` +### `get_access_token` ```python get_access_token() -> AccessToken | None @@ -52,3 +188,75 @@ request is available. **Returns:** - The access token if an authenticated user is available, None otherwise. + +## Classes + +### `InMemoryProgress` + + +In-memory progress tracker for immediate tool execution. + +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. + + +**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) + +This allows tools to use Progress() regardless of whether they're called +immediately or as background tasks. + diff --git a/docs/python-sdk/fastmcp-server-elicitation.mdx b/docs/python-sdk/fastmcp-server-elicitation.mdx index c21fc533d..04a9be73a 100644 --- a/docs/python-sdk/fastmcp-server-elicitation.mdx +++ b/docs/python-sdk/fastmcp-server-elicitation.mdx @@ -7,7 +7,45 @@ sidebarTitle: elicitation ## Functions -### `get_elicitation_schema` +### `parse_elicit_response_type` + +```python +parse_elicit_response_type(response_type: Any) -> ElicitConfig +``` + + +Parse response_type into schema and handling configuration. + +Supports multiple syntaxes: +- None: Empty object schema, expect empty response +- dict: {"low": {"title": "..."}} -> single-select titled enum +- list patterns: + - [["a", "b"]] -> multi-select untitled + - [{"low": {...}}] -> multi-select titled + - ["a", "b"] -> single-select untitled +- list\[X] type annotation: multi-select with type +- Scalar types (bool, int, float, str, Literal, Enum): single value +- Other types (dataclass, BaseModel): use directly + + +### `handle_elicit_accept` + +```python +handle_elicit_accept(config: ElicitConfig, content: Any) -> AcceptedElicitation[Any] +``` + + +Handle an accepted elicitation response. + +**Args:** +- `config`: The elicitation configuration from parse_elicit_response_type +- `content`: The response content from the client + +**Returns:** +- AcceptedElicitation with the extracted/validated data + + +### `get_elicitation_schema` ```python get_elicitation_schema(response_type: type[T]) -> dict[str, Any] @@ -20,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 @@ -45,7 +83,7 @@ This ensures the schema is compatible with MCP elicitation requirements: ## Classes -### `ElicitationJsonSchema` +### `ElicitationJsonSchema` Custom JSON schema generator for MCP elicitation that always inlines enums. @@ -57,31 +95,46 @@ Optionally adds enumNames for better UI display when available. **Methods:** -#### `generate_inner` +#### `generate_inner` ```python generate_inner(self, schema: core_schema.CoreSchema) -> JsonSchemaValue ``` -Override to prevent ref generation for enums. +Override to prevent ref generation for enums and handle list schemas. -#### `enum_schema` +#### `list_schema` + +```python +list_schema(self, schema: core_schema.ListSchema) -> JsonSchemaValue +``` + +Generate schema for list types, detecting enum items for multi-select. + + +#### `enum_schema` ```python enum_schema(self, schema: core_schema.EnumSchema) -> JsonSchemaValue ``` -Generate inline enum schema with optional enumNames for better UI. +Generate inline enum schema. -If enum members have a _display_name_ attribute or custom __str__, -we'll include enumNames for better UI representation. +Always generates enum pattern: {"enum": [value, ...]} +Titled enums are handled separately via dict-based syntax in ctx.elicit(). -### `AcceptedElicitation` +### `AcceptedElicitation` Result when user accepts the elicitation. -### `ScalarElicitationType` +### `ScalarElicitationType` + +### `ElicitConfig` + + +Configuration for an elicitation request. + diff --git a/docs/python-sdk/fastmcp-server-event_store.mdx b/docs/python-sdk/fastmcp-server-event_store.mdx new file mode 100644 index 000000000..9ff70bc56 --- /dev/null +++ b/docs/python-sdk/fastmcp-server-event_store.mdx @@ -0,0 +1,78 @@ +--- +title: event_store +sidebarTitle: event_store +--- + +# `fastmcp.server.event_store` + + +EventStore implementation backed by AsyncKeyValue. + +This module provides an EventStore implementation that enables SSE polling/resumability +for Streamable HTTP transports. Events are stored using the key_value package's +AsyncKeyValue protocol, allowing users to configure any compatible backend +(in-memory, Redis, etc.) following the same pattern as ResponseCachingMiddleware. + + +## Classes + +### `EventEntry` + + +Stored event entry. + + +### `StreamEventList` + + +List of event IDs for a stream. + + +### `EventStore` + + +EventStore implementation backed by AsyncKeyValue. + +Enables SSE polling/resumability by storing events that can be replayed +when clients reconnect. Works with any AsyncKeyValue backend (memory, Redis, etc.) +following the same pattern as ResponseCachingMiddleware and OAuthProxy. + +**Args:** +- `storage`: AsyncKeyValue backend. Defaults to MemoryStore. +- `max_events_per_stream`: Maximum events to retain per stream. Default 100. +- `ttl`: Event TTL in seconds. Default 3600 (1 hour). Set to None for no expiration. + + +**Methods:** + +#### `store_event` + +```python +store_event(self, stream_id: StreamId, message: JSONRPCMessage | None) -> EventId +``` + +Store an event and return its ID. + +**Args:** +- `stream_id`: ID of the stream the event belongs to +- `message`: The JSON-RPC message to store, or None for priming events + +**Returns:** +- The generated event ID for the stored event + + +#### `replay_events_after` + +```python +replay_events_after(self, last_event_id: EventId, send_callback: EventCallback) -> StreamId | None +``` + +Replay events that occurred after the specified event ID. + +**Args:** +- `last_event_id`: The ID of the last event the client received +- `send_callback`: A callback function to send events to the client + +**Returns:** +- The stream ID of the replayed events, or None if the event ID was not found + diff --git a/docs/python-sdk/fastmcp-server-http.mdx b/docs/python-sdk/fastmcp-server-http.mdx index 40ae6fb9b..8aaf2c934 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,10 +54,10 @@ 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, 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 +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 ``` @@ -66,7 +66,10 @@ Return an instance of the StreamableHTTP server app. **Args:** - `server`: The FastMCP server instance - `streamable_http_path`: Path for StreamableHTTP connections -- `event_store`: Optional event store for session management +- `event_store`: Optional event store for SSE polling/resumability +- `retry_interval`: Optional retry interval in milliseconds for SSE polling. +Controls how quickly clients should reconnect after server-initiated +disconnections. Requires event_store to be set. Defaults to SDK default. - `auth`: Optional authentication provider (AuthProvider) - `json_response`: Whether to use JSON response format - `stateless_http`: Whether to use stateless mode (new transport per request) @@ -80,23 +83,23 @@ Return an instance of the StreamableHTTP server app. ## 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 diff --git a/docs/python-sdk/fastmcp-server-low_level.mdx b/docs/python-sdk/fastmcp-server-low_level.mdx index fd3dcaeec..9b18bc5be 100644 --- a/docs/python-sdk/fastmcp-server-low_level.mdx +++ b/docs/python-sdk/fastmcp-server-low_level.mdx @@ -15,7 +15,7 @@ ServerSession that routes initialization requests through FastMCP middleware. **Methods:** -#### `fastmcp` +#### `fastmcp` ```python fastmcp(self) -> FastMCP @@ -24,11 +24,11 @@ fastmcp(self) -> FastMCP Get the FastMCP instance. -### `LowLevelServer` +### `LowLevelServer` **Methods:** -#### `fastmcp` +#### `fastmcp` ```python fastmcp(self) -> FastMCP @@ -37,13 +37,13 @@ fastmcp(self) -> FastMCP Get the FastMCP instance. -#### `create_initialization_options` +#### `create_initialization_options` ```python create_initialization_options(self, notification_options: NotificationOptions | None = None, experimental_capabilities: dict[str, dict[str, Any]] | None = None, **kwargs: Any) -> InitializationOptions ``` -#### `run` +#### `run` ```python run(self, read_stream: MemoryObjectReceiveStream[SessionMessage | Exception], write_stream: MemoryObjectSendStream[SessionMessage], initialization_options: InitializationOptions, raise_exceptions: bool = False, stateless: bool = False) diff --git a/docs/python-sdk/fastmcp-server-middleware-middleware.mdx b/docs/python-sdk/fastmcp-server-middleware-middleware.mdx index 4d23d9364..baeffa691 100644 --- a/docs/python-sdk/fastmcp-server-middleware-middleware.mdx +++ b/docs/python-sdk/fastmcp-server-middleware-middleware.mdx @@ -66,7 +66,7 @@ on_notification(self, context: MiddlewareContext[mt.Notification[Any, Any]], cal #### `on_initialize` ```python -on_initialize(self, context: MiddlewareContext[mt.InitializeRequest], call_next: CallNext[mt.InitializeRequest, None]) -> None +on_initialize(self, context: MiddlewareContext[mt.InitializeRequest], call_next: CallNext[mt.InitializeRequest, mt.InitializeResult | None]) -> mt.InitializeResult | None ``` #### `on_call_tool` diff --git a/docs/python-sdk/fastmcp-server-proxy.mdx b/docs/python-sdk/fastmcp-server-proxy.mdx index da1447345..9abe6e123 100644 --- a/docs/python-sdk/fastmcp-server-proxy.mdx +++ b/docs/python-sdk/fastmcp-server-proxy.mdx @@ -7,7 +7,7 @@ sidebarTitle: proxy ## Functions -### `default_proxy_roots_handler` +### `default_proxy_roots_handler` ```python default_proxy_roots_handler(context: RequestContext[ClientSession, LifespanContextT]) -> RootsList @@ -19,13 +19,13 @@ A handler that forwards the list roots request from the remote server to the pro ## Classes -### `ProxyManagerMixin` +### `ProxyManagerMixin` A mixin for proxy managers to provide a unified client retrieval method. -### `ProxyToolManager` +### `ProxyToolManager` A ToolManager that sources its tools from a remote client in addition to local and mounted tools. @@ -33,7 +33,7 @@ A ToolManager that sources its tools from a remote client in addition to local a **Methods:** -#### `get_tools` +#### `get_tools` ```python get_tools(self) -> dict[str, Tool] @@ -42,7 +42,7 @@ get_tools(self) -> dict[str, Tool] Gets the unfiltered tool inventory including local, mounted, and proxy tools. -#### `list_tools` +#### `list_tools` ```python list_tools(self) -> list[Tool] @@ -51,7 +51,7 @@ list_tools(self) -> list[Tool] Gets the filtered list of tools including local, mounted, and proxy tools. -#### `call_tool` +#### `call_tool` ```python call_tool(self, key: str, arguments: dict[str, Any]) -> ToolResult @@ -60,7 +60,7 @@ call_tool(self, key: str, arguments: dict[str, Any]) -> ToolResult Calls a tool, trying local/mounted first, then proxy if not found. -### `ProxyResourceManager` +### `ProxyResourceManager` A ResourceManager that sources its resources from a remote client in addition to local and mounted resources. @@ -68,7 +68,7 @@ A ResourceManager that sources its resources from a remote client in addition to **Methods:** -#### `get_resources` +#### `get_resources` ```python get_resources(self) -> dict[str, Resource] @@ -77,7 +77,7 @@ get_resources(self) -> dict[str, Resource] Gets the unfiltered resource inventory including local, mounted, and proxy resources. -#### `get_resource_templates` +#### `get_resource_templates` ```python get_resource_templates(self) -> dict[str, ResourceTemplate] @@ -86,7 +86,7 @@ get_resource_templates(self) -> dict[str, ResourceTemplate] Gets the unfiltered template inventory including local, mounted, and proxy templates. -#### `list_resources` +#### `list_resources` ```python list_resources(self) -> list[Resource] @@ -95,7 +95,7 @@ list_resources(self) -> list[Resource] Gets the filtered list of resources including local, mounted, and proxy resources. -#### `list_resource_templates` +#### `list_resource_templates` ```python list_resource_templates(self) -> list[ResourceTemplate] @@ -104,7 +104,7 @@ list_resource_templates(self) -> list[ResourceTemplate] Gets the filtered list of templates including local, mounted, and proxy templates. -#### `read_resource` +#### `read_resource` ```python read_resource(self, uri: AnyUrl | str) -> str | bytes @@ -113,7 +113,7 @@ read_resource(self, uri: AnyUrl | str) -> str | bytes Reads a resource, trying local/mounted first, then proxy if not found. -### `ProxyPromptManager` +### `ProxyPromptManager` A PromptManager that sources its prompts from a remote client in addition to local and mounted prompts. @@ -121,7 +121,7 @@ A PromptManager that sources its prompts from a remote client in addition to loc **Methods:** -#### `get_prompts` +#### `get_prompts` ```python get_prompts(self) -> dict[str, Prompt] @@ -130,7 +130,7 @@ get_prompts(self) -> dict[str, Prompt] Gets the unfiltered prompt inventory including local, mounted, and proxy prompts. -#### `list_prompts` +#### `list_prompts` ```python list_prompts(self) -> list[Prompt] @@ -139,7 +139,7 @@ list_prompts(self) -> list[Prompt] Gets the filtered list of prompts including local, mounted, and proxy prompts. -#### `render_prompt` +#### `render_prompt` ```python render_prompt(self, name: str, arguments: dict[str, Any] | None = None) -> GetPromptResult @@ -148,7 +148,7 @@ render_prompt(self, name: str, arguments: dict[str, Any] | None = None) -> GetPr Renders a prompt, trying local/mounted first, then proxy if not found. -### `ProxyTool` +### `ProxyTool` A Tool that represents and executes a tool on a remote server. @@ -156,7 +156,7 @@ A Tool that represents and executes a tool on a remote server. **Methods:** -#### `from_mcp_tool` +#### `from_mcp_tool` ```python from_mcp_tool(cls, client: Client, mcp_tool: mcp.types.Tool) -> ProxyTool @@ -165,7 +165,7 @@ from_mcp_tool(cls, client: Client, mcp_tool: mcp.types.Tool) -> ProxyTool 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 @@ -174,7 +174,7 @@ run(self, arguments: dict[str, Any], context: Context | None = None) -> ToolResu Executes the tool by making a call through the client. -### `ProxyResource` +### `ProxyResource` A Resource that represents and reads a resource from a remote server. @@ -182,7 +182,7 @@ A Resource that represents and reads a resource from a remote server. **Methods:** -#### `from_mcp_resource` +#### `from_mcp_resource` ```python from_mcp_resource(cls, client: Client, mcp_resource: mcp.types.Resource) -> ProxyResource @@ -191,7 +191,7 @@ from_mcp_resource(cls, client: Client, mcp_resource: mcp.types.Resource) -> Prox Factory method to create a ProxyResource from a raw MCP resource schema. -#### `read` +#### `read` ```python read(self) -> str | bytes @@ -200,7 +200,7 @@ read(self) -> str | bytes Read the resource content from the remote server. -### `ProxyTemplate` +### `ProxyTemplate` A ResourceTemplate that represents and creates resources from a remote server template. @@ -208,7 +208,7 @@ A ResourceTemplate that represents and creates resources from a remote server te **Methods:** -#### `from_mcp_template` +#### `from_mcp_template` ```python from_mcp_template(cls, client: Client, mcp_template: mcp.types.ResourceTemplate) -> ProxyTemplate @@ -217,7 +217,7 @@ from_mcp_template(cls, client: Client, mcp_template: mcp.types.ResourceTemplate) 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 @@ -226,7 +226,7 @@ create_resource(self, uri: str, params: dict[str, Any], context: Context | None Create a resource from the template by calling the remote server. -### `ProxyPrompt` +### `ProxyPrompt` A Prompt that represents and renders a prompt from a remote server. @@ -234,7 +234,7 @@ A Prompt that represents and renders a prompt from a remote server. **Methods:** -#### `from_mcp_prompt` +#### `from_mcp_prompt` ```python from_mcp_prompt(cls, client: Client, mcp_prompt: mcp.types.Prompt) -> ProxyPrompt @@ -243,7 +243,7 @@ from_mcp_prompt(cls, client: Client, mcp_prompt: mcp.types.Prompt) -> ProxyPromp Factory method to create a ProxyPrompt from a raw MCP prompt schema. -#### `render` +#### `render` ```python render(self, arguments: dict[str, Any]) -> list[PromptMessage] @@ -252,14 +252,14 @@ render(self, arguments: dict[str, Any]) -> list[PromptMessage] Render the prompt by making a call through the client. -### `FastMCPProxy` +### `FastMCPProxy` A FastMCP server that acts as a proxy to a remote MCP-compliant server. It uses specialized managers that fulfill requests via a client factory. -### `ProxyClient` +### `ProxyClient` A proxy client that forwards advanced interactions between a remote MCP server and the proxy's connected clients. @@ -268,7 +268,7 @@ Supports forwarding roots, sampling, elicitation, logging, and progress. **Methods:** -#### `default_sampling_handler` +#### `default_sampling_handler` ```python default_sampling_handler(cls, messages: list[mcp.types.SamplingMessage], params: mcp.types.CreateMessageRequestParams, context: RequestContext[ClientSession, LifespanContextT]) -> mcp.types.CreateMessageResult @@ -277,7 +277,7 @@ default_sampling_handler(cls, messages: list[mcp.types.SamplingMessage], params: A handler that forwards the sampling request from the remote server to the proxy's connected clients and relays the response back to the remote server. -#### `default_elicitation_handler` +#### `default_elicitation_handler` ```python default_elicitation_handler(cls, message: str, response_type: type, params: mcp.types.ElicitRequestParams, context: RequestContext[ClientSession, LifespanContextT]) -> ElicitResult @@ -286,7 +286,7 @@ default_elicitation_handler(cls, message: str, response_type: type, params: mcp. A handler that forwards the elicitation request from the remote server to the proxy's connected clients and relays the response back to the remote server. -#### `default_log_handler` +#### `default_log_handler` ```python default_log_handler(cls, message: LogMessage) -> None @@ -295,7 +295,7 @@ default_log_handler(cls, message: LogMessage) -> None A handler that forwards the log notification from the remote server to the proxy's connected clients. -#### `default_progress_handler` +#### `default_progress_handler` ```python default_progress_handler(cls, progress: float, total: float | None, message: str | None) -> None @@ -304,7 +304,7 @@ default_progress_handler(cls, progress: float, total: float | None, message: str A handler that forwards the progress notification from the remote server to the proxy's connected clients. -### `StatefulProxyClient` +### `StatefulProxyClient` A proxy client that provides a stateful client factory for the proxy server. @@ -318,7 +318,7 @@ Note that it is essential to ensure that the proxy server itself is also statefu **Methods:** -#### `clear` +#### `clear` ```python clear(self) @@ -327,7 +327,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-server.mdx b/docs/python-sdk/fastmcp-server-server.mdx index 79ac12f81..8ab3dbc75 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. -### `add_resource_prefix` +### `add_resource_prefix` ```python add_resource_prefix(uri: str, prefix: str) -> str @@ -58,7 +58,7 @@ add_resource_prefix("resource:///absolute/path", "prefix") - `ValueError`: If the URI doesn't match the expected protocol\://path format -### `remove_resource_prefix` +### `remove_resource_prefix` ```python remove_resource_prefix(uri: str, prefix: str) -> str @@ -90,7 +90,7 @@ remove_resource_prefix("resource://prefix//absolute/path", "prefix") - `ValueError`: If the URI doesn't match the expected protocol\://path format -### `has_resource_prefix` +### `has_resource_prefix` ```python has_resource_prefix(uri: str, prefix: str) -> bool @@ -124,53 +124,64 @@ False ## Classes -### `FastMCP` +### `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] ``` -#### `run_async` +#### `docket` + +```python +docket(self) -> Docket | None +``` + +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` ```python run_async(self, transport: Transport | None = None, show_banner: bool = True, **transport_kwargs: Any) -> None @@ -182,7 +193,7 @@ Run the FastMCP server asynchronously. - `transport`: Transport protocol to use ("stdio", "sse", or "streamable-http") -#### `run` +#### `run` ```python run(self, transport: Transport | None = None, show_banner: bool = True, **transport_kwargs: Any) -> None @@ -194,13 +205,13 @@ Run the FastMCP server. Note this is a synchronous function. - `transport`: Transport protocol to use ("stdio", "sse", or "streamable-http") -#### `add_middleware` +#### `add_middleware` ```python add_middleware(self, middleware: Middleware) -> None ``` -#### `get_tools` +#### `get_tools` ```python get_tools(self) -> dict[str, Tool] @@ -209,13 +220,13 @@ get_tools(self) -> dict[str, Tool] Get all tools (unfiltered), including mounted servers, indexed by key. -#### `get_tool` +#### `get_tool` ```python get_tool(self, key: str) -> Tool ``` -#### `get_resources` +#### `get_resources` ```python get_resources(self) -> dict[str, Resource] @@ -224,13 +235,13 @@ get_resources(self) -> dict[str, Resource] Get all resources (unfiltered), including mounted servers, indexed by key. -#### `get_resource` +#### `get_resource` ```python get_resource(self, key: str) -> Resource ``` -#### `get_resource_templates` +#### `get_resource_templates` ```python get_resource_templates(self) -> dict[str, ResourceTemplate] @@ -239,7 +250,7 @@ get_resource_templates(self) -> dict[str, ResourceTemplate] Get all resource templates (unfiltered), including mounted servers, indexed by key. -#### `get_resource_template` +#### `get_resource_template` ```python get_resource_template(self, key: str) -> ResourceTemplate @@ -248,7 +259,7 @@ get_resource_template(self, key: str) -> ResourceTemplate Get a registered resource template by key. -#### `get_prompts` +#### `get_prompts` ```python get_prompts(self) -> dict[str, Prompt] @@ -257,13 +268,13 @@ get_prompts(self) -> dict[str, Prompt] Get all prompts (unfiltered), including mounted servers, indexed by key. -#### `get_prompt` +#### `get_prompt` ```python get_prompt(self, key: str) -> Prompt ``` -#### `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]]] @@ -284,7 +295,7 @@ 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 @@ -302,7 +313,7 @@ with the Context type annotation. See the @tool decorator for examples. - The tool instance that was added to the server. -#### `remove_tool` +#### `remove_tool` ```python remove_tool(self, name: str) -> None @@ -317,7 +328,7 @@ Remove a tool from the server. - `NotFoundError`: If the tool is not found -#### `add_tool_transformation` +#### `add_tool_transformation` ```python add_tool_transformation(self, tool_name: str, transformation: ToolTransformConfig) -> None @@ -326,7 +337,7 @@ add_tool_transformation(self, tool_name: str, transformation: ToolTransformConfi Add a tool transformation. -#### `remove_tool_transformation` +#### `remove_tool_transformation` ```python remove_tool_transformation(self, tool_name: str) -> None @@ -335,19 +346,19 @@ 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 @@ -405,7 +416,7 @@ server.tool(my_function, name="custom_name") ``` -#### `add_resource` +#### `add_resource` ```python add_resource(self, resource: Resource) -> Resource @@ -420,7 +431,7 @@ Add a resource to the server. - The resource instance that was added to the server. -#### `add_template` +#### `add_template` ```python add_template(self, template: ResourceTemplate) -> ResourceTemplate @@ -435,7 +446,7 @@ Add a resource template to the server. - The template instance that was added to the server. -#### `resource` +#### `resource` ```python resource(self, uri: str) -> Callable[[AnyFunction], Resource | ResourceTemplate] @@ -495,7 +506,7 @@ async def get_weather(city: str) -> str: ``` -#### `add_prompt` +#### `add_prompt` ```python add_prompt(self, prompt: Prompt) -> Prompt @@ -510,19 +521,19 @@ Add a prompt to the server. - 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 @@ -600,7 +611,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) -> None @@ -613,7 +624,7 @@ Run the server using stdio transport. - `log_level`: Log level for the server -#### `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) -> None @@ -633,10 +644,10 @@ Run the server using HTTP transport. - `stateless_http`: Whether to use stateless HTTP (defaults to settings.stateless_http) -#### `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') -> StarletteWithLifespan +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 ``` Create a Starlette app using the specified HTTP transport. @@ -644,13 +655,22 @@ Create a Starlette app using the specified HTTP transport. **Args:** - `path`: The path for the HTTP endpoint - `middleware`: A list of middleware to apply to the app -- `transport`: Transport protocol to use - either "streamable-http" (default) or "sse" +- `json_response`: Whether to use JSON response format +- `stateless_http`: Whether to use stateless mode (new transport per request) +- `transport`: Transport protocol to use - "http", "streamable-http", or "sse" +- `event_store`: Optional event store for SSE polling/resumability. When set, +enables clients to reconnect and resume receiving events after +server-initiated disconnections. Only used with streamable-http transport. +- `retry_interval`: Optional retry interval in milliseconds for SSE polling. +Controls how quickly clients should reconnect after server-initiated +disconnections. Requires event_store to be set. Only used with +streamable-http transport. **Returns:** - A Starlette application configured with the specified transport -#### `mount` +#### `mount` ```python mount(self, server: FastMCP[LifespanResultT], prefix: str | None = None, as_proxy: bool | None = None) -> None @@ -699,15 +719,12 @@ the server's objects are accessible with their original names. - `as_proxy`: Whether to treat the mounted server as a proxy. If None (default), automatically determined based on whether the server has a custom lifespan (True if it has a custom lifespan, False otherwise). -- `tool_separator`: Deprecated. Separator character for tool names. -- `resource_separator`: Deprecated. Separator character for resource URIs. -- `prompt_separator`: Deprecated. Separator character for prompt names. -#### `import_server` +#### `import_server` ```python -import_server(self, server: FastMCP[LifespanResultT], prefix: str | None = None, tool_separator: str | None = None, resource_separator: str | None = None, prompt_separator: str | None = None) -> None +import_server(self, server: FastMCP[LifespanResultT], prefix: str | None = None) -> None ``` Import the MCP objects from another FastMCP server into this one, @@ -739,13 +756,9 @@ templates, and prompts are imported with their original names. - `server`: The FastMCP server to import - `prefix`: Optional prefix to use for the imported server's objects. If None, objects are imported with their original names. -- `tool_separator`: Deprecated. Separator for tool names. -- `resource_separator`: Deprecated and ignored. Prefix is now -applied using the protocol\://prefix/path format -- `prompt_separator`: Deprecated. Separator for prompt names. -#### `from_openapi` +#### `from_openapi` ```python from_openapi(cls, openapi_spec: dict[str, Any], client: httpx.AsyncClient, 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, **settings: Any) -> FastMCPOpenAPI @@ -754,7 +767,7 @@ from_openapi(cls, openapi_spec: dict[str, Any], client: httpx.AsyncClient, route Create a FastMCP server from an OpenAPI specification. -#### `from_fastapi` +#### `from_fastapi` ```python from_fastapi(cls, app: Any, name: str | None = None, route_maps: list[RouteMap] | None = None, route_map_fn: OpenAPIRouteMapFn | None = None, mcp_component_fn: OpenAPIComponentFn | None = None, mcp_names: dict[str, str] | None = None, httpx_client_kwargs: dict[str, Any] | None = None, tags: set[str] | None = None, **settings: Any) -> FastMCPOpenAPI @@ -763,7 +776,7 @@ from_fastapi(cls, app: Any, name: str | None = None, route_maps: list[RouteMap] Create a FastMCP server from a FastAPI application. -#### `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 @@ -777,10 +790,10 @@ 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 ``` -### `MountedServer` +### `MountedServer` diff --git a/docs/python-sdk/fastmcp-server-tasks-__init__.mdx b/docs/python-sdk/fastmcp-server-tasks-__init__.mdx new file mode 100644 index 000000000..9c9f5e88e --- /dev/null +++ b/docs/python-sdk/fastmcp-server-tasks-__init__.mdx @@ -0,0 +1,12 @@ +--- +title: __init__ +sidebarTitle: __init__ +--- + +# `fastmcp.server.tasks` + + +MCP SEP-1686 background tasks support. + +This module implements protocol-level background task execution for MCP servers. + diff --git a/docs/python-sdk/fastmcp-server-tasks-capabilities.mdx b/docs/python-sdk/fastmcp-server-tasks-capabilities.mdx new file mode 100644 index 000000000..6b8c78e3e --- /dev/null +++ b/docs/python-sdk/fastmcp-server-tasks-capabilities.mdx @@ -0,0 +1,24 @@ +--- +title: capabilities +sidebarTitle: capabilities +--- + +# `fastmcp.server.tasks.capabilities` + + +SEP-1686 task capabilities declaration. + +## Functions + +### `get_task_capabilities` + +```python +get_task_capabilities() -> dict[str, Any] +``` + + +Return the SEP-1686 task capabilities structure. + +This is the standard capabilities map advertised to clients, +declaring support for list, cancel, and request operations. + diff --git a/docs/python-sdk/fastmcp-server-tasks-config.mdx b/docs/python-sdk/fastmcp-server-tasks-config.mdx new file mode 100644 index 000000000..cac8b9254 --- /dev/null +++ b/docs/python-sdk/fastmcp-server-tasks-config.mdx @@ -0,0 +1,66 @@ +--- +title: config +sidebarTitle: config +--- + +# `fastmcp.server.tasks.config` + + +TaskConfig for MCP SEP-1686 background task execution modes. + +This module defines the configuration for how tools, resources, and prompts +handle task-augmented execution as specified in SEP-1686. + + +## Classes + +### `TaskConfig` + + +Configuration for MCP background task execution (SEP-1686). + +Controls how a component handles task-augmented requests: + +- "forbidden": Component does not support task execution. Clients must not + request task augmentation; server returns -32601 if they do. +- "optional": Component supports both synchronous and task execution. + Client may request task augmentation or call normally. +- "required": Component requires task execution. Clients must request task + augmentation; server returns -32601 if they don't. + + +**Methods:** + +#### `from_bool` + +```python +from_bool(cls, value: bool) -> TaskConfig +``` + +Convert boolean task flag to TaskConfig. + +**Args:** +- `value`: True for "optional" mode, False for "forbidden" mode. + +**Returns:** +- TaskConfig with appropriate mode. + + +#### `validate_function` + +```python +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. + +**Args:** +- `fn`: The function to validate (handles callable classes and staticmethods). +- `name`: Name for error messages. + +**Raises:** +- `ValueError`: If task execution is enabled but function is sync. + diff --git a/docs/python-sdk/fastmcp-server-tasks-converters.mdx b/docs/python-sdk/fastmcp-server-tasks-converters.mdx new file mode 100644 index 000000000..94118c394 --- /dev/null +++ b/docs/python-sdk/fastmcp-server-tasks-converters.mdx @@ -0,0 +1,77 @@ +--- +title: converters +sidebarTitle: converters +--- + +# `fastmcp.server.tasks.converters` + + +SEP-1686 task result converters. + +Converts raw task return values to MCP result types. + + +## Functions + +### `convert_tool_result` + +```python +convert_tool_result(server: FastMCP, raw_value: Any, tool_name: str, client_task_id: str) -> mcp.types.CallToolResult +``` + + +Convert raw tool return value to MCP CallToolResult. + +Replicates the serialization logic from tool.run() to properly handle +output_schema, structured content, etc. + +**Args:** +- `server`: FastMCP server instance +- `raw_value`: The raw return value from user's tool function +- `tool_name`: Name of the tool (to get output_schema and serializer) +- `client_task_id`: Client task ID for related-task metadata + +**Returns:** +- CallToolResult with properly formatted content and structured content + + +### `convert_prompt_result` + +```python +convert_prompt_result(server: FastMCP, raw_value: Any, prompt_name: str, client_task_id: str) -> mcp.types.GetPromptResult +``` + + +Convert raw prompt return value to MCP GetPromptResult. + +The user function returns raw values (strings, dicts, lists) that need +to be converted to PromptMessage objects. + +**Args:** +- `server`: FastMCP server instance +- `raw_value`: The raw return value from user's prompt function +- `prompt_name`: Name of the prompt +- `client_task_id`: Client task ID for related-task metadata + +**Returns:** +- GetPromptResult with properly formatted messages + + +### `convert_resource_result` + +```python +convert_resource_result(server: FastMCP, raw_value: Any, uri: str, client_task_id: str) -> dict[str, Any] +``` + + +Convert raw resource return value to MCP resource contents dict. + +**Args:** +- `server`: FastMCP server instance +- `raw_value`: The raw return value from user's resource function (str or bytes) +- `uri`: Resource URI (for the contents response) +- `client_task_id`: Client task ID for related-task metadata + +**Returns:** +- Dict with 'contents' key containing list of resource contents + diff --git a/docs/python-sdk/fastmcp-server-tasks-handlers.mdx b/docs/python-sdk/fastmcp-server-tasks-handlers.mdx new file mode 100644 index 000000000..423f3bdea --- /dev/null +++ b/docs/python-sdk/fastmcp-server-tasks-handlers.mdx @@ -0,0 +1,78 @@ +--- +title: handlers +sidebarTitle: handlers +--- + +# `fastmcp.server.tasks.handlers` + + +SEP-1686 task execution handlers. + +Handles queuing tool/prompt/resource executions to Docket as background tasks. + + +## Functions + +### `handle_tool_as_task` + +```python +handle_tool_as_task(server: FastMCP, tool_name: str, arguments: dict[str, Any], task_meta: dict[str, Any]) -> mcp.types.CallToolResult +``` + + +Handle tool execution as background task (SEP-1686). + +Queues the user's actual function to Docket (preserving signature for DI), +stores raw return values, converts to MCP types on retrieval. + +**Args:** +- `server`: FastMCP server instance +- `tool_name`: Name of the tool to execute +- `arguments`: Tool arguments +- `task_meta`: Task metadata from request (contains ttl) + +**Returns:** +- Task stub with task metadata in _meta + + +### `handle_prompt_as_task` + +```python +handle_prompt_as_task(server: FastMCP, prompt_name: str, arguments: dict[str, Any] | None, task_meta: dict[str, Any]) -> mcp.types.GetPromptResult +``` + + +Handle prompt execution as background task (SEP-1686). + +Queues the user's actual function to Docket (preserving signature for DI). + +**Args:** +- `server`: FastMCP server instance +- `prompt_name`: Name of the prompt to execute +- `arguments`: Prompt arguments +- `task_meta`: Task metadata from request (contains ttl) + +**Returns:** +- Task stub with task metadata in _meta + + +### `handle_resource_as_task` + +```python +handle_resource_as_task(server: FastMCP, uri: str, resource, task_meta: dict[str, Any]) -> mcp.types.ServerResult +``` + + +Handle resource read as background task (SEP-1686). + +Queues the user's actual function to Docket. + +**Args:** +- `server`: FastMCP server instance +- `uri`: Resource URI +- `resource`: Resource or ResourceTemplate object +- `task_meta`: Task metadata from request (contains ttl) + +**Returns:** +- ServerResult with ReadResourceResult stub + diff --git a/docs/python-sdk/fastmcp-server-tasks-keys.mdx b/docs/python-sdk/fastmcp-server-tasks-keys.mdx new file mode 100644 index 000000000..8094a28a7 --- /dev/null +++ b/docs/python-sdk/fastmcp-server-tasks-keys.mdx @@ -0,0 +1,91 @@ +--- +title: keys +sidebarTitle: keys +--- + +# `fastmcp.server.tasks.keys` + + +Task key management for SEP-1686 background tasks. + +Task keys encode security scoping and metadata in the Docket key format: + {session_id}:{client_task_id}:{task_type}:{component_identifier} + +This format provides: +- Session-based security scoping (prevents cross-session access) +- Task type identification (tool/prompt/resource) +- Component identification (name or URI for result conversion) + + +## Functions + +### `build_task_key` + +```python +build_task_key(session_id: str, client_task_id: str, task_type: str, component_identifier: str) -> str +``` + + +Build Docket task key with embedded metadata. + +Format: {session_id}:{client_task_id}:{task_type}:{component_identifier} + +The component_identifier is URI-encoded to handle special characters (colons, slashes, etc.). + +**Args:** +- `session_id`: Session ID for security scoping +- `client_task_id`: Client-provided task ID +- `task_type`: Type of task ("tool", "prompt", "resource") +- `component_identifier`: Tool name, prompt name, or resource URI + +**Returns:** +- Encoded task key for Docket + +**Examples:** + +>>> build_task_key("session123", "task456", "tool", "my_tool") +'session123:task456:tool:my_tool' +>>> build_task_key("session123", "task456", "resource", "file://data.txt") +'session123:task456:resource:file%3A%2F%2Fdata.txt' + + +### `parse_task_key` + +```python +parse_task_key(task_key: str) -> dict[str, str] +``` + + +Parse Docket task key to extract metadata. + +**Args:** +- `task_key`: Encoded task key from Docket + +**Returns:** +- Dict with keys: session_id, client_task_id, task_type, component_identifier + +**Examples:** + +>>> parse_task_key("session123:task456:tool:my_tool") +{'session_id': 'session123', 'client_task_id': 'task456', + 'task_type': 'tool', 'component_identifier': 'my_tool'} +>>> parse_task_key("session123:task456:resource:file%3A%2F%2Fdata.txt") +{'session_id': 'session123', 'client_task_id': 'task456', + 'task_type': 'resource', 'component_identifier': 'file://data.txt'} + + +### `get_client_task_id_from_key` + +```python +get_client_task_id_from_key(task_key: str) -> str +``` + + +Extract just the client task ID from a task key. + +**Args:** +- `task_key`: Full encoded task key + +**Returns:** +- Client-provided task ID (second segment) + diff --git a/docs/python-sdk/fastmcp-server-tasks-protocol.mdx b/docs/python-sdk/fastmcp-server-tasks-protocol.mdx new file mode 100644 index 000000000..6d355b824 --- /dev/null +++ b/docs/python-sdk/fastmcp-server-tasks-protocol.mdx @@ -0,0 +1,88 @@ +--- +title: protocol +sidebarTitle: protocol +--- + +# `fastmcp.server.tasks.protocol` + + +SEP-1686 task protocol handlers. + +Implements MCP task protocol methods: tasks/get, tasks/result, tasks/list, tasks/cancel, tasks/delete. + + +## Functions + +### `tasks_get_handler` + +```python +tasks_get_handler(server: FastMCP, params: dict[str, Any]) -> GetTaskResult +``` + + +Handle MCP 'tasks/get' request (SEP-1686). + +**Args:** +- `server`: FastMCP server instance +- `params`: Request params containing taskId + +**Returns:** +- Task status response with spec-compliant fields + + +### `tasks_result_handler` + +```python +tasks_result_handler(server: FastMCP, params: dict[str, Any]) -> Any +``` + + +Handle MCP 'tasks/result' request (SEP-1686). + +Converts raw task return values to MCP types based on task type. + +**Args:** +- `server`: FastMCP server instance +- `params`: Request params containing taskId + +**Returns:** +- MCP result (CallToolResult, GetPromptResult, or ReadResourceResult) + + +### `tasks_list_handler` + +```python +tasks_list_handler(server: FastMCP, params: dict[str, Any]) -> ListTasksResult +``` + + +Handle MCP 'tasks/list' request (SEP-1686). + +Note: With client-side tracking, this returns minimal info. + +**Args:** +- `server`: FastMCP server instance +- `params`: Request params (cursor, limit) + +**Returns:** +- Response with tasks list and pagination + + +### `tasks_cancel_handler` + +```python +tasks_cancel_handler(server: FastMCP, params: dict[str, Any]) -> CancelTaskResult +``` + + +Handle MCP 'tasks/cancel' request (SEP-1686). + +Cancels a running task, transitioning it to cancelled state. + +**Args:** +- `server`: FastMCP server instance +- `params`: Request params containing taskId + +**Returns:** +- Task status response showing cancelled state + diff --git a/docs/python-sdk/fastmcp-server-tasks-subscriptions.mdx b/docs/python-sdk/fastmcp-server-tasks-subscriptions.mdx new file mode 100644 index 000000000..78f06cf81 --- /dev/null +++ b/docs/python-sdk/fastmcp-server-tasks-subscriptions.mdx @@ -0,0 +1,35 @@ +--- +title: subscriptions +sidebarTitle: subscriptions +--- + +# `fastmcp.server.tasks.subscriptions` + + +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. + + +## Functions + +### `subscribe_to_task_updates` + +```python +subscribe_to_task_updates(task_id: str, task_key: str, session: ServerSession, docket: Docket) -> None +``` + + +Subscribe to Docket execution events and send MCP notifications. + +Per SEP-1686 lines 436-444, servers MAY send notifications/tasks/status +when task state changes. This is an optional optimization that reduces +client polling frequency. + +**Args:** +- `task_id`: Client-visible task ID (server-generated UUID) +- `task_key`: Internal Docket execution key (includes session, type, component) +- `session`: MCP ServerSession for sending notifications +- `docket`: Docket instance for subscribing to execution events + diff --git a/docs/python-sdk/fastmcp-settings.mdx b/docs/python-sdk/fastmcp-settings.mdx index bb11611e9..398896549 100644 --- a/docs/python-sdk/fastmcp-settings.mdx +++ b/docs/python-sdk/fastmcp-settings.mdx @@ -7,9 +7,15 @@ sidebarTitle: settings ## Classes -### `ExperimentalSettings` +### `DocketSettings` -### `Settings` + +Docket worker configuration. + + +### `ExperimentalSettings` + +### `Settings` FastMCP settings. @@ -17,7 +23,7 @@ FastMCP settings. **Methods:** -#### `get_setting` +#### `get_setting` ```python get_setting(self, attr: str) -> Any @@ -27,7 +33,7 @@ Get a setting. If the setting contains one or more `__`, it will be treated as a nested setting. -#### `set_setting` +#### `set_setting` ```python set_setting(self, attr: str, value: Any) -> None @@ -37,23 +43,13 @@ Set a setting. If the setting contains one or more `__`, it will be treated as a nested setting. -#### `settings` - -```python -settings(self) -> Self -``` - -This property is for backwards compatibility with FastMCP < 2.8.0, -which accessed fastmcp.settings.settings - - -#### `normalize_log_level` +#### `normalize_log_level` ```python normalize_log_level(cls, v) ``` -#### `server_auth_class` +#### `server_auth_class` ```python server_auth_class(self) -> AuthProvider | None diff --git a/docs/python-sdk/fastmcp-tools-tool.mdx b/docs/python-sdk/fastmcp-tools-tool.mdx index c6f3931a9..d6fc3accc 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,19 +33,19 @@ Internal tool registration info. **Methods:** -#### `enable` +#### `enable` ```python enable(self) -> None ``` -#### `disable` +#### `disable` ```python disable(self) -> None ``` -#### `to_mcp_tool` +#### `to_mcp_tool` ```python to_mcp_tool(self, **overrides: Any) -> MCPTool @@ -54,16 +54,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, enabled: bool | None = None) -> FunctionTool +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, enabled: bool | None = None, task: bool | TaskConfig | None = None) -> FunctionTool ``` Create a Tool from a function. -#### `run` +#### `run` ```python run(self, arguments: dict[str, Any]) -> ToolResult @@ -78,26 +78,37 @@ implemented by subclasses. (list of ContentBlocks, dict of structured output). -#### `from_tool` +#### `from_tool` ```python from_tool(cls, tool: Tool) -> TransformedTool ``` -### `FunctionTool` +### `FunctionTool` **Methods:** -#### `from_function` +#### `to_mcp_tool` ```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, enabled: bool | None = None) -> FunctionTool +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, enabled: bool | None = None, task: bool | TaskConfig | None = None) -> FunctionTool ``` Create a Tool from a function. -#### `run` +#### `run` ```python run(self, arguments: dict[str, Any]) -> ToolResult @@ -106,11 +117,11 @@ run(self, arguments: dict[str, Any]) -> ToolResult Run the tool with arguments. -### `ParsedFunction` +### `ParsedFunction` **Methods:** -#### `from_function` +#### `from_function` ```python from_function(cls, fn: Callable[..., Any], exclude_args: list[str] | None = None, validate: bool = True, wrap_non_object_output_schema: bool = True) -> ParsedFunction diff --git a/docs/python-sdk/fastmcp-utilities-tests.mdx b/docs/python-sdk/fastmcp-utilities-tests.mdx index a33f1122b..e59e40d46 100644 --- a/docs/python-sdk/fastmcp-utilities-tests.mdx +++ b/docs/python-sdk/fastmcp-utilities-tests.mdx @@ -7,7 +7,7 @@ sidebarTitle: tests ## Functions -### `temporary_settings` +### `temporary_settings` ```python temporary_settings(**kwargs: Any) @@ -20,7 +20,7 @@ Temporarily override FastMCP setting values. - `**kwargs`: The settings to override, including nested settings. -### `run_server_in_process` +### `run_server_in_process` ```python run_server_in_process(server_fn: Callable[..., None], *args: Any, **kwargs: Any) -> Generator[str, None, None] @@ -43,7 +43,7 @@ not pickleable, so we need a function that creates and runs one. - The server URL. -### `run_server_async` +### `run_server_async` ```python run_server_async(server: FastMCP, port: int | None = None, transport: Literal['http', 'streamable-http', 'sse'] = 'http', path: str = '/mcp', host: str = '127.0.0.1') -> AsyncGenerator[str, None] @@ -64,10 +64,10 @@ sleeps, and cleanup issues. - `host`: Host to bind to (default\: "127.0.0.1") -### `caplog_for_fastmcp` +### `caplog_for_fastmcp` ```python -caplog_for_fastmcp(caplog) +caplog_for_fastmcp(caplog: LogCaptureFixture) -> Generator[LogCaptureFixture, None, None] ``` @@ -76,7 +76,7 @@ Context manager to capture logs from FastMCP loggers even when propagation is di ## Classes -### `HeadlessOAuth` +### `HeadlessOAuth` OAuth provider that bypasses browser interaction for testing. @@ -87,7 +87,7 @@ instead of opening a browser and running a callback server. Useful for automated **Methods:** -#### `redirect_handler` +#### `redirect_handler` ```python redirect_handler(self, authorization_url: str) -> None @@ -96,7 +96,7 @@ redirect_handler(self, authorization_url: str) -> None Make HTTP request to authorization URL and store response for callback handler. -#### `callback_handler` +#### `callback_handler` ```python callback_handler(self) -> tuple[str, str | None] diff --git a/docs/python-sdk/fastmcp-utilities-types.mdx b/docs/python-sdk/fastmcp-utilities-types.mdx index 0026885eb..93fc7bc40 100644 --- a/docs/python-sdk/fastmcp-utilities-types.mdx +++ b/docs/python-sdk/fastmcp-utilities-types.mdx @@ -77,7 +77,7 @@ This is used to exclude parameters from type adapter processing when they can't The excluded parameters are removed from the function's __annotations__ dictionary. -### `replace_type` +### `replace_type` ```python replace_type(type_, type_map: dict[type, type]) @@ -112,7 +112,7 @@ list[list[str]] Base model for FastMCP models. -### `Image` +### `Image` Helper class for returning images from tools. @@ -120,7 +120,7 @@ Helper class for returning images from tools. **Methods:** -#### `to_image_content` +#### `to_image_content` ```python to_image_content(self, mime_type: str | None = None, annotations: Annotations | None = None) -> mcp.types.ImageContent @@ -129,7 +129,7 @@ to_image_content(self, mime_type: str | None = None, annotations: Annotations | Convert to MCP ImageContent. -#### `to_data_uri` +#### `to_data_uri` ```python to_data_uri(self, mime_type: str | None = None) -> str @@ -138,7 +138,7 @@ to_data_uri(self, mime_type: str | None = None) -> str Get image as a data URI. -### `Audio` +### `Audio` Helper class for returning audio from tools. @@ -146,13 +146,13 @@ Helper class for returning audio from tools. **Methods:** -#### `to_audio_content` +#### `to_audio_content` ```python to_audio_content(self, mime_type: str | None = None, annotations: Annotations | None = None) -> mcp.types.AudioContent ``` -### `File` +### `File` Helper class for returning file data from tools. @@ -160,10 +160,10 @@ Helper class for returning file data from tools. **Methods:** -#### `to_resource_content` +#### `to_resource_content` ```python to_resource_content(self, mime_type: str | None = None, annotations: Annotations | None = None) -> mcp.types.EmbeddedResource ``` -### `ContextSamplingFallbackProtocol` +### `ContextSamplingFallbackProtocol`