diff --git a/docs/docs.json b/docs/docs.json index 4a499ef2c..4fcc03c3b 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -463,7 +463,8 @@ "python-sdk/fastmcp-server-providers-openapi-routing" ] }, - "python-sdk/fastmcp-server-providers-proxy" + "python-sdk/fastmcp-server-providers-proxy", + "python-sdk/fastmcp-server-providers-wrapped_provider" ] }, "python-sdk/fastmcp-server-proxy", diff --git a/docs/python-sdk/fastmcp-server-context.mdx b/docs/python-sdk/fastmcp-server-context.mdx index 2fa8088d5..cf601ed8d 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_transport` +### `set_transport` ```python set_transport(transport: TransportType) -> Token[TransportType | None] @@ -17,7 +17,7 @@ set_transport(transport: TransportType) -> Token[TransportType | None] Set the current transport type. Returns token for reset. -### `reset_transport` +### `reset_transport` ```python reset_transport(token: Token[TransportType | None]) -> None @@ -27,7 +27,7 @@ reset_transport(token: Token[TransportType | None]) -> None Reset transport to previous value. -### `set_context` +### `set_context` ```python set_context(context: Context) -> Generator[Context, None, None] @@ -35,7 +35,7 @@ set_context(context: Context) -> Generator[Context, None, None] ## Classes -### `LogData` +### `LogData` Data object for passing log arguments to client-side handlers. @@ -44,7 +44,7 @@ This provides an interface to match the Python standard library logging, for compatibility with structured logging. -### `Context` +### `Context` Context object providing access to MCP capabilities. @@ -96,7 +96,7 @@ The context is optional - tools that don't need it can omit the parameter. **Methods:** -#### `fastmcp` +#### `fastmcp` ```python fastmcp(self) -> FastMCP @@ -105,7 +105,7 @@ fastmcp(self) -> FastMCP Get the FastMCP instance. -#### `request_context` +#### `request_context` ```python request_context(self) -> RequestContext[ServerSession, Any, Request] | None @@ -134,7 +134,7 @@ async def on_request(self, context, call_next): ``` -#### `lifespan_context` +#### `lifespan_context` ```python lifespan_context(self) -> dict[str, Any] @@ -157,7 +157,7 @@ def my_tool(ctx: Context) -> str: ``` -#### `report_progress` +#### `report_progress` ```python report_progress(self, progress: float, total: float | None = None, message: str | None = None) -> None @@ -170,7 +170,7 @@ Report progress for the current operation. - `total`: Optional total value e.g. 100 -#### `list_resources` +#### `list_resources` ```python list_resources(self) -> list[SDKResource] @@ -182,7 +182,7 @@ List all available resources from the server. - List of Resource objects available on the server -#### `list_prompts` +#### `list_prompts` ```python list_prompts(self) -> list[SDKPrompt] @@ -194,7 +194,7 @@ List all available prompts from the server. - List of Prompt objects available on the server -#### `get_prompt` +#### `get_prompt` ```python get_prompt(self, name: str, arguments: dict[str, Any] | None = None) -> GetPromptResult @@ -210,7 +210,7 @@ Get a prompt by name with optional arguments. - The prompt result -#### `read_resource` +#### `read_resource` ```python read_resource(self, uri: str | AnyUrl) -> ResourceResult @@ -225,7 +225,7 @@ Read a resource by URI. - ResourceResult with contents -#### `log` +#### `log` ```python log(self, message: str, level: LoggingLevel | None = None, logger_name: str | None = None, extra: Mapping[str, Any] | None = None) -> None @@ -243,7 +243,7 @@ Messages sent to Clients are also logged to the `fastmcp.server.context.to_clien - `extra`: Optional mapping for additional arguments -#### `transport` +#### `transport` ```python transport(self) -> TransportType | None @@ -255,7 +255,7 @@ Returns the transport type used to run this server: "stdio", "sse", or "streamable-http". Returns None if called outside of a server context. -#### `client_id` +#### `client_id` ```python client_id(self) -> str | None @@ -264,7 +264,7 @@ client_id(self) -> str | None Get the client ID if available. -#### `request_id` +#### `request_id` ```python request_id(self) -> str @@ -275,7 +275,7 @@ Get the unique ID for this request. Raises RuntimeError if MCP request context is not available. -#### `session_id` +#### `session_id` ```python session_id(self) -> str @@ -292,7 +292,7 @@ the same client session. - for other transports. -#### `session` +#### `session` ```python session(self) -> ServerSession @@ -303,7 +303,7 @@ Access to the underlying session for advanced usage. Raises RuntimeError if MCP request context is not available. -#### `debug` +#### `debug` ```python debug(self, message: str, logger_name: str | None = None, extra: Mapping[str, Any] | None = None) -> None @@ -314,7 +314,7 @@ Send a `DEBUG`-level message to the connected MCP Client. Messages sent to Clients are also logged to the `fastmcp.server.context.to_client` logger with a level of `DEBUG`. -#### `info` +#### `info` ```python info(self, message: str, logger_name: str | None = None, extra: Mapping[str, Any] | None = None) -> None @@ -325,7 +325,7 @@ Send a `INFO`-level message to the connected MCP Client. Messages sent to Clients are also logged to the `fastmcp.server.context.to_client` logger with a level of `DEBUG`. -#### `warning` +#### `warning` ```python warning(self, message: str, logger_name: str | None = None, extra: Mapping[str, Any] | None = None) -> None @@ -336,7 +336,7 @@ Send a `WARNING`-level message to the connected MCP Client. Messages sent to Clients are also logged to the `fastmcp.server.context.to_client` logger with a level of `DEBUG`. -#### `error` +#### `error` ```python error(self, message: str, logger_name: str | None = None, extra: Mapping[str, Any] | None = None) -> None @@ -347,7 +347,7 @@ Send a `ERROR`-level message to the connected MCP Client. Messages sent to Clients are also logged to the `fastmcp.server.context.to_client` logger with a level of `DEBUG`. -#### `list_roots` +#### `list_roots` ```python list_roots(self) -> list[Root] @@ -356,7 +356,7 @@ list_roots(self) -> list[Root] List the roots available to the server, as indicated by the client. -#### `send_notification` +#### `send_notification` ```python send_notification(self, notification: mcp.types.ServerNotificationType) -> None @@ -364,30 +364,11 @@ send_notification(self, notification: mcp.types.ServerNotificationType) -> None Send a notification to the client immediately. -Use this in async code when you want the notification sent right away. -For sync code, use send_notification_sync() which queues the notification -for the background flusher. - **Args:** - `notification`: An MCP notification instance (e.g., ToolListChangedNotification()) -#### `send_notification_sync` - -```python -send_notification_sync(self, notification: mcp.types.ServerNotificationType) -> None -``` - -Queue a notification to be sent by the background flusher. - -Use this in sync code when you can't await. The notification will be -sent within ~1 second by the background flusher. - -**Args:** -- `notification`: An MCP notification instance (e.g., ToolListChangedNotification()) - - -#### `close_sse_stream` +#### `close_sse_stream` ```python close_sse_stream(self) -> None @@ -405,7 +386,7 @@ Instead of holding a connection open for minutes, you can periodically close and let the client reconnect. -#### `sample_step` +#### `sample_step` ```python sample_step(self, messages: str | Sequence[str | SamplingMessage]) -> SampleStep @@ -442,7 +423,7 @@ Tools can raise ToolError to bypass masking. - - .text: The text content (if any) -#### `sample` +#### `sample` ```python sample(self, messages: str | Sequence[str | SamplingMessage]) -> SamplingResult[ResultT] @@ -451,7 +432,7 @@ sample(self, messages: str | Sequence[str | SamplingMessage]) -> SamplingResult[ Overload: With result_type, returns SamplingResult[ResultT]. -#### `sample` +#### `sample` ```python sample(self, messages: str | Sequence[str | SamplingMessage]) -> SamplingResult[str] @@ -460,7 +441,7 @@ sample(self, messages: str | Sequence[str | SamplingMessage]) -> SamplingResult[ Overload: Without result_type, returns SamplingResult[str]. -#### `sample` +#### `sample` ```python sample(self, messages: str | Sequence[str | SamplingMessage]) -> SamplingResult[ResultT] | SamplingResult[str] @@ -502,43 +483,43 @@ Tools can raise ToolError to bypass masking. - - .history: All messages exchanged during sampling -#### `elicit` +#### `elicit` ```python elicit(self, message: str, response_type: None) -> AcceptedElicitation[dict[str, Any]] | DeclinedElicitation | CancelledElicitation ``` -#### `elicit` +#### `elicit` ```python elicit(self, message: str, response_type: type[T]) -> AcceptedElicitation[T] | DeclinedElicitation | CancelledElicitation ``` -#### `elicit` +#### `elicit` ```python elicit(self, message: str, response_type: list[str]) -> AcceptedElicitation[str] | DeclinedElicitation | CancelledElicitation ``` -#### `elicit` +#### `elicit` ```python elicit(self, message: str, response_type: dict[str, dict[str, str]]) -> AcceptedElicitation[str] | DeclinedElicitation | CancelledElicitation ``` -#### `elicit` +#### `elicit` ```python elicit(self, message: str, response_type: list[list[str]]) -> AcceptedElicitation[list[str]] | DeclinedElicitation | CancelledElicitation ``` -#### `elicit` +#### `elicit` ```python elicit(self, message: str, response_type: list[dict[str, dict[str, str]]]) -> AcceptedElicitation[list[str]] | DeclinedElicitation | CancelledElicitation ``` -#### `elicit` +#### `elicit` ```python elicit(self, message: str, response_type: type[T] | list[str] | dict[str, dict[str, str]] | list[list[str]] | list[dict[str, dict[str, str]]] | None = None) -> AcceptedElicitation[T] | AcceptedElicitation[dict[str, Any]] | AcceptedElicitation[str] | AcceptedElicitation[list[str]] | DeclinedElicitation | CancelledElicitation @@ -567,7 +548,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 @@ -580,7 +561,7 @@ The key is automatically prefixed with the session identifier. State expires after 1 day to prevent unbounded memory growth. -#### `get_state` +#### `get_state` ```python get_state(self, key: str) -> Any @@ -591,7 +572,7 @@ Get a value from the session-scoped state store. Returns None if the key is not found. -#### `delete_state` +#### `delete_state` ```python delete_state(self, key: str) -> None diff --git a/docs/python-sdk/fastmcp-server-providers-aggregate.mdx b/docs/python-sdk/fastmcp-server-providers-aggregate.mdx index d128d1a5d..f5a5fecaa 100644 --- a/docs/python-sdk/fastmcp-server-providers-aggregate.mdx +++ b/docs/python-sdk/fastmcp-server-providers-aggregate.mdx @@ -17,7 +17,9 @@ Example: from fastmcp.server.providers import AggregateProvider # Combine multiple providers into one - combined = AggregateProvider([provider1, provider2, provider3]) + combined = AggregateProvider() + combined.add_provider(provider1) + combined.add_provider(provider2, namespace="api") # Tools become "api_foo" # Use like any other provider tools = await combined.list_tools() @@ -26,7 +28,7 @@ Example: ## Classes -### `AggregateProvider` +### `AggregateProvider` Utility provider that combines multiple providers into one. @@ -34,15 +36,35 @@ Utility provider that combines multiple providers into one. Components are aggregated from all providers. For get_* operations, providers are queried in parallel and the highest version is returned. -Errors from individual providers are logged and skipped (graceful degradation). +When adding providers with a namespace, wrap_transform() is used to apply +the Namespace transform. This means namespace transformation is handled +by the wrapped provider, not by AggregateProvider. -This is useful when you want to combine custom providers without creating -a full FastMCP server. +Errors from individual providers are logged and skipped (graceful degradation). **Methods:** -#### `get_tasks` +#### `add_provider` + +```python +add_provider(self, provider: Provider) -> None +``` + +Add a provider with optional namespace. + +If the provider is a FastMCP server, it's automatically wrapped in +FastMCPProvider to ensure middleware is invoked correctly. + +**Args:** +- `provider`: The provider to add. +- `namespace`: Optional namespace prefix. When set\: +- Tools become "namespace_toolname" +- Resources become "protocol\://namespace/path" +- Prompts become "namespace_promptname" + + +#### `get_tasks` ```python get_tasks(self) -> Sequence[FastMCPComponent] @@ -51,7 +73,7 @@ get_tasks(self) -> Sequence[FastMCPComponent] Get all task-eligible components from all providers. -#### `lifespan` +#### `lifespan` ```python lifespan(self) -> AsyncIterator[None] diff --git a/docs/python-sdk/fastmcp-server-providers-base.mdx b/docs/python-sdk/fastmcp-server-providers-base.mdx index 36ed3cc06..e7ecb6c05 100644 --- a/docs/python-sdk/fastmcp-server-providers-base.mdx +++ b/docs/python-sdk/fastmcp-server-providers-base.mdx @@ -72,7 +72,30 @@ through the provider. They're applied in order - first added is innermost. - `transform`: The transform to add. -#### `list_tools` +#### `wrap_transform` + +```python +wrap_transform(self, transform: Transform) -> Provider +``` + +Return a new provider with this transform applied (immutable). + +Unlike add_transform() which mutates this provider, wrap_transform() +returns a new provider that wraps this one. The original provider +is unchanged. + +This is useful when you want to apply transforms without side effects, +such as adding the same provider to multiple aggregators with different +namespaces. + +**Args:** +- `transform`: The transform to apply. + +**Returns:** +- A new provider that wraps this one with the transform applied. + + +#### `list_tools` ```python list_tools(self) -> Sequence[Tool] @@ -89,7 +112,7 @@ filtering happens at the server level to allow session transforms to override. - Transformed sequence of tools (including disabled ones). -#### `get_tool` +#### `get_tool` ```python get_tool(self, name: str, version: VersionSpec | None = None) -> Tool | None @@ -109,7 +132,7 @@ allowing session-level transforms to override provider-level disables. - The tool if found (may be marked disabled), None if not found. -#### `list_resources` +#### `list_resources` ```python list_resources(self) -> Sequence[Resource] @@ -120,7 +143,7 @@ List resources with all transforms applied. Components may be marked as disabled but are NOT filtered here. -#### `get_resource` +#### `get_resource` ```python get_resource(self, uri: str, version: VersionSpec | None = None) -> Resource | None @@ -139,7 +162,7 @@ Note: This method does NOT filter disabled components. The Server - The resource if found (may be marked disabled), None if not found. -#### `list_resource_templates` +#### `list_resource_templates` ```python list_resource_templates(self) -> Sequence[ResourceTemplate] @@ -150,7 +173,7 @@ List resource templates with all transforms applied. Components may be marked as disabled but are NOT filtered here. -#### `get_resource_template` +#### `get_resource_template` ```python get_resource_template(self, uri: str, version: VersionSpec | None = None) -> ResourceTemplate | None @@ -169,7 +192,7 @@ Note: This method does NOT filter disabled components. The Server - The template if found (may be marked disabled), None if not found. -#### `list_prompts` +#### `list_prompts` ```python list_prompts(self) -> Sequence[Prompt] @@ -180,7 +203,7 @@ List prompts with all transforms applied. Components may be marked as disabled but are NOT filtered here. -#### `get_prompt` +#### `get_prompt` ```python get_prompt(self, name: str, version: VersionSpec | None = None) -> Prompt | None @@ -199,7 +222,7 @@ Note: This method does NOT filter disabled components. The Server - The prompt if found (may be marked disabled), None if not found. -#### `get_tasks` +#### `get_tasks` ```python get_tasks(self) -> Sequence[FastMCPComponent] @@ -214,7 +237,7 @@ for components with task_config.mode != 'forbidden'. Used by the server during startup to register functions with Docket. -#### `lifespan` +#### `lifespan` ```python lifespan(self) -> AsyncIterator[None] @@ -230,7 +253,7 @@ The lifespan scope matches the server's lifespan - code before yield runs at startup, code after yield runs at shutdown. -#### `enable` +#### `enable` ```python enable(self) -> Self @@ -258,7 +281,7 @@ VersionSpec(gte="v2")). Unversioned components will not match. - Self for method chaining. -#### `disable` +#### `disable` ```python disable(self) -> Self diff --git a/docs/python-sdk/fastmcp-server-providers-fastmcp_provider.mdx b/docs/python-sdk/fastmcp-server-providers-fastmcp_provider.mdx index fda42ad19..821cbd794 100644 --- a/docs/python-sdk/fastmcp-server-providers-fastmcp_provider.mdx +++ b/docs/python-sdk/fastmcp-server-providers-fastmcp_provider.mdx @@ -39,7 +39,7 @@ wrap(cls, server: Any, tool: Tool) -> FastMCPProviderTool Wrap a Tool to delegate execution to the server's middleware. -#### `run` +#### `run` ```python run(self, arguments: dict[str, Any]) -> ToolResult @@ -51,13 +51,13 @@ This is called when the tool is used within a TransformedTool forwarding function or other contexts where task_meta is not available. -#### `get_span_attributes` +#### `get_span_attributes` ```python get_span_attributes(self) -> dict[str, Any] ``` -### `FastMCPProviderResource` +### `FastMCPProviderResource` Resource that delegates reading to a wrapped server's read_resource(). @@ -68,7 +68,7 @@ When `read()` is called, this resource invokes the wrapped server's **Methods:** -#### `wrap` +#### `wrap` ```python wrap(cls, server: Any, resource: Resource) -> FastMCPProviderResource @@ -77,13 +77,13 @@ wrap(cls, server: Any, resource: Resource) -> FastMCPProviderResource Wrap a Resource to delegate reading to the server's middleware. -#### `get_span_attributes` +#### `get_span_attributes` ```python get_span_attributes(self) -> dict[str, Any] ``` -### `FastMCPProviderPrompt` +### `FastMCPProviderPrompt` Prompt that delegates rendering to a wrapped server's render_prompt(). @@ -94,7 +94,7 @@ When `render()` is called, this prompt invokes the wrapped server's **Methods:** -#### `wrap` +#### `wrap` ```python wrap(cls, server: Any, prompt: Prompt) -> FastMCPProviderPrompt @@ -103,7 +103,7 @@ wrap(cls, server: Any, prompt: Prompt) -> FastMCPProviderPrompt Wrap a Prompt to delegate rendering to the server's middleware. -#### `render` +#### `render` ```python render(self, arguments: dict[str, Any] | None = None) -> PromptResult @@ -115,13 +115,13 @@ This is called when the prompt is used within a transformed context or other contexts where task_meta is not available. -#### `get_span_attributes` +#### `get_span_attributes` ```python get_span_attributes(self) -> dict[str, Any] ``` -### `FastMCPProviderResourceTemplate` +### `FastMCPProviderResourceTemplate` Resource template that creates FastMCPProviderResources. @@ -133,7 +133,7 @@ when read. **Methods:** -#### `wrap` +#### `wrap` ```python wrap(cls, server: Any, template: ResourceTemplate) -> FastMCPProviderResourceTemplate @@ -142,7 +142,7 @@ wrap(cls, server: Any, template: ResourceTemplate) -> FastMCPProviderResourceTem Wrap a ResourceTemplate to create FastMCPProviderResources. -#### `create_resource` +#### `create_resource` ```python create_resource(self, uri: str, params: dict[str, Any]) -> Resource @@ -155,7 +155,7 @@ We use `_original_uri_template` with `params` to construct the internal URI that the nested server understands. -#### `read` +#### `read` ```python read(self, arguments: dict[str, Any]) -> str | bytes | ResourceResult @@ -167,7 +167,7 @@ Reads the resource via the wrapped server and returns the ResourceResult. This method is called by Docket during background task execution. -#### `register_with_docket` +#### `register_with_docket` ```python register_with_docket(self, docket: Docket) -> None @@ -176,7 +176,7 @@ register_with_docket(self, docket: Docket) -> None No-op: the child's actual template is registered via get_tasks(). -#### `add_to_docket` +#### `add_to_docket` ```python add_to_docket(self, docket: Docket, params: dict[str, Any], **kwargs: Any) -> Execution @@ -188,13 +188,13 @@ The child's FunctionResourceTemplate.fn is registered (via get_tasks), and it expects splatted **kwargs, so we splat params here. -#### `get_span_attributes` +#### `get_span_attributes` ```python get_span_attributes(self) -> dict[str, Any] ``` -### `FastMCPProvider` +### `FastMCPProvider` Provider that wraps a FastMCP server. @@ -210,7 +210,7 @@ This ensures middleware runs when components are executed. **Methods:** -#### `get_tasks` +#### `get_tasks` ```python get_tasks(self) -> Sequence[FastMCPComponent] @@ -224,7 +224,7 @@ server's transforms applied, then applies this provider's transforms for correct registration keys. -#### `lifespan` +#### `lifespan` ```python lifespan(self) -> AsyncIterator[None] diff --git a/docs/python-sdk/fastmcp-server-providers-local_provider.mdx b/docs/python-sdk/fastmcp-server-providers-local_provider.mdx index 0cd3fbbb9..5fa847d37 100644 --- a/docs/python-sdk/fastmcp-server-providers-local_provider.mdx +++ b/docs/python-sdk/fastmcp-server-providers-local_provider.mdx @@ -47,7 +47,7 @@ like `_tool_serializer` and `_support_tasks_by_default` are injected. **Methods:** -#### `add_tool` +#### `add_tool` ```python add_tool(self, tool: Tool | Callable[..., Any]) -> Tool @@ -58,7 +58,7 @@ Add a tool to this provider's storage. Accepts either a Tool object or a decorated function with __fastmcp__ metadata. -#### `remove_tool` +#### `remove_tool` ```python remove_tool(self, name: str, version: str | None = None) -> None @@ -74,7 +74,7 @@ Remove tool(s) from this provider's storage. - `KeyError`: If no matching tool is found. -#### `add_resource` +#### `add_resource` ```python add_resource(self, resource: Resource | ResourceTemplate | Callable[..., Any]) -> Resource | ResourceTemplate @@ -85,7 +85,7 @@ Add a resource to this provider's storage. Accepts either a Resource/ResourceTemplate object or a decorated function with __fastmcp__ metadata. -#### `remove_resource` +#### `remove_resource` ```python remove_resource(self, uri: str, version: str | None = None) -> None @@ -101,7 +101,7 @@ Remove resource(s) from this provider's storage. - `KeyError`: If no matching resource is found. -#### `add_template` +#### `add_template` ```python add_template(self, template: ResourceTemplate) -> ResourceTemplate @@ -110,7 +110,7 @@ add_template(self, template: ResourceTemplate) -> ResourceTemplate Add a resource template to this provider's storage. -#### `remove_template` +#### `remove_template` ```python remove_template(self, uri_template: str, version: str | None = None) -> None @@ -126,7 +126,7 @@ Remove resource template(s) from this provider's storage. - `KeyError`: If no matching template is found. -#### `add_prompt` +#### `add_prompt` ```python add_prompt(self, prompt: Prompt | Callable[..., Any]) -> Prompt @@ -137,7 +137,7 @@ Add a prompt to this provider's storage. Accepts either a Prompt object or a decorated function with __fastmcp__ metadata. -#### `remove_prompt` +#### `remove_prompt` ```python remove_prompt(self, name: str, version: str | None = None) -> None @@ -153,7 +153,7 @@ Remove prompt(s) from this provider's storage. - `KeyError`: If no matching prompt is found. -#### `get_tasks` +#### `get_tasks` ```python get_tasks(self) -> Sequence[FastMCPComponent] @@ -166,19 +166,19 @@ This includes both FunctionTool/Resource/Prompt instances created via decorators and custom Tool/Resource/Prompt subclasses. -#### `tool` +#### `tool` ```python tool(self, name_or_fn: AnyFunction) -> FunctionTool ``` -#### `tool` +#### `tool` ```python tool(self, name_or_fn: str | None = None) -> Callable[[AnyFunction], FunctionTool] ``` -#### `tool` +#### `tool` ```python tool(self, name_or_fn: str | AnyFunction | None = None) -> Callable[[AnyFunction], FunctionTool] | FunctionTool | partial[Callable[[AnyFunction], FunctionTool] | FunctionTool] @@ -212,7 +212,7 @@ This decorator supports multiple calling patterns: - The registered FunctionTool or a decorator function. -#### `resource` +#### `resource` ```python resource(self, uri: str) -> Callable[[AnyFunction], Resource | ResourceTemplate | AnyFunction] @@ -241,19 +241,19 @@ has parameters, it will be registered as a template resource. - A decorator function. -#### `prompt` +#### `prompt` ```python prompt(self, name_or_fn: AnyFunction) -> FunctionPrompt ``` -#### `prompt` +#### `prompt` ```python prompt(self, name_or_fn: str | None = None) -> Callable[[AnyFunction], FunctionPrompt] ``` -#### `prompt` +#### `prompt` ```python prompt(self, name_or_fn: str | AnyFunction | None = None) -> Callable[[AnyFunction], FunctionPrompt] | FunctionPrompt | partial[Callable[[AnyFunction], FunctionPrompt] | FunctionPrompt] diff --git a/docs/python-sdk/fastmcp-server-providers-wrapped_provider.mdx b/docs/python-sdk/fastmcp-server-providers-wrapped_provider.mdx new file mode 100644 index 000000000..22fc90b40 --- /dev/null +++ b/docs/python-sdk/fastmcp-server-providers-wrapped_provider.mdx @@ -0,0 +1,13 @@ +--- +title: wrapped_provider +sidebarTitle: wrapped_provider +--- + +# `fastmcp.server.providers.wrapped_provider` + + +WrappedProvider for immutable transform composition. + +This module provides `_WrappedProvider`, an internal class that wraps a provider +with an additional transform. Created by `Provider.wrap_transform()`. + diff --git a/docs/python-sdk/fastmcp-server-server.mdx b/docs/python-sdk/fastmcp-server-server.mdx index ae6831070..c058bb7a6 100644 --- a/docs/python-sdk/fastmcp-server-server.mdx +++ b/docs/python-sdk/fastmcp-server-server.mdx @@ -10,7 +10,7 @@ FastMCP - A more ergonomic interface for MCP servers. ## Functions -### `default_lifespan` +### `default_lifespan` ```python default_lifespan(server: FastMCP[LifespanResultT]) -> AsyncIterator[Any] @@ -26,7 +26,7 @@ Default lifespan context manager that does nothing. - An empty dictionary as the lifespan result. -### `create_proxy` +### `create_proxy` ```python create_proxy(target: Client[ClientTransportT] | ClientTransport | FastMCP[Any] | FastMCP1Server | AnyUrl | Path | MCPConfig | dict[str, Any] | str, **settings: Any) -> FastMCPProxy @@ -54,59 +54,59 @@ use `FastMCPProxy` or `ProxyProvider` directly from `fastmcp.server.providers.pr ## Classes -### `StateValue` +### `StateValue` Wrapper for stored context state values. -### `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] ``` -#### `docket` +#### `docket` ```python docket(self) -> Docket | None @@ -117,7 +117,7 @@ Get the Docket instance if Docket support is enabled. Returns None if Docket is not enabled or server hasn't been started yet. -#### `run_async` +#### `run_async` ```python run_async(self, transport: Transport | None = None, show_banner: bool | None = None, **transport_kwargs: Any) -> None @@ -131,7 +131,7 @@ Run the FastMCP server asynchronously. FASTMCP_SHOW_SERVER_BANNER setting (default\: True). -#### `run` +#### `run` ```python run(self, transport: Transport | None = None, show_banner: bool | None = None, **transport_kwargs: Any) -> None @@ -145,13 +145,13 @@ Run the FastMCP server. Note this is a synchronous function. FASTMCP_SHOW_SERVER_BANNER setting (default\: True). -#### `add_middleware` +#### `add_middleware` ```python add_middleware(self, middleware: Middleware) -> None ``` -#### `add_provider` +#### `add_provider` ```python add_provider(self, provider: Provider) -> None @@ -165,9 +165,13 @@ always take precedence over providers. **Args:** - `provider`: A Provider instance that will provide components dynamically. +- `namespace`: Optional namespace prefix. When set\: +- Tools become "namespace_toolname" +- Resources become "protocol\://namespace/path" +- Prompts become "namespace_promptname" -#### `get_tasks` +#### `get_tasks` ```python get_tasks(self) -> Sequence[FastMCPComponent] @@ -175,11 +179,11 @@ get_tasks(self) -> Sequence[FastMCPComponent] Get task-eligible components with all transforms applied. -Overrides Provider.get_tasks() to collect task-eligible components -from all sub-providers and apply server-level transforms. +Overrides AggregateProvider.get_tasks() to apply server-level transforms +after aggregation. AggregateProvider handles provider-level namespacing. -#### `add_transform` +#### `add_transform` ```python add_transform(self, transform: Transform) -> None @@ -194,7 +198,7 @@ They transform tools, resources, and prompts from ALL providers. - `transform`: The transform to add. -#### `add_tool_transformation` +#### `add_tool_transformation` ```python add_tool_transformation(self, tool_name: str, transformation: ToolTransformConfig) -> None @@ -206,7 +210,7 @@ Add a tool transformation. Use ``add_transform(ToolTransform({...}))`` instead. -#### `remove_tool_transformation` +#### `remove_tool_transformation` ```python remove_tool_transformation(self, _tool_name: str) -> None @@ -218,23 +222,20 @@ Remove a tool transformation. Tool transformations are now immutable. Use enable/disable controls instead. -#### `get_tools` +#### `list_tools` ```python -get_tools(self) -> list[Tool] +list_tools(self) -> Sequence[Tool] ``` -Get all enabled tools from providers. +List all enabled tools from providers. -Queries all providers via the root provider (which applies provider transforms, -server transforms, and enabled filtering). First provider wins for duplicate keys. - -**Args:** -- `run_middleware`: If True, apply the middleware chain before returning. -Used by MCP handlers and FastMCPProvider for nested servers. +Overrides Provider.list_tools() to add enabled filtering, auth filtering, +and middleware execution. Returns all versions (no deduplication). +Protocol handlers deduplicate for MCP wire format. -#### `get_tool` +#### `get_tool` ```python get_tool(self, name: str, version: VersionSpec | None = None) -> Tool | None @@ -254,23 +255,20 @@ session transforms can override provider-level disables. - The tool if found and enabled, None otherwise. -#### `get_resources` +#### `list_resources` ```python -get_resources(self) -> list[Resource] +list_resources(self) -> Sequence[Resource] ``` -Get all enabled resources from providers. +List all enabled resources from providers. -Queries all providers via the root provider (which applies provider transforms, -server transforms, and enabled filtering). First provider wins for duplicate keys. - -**Args:** -- `run_middleware`: If True, apply the middleware chain before returning. -Used by MCP handlers and FastMCPProvider for nested servers. +Overrides Provider.list_resources() to add enabled filtering, auth filtering, +and middleware execution. Returns all versions (no deduplication). +Protocol handlers deduplicate for MCP wire format. -#### `get_resource` +#### `get_resource` ```python get_resource(self, uri: str, version: VersionSpec | None = None) -> Resource | None @@ -289,23 +287,20 @@ transforms (including session-level) have been applied. - The resource if found and enabled, None otherwise. -#### `get_resource_templates` +#### `list_resource_templates` ```python -get_resource_templates(self) -> list[ResourceTemplate] +list_resource_templates(self) -> Sequence[ResourceTemplate] ``` -Get all enabled resource templates from providers. +List all enabled resource templates from providers. -Queries all providers via the root provider (which applies provider transforms, -server transforms, and enabled filtering). First provider wins for duplicate keys. - -**Args:** -- `run_middleware`: If True, apply the middleware chain before returning. -Used by MCP handlers and FastMCPProvider for nested servers. +Overrides Provider.list_resource_templates() to add enabled filtering, +auth filtering, and middleware execution. Returns all versions (no deduplication). +Protocol handlers deduplicate for MCP wire format. -#### `get_resource_template` +#### `get_resource_template` ```python get_resource_template(self, uri: str, version: VersionSpec | None = None) -> ResourceTemplate | None @@ -324,23 +319,20 @@ all transforms (including session-level) have been applied. - The template if found and enabled, None otherwise. -#### `get_prompts` +#### `list_prompts` ```python -get_prompts(self) -> list[Prompt] +list_prompts(self) -> Sequence[Prompt] ``` -Get all enabled prompts from providers. +List all enabled prompts from providers. -Queries all providers via the root provider (which applies provider transforms, -server transforms, and enabled filtering). First provider wins for duplicate keys. - -**Args:** -- `run_middleware`: If True, apply the middleware chain before returning. -Used by MCP handlers and FastMCPProvider for nested servers. +Overrides Provider.list_prompts() to add enabled filtering, auth filtering, +and middleware execution. Returns all versions (no deduplication). +Protocol handlers deduplicate for MCP wire format. -#### `get_prompt` +#### `get_prompt` ```python get_prompt(self, name: str, version: VersionSpec | None = None) -> Prompt | None @@ -359,19 +351,19 @@ transforms (including session-level) have been applied. - The prompt if found and enabled, None otherwise. -#### `call_tool` +#### `call_tool` ```python call_tool(self, name: str, arguments: dict[str, Any] | None = None) -> ToolResult ``` -#### `call_tool` +#### `call_tool` ```python call_tool(self, name: str, arguments: dict[str, Any] | None = None) -> mcp.types.CreateTaskResult ``` -#### `call_tool` +#### `call_tool` ```python call_tool(self, name: str, arguments: dict[str, Any] | None = None) -> ToolResult | mcp.types.CreateTaskResult @@ -401,19 +393,19 @@ return ToolResult. - `ValidationError`: If arguments fail validation -#### `read_resource` +#### `read_resource` ```python read_resource(self, uri: str) -> ResourceResult ``` -#### `read_resource` +#### `read_resource` ```python read_resource(self, uri: str) -> mcp.types.CreateTaskResult ``` -#### `read_resource` +#### `read_resource` ```python read_resource(self, uri: str) -> ResourceResult | mcp.types.CreateTaskResult @@ -442,19 +434,19 @@ return ResourceResult. - `ResourceError`: If resource read fails -#### `render_prompt` +#### `render_prompt` ```python render_prompt(self, name: str, arguments: dict[str, Any] | None = None) -> PromptResult ``` -#### `render_prompt` +#### `render_prompt` ```python render_prompt(self, name: str, arguments: dict[str, Any] | None = None) -> mcp.types.CreateTaskResult ``` -#### `render_prompt` +#### `render_prompt` ```python render_prompt(self, name: str, arguments: dict[str, Any] | None = None) -> PromptResult | mcp.types.CreateTaskResult @@ -484,7 +476,7 @@ return PromptResult. - `PromptError`: If prompt rendering fails -#### `custom_route` +#### `custom_route` ```python custom_route(self, path: str, methods: list[str], name: str | None = None, include_in_schema: bool = True) -> Callable[[Callable[[Request], Awaitable[Response]]], Callable[[Request], Awaitable[Response]]] @@ -505,7 +497,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 | Callable[..., Any]) -> Tool @@ -523,7 +515,7 @@ with the Context type annotation. See the @tool decorator for examples. - The tool instance that was added to the server. -#### `remove_tool` +#### `remove_tool` ```python remove_tool(self, name: str, version: str | None = None) -> None @@ -539,19 +531,19 @@ Remove tool(s) from the server. - `NotFoundError`: If no matching tool is found. -#### `tool` +#### `tool` ```python tool(self, name_or_fn: AnyFunction) -> FunctionTool ``` -#### `tool` +#### `tool` ```python tool(self, name_or_fn: str | None = None) -> Callable[[AnyFunction], FunctionTool] ``` -#### `tool` +#### `tool` ```python tool(self, name_or_fn: str | AnyFunction | None = None) -> Callable[[AnyFunction], FunctionTool] | FunctionTool | partial[Callable[[AnyFunction], FunctionTool] | FunctionTool] @@ -607,7 +599,7 @@ server.tool(my_function, name="custom_name") ``` -#### `add_resource` +#### `add_resource` ```python add_resource(self, resource: Resource | Callable[..., Any]) -> Resource | ResourceTemplate @@ -622,7 +614,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 @@ -637,7 +629,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 | AnyFunction] @@ -696,7 +688,7 @@ async def get_weather(city: str) -> str: ``` -#### `add_prompt` +#### `add_prompt` ```python add_prompt(self, prompt: Prompt | Callable[..., Any]) -> Prompt @@ -711,19 +703,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 | partial[Callable[[AnyFunction], FunctionPrompt] | FunctionPrompt] @@ -800,7 +792,7 @@ Decorator to register a prompt. ``` -#### `run_stdio_async` +#### `run_stdio_async` ```python run_stdio_async(self, show_banner: bool = True, log_level: str | None = None, stateless: bool = False) -> None @@ -814,7 +806,7 @@ Run the server using stdio transport. - `stateless`: Whether to run in stateless mode (no session initialization) -#### `run_http_async` +#### `run_http_async` ```python run_http_async(self, show_banner: bool = True, transport: Literal['http', 'streamable-http', 'sse'] = 'http', host: str | None = None, port: int | None = None, log_level: str | None = None, path: str | None = None, uvicorn_config: dict[str, Any] | None = None, middleware: list[ASGIMiddleware] | None = None, json_response: bool | None = None, stateless_http: bool | None = None, stateless: bool | None = None) -> None @@ -835,7 +827,7 @@ Run the server using HTTP transport. - `stateless`: Alias for stateless_http for CLI consistency -#### `http_app` +#### `http_app` ```python http_app(self, path: str | None = None, middleware: list[ASGIMiddleware] | None = None, json_response: bool | None = None, stateless_http: bool | None = None, transport: Literal['http', 'streamable-http', 'sse'] = 'http', event_store: EventStore | None = None, retry_interval: int | None = None) -> StarletteWithLifespan @@ -861,7 +853,7 @@ streamable-http transport. - A Starlette application configured with the specified transport -#### `mount` +#### `mount` ```python mount(self, server: FastMCP[LifespanResultT], namespace: str | None = None, as_proxy: bool | None = None, tool_names: dict[str, str] | None = None, prefix: str | None = None) -> None @@ -908,7 +900,7 @@ mounted server. - `prefix`: Deprecated. Use namespace instead. -#### `import_server` +#### `import_server` ```python import_server(self, server: FastMCP[LifespanResultT], prefix: str | None = None) -> None @@ -949,7 +941,7 @@ templates, and prompts are imported with their original names. objects are imported with their original names. -#### `from_openapi` +#### `from_openapi` ```python from_openapi(cls, openapi_spec: dict[str, Any], client: httpx.AsyncClient, name: str = 'OpenAPI Server', route_maps: list[RouteMap] | None = None, route_map_fn: OpenAPIRouteMapFn | None = None, mcp_component_fn: OpenAPIComponentFn | None = None, mcp_names: dict[str, str] | None = None, tags: set[str] | None = None, timeout: float | None = None, **settings: Any) -> Self @@ -973,7 +965,7 @@ Create a FastMCP server from an OpenAPI specification. - A FastMCP server with an OpenAPIProvider attached. -#### `from_fastapi` +#### `from_fastapi` ```python from_fastapi(cls, app: Any, name: str | None = None, route_maps: list[RouteMap] | None = None, route_map_fn: OpenAPIRouteMapFn | None = None, mcp_component_fn: OpenAPIComponentFn | None = None, mcp_names: dict[str, str] | None = None, httpx_client_kwargs: dict[str, Any] | None = None, tags: set[str] | None = None, timeout: float | None = None, **settings: Any) -> Self @@ -997,7 +989,7 @@ Create a FastMCP server from a FastAPI application. - A FastMCP server with an OpenAPIProvider attached. -#### `as_proxy` +#### `as_proxy` ```python as_proxy(cls, backend: Client[ClientTransportT] | ClientTransport | FastMCP[Any] | FastMCP1Server | AnyUrl | Path | MCPConfig | dict[str, Any] | str, **settings: Any) -> FastMCPProxy @@ -1015,7 +1007,7 @@ instance or any value accepted as the `transport` argument of `fastmcp.client.Client` constructor. -#### `generate_name` +#### `generate_name` ```python generate_name(cls, name: str | None = None) -> str