mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-22 13:34:17 +02:00
Trim fastmcp.types to FastMCP-unique types only
fastmcp.types re-exported 29 mcp_types symbols verbatim, which was pointless indirection users had to discover. It now holds only Textarea, the one type FastMCP actually defines; everything else imports from mcp_types directly. These mirrors were added during unreleased SDK v2 migration work and never shipped, so this is not a breaking change.
This commit is contained in:
parent
9d9bf2b717
commit
e32a2098f9
22 changed files with 60 additions and 165 deletions
|
|
@ -1426,7 +1426,7 @@ Prompt functions now use `Message` instead of `mcp.types.PromptMessage`:
|
|||
|
||||
```python
|
||||
# v2.x
|
||||
from fastmcp.types import PromptMessage, TextContent
|
||||
from mcp_types import PromptMessage, TextContent
|
||||
|
||||
@mcp.prompt
|
||||
def my_prompt() -> PromptMessage:
|
||||
|
|
|
|||
|
|
@ -28,9 +28,13 @@ The `mcp.types` module no longer exists. Any `from mcp.types import X` or `impor
|
|||
|
||||
### `fastmcp.types` is the stable home — Bridged
|
||||
|
||||
<Note>
|
||||
Superseded before release — see "`fastmcp.types` trimmed to FastMCP-unique types only" below. This section documents the re-export set as it existed mid-migration; none of it ever shipped.
|
||||
</Note>
|
||||
|
||||
FastMCP re-exports the protocol types users are most likely to touch from `fastmcp.types`, sourced from `mcp_types` (the `mcp` root package lacks most of them):
|
||||
|
||||
```python
|
||||
```python test="skip"
|
||||
from fastmcp.types import TextContent, Tool, ToolAnnotations, ErrorData
|
||||
```
|
||||
|
||||
|
|
@ -38,6 +42,18 @@ The re-export set is deliberately limited to names that trace to a documented us
|
|||
|
||||
*Verify:* `fastmcp_slim/fastmcp/types.py` `__all__`.
|
||||
|
||||
### `fastmcp.types` trimmed to FastMCP-unique types only — Absorbed (post-review cleanup)
|
||||
|
||||
The re-export set above never shipped in a release, so it was cut before 4.0 rather than deprecated. `fastmcp.types` now holds only types FastMCP defines itself — `Textarea` — and every bare `mcp_types` mirror (`TextContent`, `Tool`, `ToolAnnotations`, `ErrorData`, and the rest of the 29-name list) is gone. Code that imported those from `fastmcp.types` now imports them from `mcp_types` directly:
|
||||
|
||||
```python
|
||||
from mcp_types import TextContent, Tool, ToolAnnotations, ErrorData
|
||||
```
|
||||
|
||||
Because `fastmcp.types.__all__` was `["Textarea"]` as of the last stable release (v3.4.4) and the mirrors were added only in this unreleased migration work, removing them breaks no released user — there is no bridge or deprecation warning to write.
|
||||
|
||||
*Verify:* `fastmcp_slim/fastmcp/types.py` `__all__` (back down to `["Textarea"]`).
|
||||
|
||||
### camelCase field reads are bridged — Bridged (deprecated)
|
||||
|
||||
Objects FastMCP hands back — results of `client.list_tools()`, `client.call_tool_mcp()`, `client.read_resource()`, and the parameter objects passed to sampling and elicitation handlers — are SDK v2 objects with snake_case fields. A compatibility bridge installed at import time routes the old camelCase names to their snake_case fields, warning once per read:
|
||||
|
|
@ -405,7 +421,7 @@ A FastMCP server can emit SEP-2549 freshness hints so a caching client (`fastmcp
|
|||
|
||||
### Elicitation on the modern protocol (SEP-2322), guard form — New (opt-in feature)
|
||||
|
||||
A tool can gather client input across rounds on a `2026-07-28` call by returning an `InputRequiredResult` (see [Elicitation on the modern protocol](/servers/elicitation#elicitation-on-the-modern-protocol)). Each round is a complete request→response cycle: the tool re-runs per round and reads the client's answers off two new `Context` properties, `ctx.input_responses` (`None` on the first round) and `ctx.request_state` (the echoed opaque state) — thin passthroughs matching the SDK's mcpserver semantics. This is the modern-era elicitation path the earlier per-feature matrix flagged as "MRTR rewrite pending"; it mirrors the SDK's base guard model exactly (tool re-runs, checks whether answers are present, returns to ask for more), with no FastMCP-invented resolver or annotation layer. `fastmcp.types` gains `InputRequiredResult`, `ElicitRequest`, and `ElicitRequestFormParams` for authoring these requests. The `request_state` channel is sealed by the framework, not the author: FastMCP installs the SDK's `RequestStateBoundary` middleware on its low-level server, which seals every outgoing `request_state` and unseals and verifies every inbound echo before a tool runs — so a tool only ever sees plaintext and a tampered, expired, or foreign token is rejected with a frozen wire error. `FastMCP(request_state_security=RequestStateSecurity(keys=[...]))` supplies shared keys for multi-replica deployments; omitted, each process seals under an ephemeral key (correct single-process). Returning this result on a handshake-era (≤ 2025-11-25) connection raises a clear era error naming the mismatch rather than failing as a generic invalid result. The client half (`fastmcp.Client` at `mode="auto"`) drives the loop through its existing elicitation/sampling/roots handlers, capped by `input_required_max_rounds`.
|
||||
A tool can gather client input across rounds on a `2026-07-28` call by returning an `InputRequiredResult` (see [Elicitation on the modern protocol](/servers/elicitation#elicitation-on-the-modern-protocol)). Each round is a complete request→response cycle: the tool re-runs per round and reads the client's answers off two new `Context` properties, `ctx.input_responses` (`None` on the first round) and `ctx.request_state` (the echoed opaque state) — thin passthroughs matching the SDK's mcpserver semantics. This is the modern-era elicitation path the earlier per-feature matrix flagged as "MRTR rewrite pending"; it mirrors the SDK's base guard model exactly (tool re-runs, checks whether answers are present, returns to ask for more), with no FastMCP-invented resolver or annotation layer. For authoring these requests, `InputRequiredResult`, `ElicitRequest`, and `ElicitRequestFormParams` import from `mcp_types`. The `request_state` channel is sealed by the framework, not the author: FastMCP installs the SDK's `RequestStateBoundary` middleware on its low-level server, which seals every outgoing `request_state` and unseals and verifies every inbound echo before a tool runs — so a tool only ever sees plaintext and a tampered, expired, or foreign token is rejected with a frozen wire error. `FastMCP(request_state_security=RequestStateSecurity(keys=[...]))` supplies shared keys for multi-replica deployments; omitted, each process seals under an ephemeral key (correct single-process). Returning this result on a handshake-era (≤ 2025-11-25) connection raises a clear era error naming the mismatch rather than failing as a generic invalid result. The client half (`fastmcp.Client` at `mode="auto"`) drives the loop through its existing elicitation/sampling/roots handlers, capped by `input_required_max_rounds`.
|
||||
|
||||
*Verify:* `fastmcp_slim/fastmcp/server/context.py` (`input_responses`/`request_state` properties), `fastmcp_slim/fastmcp/server/low_level.py` (`RequestStateBoundary` install), `fastmcp_slim/fastmcp/server/server.py` (`request_state_security` param), `fastmcp_slim/fastmcp/server/mixins/mcp_operations.py` (`_on_call_tool` input-required passthrough + era gate), `fastmcp_slim/fastmcp/tools/base.py` (`InputRequiredToolResult`), `tests/server/test_mrtr_guards.py`.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue