Context
As of PR #205, all 57 MCP tools auto-generate their inputSchema from Pydantic request models via _generate_pydantic_schemas() at src/adcp/server/mcp_tools.py:915. Pydantic emits $defs + $ref for nested models, which is valid JSON Schema but trips up some MCP clients that don't resolve $ref.
What to do
Add an inlining pass after _generate_pydantic_schemas() that resolves every $ref into its $defs body and drops the $defs block. Preserve descriptions and required-field lists. Gate behind a flag if we want to keep the $defs form available for clients that do resolve refs.
Acceptance
- All 57 tools'
inputSchema survive the transform with no lost semantics
- A new
tests/test_mcp_schema_drift.py test asserts no $ref strings appear in any generated schema
- MCP Inspector + the
@adcp/client storyboard runner both still accept the output
Priority
4.1 follow-up. Current state is spec-valid; this is strictly DX for clients that take the inline path.
Surfaced from: #205
Context
As of PR #205, all 57 MCP tools auto-generate their
inputSchemafrom Pydantic request models via_generate_pydantic_schemas()atsrc/adcp/server/mcp_tools.py:915. Pydantic emits$defs+$reffor nested models, which is valid JSON Schema but trips up some MCP clients that don't resolve$ref.What to do
Add an inlining pass after
_generate_pydantic_schemas()that resolves every$refinto its$defsbody and drops the$defsblock. Preserve descriptions and required-field lists. Gate behind a flag if we want to keep the$defsform available for clients that do resolve refs.Acceptance
inputSchemasurvive the transform with no lost semanticstests/test_mcp_schema_drift.pytest asserts no$refstrings appear in any generated schema@adcp/clientstoryboard runner both still accept the outputPriority
4.1 follow-up. Current state is spec-valid; this is strictly DX for clients that take the inline path.
Surfaced from: #205