mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-10-18 19:03:20 +02:00
* fix: don't infer an output schema for unconstrained sequences
`Any` is already excluded from output-schema inference because the schema
it produces constrains nothing. A bare `list` or `tuple` is the
sequence-shaped equivalent: it yields `{"result": {"items": {}, "type":
"array"}}`, which permits every value that no schema at all permits.
Inferring it is not free. An output schema forces structured content, and
`replace_type` cannot suppress the MCP content types inside a sequence
that has no item type to match -- which is why `list[ContentBlock]`
already infers nothing but bare `list` does not. So a tool annotated
`-> list` returning `[ImageContent(...), {...}]`, the shape used to pair
a picture with its metadata, puts the base64 image on the wire twice:
once as an image content block, and once again serialised into
`structuredContent`.
Clients break on that in both directions. Some render the JSON blob
instead of the picture; others inject the duplicated base64 into model
context and blow their tool-output token cap. Server authors currently
work around it per-tool with `output_schema=None`, which also discards
the schema for tools that wanted one.
`list`, `tuple`, `list[Any]` and `tuple[Any, ...]` now infer no schema,
matching `Any`. Annotations that say something about their items --
`list[int]`, `tuple[int, str]`, `dict`, `str` -- are untouched.
Two parametrized sweeps asserted the old bare-`list` schema as one case
among many annotations; `list` is dropped from both, and the new
behaviour gets its own tests including a regression test that a returned
image is not duplicated into `structuredContent`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* tools: catch typing.List, Sequence, and Annotated in the unconstrained-sequence guard
fixed-length tuple[Any, ...] variants keep their schema since they still
pin a length. documents the exception in the tools docs.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0186WjrVNudDm5qaDPw5mntN
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: zzstoatzz <thrast36@gmail.com>
|
||
|---|---|---|
| .. | ||
| auth | ||
| http | ||
| middleware | ||
| mount | ||
| providers | ||
| telemetry | ||
| transforms | ||
| versioning | ||
| __init__.py | ||
| test_app_state.py | ||
| test_auth_integration.py | ||
| test_auth_integration_errors.py | ||
| test_cache_hints.py | ||
| test_call_arguments.py | ||
| test_completions.py | ||
| test_context.py | ||
| test_dependencies.py | ||
| test_dependencies_advanced.py | ||
| test_event_store.py | ||
| test_extensions.py | ||
| test_fastapi_testclient_compat.py | ||
| test_file_server.py | ||
| test_icons.py | ||
| test_input_validation.py | ||
| test_legacy_httpx_errors.py | ||
| test_log_level.py | ||
| test_logging.py | ||
| test_mrtr_guards.py | ||
| test_mrtr_guards_components.py | ||
| test_pagination.py | ||
| test_protocol_eras.py | ||
| test_providers.py | ||
| test_server.py | ||
| test_server_docket.py | ||
| test_server_lifespan.py | ||
| test_server_safety.py | ||
| test_session_provider.py | ||
| test_session_visibility.py | ||
| test_sessions.py | ||
| test_streamable_http_no_redirect.py | ||
| test_tool_annotations.py | ||
| test_tool_transformation.py | ||
| test_transport.py | ||