tools/base.py:76 uses raw model_json_schema() which emits $ref/$defs for nested Pydantic models. LLM clients consuming tools/list often can't resolve $ref, leading to params being passed as stringified JSON instead of structured objects.
Repro / demand: anthropics/claude-code#18260 (Notion MCP server, $ref params get stringified by the model).
typescript-sdk addresses this in modelcontextprotocol/typescript-sdk#1563 by adding a dereferenceLocalRefs() step that inlines local $ref and throws on cycles (matching go-sdk precedent). Python should do the equivalent in the tool schema pipeline so all SDKs emit LLM-consumable schemas.
Relevant file: src/mcp/server/mcpserver/tools/base.py:76
tools/base.py:76uses rawmodel_json_schema()which emits$ref/$defsfor nested Pydantic models. LLM clients consumingtools/listoften can't resolve$ref, leading to params being passed as stringified JSON instead of structured objects.Repro / demand: anthropics/claude-code#18260 (Notion MCP server,
$refparams get stringified by the model).typescript-sdk addresses this in modelcontextprotocol/typescript-sdk#1563 by adding a
dereferenceLocalRefs()step that inlines local$refand throws on cycles (matching go-sdk precedent). Python should do the equivalent in the tool schema pipeline so all SDKs emit LLM-consumable schemas.Relevant file:
src/mcp/server/mcpserver/tools/base.py:76