Repository navigation
PydanticSchemaGenerationError: Unable to generate pydantic-core schema for Image type #1060
Description
Activity
FYI, this is also reproducible on today's main (6f43d1f)
Whats your pydantic version?
- addedneeds confirmationNeeds confirmation that the PR is actually required or needed.Needs confirmation that the PR is actually required or needed.
on Aug 9, 2025 When running the above modified unit test using mcp 1.9.4:
$ uv tree --frozen | grep pydantic │ ├── pydantic v2.10.1 │ │ ├── pydantic-core v2.27.1 │ ├── pydantic-settings v2.6.1 │ │ ├── pydantic v2.10.1 (*) ├── pydantic v2.10.1 (*) ├── pydantic-settings v2.6.1 (*)When running the above modified unit test using mcp 1.12.4:
$ uv tree --frozen | grep pydantic ├── pydantic v2.11.7 │ ├── pydantic-core v2.33.2 ├── pydantic-settings v2.10.1 │ ├── pydantic v2.11.7 (*) ├── pydantic v2.11.7 (*) ├── pydantic-settings v2.10.1 (*)As originally described, in mcp 1.9.4 this style of mixed return from a tool was working.
But in current versions it still fails with:
pydantic.errors.PydanticSchemaGenerationError: Unable to generate pydantic-core schema for <class 'mcp.server.fastmcp.utilities.types.Image'>. Set `arbitrary_types_allowed=True` in the model_config to ignore this error or implement `__get_pydantic_core_schema__` on your type to fully support it.We've managed to work around this by using
ImageContenttype instead ofImage, as it would seemImageis not compatible with Pydantic-based schema generation, and older versions of MCP SDK had, perhaps, some special case forImagetype.Perhaps
Imagetype should be avoided? And docs/readme should steer people to useImageContent?- addedbugSomething isn't workingSomething isn't workingready for workEnough information for someone to start working onEnough information for someone to start working onP2Moderate issues affecting some users, edge cases, potentially valuable featureModerate issues affecting some users, edge cases, potentially valuable featureand removedneeds confirmationNeeds confirmation that the PR is actually required or needed.Needs confirmation that the PR is actually required or needed.
on Oct 6, 2025 Still reproduces on
main(52ad0a88, pydantic 2.12.5, Python 3.12), and it turns out to be a bit wider than the report.The class moved to
mcp.server.mcpserver.utilities.types.Imagesince this was filed, but the behaviour is the same. What matters is that a bareImagereturn is fine, and every container of one fails:return annotation on mainImageok, output_schema=NoneAudiook, output_schema=Nonelist[Image]PydanticSchemaGenerationErrordict[str, Image]PydanticSchemaGenerationErrortuple[str, Image, AudioContent]PydanticSchemaGenerationError(the reported case)Image | NonePydanticSchemaGenerationErrorlist[Audio]PydanticSchemaGenerationErrorThe error escapes
func_metadata(), so it takes out tool registration rather than just the output schema.Cause
In
src/mcp/server/mcpserver/utilities/func_metadata.py,_try_create_model_and_schema()wraps only the schema call:try: schema = model.model_json_schema(schema_generator=StrictJsonSchema) except (PydanticUserError, TypeError, ValueError, pydantic_core.SchemaError, pydantic_core.ValidationError):
but
PydanticSchemaGenerationErroris raised earlier than that, duringcreate_model()inside_create_wrapped_model(), which sits above thetry. It is a subclass ofPydanticUserError(and ofTypeError), so that existing tuple would already catch it if it were in scope. The guard is in the right shape and just does not cover model construction.That also explains the bare/container split: a bare
Imagenever reachescreate_model(), because it falls to the "other class types" branch, has no type hints, and leavesmodelasNone.Possible fix
Split model building into its own helper and guard both halves with the same exception tuple. Containers of
Imagethen degrade tooutput_schema=None, which is exactly what a bareImagealready does, andstructured_output=Trueraises the intendedInvalidSignature("is not serializable for structured output") instead of leaking a raw pydantic error.I have this written and verified locally:
- All five failing shapes above degrade to no structured output, matching bare
Image. - End to end, a
list[Image]tool registers, lists withoutputSchema: null, and returns realImageContentblocks with the right mime types and decodable data. The runtime path inconvert_resultalready handledImagecorrectly, so only schema derivation was breaking. - Full suite passes, 5633 passed / 8 skipped / 1 xfailed.
ruff check,ruff format --checkandpyrightare clean. - The regression test is parametrized over the five shapes and is not vacuous: reverting only the source change turns 5 of its 6 cases red.
The alternative would be giving
ImageandAudioa__get_pydantic_core_schema__so they describe themselves properly, but that is a larger call about whether these helpers should be part of the structured output surface at all, and it would change the schema of tools that currently return them. I went with the narrow fix, though I am happy to go the other way if you would rather.Before I open anything
This is labelled
ready for work, which per CONTRIBUTING is the maintainer queue rather than an invitation, so I would rather ask than assume. If you would like this from an outside contributor, could you assign it to me and I will open the PR. If you would rather keep it in house, no problem, and hopefully the diagnosis above still saves someone the reproduction work.Disclosure: I used AI assistance while investigating and writing this. I have reviewed and verified all of it myself and can speak to any part of it.
- All five failing shapes above degrade to no structured output, matching bare
Initial Checks
Description
The
Imagetype in question is imported like this:from mcp.server.fastmcp.utilities.types import ImageWe are upgrading our dependency on
mcpfrom 1.9.4 to 1.10.1.Once on 1.10.1 our application and tests began to fail with error like this:
I found a test tool function among this repo's unit tests, that is pretty close to the mixed content
use case in our server. So I tweaked it to create a repro case for you:
test_tool_mixed_contentfails withPydanticSchemaGenerationErroron 1.10.1 but succeeds on 1.9.4.Python & MCP Python SDK