feat(utilities): add dereference_json_schema helper#2587
Open
Burton-David wants to merge 1 commit into
Open
Conversation
Pydantic's model_json_schema() emits $defs + $ref for nested models; some MCP clients don't resolve those during tools/list discovery, leaving fields with nested types unusable. dereference_json_schema is an opt-in helper that inlines internal $defs references while leaving external refs and self-referential definitions intact. The function lives in mcp.server.mcpserver.utilities.json_schema. No existing call sites are changed — this is purely additive. Callers who want fully-flat schemas can post-process the output of model_json_schema() with one extra call. Covers: empty schemas, single inline, multiple refs to same def, arrays of nested models, anyOf, transitive resolution, sibling-key merging, external/unknown ref preservation, direct self-reference, mutual recursion. 21 tests; existing func_metadata + tool_manager tests still pass.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #2586
Summary
Add
dereference_json_schema(schema: dict[str, Any]) -> dict[str, Any]inmcp.server.mcpserver.utilities.json_schema. Post-processes the output of Pydantic'smodel_json_schema()by inlining internal#/\$defs/refs while preserving external refs and self-referential definitions.Pure function, no mutation of input. Opt-in only — no existing SDK behavior changes. Callers who want flat schemas for clients that don't resolve
\$ref(e.g. Claude Desktop's tools/list discovery) apply this helper once after building the schema.Test plan
tests/server/mcpserver/test_json_schema.pytest_func_metadata.py(66 tests) — no regressionstest_tool_manager.py(17 tests) — no regressionsruff checkcleanpyrightstrict cleanTest coverage:
\$defsschemas (no-op + strip)anyOf/oneOf/allOf\$ref(Pydantic emits these for some types)\$ref(URL) preserved\$refpreserved (don't silence producer bugs)\$defsinternal refs (#/properties/x) preserved\$refkept at boundary,\$defsentry retained\$refat innermost boundarymodel_json_schema()outputs (nested, list of nested, self-referencing).Notes on design choices
mcp.server.mcpserver.utilitiesalongsidefunc_metadatasince it's the natural sibling to the existingmodel_json_schemacall sites.\$refat the boundary rather than raising — the alternative (raising on cycles) would force users with legitimate recursive schemas to fall back to the current\$refform anyway.\$refsiblings provide overrides/refinements.func_metadata.pyortools/base.py— the helper is purely additive. If maintainers want it folded in as a flag on existing APIs, happy to update.Happy to iterate on the approach if the maintainers prefer a different shape.