Expose local_provider property, deprecate FastMCP.remove_tool() (#3155)

Co-authored-by: marvin-context-protocol[bot] <225465937+marvin-context-protocol[bot]@users.noreply.github.com>
This commit is contained in:
Jeremiah Lowin 2026-02-11 20:37:19 -05:00 committed by GitHub
commit a307e9c3cc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 170 additions and 54 deletions

View file

@ -26,7 +26,7 @@ Default lifespan context manager that does nothing.
- An empty dictionary as the lifespan result.
### `create_proxy` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L2057" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `create_proxy` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L2079" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
create_proxy(target: Client[ClientTransportT] | ClientTransport | FastMCP[Any] | FastMCP1Server | AnyUrl | Path | MCPConfig | dict[str, Any] | str, **settings: Any) -> FastMCPProxy
@ -100,13 +100,28 @@ website_url(self) -> str | None
icons(self) -> list[mcp.types.Icon]
```
#### `add_middleware` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L382" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `local_provider` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L372" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
local_provider(self) -> LocalProvider
```
The server's local provider, which stores directly-registered components.
Use this to remove components:
mcp.local_provider.remove_tool("my_tool")
mcp.local_provider.remove_resource("data://info")
mcp.local_provider.remove_prompt("my_prompt")
#### `add_middleware` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L394" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
add_middleware(self, middleware: Middleware) -> None
```
#### `add_provider` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L385" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `add_provider` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L397" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
add_provider(self, provider: Provider) -> None
@ -126,7 +141,7 @@ always take precedence over providers.
- Prompts become "namespace_promptname"
#### `get_tasks` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L407" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `get_tasks` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L419" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_tasks(self) -> Sequence[FastMCPComponent]
@ -138,7 +153,7 @@ Overrides AggregateProvider.get_tasks() to apply server-level transforms
after aggregation. AggregateProvider handles provider-level namespacing.
#### `add_transform` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L436" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `add_transform` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L448" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
add_transform(self, transform: Transform) -> None
@ -153,7 +168,7 @@ They transform tools, resources, and prompts from ALL providers.
- `transform`: The transform to add.
#### `add_tool_transformation` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L456" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `add_tool_transformation` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L468" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
add_tool_transformation(self, tool_name: str, transformation: ToolTransformConfig) -> None
@ -165,7 +180,7 @@ Add a tool transformation.
Use ``add_transform(ToolTransform({...}))`` instead.
#### `remove_tool_transformation` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L473" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `remove_tool_transformation` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L485" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
remove_tool_transformation(self, _tool_name: str) -> None
@ -177,7 +192,7 @@ Remove a tool transformation.
Tool transformations are now immutable. Use enable/disable controls instead.
#### `list_tools` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L488" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `list_tools` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L500" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
list_tools(self) -> Sequence[Tool]
@ -190,7 +205,7 @@ and middleware execution. Returns all versions (no deduplication).
Protocol handlers deduplicate for MCP wire format.
#### `get_tool` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L558" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `get_tool` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L570" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_tool(self, name: str, version: VersionSpec | None = None) -> Tool | None
@ -210,7 +225,7 @@ session transforms can override provider-level disables.
- The tool if found and enabled, None otherwise.
#### `list_resources` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L584" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `list_resources` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L596" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
list_resources(self) -> Sequence[Resource]
@ -223,7 +238,7 @@ and middleware execution. Returns all versions (no deduplication).
Protocol handlers deduplicate for MCP wire format.
#### `get_resource` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L656" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `get_resource` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L668" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_resource(self, uri: str, version: VersionSpec | None = None) -> Resource | None
@ -242,7 +257,7 @@ transforms (including session-level) have been applied.
- The resource if found and enabled, None otherwise.
#### `list_resource_templates` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L681" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `list_resource_templates` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L693" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
list_resource_templates(self) -> Sequence[ResourceTemplate]
@ -255,7 +270,7 @@ auth filtering, and middleware execution. Returns all versions (no deduplication
Protocol handlers deduplicate for MCP wire format.
#### `get_resource_template` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L755" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `get_resource_template` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L767" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_resource_template(self, uri: str, version: VersionSpec | None = None) -> ResourceTemplate | None
@ -274,7 +289,7 @@ all transforms (including session-level) have been applied.
- The template if found and enabled, None otherwise.
#### `list_prompts` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L780" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `list_prompts` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L792" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
list_prompts(self) -> Sequence[Prompt]
@ -287,7 +302,7 @@ and middleware execution. Returns all versions (no deduplication).
Protocol handlers deduplicate for MCP wire format.
#### `get_prompt` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L850" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `get_prompt` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L862" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_prompt(self, name: str, version: VersionSpec | None = None) -> Prompt | None
@ -306,19 +321,19 @@ transforms (including session-level) have been applied.
- The prompt if found and enabled, None otherwise.
#### `call_tool` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L876" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `call_tool` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L888" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
call_tool(self, name: str, arguments: dict[str, Any] | None = None) -> ToolResult
```
#### `call_tool` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L887" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `call_tool` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L899" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
call_tool(self, name: str, arguments: dict[str, Any] | None = None) -> mcp.types.CreateTaskResult
```
#### `call_tool` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L897" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `call_tool` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L909" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
call_tool(self, name: str, arguments: dict[str, Any] | None = None) -> ToolResult | mcp.types.CreateTaskResult
@ -348,19 +363,19 @@ return ToolResult.
- `ValidationError`: If arguments fail validation
#### `read_resource` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L993" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `read_resource` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1005" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
read_resource(self, uri: str) -> ResourceResult
```
#### `read_resource` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1003" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `read_resource` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1015" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
read_resource(self, uri: str) -> mcp.types.CreateTaskResult
```
#### `read_resource` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1012" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `read_resource` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1024" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
read_resource(self, uri: str) -> ResourceResult | mcp.types.CreateTaskResult
@ -389,19 +404,19 @@ return ResourceResult.
- `ResourceError`: If resource read fails
#### `render_prompt` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1146" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `render_prompt` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1158" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
render_prompt(self, name: str, arguments: dict[str, Any] | None = None) -> PromptResult
```
#### `render_prompt` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1157" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `render_prompt` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1169" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
render_prompt(self, name: str, arguments: dict[str, Any] | None = None) -> mcp.types.CreateTaskResult
```
#### `render_prompt` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1167" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `render_prompt` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1179" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
render_prompt(self, name: str, arguments: dict[str, Any] | None = None) -> PromptResult | mcp.types.CreateTaskResult
@ -431,7 +446,7 @@ return PromptResult.
- `PromptError`: If prompt rendering fails
#### `add_tool` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1243" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `add_tool` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1255" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
add_tool(self, tool: Tool | Callable[..., Any]) -> Tool
@ -449,7 +464,7 @@ with the Context type annotation. See the @tool decorator for examples.
- The tool instance that was added to the server.
#### `remove_tool` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1257" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `remove_tool` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1269" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
remove_tool(self, name: str, version: str | None = None) -> None
@ -457,6 +472,9 @@ remove_tool(self, name: str, version: str | None = None) -> None
Remove tool(s) from the server.
.. deprecated::
Use ``mcp.local_provider.remove_tool(name)`` instead.
**Args:**
- `name`: The name of the tool to remove.
- `version`: If None, removes ALL versions. If specified, removes only that version.
@ -465,19 +483,19 @@ Remove tool(s) from the server.
- `NotFoundError`: If no matching tool is found.
#### `tool` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1277" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `tool` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1299" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
tool(self, name_or_fn: AnyFunction) -> FunctionTool
```
#### `tool` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1298" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `tool` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1320" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
tool(self, name_or_fn: str | None = None) -> Callable[[AnyFunction], FunctionTool]
```
#### `tool` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1318" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `tool` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1340" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
tool(self, name_or_fn: str | AnyFunction | None = None) -> Callable[[AnyFunction], FunctionTool] | FunctionTool | partial[Callable[[AnyFunction], FunctionTool] | FunctionTool]
@ -533,7 +551,7 @@ server.tool(my_function, name="custom_name")
```
#### `add_resource` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1417" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `add_resource` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1439" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
add_resource(self, resource: Resource | Callable[..., Any]) -> Resource | ResourceTemplate
@ -548,7 +566,7 @@ Add a resource to the server.
- The resource instance that was added to the server.
#### `add_template` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1430" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `add_template` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1452" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
add_template(self, template: ResourceTemplate) -> ResourceTemplate
@ -563,7 +581,7 @@ Add a resource template to the server.
- The template instance that was added to the server.
#### `resource` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1441" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `resource` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1463" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
resource(self, uri: str) -> Callable[[AnyFunction], Resource | ResourceTemplate | AnyFunction]
@ -622,7 +640,7 @@ async def get_weather(city: str) -> str:
```
#### `add_prompt` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1563" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `add_prompt` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1585" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
add_prompt(self, prompt: Prompt | Callable[..., Any]) -> Prompt
@ -637,19 +655,19 @@ Add a prompt to the server.
- The prompt instance that was added to the server.
#### `prompt` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1575" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `prompt` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1597" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
prompt(self, name_or_fn: AnyFunction) -> FunctionPrompt
```
#### `prompt` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1591" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `prompt` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1613" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
prompt(self, name_or_fn: str | None = None) -> Callable[[AnyFunction], FunctionPrompt]
```
#### `prompt` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1606" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `prompt` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1628" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
prompt(self, name_or_fn: str | AnyFunction | None = None) -> Callable[[AnyFunction], FunctionPrompt] | FunctionPrompt | partial[Callable[[AnyFunction], FunctionPrompt] | FunctionPrompt]
@ -726,7 +744,7 @@ Decorator to register a prompt.
```
#### `mount` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1706" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `mount` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1728" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```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
@ -773,7 +791,7 @@ mounted server.
- `prefix`: Deprecated. Use namespace instead.
#### `import_server` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1800" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `import_server` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1822" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
import_server(self, server: FastMCP[LifespanResultT], prefix: str | None = None) -> None
@ -814,7 +832,7 @@ templates, and prompts are imported with their original names.
objects are imported with their original names.
#### `from_openapi` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1900" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `from_openapi` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1922" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
from_openapi(cls, openapi_spec: dict[str, Any], client: httpx.AsyncClient | None = None, name: str = 'OpenAPI Server', route_maps: list[RouteMap] | None = None, route_map_fn: OpenAPIRouteMapFn | None = None, mcp_component_fn: OpenAPIComponentFn | None = None, mcp_names: dict[str, str] | None = None, tags: set[str] | None = None, validate_output: bool = True, **settings: Any) -> Self
@ -843,7 +861,7 @@ response structure while still returning structured JSON.
- A FastMCP server with an OpenAPIProvider attached.
#### `from_fastapi` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1951" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `from_fastapi` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1973" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
from_fastapi(cls, app: Any, name: str | None = None, route_maps: list[RouteMap] | None = None, route_map_fn: OpenAPIRouteMapFn | None = None, mcp_component_fn: OpenAPIComponentFn | None = None, mcp_names: dict[str, str] | None = None, httpx_client_kwargs: dict[str, Any] | None = None, tags: set[str] | None = None, **settings: Any) -> Self
@ -867,7 +885,7 @@ Use this to configure timeout and other client settings.
- A FastMCP server with an OpenAPIProvider attached.
#### `as_proxy` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L2006" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `as_proxy` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L2028" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
as_proxy(cls, backend: Client[ClientTransportT] | ClientTransport | FastMCP[Any] | FastMCP1Server | AnyUrl | Path | MCPConfig | dict[str, Any] | str, **settings: Any) -> FastMCPProxy
@ -885,7 +903,7 @@ instance or any value accepted as the `transport` argument of
`fastmcp.client.Client` constructor.
#### `generate_name` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L2043" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `generate_name` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L2065" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
generate_name(cls, name: str | None = None) -> str

View file

@ -81,9 +81,9 @@ mcp.add_prompt(my_prompt)
Remove components by name or URI:
```python
mcp.remove_tool("my_tool")
mcp.remove_resource("data://info")
mcp.remove_prompt("my_prompt")
mcp.local_provider.remove_tool("my_tool")
mcp.local_provider.remove_resource("data://info")
mcp.local_provider.remove_prompt("my_prompt")
```
## Duplicate Handling

View file

@ -975,7 +975,7 @@ def example_tool() -> str:
mcp.add_tool(example_tool) # Sends tools/list_changed notification
mcp.disable(keys={"tool:example_tool"}) # Sends tools/list_changed notification
mcp.enable(keys={"tool:example_tool"}) # Sends tools/list_changed notification
mcp.remove_tool("example_tool") # Sends tools/list_changed notification
mcp.local_provider.remove_tool("example_tool") # Sends tools/list_changed notification
```
Notifications are only sent when these operations occur within an active MCP request context (e.g., when called from within a tool or other MCP operation). Operations performed during server initialization do not trigger notifications.
@ -1060,7 +1060,7 @@ The duplicate behavior options are:
<VersionBadge version="2.3.4" />
You can dynamically remove tools from a server using the `remove_tool` method:
You can dynamically remove tools from a server through its [local provider](/servers/providers/local):
```python
from fastmcp import FastMCP
@ -1072,7 +1072,7 @@ def calculate_sum(a: int, b: int) -> int:
"""Add two numbers together."""
return a + b
mcp.remove_tool("calculate_sum")
mcp.local_provider.remove_tool("calculate_sum")
```
## Versioning

View file

@ -293,14 +293,14 @@ If the requested version doesn't exist, a `NotFoundError` is raised.
## Removing Versions
The `remove_tool`, `remove_resource`, and `remove_prompt` methods accept an optional `version` parameter that controls what gets removed.
The `remove_tool`, `remove_resource`, and `remove_prompt` methods on the server's [local provider](/servers/providers/local) accept an optional `version` parameter that controls what gets removed.
```python
# Remove ALL versions of a component
mcp.remove_tool("calculate")
mcp.local_provider.remove_tool("calculate")
# Remove only a specific version
mcp.remove_tool("calculate", version="1.0")
mcp.local_provider.remove_tool("calculate", version="1.0")
```
When you remove a specific version, other versions remain registered. When you remove without specifying a version, all versions are removed.
@ -332,5 +332,5 @@ Clients automatically see version 2.0 (the highest). During the transition, your
Once the migration is complete, remove the old version.
```python
mcp.remove_tool("process_data", version="1.0")
mcp.local_provider.remove_tool("process_data", version="1.0")
```

View file

@ -368,6 +368,18 @@ class FastMCP(
else:
return list(self._mcp_server.icons)
@property
def local_provider(self) -> LocalProvider:
"""The server's local provider, which stores directly-registered components.
Use this to remove components:
mcp.local_provider.remove_tool("my_tool")
mcp.local_provider.remove_resource("data://info")
mcp.local_provider.remove_prompt("my_prompt")
"""
return self._local_provider
async def _run_middleware(
self,
context: MiddlewareContext[Any],
@ -1257,6 +1269,9 @@ class FastMCP(
def remove_tool(self, name: str, version: str | None = None) -> None:
"""Remove tool(s) from the server.
.. deprecated::
Use ``mcp.local_provider.remove_tool(name)`` instead.
Args:
name: The name of the tool to remove.
version: If None, removes ALL versions. If specified, removes only that version.
@ -1264,6 +1279,13 @@ class FastMCP(
Raises:
NotFoundError: If no matching tool is found.
"""
if fastmcp.settings.deprecation_warnings:
warnings.warn(
"remove_tool() is deprecated. Use "
"mcp.local_provider.remove_tool(name) instead.",
DeprecationWarning,
stacklevel=2,
)
try:
self._local_provider.remove_tool(name, version)
except KeyError:

View file

@ -53,8 +53,8 @@ class TestDynamicChanges:
tools = await main_app.list_tools()
assert any(t.name == "sub_temp_tool" for t in tools)
# Remove the tool from sub_app using public API
sub_app.remove_tool("temp_tool")
# Remove the tool from sub_app
sub_app.local_provider.remove_tool("temp_tool")
# The tool should no longer be accessible
tools = await main_app.list_tools()

View file

@ -1,4 +1,5 @@
import os
import warnings
from pathlib import Path
from tempfile import TemporaryDirectory
from textwrap import dedent
@ -7,6 +8,7 @@ from unittest import mock
from mcp.types import TextContent, TextResourceContents
from fastmcp import Client, FastMCP
from fastmcp.server.providers import LocalProvider
from fastmcp.tools import FunctionTool
from fastmcp.tools.tool import Tool
from fastmcp.utilities.tests import temporary_settings
@ -116,6 +118,80 @@ class TestServerDelegation:
assert any(t.name == "local_tool" for t in tools)
class TestLocalProviderProperty:
"""Test the public local_provider property."""
async def test_local_provider_returns_local_provider(self):
mcp = FastMCP()
assert isinstance(mcp.local_provider, LocalProvider)
assert mcp.local_provider is mcp._local_provider
async def test_remove_tool_via_local_provider(self):
mcp = FastMCP()
@mcp.tool
def my_tool() -> str:
return "result"
assert await mcp.local_provider.get_tool("my_tool") is not None
mcp.local_provider.remove_tool("my_tool")
tools = await mcp.list_tools()
assert not any(t.name == "my_tool" for t in tools)
async def test_remove_resource_via_local_provider(self):
mcp = FastMCP()
@mcp.resource("resource://test")
def my_resource() -> str:
return "data"
mcp.local_provider.remove_resource("resource://test")
resources = await mcp.list_resources()
assert not any(r.uri == "resource://test" for r in resources)
async def test_remove_prompt_via_local_provider(self):
mcp = FastMCP()
@mcp.prompt
def my_prompt() -> str:
return "hello"
mcp.local_provider.remove_prompt("my_prompt")
prompts = await mcp.list_prompts()
assert not any(p.name == "my_prompt" for p in prompts)
class TestRemoveToolDeprecation:
async def test_remove_tool_emits_deprecation_warning(self):
mcp = FastMCP()
@mcp.tool
def my_tool() -> str:
return "result"
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("always")
mcp.remove_tool("my_tool")
assert len(w) == 1
assert issubclass(w[0].category, DeprecationWarning)
assert "local_provider" in str(w[0].message)
async def test_remove_tool_still_works(self):
mcp = FastMCP()
@mcp.tool
def my_tool() -> str:
return "result"
with warnings.catch_warnings():
warnings.simplefilter("ignore", DeprecationWarning)
mcp.remove_tool("my_tool")
tools = await mcp.list_tools()
assert not any(t.name == "my_tool" for t in tools)
class TestResourcePrefixMounting:
"""Test resource prefixing in mounted servers."""