Skip to content

Inline MCP tool $ref/$defs schemas for Anthropic agent tool calls#5786

Open
sanidhyasin wants to merge 1 commit into
Mintplex-Labs:masterfrom
sanidhyasin:3938-anthropic-mcp-nested-params
Open

Inline MCP tool $ref/$defs schemas for Anthropic agent tool calls#5786
sanidhyasin wants to merge 1 commit into
Mintplex-Labs:masterfrom
sanidhyasin:3938-anthropic-mcp-nested-params

Conversation

@sanidhyasin

Copy link
Copy Markdown
Contributor

Pull Request Type

  • ✨ feat (New feature)
  • 🐛 fix (Bug fix)
  • ♻️ refactor (Code refactoring without changing behavior)
  • 💄 style (UI style changes)
  • 🔨 chore (Build, CI, maintenance)
  • 📝 docs (Documentation updates)

Relevant Issues

resolves #3938

Description

MCP tools whose inputSchema describes nested object parameters (for example tools defined with Pydantic v2 nested models) emit JSON Schema that uses $ref/$defs:

{
  "type": "object",
  "properties": { "pagination": { "$ref": "#/$defs/PaginationParams" } },
  "$defs": { "PaginationParams": { "type": "object", "properties": { "page": { "type": "integer" }, "limit": { "type": "integer" } } } }
}

When building the Anthropic input_schema, #formatFunctions copied only type, properties, and requireddropping the $defs block. The forwarded schema then contained a $ref pointing at a definition that no longer existed. Anthropic does not resolve local references on its end, so the dangling pointer rejected the request and crashed the entire agent session. Flat (non-nested) tools were unaffected, which is why this only surfaced for nested-parameter MCP servers.

Fix

Added a small, pure helper dereferenceSchema() that inlines local $refs using the schema's $defs/definitions and strips the definition blocks, producing a self-contained schema before it is handed to Anthropic.

  • Flat schemas are returned structurally unchanged, so existing built-in tools and flat MCP tools forward exactly the same input_schema as before — this keeps the change scoped and avoids altering every tool call.
  • Chained references between definitions are fully resolved.
  • Self-referencing (recursive) models collapse to a generic object schema instead of recursing forever.
  • References that cannot be resolved are dropped rather than forwarded as dangling pointers.

This was the concern raised on the earlier attempt (#3939) — that spreading the whole schema would change behavior for every tool. By inlining references and leaving flat schemas byte-for-byte identical, this approach works for all cases without that side effect, so flattening the MCP tool definition by hand is no longer required.

Visuals (if applicable)

N/A

Additional Information

The dereference logic lives in server/utils/agents/aibitat/providers/helpers/dereferenceSchema.js and is covered by unit tests in server/__tests__/utils/agents/aibitat/providers/helpers/dereferenceSchema.test.js.

Developer Validations

  • I ran yarn lint from the root of the repo & committed changes
  • Relevant documentation has been updated (if applicable)
  • I have tested my code functionality
  • Docker build succeeds locally

Files were formatted with the repo's Prettier config (.prettierrc); all three pass prettier --check.

Focused validation run:

npx jest server/__tests__/utils/agents/aibitat/providers/helpers/dereferenceSchema.test.js --runInBand

Anthropic's `input_schema` does not resolve local JSON-Schema references, so
MCP tools that describe nested parameters with `$ref`/`$defs` (e.g. Pydantic v2
nested models) were forwarded with dangling pointers, crashing the agent.

Inline local references and strip the definition blocks before building
`input_schema` so the schema is self-contained. Flat schemas are unchanged.
Recursive models collapse to a generic object and unresolvable references are
dropped rather than forwarded.

Resolves Mintplex-Labs#3938
@sanidhyasin

Copy link
Copy Markdown
Contributor Author

@timothycarambat friendly ping — this inlines MCP tool $ref/$defs schemas so Anthropic agent tool calls work with nested params (#3938). Would appreciate a review when convenient. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG]: MCP servers with nested params in input_schema crash an Anthropic agent

1 participant