mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-09 07:09:11 +02:00
parent
b0d3e653b9
commit
8efa405833
4 changed files with 23 additions and 3 deletions
|
|
@ -6,7 +6,7 @@ This is the complete register of user-facing changes from the MCP Python SDK v2
|
|||
|
||||
Each entry is tagged **Absorbed** (public surface unchanged), **Bridged** (shim keeps old code working, usually warning), **Breaking** (user code must change), or **Deprecated** (works, warns, slated for removal). See the [overview](/development/v4-notes/index) for what each disposition means.
|
||||
|
||||
**Empirical validation (WS2 upgrade reality-check).** The register's compatibility claims are verified, not predicted. Running unchanged 3.x-era code against this branch, all 11 upgrade scenarios pass or warn — the only failures are the two predicted breaks, user `mcp.types` imports and positional `McpError(ErrorData(...))` construction. Cross-version wire interop between a 3.4.3 peer and this branch is bidirectionally clean across 9 operations (3.4.3 client ↔ v4 server and v4 client ↔ 3.4.3 server over HTTP). All 25 `_ALIASES` bridge entries warn correctly with actionable messages.
|
||||
**Empirical validation (WS2 upgrade reality-check).** The register's compatibility claims are verified, not predicted. Running unchanged 3.x-era code against this branch, all 11 upgrade scenarios pass or warn — the only failures are the two predicted breaks, user `mcp.types` imports and positional `McpError(ErrorData(...))` construction. Cross-version wire interop between a 3.4.3 peer and this branch is bidirectionally clean across 9 operations (3.4.3 client ↔ v4 server and v4 client ↔ 3.4.3 server over HTTP). All 29 `_ALIASES` bridge entries warn correctly with actionable messages.
|
||||
|
||||
## Environment
|
||||
|
||||
|
|
@ -68,7 +68,7 @@ async def read_schema():
|
|||
return tools[0].inputSchema # works, warns; prefer .input_schema
|
||||
```
|
||||
|
||||
The bridged fields are exactly those users read, data-driven from an `_ALIASES` table: `inputSchema`/`outputSchema` (Tool); `mimeType` (Resource, ResourceTemplate, TextResourceContents, BlobResourceContents, ImageContent, AudioContent) and `uriTemplate` (ResourceTemplate); `isError`/`structuredContent` (CallToolResult); `hasMore` (Completion); `serverInfo`/`protocolVersion` (InitializeResult); `nextCursor`/`resourceTemplates` (List\*Result); `systemPrompt`/`maxTokens`/`stopSequences`/`modelPreferences`/`toolChoice` (CreateMessageRequestParams); `requestedSchema` (ElicitRequestFormParams). WS2 verified all 25 alias entries warn correctly with actionable messages.
|
||||
The bridged fields are exactly those users read, data-driven from an `_ALIASES` table: `inputSchema`/`outputSchema` (Tool); `readOnlyHint`/`destructiveHint`/`idempotentHint`/`openWorldHint` (ToolAnnotations); `mimeType` (Resource, ResourceTemplate, TextResourceContents, BlobResourceContents, ImageContent, AudioContent) and `uriTemplate` (ResourceTemplate); `isError`/`structuredContent` (CallToolResult); `hasMore` (Completion); `serverInfo`/`protocolVersion` (InitializeResult); `nextCursor`/`resourceTemplates` (List\*Result); `systemPrompt`/`maxTokens`/`stopSequences`/`modelPreferences`/`toolChoice` (CreateMessageRequestParams); `requestedSchema` (ElicitRequestFormParams). WS2 verified all 29 alias entries warn correctly with actionable messages.
|
||||
|
||||
*Verify:* `fastmcp_slim/fastmcp/_compat.py` (the `_ALIASES` table and `install()`).
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ async with Client("my_mcp_server.py") as client:
|
|||
schema = tools[0].inputSchema # still works, warns once
|
||||
```
|
||||
|
||||
Each bridged read emits a `FastMCPDeprecationWarning` pointing you at the snake_case name (`tools[0].input_schema` here). The bridge covers the fields users actually read: `inputSchema`/`outputSchema` on tools, `mimeType` on resources and content, `isError`/`structuredContent` on tool results, `nextCursor` on paginated results, `serverInfo`/`protocolVersion` on the initialize result, the sampling parameter fields (`systemPrompt`, `maxTokens`, `stopSequences`, `modelPreferences`, `toolChoice`), and `requestedSchema` on elicitation parameters.
|
||||
Each bridged read emits a `FastMCPDeprecationWarning` pointing you at the snake_case name (`tools[0].input_schema` here). The bridge covers the fields users actually read: `inputSchema`/`outputSchema` on tools; `readOnlyHint`, `destructiveHint`, `idempotentHint`, and `openWorldHint` on tool annotations; `mimeType` on resources and content; `isError`/`structuredContent` on tool results; `nextCursor` on paginated results; `serverInfo`/`protocolVersion` on the initialize result; the sampling parameter fields (`systemPrompt`, `maxTokens`, `stopSequences`, `modelPreferences`, `toolChoice`); and `requestedSchema` on elicitation parameters.
|
||||
|
||||
The bridge is controlled by the `mcp_camelcase_compat` setting, which defaults to on. Set it to `False` (or the environment variable `FASTMCP_MCP_CAMELCASE_COMPAT=false`) to turn the shims off, in which case only the snake_case names resolve:
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,12 @@ _ALIASES: dict[type, dict[str, str]] = {
|
|||
"inputSchema": "input_schema",
|
||||
"outputSchema": "output_schema",
|
||||
},
|
||||
mcp_types.ToolAnnotations: {
|
||||
"readOnlyHint": "read_only_hint",
|
||||
"destructiveHint": "destructive_hint",
|
||||
"idempotentHint": "idempotent_hint",
|
||||
"openWorldHint": "open_world_hint",
|
||||
},
|
||||
mcp_types.Resource: {
|
||||
"mimeType": "mime_type",
|
||||
},
|
||||
|
|
|
|||
|
|
@ -51,6 +51,20 @@ class TestCamelCaseBridge:
|
|||
with pytest.warns(FastMCPDeprecationWarning):
|
||||
assert tool.outputSchema == {"type": "string"} # ty: ignore[unresolved-attribute]
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("camel", "snake", "value"),
|
||||
[
|
||||
("readOnlyHint", "read_only_hint", True),
|
||||
("destructiveHint", "destructive_hint", False),
|
||||
("idempotentHint", "idempotent_hint", True),
|
||||
("openWorldHint", "open_world_hint", False),
|
||||
],
|
||||
)
|
||||
def test_tool_annotations_bridged(self, camel, snake, value):
|
||||
annotations = mcp_types.ToolAnnotations(**{snake: value})
|
||||
with pytest.warns(FastMCPDeprecationWarning):
|
||||
assert getattr(annotations, camel) is value
|
||||
|
||||
def test_call_tool_result_is_error_bridged(self):
|
||||
result = mcp_types.CallToolResult(content=[], is_error=True)
|
||||
with pytest.warns(FastMCPDeprecationWarning):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue