mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-09 07:09:11 +02:00
Remove deprecated FastMCP() constructor kwargs (#3148)
Co-authored-by: marvin-context-protocol[bot] <225465937+marvin-context-protocol[bot]@users.noreply.github.com>
This commit is contained in:
parent
0f95ed72cd
commit
25e2f4da32
21 changed files with 285 additions and 800 deletions
|
|
@ -66,6 +66,32 @@ async def get_emails(
|
|||
|
||||
Background tasks now use a distributed Redis notification queue for reliable delivery ([#2906](https://github.com/jlowin/fastmcp/pull/2906)). Elicitation switches from polling to BLPOP (single blocking call instead of ~7,200 round-trips/hour), and notification delivery retries up to 3x with TTL-based expiration.
|
||||
|
||||
### Breaking: Deprecated `FastMCP()` Constructor Kwargs Removed
|
||||
|
||||
Sixteen deprecated keyword arguments have been removed from `FastMCP.__init__`. Passing any of them now raises `TypeError` with a migration hint. Environment variables (e.g., `FASTMCP_HOST`) continue to work — only the constructor kwargs moved.
|
||||
|
||||
**Transport/server settings** (`host`, `port`, `log_level`, `debug`, `sse_path`, `message_path`, `streamable_http_path`, `json_response`, `stateless_http`): Pass to `run()`, `run_http_async()`, or `http_app()` as appropriate, or set via environment variables.
|
||||
|
||||
```python
|
||||
# Before
|
||||
mcp = FastMCP("server", host="0.0.0.0", port=8080)
|
||||
mcp.run()
|
||||
|
||||
# After
|
||||
mcp = FastMCP("server")
|
||||
mcp.run(transport="http", host="0.0.0.0", port=8080)
|
||||
```
|
||||
|
||||
**Duplicate handling** (`on_duplicate_tools`, `on_duplicate_resources`, `on_duplicate_prompts`): Use the unified `on_duplicate=` parameter.
|
||||
|
||||
**Tag filtering** (`include_tags`, `exclude_tags`): Use `server.enable(tags=..., only=True)` and `server.disable(tags=...)` after construction.
|
||||
|
||||
**Tool serializer** (`tool_serializer`): Return `ToolResult` from tools instead.
|
||||
|
||||
**Tool transformations** (`tool_transformations`): Use `server.add_transform(ToolTransform(...))` after construction.
|
||||
|
||||
The `_deprecated_settings` attribute and `.settings` property are also removed. `ExperimentalSettings` has been deleted (dead code).
|
||||
|
||||
### Breaking: `ui=` Renamed to `app=`
|
||||
|
||||
The MCP Apps decorator parameter has been renamed from `ui=ToolUI(...)` / `ui=ResourceUI(...)` to `app=AppConfig(...)` ([#3117](https://github.com/jlowin/fastmcp/pull/3117)). `ToolUI` and `ResourceUI` are consolidated into a single `AppConfig` class. Wire format is unchanged. See the MCP Apps section under beta2 for full details.
|
||||
|
|
@ -1266,35 +1292,9 @@ main.mount(subserver, prefix="api")
|
|||
main.mount(subserver, namespace="api")
|
||||
```
|
||||
|
||||
#### Tag Filtering Init Parameters
|
||||
#### Tag Filtering, Tool Serializer, Tool Transformations Init Parameters
|
||||
|
||||
`FastMCP(include_tags=..., exclude_tags=...)` deprecated. Use `enable()`/`disable()` methods:
|
||||
|
||||
```python
|
||||
# Deprecated
|
||||
mcp = FastMCP("server", exclude_tags={"internal"})
|
||||
|
||||
# New
|
||||
mcp = FastMCP("server")
|
||||
mcp.disable(tags={"internal"})
|
||||
```
|
||||
|
||||
#### Tool Serializer Parameter
|
||||
|
||||
The `tool_serializer` parameter on `FastMCP` is deprecated. Return `ToolResult` for explicit serialization control.
|
||||
|
||||
#### Tool Transformation Methods
|
||||
|
||||
`add_tool_transformation()`, `remove_tool_transformation()`, and `tool_transformations` constructor parameter are deprecated. Use `add_transform(ToolTransform({...}))` instead:
|
||||
|
||||
```python
|
||||
# Deprecated
|
||||
mcp.add_tool_transformation("name", config)
|
||||
|
||||
# New
|
||||
from fastmcp.server.transforms import ToolTransform
|
||||
mcp.add_transform(ToolTransform({"name": config}))
|
||||
```
|
||||
These constructor parameters have been **removed** (not just deprecated) as of rc1. See "Breaking: Deprecated `FastMCP()` Constructor Kwargs Removed" in the rc1 section above. The `add_tool_transformation()` and `remove_tool_transformation()` methods remain as deprecated shims.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ infer_transport_type_from_url(url: str | AnyUrl) -> Literal['http', 'sse']
|
|||
Infer the appropriate transport type from the given URL.
|
||||
|
||||
|
||||
### `update_config_file` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/mcp_config.py#L321" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
### `update_config_file` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/mcp_config.py#L324" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
update_config_file(file_path: Path, server_name: str, server_config: CanonicalMCPServerTypes) -> None
|
||||
|
|
@ -57,7 +57,7 @@ worry about transforming server objects here.
|
|||
|
||||
## Classes
|
||||
|
||||
### `StdioMCPServer` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/mcp_config.py#L131" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
### `StdioMCPServer` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/mcp_config.py#L134" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
|
||||
MCP server configuration for stdio transport.
|
||||
|
|
@ -67,19 +67,19 @@ This is the canonical configuration format for MCP servers using stdio transport
|
|||
|
||||
**Methods:**
|
||||
|
||||
#### `to_transport` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/mcp_config.py#L164" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
#### `to_transport` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/mcp_config.py#L167" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
to_transport(self) -> StdioTransport
|
||||
```
|
||||
|
||||
### `TransformingStdioMCPServer` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/mcp_config.py#L176" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
### `TransformingStdioMCPServer` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/mcp_config.py#L179" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
|
||||
A Stdio server with tool transforms.
|
||||
|
||||
|
||||
### `RemoteMCPServer` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/mcp_config.py#L180" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
### `RemoteMCPServer` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/mcp_config.py#L183" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
|
||||
MCP server configuration for HTTP/SSE transport.
|
||||
|
|
@ -89,19 +89,19 @@ This is the canonical configuration format for MCP servers using remote transpor
|
|||
|
||||
**Methods:**
|
||||
|
||||
#### `to_transport` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/mcp_config.py#L216" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
#### `to_transport` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/mcp_config.py#L219" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
to_transport(self) -> StreamableHttpTransport | SSETransport
|
||||
```
|
||||
|
||||
### `TransformingRemoteMCPServer` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/mcp_config.py#L241" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
### `TransformingRemoteMCPServer` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/mcp_config.py#L244" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
|
||||
A Remote server with tool transforms.
|
||||
|
||||
|
||||
### `MCPConfig` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/mcp_config.py#L252" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
### `MCPConfig` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/mcp_config.py#L255" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
|
||||
A configuration object for MCP Servers that conforms to the canonical MCP configuration format
|
||||
|
|
@ -113,7 +113,7 @@ For an MCPConfig that is strictly canonical, see the `CanonicalMCPConfig` class.
|
|||
|
||||
**Methods:**
|
||||
|
||||
#### `wrap_servers_at_root` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/mcp_config.py#L266" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
#### `wrap_servers_at_root` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/mcp_config.py#L269" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
wrap_servers_at_root(cls, values: dict[str, Any]) -> dict[str, Any]
|
||||
|
|
@ -122,7 +122,7 @@ wrap_servers_at_root(cls, values: dict[str, Any]) -> dict[str, Any]
|
|||
If there's no mcpServers key but there are server configs at root, wrap them.
|
||||
|
||||
|
||||
#### `add_server` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/mcp_config.py#L279" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
#### `add_server` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/mcp_config.py#L282" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
add_server(self, name: str, server: MCPServerTypes) -> None
|
||||
|
|
@ -131,7 +131,7 @@ add_server(self, name: str, server: MCPServerTypes) -> None
|
|||
Add or update a server in the configuration.
|
||||
|
||||
|
||||
#### `from_dict` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/mcp_config.py#L284" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
#### `from_dict` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/mcp_config.py#L287" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
from_dict(cls, config: dict[str, Any]) -> Self
|
||||
|
|
@ -140,7 +140,7 @@ from_dict(cls, config: dict[str, Any]) -> Self
|
|||
Parse MCP configuration from dictionary format.
|
||||
|
||||
|
||||
#### `to_dict` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/mcp_config.py#L288" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
#### `to_dict` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/mcp_config.py#L291" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
to_dict(self) -> dict[str, Any]
|
||||
|
|
@ -149,7 +149,7 @@ to_dict(self) -> dict[str, Any]
|
|||
Convert MCPConfig to dictionary format, preserving all fields.
|
||||
|
||||
|
||||
#### `write_to_file` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/mcp_config.py#L292" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
#### `write_to_file` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/mcp_config.py#L295" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
write_to_file(self, file_path: Path) -> None
|
||||
|
|
@ -158,7 +158,7 @@ write_to_file(self, file_path: Path) -> None
|
|||
Write configuration to JSON file.
|
||||
|
||||
|
||||
#### `from_file` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/mcp_config.py#L298" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
#### `from_file` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/mcp_config.py#L301" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
from_file(cls, file_path: Path) -> Self
|
||||
|
|
@ -167,7 +167,7 @@ from_file(cls, file_path: Path) -> Self
|
|||
Load configuration from JSON file.
|
||||
|
||||
|
||||
### `CanonicalMCPConfig` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/mcp_config.py#L306" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
### `CanonicalMCPConfig` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/mcp_config.py#L309" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
|
||||
Canonical MCP configuration format.
|
||||
|
|
@ -178,7 +178,7 @@ The format is designed to be client-agnostic and extensible for future use cases
|
|||
|
||||
**Methods:**
|
||||
|
||||
#### `add_server` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/mcp_config.py#L316" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
#### `add_server` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/mcp_config.py#L319" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
add_server(self, name: str, server: CanonicalMCPServerTypes) -> None
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ Run the server using HTTP transport.
|
|||
- `stateless`: Alias for stateless_http for CLI consistency
|
||||
|
||||
|
||||
#### `http_app` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/mixins/transport.py#L281" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
#### `http_app` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/mixins/transport.py#L279" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
http_app(self: FastMCP, 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
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ FastMCP - A more ergonomic interface for MCP servers.
|
|||
|
||||
## Functions
|
||||
|
||||
### `default_lifespan` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L174" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
### `default_lifespan` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L168" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```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` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L2179" 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#L2049" 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
|
||||
|
|
@ -54,65 +54,59 @@ use `FastMCPProxy` or `ProxyProvider` directly from `fastmcp.server.providers.pr
|
|||
|
||||
## Classes
|
||||
|
||||
### `StateValue` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L210" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
### `StateValue` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L204" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
|
||||
Wrapper for stored context state values.
|
||||
|
||||
|
||||
### `FastMCP` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L216" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
### `FastMCP` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L210" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
**Methods:**
|
||||
|
||||
#### `settings` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L455" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
settings(self) -> Settings
|
||||
```
|
||||
|
||||
#### `name` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L466" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
#### `name` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L337" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
name(self) -> str
|
||||
```
|
||||
|
||||
#### `instructions` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L470" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
#### `instructions` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L341" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
instructions(self) -> str | None
|
||||
```
|
||||
|
||||
#### `instructions` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L474" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
#### `instructions` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L345" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
instructions(self, value: str | None) -> None
|
||||
```
|
||||
|
||||
#### `version` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L478" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
#### `version` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L349" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
version(self) -> str | None
|
||||
```
|
||||
|
||||
#### `website_url` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L482" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
#### `website_url` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L353" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
website_url(self) -> str | None
|
||||
```
|
||||
|
||||
#### `icons` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L486" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
#### `icons` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L357" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
icons(self) -> list[mcp.types.Icon]
|
||||
```
|
||||
|
||||
#### `add_middleware` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L503" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
#### `add_middleware` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L374" 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#L506" 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#L377" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
add_provider(self, provider: Provider) -> None
|
||||
|
|
@ -132,7 +126,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#L528" 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#L399" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
get_tasks(self) -> Sequence[FastMCPComponent]
|
||||
|
|
@ -144,7 +138,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#L557" 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#L428" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
add_transform(self, transform: Transform) -> None
|
||||
|
|
@ -159,7 +153,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#L577" 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#L448" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
add_tool_transformation(self, tool_name: str, transformation: ToolTransformConfig) -> None
|
||||
|
|
@ -171,7 +165,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#L594" 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#L465" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
remove_tool_transformation(self, _tool_name: str) -> None
|
||||
|
|
@ -183,7 +177,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#L609" 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#L480" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
list_tools(self) -> Sequence[Tool]
|
||||
|
|
@ -196,7 +190,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#L679" 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#L550" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
get_tool(self, name: str, version: VersionSpec | None = None) -> Tool | None
|
||||
|
|
@ -216,7 +210,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#L705" 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#L576" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
list_resources(self) -> Sequence[Resource]
|
||||
|
|
@ -229,7 +223,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#L777" 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#L648" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
get_resource(self, uri: str, version: VersionSpec | None = None) -> Resource | None
|
||||
|
|
@ -248,7 +242,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#L802" 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#L673" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
list_resource_templates(self) -> Sequence[ResourceTemplate]
|
||||
|
|
@ -261,7 +255,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#L876" 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#L747" 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
|
||||
|
|
@ -280,7 +274,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#L901" 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#L772" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
list_prompts(self) -> Sequence[Prompt]
|
||||
|
|
@ -293,7 +287,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#L971" 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#L842" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
get_prompt(self, name: str, version: VersionSpec | None = None) -> Prompt | None
|
||||
|
|
@ -312,19 +306,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#L997" 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#L868" 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#L1008" 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#L879" 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#L1018" 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#L889" 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
|
||||
|
|
@ -354,19 +348,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#L1114" 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#L985" 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#L1124" 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#L995" 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#L1133" 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#L1004" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
read_resource(self, uri: str) -> ResourceResult | mcp.types.CreateTaskResult
|
||||
|
|
@ -395,19 +389,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#L1267" 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#L1138" 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#L1278" 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#L1149" 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#L1288" 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#L1159" 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
|
||||
|
|
@ -437,7 +431,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#L1364" 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#L1235" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
add_tool(self, tool: Tool | Callable[..., Any]) -> Tool
|
||||
|
|
@ -455,7 +449,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#L1378" 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#L1249" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
remove_tool(self, name: str, version: str | None = None) -> None
|
||||
|
|
@ -471,19 +465,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#L1398" 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#L1269" 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#L1419" 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#L1290" 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#L1439" 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#L1310" 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]
|
||||
|
|
@ -539,7 +533,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#L1539" 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#L1409" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
add_resource(self, resource: Resource | Callable[..., Any]) -> Resource | ResourceTemplate
|
||||
|
|
@ -554,7 +548,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#L1552" 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#L1422" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
add_template(self, template: ResourceTemplate) -> ResourceTemplate
|
||||
|
|
@ -569,7 +563,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#L1563" 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#L1433" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
resource(self, uri: str) -> Callable[[AnyFunction], Resource | ResourceTemplate | AnyFunction]
|
||||
|
|
@ -628,7 +622,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#L1685" 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#L1555" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
add_prompt(self, prompt: Prompt | Callable[..., Any]) -> Prompt
|
||||
|
|
@ -643,19 +637,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#L1697" 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#L1567" 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#L1713" 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#L1583" 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#L1728" 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#L1598" 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]
|
||||
|
|
@ -732,7 +726,7 @@ Decorator to register a prompt.
|
|||
```
|
||||
|
||||
|
||||
#### `mount` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/server.py#L1828" 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#L1698" 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
|
||||
|
|
@ -779,7 +773,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#L1922" 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#L1792" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
import_server(self, server: FastMCP[LifespanResultT], prefix: str | None = None) -> None
|
||||
|
|
@ -820,7 +814,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#L2022" 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#L1892" 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
|
||||
|
|
@ -849,7 +843,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#L2073" 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#L1943" 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
|
||||
|
|
@ -873,7 +867,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#L2128" 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#L1998" 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
|
||||
|
|
@ -891,7 +885,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#L2165" 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#L2035" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
generate_name(cls, name: str | None = None) -> str
|
||||
|
|
|
|||
|
|
@ -7,15 +7,13 @@ sidebarTitle: settings
|
|||
|
||||
## Classes
|
||||
|
||||
### `DocketSettings` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/settings.py#L30" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
### `DocketSettings` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/settings.py#L29" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
|
||||
Docket worker configuration.
|
||||
|
||||
|
||||
### `ExperimentalSettings` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/settings.py#L118" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
### `Settings` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/settings.py#L142" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
### `Settings` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/settings.py#L117" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
|
||||
FastMCP settings.
|
||||
|
|
@ -23,7 +21,7 @@ FastMCP settings.
|
|||
|
||||
**Methods:**
|
||||
|
||||
#### `get_setting` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/settings.py#L154" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
#### `get_setting` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/settings.py#L129" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
get_setting(self, attr: str) -> Any
|
||||
|
|
@ -33,7 +31,7 @@ Get a setting. If the setting contains one or more `__`, it will be
|
|||
treated as a nested setting.
|
||||
|
||||
|
||||
#### `set_setting` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/settings.py#L167" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
#### `set_setting` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/settings.py#L142" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
set_setting(self, attr: str, value: Any) -> None
|
||||
|
|
@ -43,7 +41,7 @@ Set a setting. If the setting contains one or more `__`, it will be
|
|||
treated as a nested setting.
|
||||
|
||||
|
||||
#### `normalize_log_level` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/settings.py#L189" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
#### `normalize_log_level` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/settings.py#L164" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
|
||||
|
||||
```python
|
||||
normalize_log_level(cls, v)
|
||||
|
|
|
|||
|
|
@ -109,10 +109,13 @@ class _TransformingMCPServerMixin(FastMCPBaseModel):
|
|||
wrapped_mcp_server = create_proxy(
|
||||
client,
|
||||
name=server_name,
|
||||
include_tags=self.include_tags,
|
||||
exclude_tags=self.exclude_tags,
|
||||
)
|
||||
|
||||
if self.include_tags is not None:
|
||||
wrapped_mcp_server.enable(tags=self.include_tags, only=True)
|
||||
if self.exclude_tags is not None:
|
||||
wrapped_mcp_server.disable(tags=self.exclude_tags)
|
||||
|
||||
# Apply tool transforms if configured
|
||||
if self.tools:
|
||||
from fastmcp.server.transforms import ToolTransform
|
||||
|
|
|
|||
|
|
@ -231,17 +231,15 @@ class TransportMixin:
|
|||
|
||||
# Resolve from settings/env var if not explicitly set
|
||||
if stateless_http is None:
|
||||
stateless_http = self._deprecated_settings.stateless_http
|
||||
stateless_http = fastmcp.settings.stateless_http
|
||||
|
||||
# SSE doesn't support stateless mode
|
||||
if stateless_http and transport == "sse":
|
||||
raise ValueError("SSE transport does not support stateless mode")
|
||||
|
||||
host = host or self._deprecated_settings.host
|
||||
port = port or self._deprecated_settings.port
|
||||
default_log_level_to_use = (
|
||||
log_level or self._deprecated_settings.log_level
|
||||
).lower()
|
||||
host = host or fastmcp.settings.host
|
||||
port = port or fastmcp.settings.port
|
||||
default_log_level_to_use = (log_level or fastmcp.settings.log_level).lower()
|
||||
|
||||
app = self.http_app(
|
||||
path=path,
|
||||
|
|
@ -311,31 +309,30 @@ class TransportMixin:
|
|||
if transport in ("streamable-http", "http"):
|
||||
return create_streamable_http_app(
|
||||
server=self,
|
||||
streamable_http_path=path
|
||||
or self._deprecated_settings.streamable_http_path,
|
||||
streamable_http_path=path or fastmcp.settings.streamable_http_path,
|
||||
event_store=event_store,
|
||||
retry_interval=retry_interval,
|
||||
auth=self.auth,
|
||||
json_response=(
|
||||
json_response
|
||||
if json_response is not None
|
||||
else self._deprecated_settings.json_response
|
||||
else fastmcp.settings.json_response
|
||||
),
|
||||
stateless_http=(
|
||||
stateless_http
|
||||
if stateless_http is not None
|
||||
else self._deprecated_settings.stateless_http
|
||||
else fastmcp.settings.stateless_http
|
||||
),
|
||||
debug=self._deprecated_settings.debug,
|
||||
debug=fastmcp.settings.debug,
|
||||
middleware=middleware,
|
||||
)
|
||||
elif transport == "sse":
|
||||
return create_sse_app(
|
||||
server=self,
|
||||
message_path=self._deprecated_settings.message_path,
|
||||
sse_path=path or self._deprecated_settings.sse_path,
|
||||
message_path=fastmcp.settings.message_path,
|
||||
sse_path=path or fastmcp.settings.sse_path,
|
||||
auth=self.auth,
|
||||
debug=self._deprecated_settings.debug,
|
||||
debug=fastmcp.settings.debug,
|
||||
middleware=middleware,
|
||||
)
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -10,8 +10,6 @@ from collections.abc import (
|
|||
AsyncIterator,
|
||||
Awaitable,
|
||||
Callable,
|
||||
Collection,
|
||||
Mapping,
|
||||
Sequence,
|
||||
)
|
||||
from contextlib import (
|
||||
|
|
@ -79,7 +77,6 @@ from fastmcp.server.transforms import (
|
|||
)
|
||||
from fastmcp.server.transforms.visibility import apply_session_transforms, is_enabled
|
||||
from fastmcp.settings import DuplicateBehavior as DuplicateBehaviorSetting
|
||||
from fastmcp.settings import Settings
|
||||
from fastmcp.tools.function_tool import FunctionTool
|
||||
from fastmcp.tools.tool import AuthCheckCallable, Tool, ToolResult
|
||||
from fastmcp.tools.tool_transform import ToolTransformConfig
|
||||
|
|
@ -99,7 +96,6 @@ if TYPE_CHECKING:
|
|||
from fastmcp.server.providers.openapi import RouteMap
|
||||
from fastmcp.server.providers.openapi import RouteMapFn as OpenAPIRouteMapFn
|
||||
from fastmcp.server.providers.proxy import FastMCPProxy
|
||||
from fastmcp.tools.tool import ToolResultSerializerType
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
|
@ -107,39 +103,37 @@ logger = get_logger(__name__)
|
|||
DuplicateBehavior = Literal["warn", "error", "replace", "ignore"]
|
||||
|
||||
|
||||
def _resolve_on_duplicate(
|
||||
on_duplicate: DuplicateBehavior | None,
|
||||
on_duplicate_tools: DuplicateBehavior | None,
|
||||
on_duplicate_resources: DuplicateBehavior | None,
|
||||
on_duplicate_prompts: DuplicateBehavior | None,
|
||||
) -> DuplicateBehavior:
|
||||
"""Resolve on_duplicate from deprecated per-type params.
|
||||
_REMOVED_KWARGS: dict[str, str] = {
|
||||
"host": "Pass `host` to `run_http_async()`, or set FASTMCP_HOST.",
|
||||
"port": "Pass `port` to `run_http_async()`, or set FASTMCP_PORT.",
|
||||
"sse_path": "Pass `path` to `run_http_async()` or `http_app()`, or set FASTMCP_SSE_PATH.",
|
||||
"message_path": "Set FASTMCP_MESSAGE_PATH.",
|
||||
"streamable_http_path": "Pass `path` to `run_http_async()` or `http_app()`, or set FASTMCP_STREAMABLE_HTTP_PATH.",
|
||||
"json_response": "Pass `json_response` to `run_http_async()` or `http_app()`, or set FASTMCP_JSON_RESPONSE.",
|
||||
"stateless_http": "Pass `stateless_http` to `run_http_async()` or `http_app()`, or set FASTMCP_STATELESS_HTTP.",
|
||||
"debug": "Set FASTMCP_DEBUG.",
|
||||
"log_level": "Pass `log_level` to `run_http_async()`, or set FASTMCP_LOG_LEVEL.",
|
||||
"on_duplicate_tools": "Use `on_duplicate=` instead.",
|
||||
"on_duplicate_resources": "Use `on_duplicate=` instead.",
|
||||
"on_duplicate_prompts": "Use `on_duplicate=` instead.",
|
||||
"tool_serializer": "Return ToolResult from your tools instead. See https://gofastmcp.com/servers/tools#custom-serialization",
|
||||
"include_tags": "Use `server.enable(tags=..., only=True)` after creating the server.",
|
||||
"exclude_tags": "Use `server.disable(tags=...)` after creating the server.",
|
||||
"tool_transformations": "Use `server.add_transform(ToolTransform(...))` after creating the server.",
|
||||
}
|
||||
|
||||
Takes the most strict value if multiple are provided.
|
||||
Delete this function when removing deprecated params.
|
||||
"""
|
||||
strictness_order: list[DuplicateBehavior] = ["error", "warn", "replace", "ignore"]
|
||||
deprecated_values: list[DuplicateBehavior] = []
|
||||
|
||||
deprecated_params: list[tuple[str, DuplicateBehavior | None]] = [
|
||||
("on_duplicate_tools", on_duplicate_tools),
|
||||
("on_duplicate_resources", on_duplicate_resources),
|
||||
("on_duplicate_prompts", on_duplicate_prompts),
|
||||
]
|
||||
for name, value in deprecated_params:
|
||||
if value is not None:
|
||||
if fastmcp.settings.deprecation_warnings:
|
||||
warnings.warn(
|
||||
f"{name} is deprecated, use on_duplicate instead",
|
||||
DeprecationWarning,
|
||||
stacklevel=4,
|
||||
)
|
||||
deprecated_values.append(value)
|
||||
|
||||
if on_duplicate is None and deprecated_values:
|
||||
return min(deprecated_values, key=lambda x: strictness_order.index(x))
|
||||
|
||||
return on_duplicate or "warn"
|
||||
def _check_removed_kwargs(kwargs: dict[str, Any]) -> None:
|
||||
"""Raise helpful TypeErrors for kwargs removed in v3."""
|
||||
for key in kwargs:
|
||||
if key in _REMOVED_KWARGS:
|
||||
raise TypeError(
|
||||
f"FastMCP() no longer accepts `{key}`. {_REMOVED_KWARGS[key]}"
|
||||
)
|
||||
if kwargs:
|
||||
raise TypeError(
|
||||
f"FastMCP() got unexpected keyword argument(s): {', '.join(repr(k) for k in kwargs)}"
|
||||
)
|
||||
|
||||
|
||||
Transport = Literal["stdio", "http", "sse", "streamable-http"]
|
||||
|
|
@ -232,45 +226,23 @@ class FastMCP(
|
|||
middleware: Sequence[Middleware] | None = None,
|
||||
providers: Sequence[Provider] | None = None,
|
||||
lifespan: LifespanCallable | Lifespan | None = None,
|
||||
mask_error_details: bool | None = None,
|
||||
tools: Sequence[Tool | Callable[..., Any]] | None = None,
|
||||
tool_serializer: ToolResultSerializerType | None = None,
|
||||
include_tags: Collection[str] | None = None,
|
||||
exclude_tags: Collection[str] | None = None,
|
||||
on_duplicate: DuplicateBehavior | None = None,
|
||||
mask_error_details: bool | None = None,
|
||||
strict_input_validation: bool | None = None,
|
||||
list_page_size: int | None = None,
|
||||
tasks: bool | None = None,
|
||||
session_state_store: AsyncKeyValue | None = None,
|
||||
# ---
|
||||
# --- DEPRECATED parameters ---
|
||||
# ---
|
||||
on_duplicate_tools: DuplicateBehavior | None = None,
|
||||
on_duplicate_resources: DuplicateBehavior | None = None,
|
||||
on_duplicate_prompts: DuplicateBehavior | None = None,
|
||||
log_level: str | None = None,
|
||||
debug: bool | None = None,
|
||||
host: str | None = None,
|
||||
port: int | None = None,
|
||||
sse_path: str | None = None,
|
||||
message_path: str | None = None,
|
||||
streamable_http_path: str | None = None,
|
||||
json_response: bool | None = None,
|
||||
stateless_http: bool | None = None,
|
||||
sampling_handler: SamplingHandler | None = None,
|
||||
sampling_handler_behavior: Literal["always", "fallback"] | None = None,
|
||||
tool_transformations: Mapping[str, ToolTransformConfig] | None = None,
|
||||
**kwargs: Any,
|
||||
):
|
||||
_check_removed_kwargs(kwargs)
|
||||
|
||||
# Initialize Provider (sets up _transforms)
|
||||
super().__init__()
|
||||
|
||||
# Resolve on_duplicate from deprecated params (delete when removing deprecation)
|
||||
self._on_duplicate: DuplicateBehaviorSetting = _resolve_on_duplicate(
|
||||
on_duplicate,
|
||||
on_duplicate_tools,
|
||||
on_duplicate_resources,
|
||||
on_duplicate_prompts,
|
||||
)
|
||||
self._on_duplicate: DuplicateBehaviorSetting = on_duplicate or "warn"
|
||||
|
||||
# Resolve server default for background task support
|
||||
self._support_tasks_by_default: bool = tasks if tasks is not None else False
|
||||
|
|
@ -312,16 +284,6 @@ class FastMCP(
|
|||
raise ValueError("list_page_size must be a positive integer")
|
||||
self._list_page_size: int | None = list_page_size
|
||||
|
||||
if tool_serializer is not None and fastmcp.settings.deprecation_warnings:
|
||||
warnings.warn(
|
||||
"The `tool_serializer` parameter is deprecated. "
|
||||
"Return ToolResult from your tools for full control over serialization. "
|
||||
"See https://gofastmcp.com/servers/tools#custom-serialization for migration examples.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
self._tool_serializer: Callable[[Any], str] | None = tool_serializer
|
||||
|
||||
# Handle Lifespan instances (they're callable) or regular lifespan functions
|
||||
if lifespan is not None:
|
||||
self._lifespan: LifespanCallable[LifespanResultT] = lifespan
|
||||
|
|
@ -349,38 +311,9 @@ class FastMCP(
|
|||
if tools:
|
||||
for tool in tools:
|
||||
if not isinstance(tool, Tool):
|
||||
tool = Tool.from_function(tool, serializer=self._tool_serializer)
|
||||
tool = Tool.from_function(tool)
|
||||
self.add_tool(tool)
|
||||
|
||||
# Handle deprecated include_tags and exclude_tags parameters
|
||||
if include_tags is not None:
|
||||
warnings.warn(
|
||||
"include_tags is deprecated. Use server.enable(tags=..., only=True) instead.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
# For backwards compatibility, initialize allowlist from include_tags
|
||||
self.enable(tags=set(include_tags), only=True)
|
||||
if exclude_tags is not None:
|
||||
warnings.warn(
|
||||
"exclude_tags is deprecated. Use server.disable(tags=...) instead.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
# For backwards compatibility, initialize blocklist from exclude_tags
|
||||
self.disable(tags=set(exclude_tags))
|
||||
|
||||
# Handle deprecated tool_transformations parameter
|
||||
if tool_transformations:
|
||||
if fastmcp.settings.deprecation_warnings:
|
||||
warnings.warn(
|
||||
"The tool_transformations parameter is deprecated. Use "
|
||||
"server.add_transform(ToolTransform({...})) instead.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
self._transforms.append(ToolTransform(dict(tool_transformations)))
|
||||
|
||||
self.strict_input_validation: bool = (
|
||||
strict_input_validation
|
||||
if strict_input_validation is not None
|
||||
|
|
@ -397,71 +330,9 @@ class FastMCP(
|
|||
sampling_handler_behavior or "fallback"
|
||||
)
|
||||
|
||||
self._handle_deprecated_settings(
|
||||
log_level=log_level,
|
||||
debug=debug,
|
||||
host=host,
|
||||
port=port,
|
||||
sse_path=sse_path,
|
||||
message_path=message_path,
|
||||
streamable_http_path=streamable_http_path,
|
||||
json_response=json_response,
|
||||
stateless_http=stateless_http,
|
||||
)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"{type(self).__name__}({self.name!r})"
|
||||
|
||||
def _handle_deprecated_settings(
|
||||
self,
|
||||
log_level: str | None,
|
||||
debug: bool | None,
|
||||
host: str | None,
|
||||
port: int | None,
|
||||
sse_path: str | None,
|
||||
message_path: str | None,
|
||||
streamable_http_path: str | None,
|
||||
json_response: bool | None,
|
||||
stateless_http: bool | None,
|
||||
) -> None:
|
||||
"""Handle deprecated settings. Deprecated in 2.8.0."""
|
||||
deprecated_settings: dict[str, Any] = {}
|
||||
|
||||
for name, arg in [
|
||||
("log_level", log_level),
|
||||
("debug", debug),
|
||||
("host", host),
|
||||
("port", port),
|
||||
("sse_path", sse_path),
|
||||
("message_path", message_path),
|
||||
("streamable_http_path", streamable_http_path),
|
||||
("json_response", json_response),
|
||||
("stateless_http", stateless_http),
|
||||
]:
|
||||
if arg is not None:
|
||||
# Deprecated in 2.8.0
|
||||
if fastmcp.settings.deprecation_warnings:
|
||||
warnings.warn(
|
||||
f"Providing `{name}` when creating a server is deprecated. Provide it when calling `run` or as a global setting instead.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
deprecated_settings[name] = arg
|
||||
|
||||
combined_settings = fastmcp.settings.model_dump() | deprecated_settings
|
||||
self._deprecated_settings = Settings(**combined_settings)
|
||||
|
||||
@property
|
||||
def settings(self) -> Settings:
|
||||
# Deprecated in 2.8.0
|
||||
if fastmcp.settings.deprecation_warnings:
|
||||
warnings.warn(
|
||||
"Accessing `.settings` on a FastMCP instance is deprecated. Use the global `fastmcp.settings` instead.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return self._deprecated_settings
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
return self._mcp_server.name
|
||||
|
|
@ -1530,7 +1401,6 @@ class FastMCP(
|
|||
meta=meta,
|
||||
task=task if task is not None else self._support_tasks_by_default,
|
||||
timeout=timeout,
|
||||
serializer=self._tool_serializer,
|
||||
auth=auth,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ from __future__ import annotations as _annotations
|
|||
|
||||
import inspect
|
||||
import os
|
||||
import warnings
|
||||
from datetime import timedelta
|
||||
from pathlib import Path
|
||||
from typing import Annotated, Any, Literal
|
||||
|
|
@ -115,30 +114,6 @@ class DocketSettings(BaseSettings):
|
|||
] = timedelta(seconds=5)
|
||||
|
||||
|
||||
class ExperimentalSettings(BaseSettings):
|
||||
model_config = SettingsConfigDict(
|
||||
env_prefix="FASTMCP_EXPERIMENTAL_",
|
||||
extra="ignore",
|
||||
validate_assignment=True,
|
||||
)
|
||||
|
||||
# Deprecated in 2.14 - the new OpenAPI parser is now the default and only parser
|
||||
enable_new_openapi_parser: bool = False
|
||||
|
||||
@field_validator("enable_new_openapi_parser", mode="after")
|
||||
@classmethod
|
||||
def _warn_openapi_parser_deprecated(cls, v: bool) -> bool:
|
||||
if v:
|
||||
warnings.warn(
|
||||
"enable_new_openapi_parser is deprecated. "
|
||||
"The new OpenAPI parser is now the default (and only) parser. "
|
||||
"You can remove this setting.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return v
|
||||
|
||||
|
||||
class Settings(BaseSettings):
|
||||
"""FastMCP settings."""
|
||||
|
||||
|
|
@ -191,8 +166,6 @@ class Settings(BaseSettings):
|
|||
return v.upper()
|
||||
return v
|
||||
|
||||
experimental: ExperimentalSettings = ExperimentalSettings()
|
||||
|
||||
docket: DocketSettings = DocketSettings()
|
||||
|
||||
enable_rich_logging: Annotated[
|
||||
|
|
|
|||
|
|
@ -1,68 +1,25 @@
|
|||
"""Tests for deprecated include_tags/exclude_tags parameters."""
|
||||
"""Tests for removed include_tags/exclude_tags parameters."""
|
||||
|
||||
import pytest
|
||||
|
||||
from fastmcp import FastMCP
|
||||
from fastmcp.server.transforms.visibility import Visibility
|
||||
|
||||
|
||||
class TestIncludeExcludeTagsDeprecation:
|
||||
"""Test that include_tags/exclude_tags emit deprecation warnings but still work."""
|
||||
class TestIncludeExcludeTagsRemoved:
|
||||
"""Test that include_tags/exclude_tags raise TypeError with migration hints."""
|
||||
|
||||
def test_exclude_tags_emits_warning(self):
|
||||
"""exclude_tags parameter emits deprecation warning."""
|
||||
with pytest.warns(DeprecationWarning, match="exclude_tags.*deprecated"):
|
||||
def test_exclude_tags_raises_type_error(self):
|
||||
with pytest.raises(TypeError, match="no longer accepts `exclude_tags`"):
|
||||
FastMCP(exclude_tags={"internal"})
|
||||
|
||||
def test_include_tags_emits_warning(self):
|
||||
"""include_tags parameter emits deprecation warning."""
|
||||
with pytest.warns(DeprecationWarning, match="include_tags.*deprecated"):
|
||||
def test_include_tags_raises_type_error(self):
|
||||
with pytest.raises(TypeError, match="no longer accepts `include_tags`"):
|
||||
FastMCP(include_tags={"public"})
|
||||
|
||||
def test_exclude_tags_still_works(self):
|
||||
"""exclude_tags adds a Visibility transform that disables matching tags."""
|
||||
with pytest.warns(DeprecationWarning):
|
||||
mcp = FastMCP(exclude_tags={"internal"})
|
||||
def test_exclude_tags_error_mentions_disable(self):
|
||||
with pytest.raises(TypeError, match="server.disable"):
|
||||
FastMCP(exclude_tags={"internal"})
|
||||
|
||||
# Should have added a Visibility transform that disables the tag
|
||||
enabled_transforms = [t for t in mcp._transforms if isinstance(t, Visibility)]
|
||||
assert len(enabled_transforms) == 1
|
||||
e = enabled_transforms[0]
|
||||
assert e._enabled is False
|
||||
assert e.tags == {"internal"}
|
||||
|
||||
def test_include_tags_still_works(self):
|
||||
"""include_tags adds Visibility transforms for allowlist mode."""
|
||||
with pytest.warns(DeprecationWarning):
|
||||
mcp = FastMCP(include_tags={"public"})
|
||||
|
||||
# Should have added Visibility transforms for allowlist mode
|
||||
# (one to disable all, one to enable matching)
|
||||
enabled_transforms = [t for t in mcp._transforms if isinstance(t, Visibility)]
|
||||
assert len(enabled_transforms) == 2
|
||||
|
||||
# First should disable all (Visibility.all(False))
|
||||
disable_all_transform = enabled_transforms[0]
|
||||
assert disable_all_transform._enabled is False
|
||||
assert disable_all_transform.match_all is True
|
||||
|
||||
# Second should enable matching tags
|
||||
enable_transform = enabled_transforms[1]
|
||||
assert enable_transform._enabled is True
|
||||
assert enable_transform.tags == {"public"}
|
||||
|
||||
def test_exclude_and_include_both_create_transforms(self):
|
||||
"""exclude_tags and include_tags both create transforms."""
|
||||
with pytest.warns(DeprecationWarning):
|
||||
mcp = FastMCP(include_tags={"public"}, exclude_tags={"deprecated"})
|
||||
|
||||
# Should have added transforms for both
|
||||
# include_tags creates 2 (disable all + enable matching)
|
||||
# exclude_tags creates 1 (disable matching)
|
||||
enabled_transforms = [t for t in mcp._transforms if isinstance(t, Visibility)]
|
||||
assert len(enabled_transforms) == 3
|
||||
|
||||
# Check we have both tag rules
|
||||
tags_in_transforms = [t.tags for t in enabled_transforms if t.tags]
|
||||
assert {"public"} in tags_in_transforms
|
||||
assert {"deprecated"} in tags_in_transforms
|
||||
def test_include_tags_error_mentions_enable(self):
|
||||
with pytest.raises(TypeError, match="server.enable"):
|
||||
FastMCP(include_tags={"public"})
|
||||
|
|
|
|||
|
|
@ -68,37 +68,12 @@ class TestAddToolTransformationDeprecated:
|
|||
assert "remove_tool_transformation is deprecated" in str(w[0].message)
|
||||
assert "no effect" in str(w[0].message)
|
||||
|
||||
async def test_tool_transformations_constructor_emits_warning(self):
|
||||
"""tool_transformations constructor param should emit deprecation warning."""
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter("always")
|
||||
async def test_tool_transformations_constructor_raises_type_error(self):
|
||||
"""tool_transformations constructor param should raise TypeError."""
|
||||
import pytest
|
||||
|
||||
with pytest.raises(TypeError, match="no longer accepts `tool_transformations`"):
|
||||
FastMCP(
|
||||
"test",
|
||||
tool_transformations={"my_tool": ToolTransformConfig(name="renamed")},
|
||||
)
|
||||
|
||||
assert len(w) == 1
|
||||
assert issubclass(w[0].category, DeprecationWarning)
|
||||
assert "tool_transformations parameter is deprecated" in str(w[0].message)
|
||||
|
||||
async def test_tool_transformations_constructor_still_works(self):
|
||||
"""tool_transformations constructor param should still apply transforms."""
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore", DeprecationWarning)
|
||||
mcp = FastMCP(
|
||||
"test",
|
||||
tool_transformations={
|
||||
"my_tool": ToolTransformConfig(name="renamed_tool")
|
||||
},
|
||||
)
|
||||
|
||||
@mcp.tool
|
||||
def my_tool() -> str:
|
||||
return "result"
|
||||
|
||||
async with Client(mcp) as client:
|
||||
tools = await client.list_tools()
|
||||
tool_names = [t.name for t in tools]
|
||||
|
||||
assert "my_tool" not in tool_names
|
||||
assert "renamed_tool" in tool_names
|
||||
|
|
|
|||
|
|
@ -1,48 +1,23 @@
|
|||
import warnings
|
||||
|
||||
import pytest
|
||||
from starlette.applications import Starlette
|
||||
|
||||
from fastmcp import FastMCP
|
||||
from fastmcp.utilities.tests import temporary_settings
|
||||
|
||||
# reset deprecation warnings for this module
|
||||
pytestmark = pytest.mark.filterwarnings("default::DeprecationWarning")
|
||||
|
||||
|
||||
class TestDeprecationWarningsSetting:
|
||||
def test_deprecation_warnings_setting_true(self):
|
||||
with temporary_settings(deprecation_warnings=True):
|
||||
with pytest.warns(DeprecationWarning) as recorded_warnings:
|
||||
# will warn once for providing deprecated arg
|
||||
mcp = FastMCP(host="1.2.3.4")
|
||||
# will warn once for accessing deprecated property
|
||||
mcp.settings
|
||||
class TestRemovedKwargs:
|
||||
def test_host_kwarg_raises_type_error(self):
|
||||
with pytest.raises(TypeError, match="no longer accepts `host`"):
|
||||
FastMCP(host="1.2.3.4")
|
||||
|
||||
assert len(recorded_warnings) == 2
|
||||
|
||||
def test_deprecation_warnings_setting_false(self):
|
||||
with temporary_settings(deprecation_warnings=False):
|
||||
# will error if a warning is raised
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("error")
|
||||
# will warn once for providing deprecated arg
|
||||
mcp = FastMCP(host="1.2.3.4")
|
||||
# will warn once for accessing deprecated property
|
||||
mcp.settings
|
||||
def test_settings_property_removed(self):
|
||||
mcp = FastMCP()
|
||||
assert not hasattr(mcp, "_deprecated_settings")
|
||||
with pytest.raises(AttributeError):
|
||||
mcp.settings # noqa: B018 # ty: ignore[unresolved-attribute]
|
||||
|
||||
|
||||
def test_http_app_with_sse_transport():
|
||||
"""Test that http_app with SSE transport works (no warning)."""
|
||||
"""Test that http_app with SSE transport works."""
|
||||
server = FastMCP("TestServer")
|
||||
|
||||
# This should not raise a warning since we're using the new API
|
||||
with warnings.catch_warnings(record=True) as recorded_warnings:
|
||||
app = server.http_app(transport="sse")
|
||||
assert isinstance(app, Starlette)
|
||||
|
||||
# Verify no deprecation warnings were raised for using transport parameter
|
||||
deprecation_warnings = [
|
||||
w for w in recorded_warnings if issubclass(w.category, DeprecationWarning)
|
||||
]
|
||||
assert len(deprecation_warnings) == 0
|
||||
app = server.http_app(transport="sse")
|
||||
assert isinstance(app, Starlette)
|
||||
|
|
|
|||
|
|
@ -5,34 +5,9 @@ import warnings
|
|||
|
||||
import pytest
|
||||
|
||||
import fastmcp
|
||||
|
||||
pytestmark = pytest.mark.filterwarnings("default::DeprecationWarning")
|
||||
|
||||
|
||||
class TestEnableNewOpenAPIParserDeprecation:
|
||||
"""Test enable_new_openapi_parser setting deprecation."""
|
||||
|
||||
def test_setting_true_emits_warning(self):
|
||||
"""Setting enable_new_openapi_parser=True should emit deprecation warning."""
|
||||
with pytest.warns(
|
||||
DeprecationWarning,
|
||||
match=r"enable_new_openapi_parser is deprecated.*now the default",
|
||||
):
|
||||
fastmcp.settings.experimental.enable_new_openapi_parser = True
|
||||
|
||||
def test_setting_false_no_warning(self):
|
||||
"""Setting enable_new_openapi_parser=False should not emit warning."""
|
||||
with warnings.catch_warnings(record=True) as recorded:
|
||||
warnings.simplefilter("always")
|
||||
fastmcp.settings.experimental.enable_new_openapi_parser = False
|
||||
|
||||
deprecation_warnings = [
|
||||
w for w in recorded if issubclass(w.category, DeprecationWarning)
|
||||
]
|
||||
assert len(deprecation_warnings) == 0
|
||||
|
||||
|
||||
class TestExperimentalOpenAPIImportDeprecation:
|
||||
"""Test experimental OpenAPI import path deprecations."""
|
||||
|
||||
|
|
|
|||
|
|
@ -1,319 +1,64 @@
|
|||
import warnings
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
from fastmcp import FastMCP
|
||||
|
||||
# reset deprecation warnings for this module
|
||||
pytestmark = pytest.mark.filterwarnings("default::DeprecationWarning")
|
||||
|
||||
class TestRemovedServerInitKwargs:
|
||||
"""Test that removed server initialization keyword arguments raise TypeError."""
|
||||
|
||||
class TestDeprecatedServerInitKwargs:
|
||||
"""Test deprecated server initialization keyword arguments."""
|
||||
@pytest.mark.parametrize(
|
||||
"kwarg, value, expected_message",
|
||||
[
|
||||
("host", "0.0.0.0", "run_http_async"),
|
||||
("port", 8080, "run_http_async"),
|
||||
("sse_path", "/custom-sse", "FASTMCP_SSE_PATH"),
|
||||
("message_path", "/custom-message", "FASTMCP_MESSAGE_PATH"),
|
||||
("streamable_http_path", "/custom-http", "run_http_async"),
|
||||
("json_response", True, "run_http_async"),
|
||||
("stateless_http", True, "run_http_async"),
|
||||
("debug", True, "FASTMCP_DEBUG"),
|
||||
("log_level", "DEBUG", "run_http_async"),
|
||||
("on_duplicate_tools", "warn", "on_duplicate="),
|
||||
("on_duplicate_resources", "error", "on_duplicate="),
|
||||
("on_duplicate_prompts", "replace", "on_duplicate="),
|
||||
("tool_serializer", lambda x: str(x), "ToolResult"),
|
||||
("include_tags", {"public"}, "server.enable"),
|
||||
("exclude_tags", {"internal"}, "server.disable"),
|
||||
(
|
||||
"tool_transformations",
|
||||
{"my_tool": {"name": "renamed"}},
|
||||
"server.add_transform",
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_removed_kwarg_raises_type_error(self, kwarg, value, expected_message):
|
||||
with pytest.raises(TypeError, match=f"no longer accepts `{kwarg}`"):
|
||||
FastMCP("TestServer", **{kwarg: value})
|
||||
|
||||
def test_log_level_deprecation_warning(self):
|
||||
"""Test that log_level raises a deprecation warning."""
|
||||
with pytest.warns(
|
||||
DeprecationWarning,
|
||||
match=r"Providing `log_level` when creating a server is deprecated\. Provide it when calling `run` or as a global setting instead\.",
|
||||
):
|
||||
server = FastMCP("TestServer", log_level="DEBUG")
|
||||
@pytest.mark.parametrize(
|
||||
"kwarg, value, expected_message",
|
||||
[
|
||||
("host", "0.0.0.0", "run_http_async"),
|
||||
("on_duplicate_tools", "warn", "on_duplicate="),
|
||||
("include_tags", {"public"}, "server.enable"),
|
||||
],
|
||||
)
|
||||
def test_removed_kwarg_error_includes_migration_hint(
|
||||
self, kwarg, value, expected_message
|
||||
):
|
||||
with pytest.raises(TypeError, match=expected_message):
|
||||
FastMCP("TestServer", **{kwarg: value})
|
||||
|
||||
# Verify the setting is still applied
|
||||
assert server._deprecated_settings.log_level == "DEBUG"
|
||||
def test_unknown_kwarg_raises_standard_type_error(self):
|
||||
with pytest.raises(TypeError, match="unexpected keyword argument"):
|
||||
FastMCP("TestServer", **{"totally_fake_param": True}) # ty: ignore[invalid-argument-type]
|
||||
|
||||
def test_debug_deprecation_warning(self):
|
||||
"""Test that debug raises a deprecation warning."""
|
||||
with pytest.warns(
|
||||
DeprecationWarning,
|
||||
match=r"Providing `debug` when creating a server is deprecated\. Provide it when calling `run` or as a global setting instead\.",
|
||||
):
|
||||
server = FastMCP("TestServer", debug=True)
|
||||
|
||||
# Verify the setting is still applied
|
||||
assert server._deprecated_settings.debug is True
|
||||
|
||||
def test_host_deprecation_warning(self):
|
||||
"""Test that host raises a deprecation warning."""
|
||||
with pytest.warns(
|
||||
DeprecationWarning,
|
||||
match=r"Providing `host` when creating a server is deprecated\. Provide it when calling `run` or as a global setting instead\.",
|
||||
):
|
||||
server = FastMCP("TestServer", host="0.0.0.0")
|
||||
|
||||
# Verify the setting is still applied
|
||||
assert server._deprecated_settings.host == "0.0.0.0"
|
||||
|
||||
def test_port_deprecation_warning(self):
|
||||
"""Test that port raises a deprecation warning."""
|
||||
with pytest.warns(
|
||||
DeprecationWarning,
|
||||
match=r"Providing `port` when creating a server is deprecated\. Provide it when calling `run` or as a global setting instead\.",
|
||||
):
|
||||
server = FastMCP("TestServer", port=8080)
|
||||
|
||||
# Verify the setting is still applied
|
||||
assert server._deprecated_settings.port == 8080
|
||||
|
||||
def test_sse_path_deprecation_warning(self):
|
||||
"""Test that sse_path raises a deprecation warning."""
|
||||
with pytest.warns(
|
||||
DeprecationWarning,
|
||||
match=r"Providing `sse_path` when creating a server is deprecated\. Provide it when calling `run` or as a global setting instead\.",
|
||||
):
|
||||
server = FastMCP("TestServer", sse_path="/custom-sse")
|
||||
|
||||
# Verify the setting is still applied
|
||||
assert server._deprecated_settings.sse_path == "/custom-sse"
|
||||
|
||||
def test_message_path_deprecation_warning(self):
|
||||
"""Test that message_path raises a deprecation warning."""
|
||||
with pytest.warns(
|
||||
DeprecationWarning,
|
||||
match=r"Providing `message_path` when creating a server is deprecated\. Provide it when calling `run` or as a global setting instead\.",
|
||||
):
|
||||
server = FastMCP("TestServer", message_path="/custom-message")
|
||||
|
||||
# Verify the setting is still applied
|
||||
assert server._deprecated_settings.message_path == "/custom-message"
|
||||
|
||||
def test_streamable_http_path_deprecation_warning(self):
|
||||
"""Test that streamable_http_path raises a deprecation warning."""
|
||||
with pytest.warns(
|
||||
DeprecationWarning,
|
||||
match=r"Providing `streamable_http_path` when creating a server is deprecated\. Provide it when calling `run` or as a global setting instead\.",
|
||||
):
|
||||
server = FastMCP("TestServer", streamable_http_path="/custom-http")
|
||||
|
||||
# Verify the setting is still applied
|
||||
assert server._deprecated_settings.streamable_http_path == "/custom-http"
|
||||
|
||||
def test_json_response_deprecation_warning(self):
|
||||
"""Test that json_response raises a deprecation warning."""
|
||||
with pytest.warns(
|
||||
DeprecationWarning,
|
||||
match=r"Providing `json_response` when creating a server is deprecated\. Provide it when calling `run` or as a global setting instead\.",
|
||||
):
|
||||
server = FastMCP("TestServer", json_response=True)
|
||||
|
||||
# Verify the setting is still applied
|
||||
assert server._deprecated_settings.json_response is True
|
||||
|
||||
def test_stateless_http_deprecation_warning(self):
|
||||
"""Test that stateless_http raises a deprecation warning."""
|
||||
with pytest.warns(
|
||||
DeprecationWarning,
|
||||
match=r"Providing `stateless_http` when creating a server is deprecated\. Provide it when calling `run` or as a global setting instead\.",
|
||||
):
|
||||
server = FastMCP("TestServer", stateless_http=True)
|
||||
|
||||
# Verify the setting is still applied
|
||||
assert server._deprecated_settings.stateless_http is True
|
||||
|
||||
def test_multiple_deprecated_kwargs_warnings(self):
|
||||
"""Test that multiple deprecated kwargs each raise their own warning."""
|
||||
with warnings.catch_warnings(record=True) as recorded_warnings:
|
||||
warnings.simplefilter("always")
|
||||
server = FastMCP(
|
||||
"TestServer",
|
||||
log_level="INFO",
|
||||
debug=False,
|
||||
host="127.0.0.1",
|
||||
port=9999,
|
||||
sse_path="/sse/",
|
||||
message_path="/msg",
|
||||
streamable_http_path="/http",
|
||||
json_response=False,
|
||||
stateless_http=False,
|
||||
)
|
||||
|
||||
# Should have 9 deprecation warnings (one for each deprecated parameter)
|
||||
deprecation_warnings = [
|
||||
w for w in recorded_warnings if issubclass(w.category, DeprecationWarning)
|
||||
]
|
||||
assert len(deprecation_warnings) == 9
|
||||
|
||||
# Verify all expected parameters are mentioned in warnings
|
||||
expected_params = {
|
||||
"log_level",
|
||||
"debug",
|
||||
"host",
|
||||
"port",
|
||||
"sse_path",
|
||||
"message_path",
|
||||
"streamable_http_path",
|
||||
"json_response",
|
||||
"stateless_http",
|
||||
}
|
||||
mentioned_params = set()
|
||||
for warning in deprecation_warnings:
|
||||
message = str(warning.message)
|
||||
for param in expected_params:
|
||||
if f"Providing `{param}`" in message:
|
||||
mentioned_params.add(param)
|
||||
|
||||
assert mentioned_params == expected_params
|
||||
|
||||
# Verify all settings are still applied
|
||||
assert server._deprecated_settings.log_level == "INFO"
|
||||
assert server._deprecated_settings.debug is False
|
||||
assert server._deprecated_settings.host == "127.0.0.1"
|
||||
assert server._deprecated_settings.port == 9999
|
||||
assert server._deprecated_settings.sse_path == "/sse/"
|
||||
assert server._deprecated_settings.message_path == "/msg"
|
||||
assert server._deprecated_settings.streamable_http_path == "/http"
|
||||
assert server._deprecated_settings.json_response is False
|
||||
assert server._deprecated_settings.stateless_http is False
|
||||
|
||||
def test_non_deprecated_kwargs_no_warnings(self):
|
||||
"""Test that non-deprecated kwargs don't raise warnings."""
|
||||
with warnings.catch_warnings(record=True) as recorded_warnings:
|
||||
warnings.simplefilter("always")
|
||||
server = FastMCP(
|
||||
name="TestServer",
|
||||
instructions="Test instructions",
|
||||
on_duplicate="warn", # New unified parameter
|
||||
mask_error_details=True,
|
||||
)
|
||||
|
||||
# Should have no deprecation warnings
|
||||
deprecation_warnings = [
|
||||
w for w in recorded_warnings if issubclass(w.category, DeprecationWarning)
|
||||
]
|
||||
assert len(deprecation_warnings) == 0
|
||||
|
||||
# Verify server was created successfully
|
||||
def test_valid_kwargs_still_work(self):
|
||||
server = FastMCP(
|
||||
name="TestServer",
|
||||
instructions="Test instructions",
|
||||
on_duplicate="warn",
|
||||
mask_error_details=True,
|
||||
)
|
||||
assert server.name == "TestServer"
|
||||
assert server.instructions == "Test instructions"
|
||||
|
||||
def test_deprecated_duplicate_kwargs_raise_warnings(self):
|
||||
"""Test that deprecated on_duplicate_* kwargs raise warnings."""
|
||||
with warnings.catch_warnings(record=True) as recorded_warnings:
|
||||
warnings.simplefilter("always")
|
||||
FastMCP(
|
||||
name="TestServer",
|
||||
on_duplicate_tools="warn",
|
||||
on_duplicate_resources="error",
|
||||
on_duplicate_prompts="replace",
|
||||
)
|
||||
|
||||
# Should have 3 deprecation warnings (one for each deprecated param)
|
||||
deprecation_warnings = [
|
||||
w for w in recorded_warnings if issubclass(w.category, DeprecationWarning)
|
||||
]
|
||||
assert len(deprecation_warnings) == 3
|
||||
|
||||
# Check warning messages
|
||||
warning_messages = [str(w.message) for w in deprecation_warnings]
|
||||
assert any("on_duplicate_tools" in msg for msg in warning_messages)
|
||||
assert any("on_duplicate_resources" in msg for msg in warning_messages)
|
||||
assert any("on_duplicate_prompts" in msg for msg in warning_messages)
|
||||
|
||||
def test_none_values_no_warnings(self):
|
||||
"""Test that None values for deprecated kwargs don't raise warnings."""
|
||||
with warnings.catch_warnings(record=True) as recorded_warnings:
|
||||
warnings.simplefilter("always")
|
||||
FastMCP(
|
||||
"TestServer",
|
||||
log_level=None,
|
||||
debug=None,
|
||||
host=None,
|
||||
port=None,
|
||||
sse_path=None,
|
||||
message_path=None,
|
||||
streamable_http_path=None,
|
||||
json_response=None,
|
||||
stateless_http=None,
|
||||
)
|
||||
|
||||
# Should have no deprecation warnings for None values
|
||||
deprecation_warnings = [
|
||||
w for w in recorded_warnings if issubclass(w.category, DeprecationWarning)
|
||||
]
|
||||
assert len(deprecation_warnings) == 0
|
||||
|
||||
def test_deprecated_settings_inheritance_from_global(self):
|
||||
"""Test that deprecated settings inherit from global settings when not provided."""
|
||||
# Mock fastmcp.settings to test inheritance
|
||||
with patch("fastmcp.settings") as mock_settings:
|
||||
mock_settings.model_dump.return_value = {
|
||||
"log_level": "WARNING",
|
||||
"debug": True,
|
||||
"host": "0.0.0.0",
|
||||
"port": 3000,
|
||||
"sse_path": "/events",
|
||||
"message_path": "/messages",
|
||||
"streamable_http_path": "/stream",
|
||||
"json_response": True,
|
||||
"stateless_http": True,
|
||||
}
|
||||
|
||||
server = FastMCP("TestServer")
|
||||
|
||||
# Verify settings are inherited from global settings
|
||||
assert server._deprecated_settings.log_level == "WARNING"
|
||||
assert server._deprecated_settings.debug is True
|
||||
assert server._deprecated_settings.host == "0.0.0.0"
|
||||
assert server._deprecated_settings.port == 3000
|
||||
assert server._deprecated_settings.sse_path == "/events"
|
||||
assert server._deprecated_settings.message_path == "/messages"
|
||||
assert server._deprecated_settings.streamable_http_path == "/stream"
|
||||
assert server._deprecated_settings.json_response is True
|
||||
assert server._deprecated_settings.stateless_http is True
|
||||
|
||||
def test_deprecated_settings_override_global(self):
|
||||
"""Test that deprecated settings override global settings when provided."""
|
||||
# Mock fastmcp.settings to test override behavior
|
||||
with patch("fastmcp.settings") as mock_settings:
|
||||
mock_settings.model_dump.return_value = {
|
||||
"log_level": "WARNING",
|
||||
"debug": True,
|
||||
"host": "0.0.0.0",
|
||||
"port": 3000,
|
||||
"sse_path": "/events",
|
||||
"message_path": "/messages",
|
||||
"streamable_http_path": "/stream",
|
||||
"json_response": True,
|
||||
"stateless_http": True,
|
||||
}
|
||||
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore") # Ignore warnings for this test
|
||||
server = FastMCP(
|
||||
"TestServer",
|
||||
log_level="ERROR",
|
||||
debug=False,
|
||||
host="127.0.0.1",
|
||||
port=8080,
|
||||
)
|
||||
|
||||
# Verify provided settings override global settings
|
||||
assert server._deprecated_settings.log_level == "ERROR"
|
||||
assert server._deprecated_settings.debug is False
|
||||
assert server._deprecated_settings.host == "127.0.0.1"
|
||||
assert server._deprecated_settings.port == 8080
|
||||
# Non-overridden settings should still come from global
|
||||
assert server._deprecated_settings.sse_path == "/events"
|
||||
assert server._deprecated_settings.message_path == "/messages"
|
||||
assert server._deprecated_settings.streamable_http_path == "/stream"
|
||||
assert server._deprecated_settings.json_response is True
|
||||
assert server._deprecated_settings.stateless_http is True
|
||||
|
||||
def test_stacklevel_points_to_constructor_call(self):
|
||||
"""Test that deprecation warnings point to the FastMCP constructor call."""
|
||||
with warnings.catch_warnings(record=True) as recorded_warnings:
|
||||
warnings.simplefilter("always")
|
||||
|
||||
FastMCP("TestServer", log_level="DEBUG")
|
||||
|
||||
# Should have exactly one deprecation warning
|
||||
deprecation_warnings = [
|
||||
w for w in recorded_warnings if issubclass(w.category, DeprecationWarning)
|
||||
]
|
||||
assert len(deprecation_warnings) == 1
|
||||
|
||||
# The warning should point to the server.py file where FastMCP.__init__ is called
|
||||
# This verifies the stacklevel is working as intended (pointing to constructor)
|
||||
warning = deprecation_warnings[0]
|
||||
assert "server.py" in warning.filename
|
||||
|
|
|
|||
|
|
@ -143,15 +143,14 @@ class TestSerializerDeprecationWarnings:
|
|||
with pytest.warns(DeprecationWarning, match="serializer.*deprecated"):
|
||||
provider.tool(my_tool, serializer=custom_serializer)
|
||||
|
||||
def test_fastmcp_tool_serializer_parameter_warning(self):
|
||||
"""Test that FastMCP tool_serializer parameter warns."""
|
||||
def test_fastmcp_tool_serializer_parameter_raises_type_error(self):
|
||||
"""Test that FastMCP tool_serializer parameter raises TypeError."""
|
||||
|
||||
def custom_serializer(data) -> str:
|
||||
return f"Custom: {data}"
|
||||
|
||||
with temporary_settings(deprecation_warnings=True):
|
||||
with pytest.warns(DeprecationWarning, match="tool_serializer.*deprecated"):
|
||||
FastMCP("TestServer", tool_serializer=custom_serializer)
|
||||
with pytest.raises(TypeError, match="no longer accepts `tool_serializer`"):
|
||||
FastMCP("TestServer", tool_serializer=custom_serializer)
|
||||
|
||||
def test_transformed_tool_from_tool_serializer_warning(self):
|
||||
"""Test that TransformedTool.from_tool warns when serializer is provided."""
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@ class TestParentTagFiltering:
|
|||
|
||||
async def test_parent_include_tags_filters_mounted_tools(self):
|
||||
"""Test that parent include_tags filters out non-matching mounted tools."""
|
||||
parent = FastMCP("Parent", include_tags={"allowed"})
|
||||
parent = FastMCP("Parent")
|
||||
parent.enable(tags={"allowed"}, only=True)
|
||||
mounted = FastMCP("Mounted")
|
||||
|
||||
@mounted.tool(tags={"allowed"})
|
||||
|
|
@ -38,7 +39,8 @@ class TestParentTagFiltering:
|
|||
|
||||
async def test_parent_exclude_tags_filters_mounted_tools(self):
|
||||
"""Test that parent exclude_tags filters out matching mounted tools."""
|
||||
parent = FastMCP("Parent", exclude_tags={"blocked"})
|
||||
parent = FastMCP("Parent")
|
||||
parent.disable(tags={"blocked"})
|
||||
mounted = FastMCP("Mounted")
|
||||
|
||||
@mounted.tool(tags={"production"})
|
||||
|
|
@ -58,7 +60,8 @@ class TestParentTagFiltering:
|
|||
|
||||
async def test_parent_filters_apply_to_mounted_resources(self):
|
||||
"""Test that parent tag filters apply to mounted resources."""
|
||||
parent = FastMCP("Parent", include_tags={"allowed"})
|
||||
parent = FastMCP("Parent")
|
||||
parent.enable(tags={"allowed"}, only=True)
|
||||
mounted = FastMCP("Mounted")
|
||||
|
||||
@mounted.resource("resource://allowed", tags={"allowed"})
|
||||
|
|
@ -78,7 +81,8 @@ class TestParentTagFiltering:
|
|||
|
||||
async def test_parent_filters_apply_to_mounted_prompts(self):
|
||||
"""Test that parent tag filters apply to mounted prompts."""
|
||||
parent = FastMCP("Parent", exclude_tags={"blocked"})
|
||||
parent = FastMCP("Parent")
|
||||
parent.disable(tags={"blocked"})
|
||||
mounted = FastMCP("Mounted")
|
||||
|
||||
@mounted.prompt(tags={"allowed"})
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ class PersonDataclass:
|
|||
|
||||
class TestToolTags:
|
||||
def create_server(self, include_tags=None, exclude_tags=None):
|
||||
mcp = FastMCP(include_tags=include_tags, exclude_tags=exclude_tags)
|
||||
mcp = FastMCP()
|
||||
|
||||
@mcp.tool(tags={"a", "b"})
|
||||
def tool_1() -> int:
|
||||
|
|
@ -50,6 +50,11 @@ class TestToolTags:
|
|||
def tool_2() -> int:
|
||||
return 2
|
||||
|
||||
if include_tags:
|
||||
mcp.enable(tags=include_tags, only=True)
|
||||
if exclude_tags:
|
||||
mcp.disable(tags=exclude_tags)
|
||||
|
||||
return mcp
|
||||
|
||||
async def test_include_tags_all_tools(self):
|
||||
|
|
|
|||
|
|
@ -415,7 +415,7 @@ class TestPromptEnabled:
|
|||
|
||||
class TestPromptTags:
|
||||
def create_server(self, include_tags=None, exclude_tags=None):
|
||||
mcp = FastMCP(include_tags=include_tags, exclude_tags=exclude_tags)
|
||||
mcp = FastMCP()
|
||||
|
||||
@mcp.prompt(tags={"a", "b"})
|
||||
def prompt_1() -> str:
|
||||
|
|
@ -425,6 +425,11 @@ class TestPromptTags:
|
|||
def prompt_2() -> str:
|
||||
return "2"
|
||||
|
||||
if include_tags:
|
||||
mcp.enable(tags=include_tags, only=True)
|
||||
if exclude_tags:
|
||||
mcp.disable(tags=exclude_tags)
|
||||
|
||||
return mcp
|
||||
|
||||
async def test_include_tags_all_prompts(self):
|
||||
|
|
|
|||
|
|
@ -676,7 +676,7 @@ class TestTemplateDecorator:
|
|||
|
||||
class TestResourceTags:
|
||||
def create_server(self, include_tags=None, exclude_tags=None):
|
||||
mcp = FastMCP(include_tags=include_tags, exclude_tags=exclude_tags)
|
||||
mcp = FastMCP()
|
||||
|
||||
@mcp.resource("resource://1", tags={"a", "b"})
|
||||
def resource_1() -> str:
|
||||
|
|
@ -686,6 +686,11 @@ class TestResourceTags:
|
|||
def resource_2() -> str:
|
||||
return "2"
|
||||
|
||||
if include_tags:
|
||||
mcp.enable(tags=include_tags, only=True)
|
||||
if exclude_tags:
|
||||
mcp.disable(tags=exclude_tags)
|
||||
|
||||
return mcp
|
||||
|
||||
async def test_include_tags_all_resources(self):
|
||||
|
|
@ -823,7 +828,7 @@ class TestResourceEnabled:
|
|||
|
||||
class TestResourceTemplatesTags:
|
||||
def create_server(self, include_tags=None, exclude_tags=None):
|
||||
mcp = FastMCP(include_tags=include_tags, exclude_tags=exclude_tags)
|
||||
mcp = FastMCP()
|
||||
|
||||
@mcp.resource("resource://1/{param}", tags={"a", "b"})
|
||||
def template_resource_1(param: str) -> str:
|
||||
|
|
@ -833,6 +838,11 @@ class TestResourceTemplatesTags:
|
|||
def template_resource_2(param: str) -> str:
|
||||
return f"Template resource 2: {param}"
|
||||
|
||||
if include_tags:
|
||||
mcp.enable(tags=include_tags, only=True)
|
||||
if exclude_tags:
|
||||
mcp.disable(tags=exclude_tags)
|
||||
|
||||
return mcp
|
||||
|
||||
async def test_include_tags_all_resources(self):
|
||||
|
|
|
|||
|
|
@ -211,9 +211,9 @@ class TestAbstractCollectionTypes:
|
|||
"test",
|
||||
middleware=(), # Empty tuple
|
||||
tools=(Tool.from_function(dummy_tool),), # Tuple of tools
|
||||
include_tags={"tag1", "tag2"}, # Set
|
||||
exclude_tags={"tag3"}, # Set
|
||||
)
|
||||
mcp.enable(tags={"tag1", "tag2"}, only=True)
|
||||
mcp.disable(tags={"tag3"})
|
||||
assert mcp is not None
|
||||
assert mcp.name == "test"
|
||||
assert isinstance(mcp.middleware, list) # Should be converted to list
|
||||
|
|
|
|||
|
|
@ -281,10 +281,8 @@ class TestGetFastMCPInfo:
|
|||
components weren't actually available to clients.
|
||||
"""
|
||||
# Create server with include_tags that will filter out untagged components
|
||||
mcp = FastMCP(
|
||||
"FilteredServer",
|
||||
include_tags={"fetch", "analyze", "create"},
|
||||
)
|
||||
mcp = FastMCP("FilteredServer")
|
||||
mcp.enable(tags={"fetch", "analyze", "create"}, only=True)
|
||||
|
||||
# Add tools with and without matching tags
|
||||
@mcp.tool(tags={"fetch"})
|
||||
|
|
@ -396,7 +394,8 @@ class TestGetFastMCPInfo:
|
|||
return [{"role": "user", "content": "blocked"}]
|
||||
|
||||
# Create parent server with tag filtering
|
||||
parent = FastMCP("ParentServer", include_tags={"allowed"})
|
||||
parent = FastMCP("ParentServer")
|
||||
parent.enable(tags={"allowed"}, only=True)
|
||||
parent.mount(mounted)
|
||||
|
||||
# Get inspect info
|
||||
|
|
@ -448,7 +447,8 @@ class TestGetFastMCPInfo:
|
|||
return "untagged"
|
||||
|
||||
# Create parent with exclude_tags - should filter mounted components
|
||||
parent = FastMCP("ParentServer", exclude_tags={"development"})
|
||||
parent = FastMCP("ParentServer")
|
||||
parent.disable(tags={"development"})
|
||||
parent.mount(mounted)
|
||||
|
||||
# Get inspect info
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue