Skip to content

fix(mcp): preserve 'definitions' as a property name in tool schemas - #56150

Merged
teknium1 merged 2 commits into
mainfrom
hermes/hermes-6380f664
Jul 1, 2026
Merged

fix(mcp): preserve 'definitions' as a property name in tool schemas#56150
teknium1 merged 2 commits into
mainfrom
hermes/hermes-6380f664

Conversation

@teknium1

@teknium1 teknium1 commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Summary

MCP tools that expose a parameter literally named definitions no longer get that parameter name corrupted to $defs, which providers reject.

Root cause: _rewrite_local_refs in _normalize_mcp_input_schema promoted the legacy definitions meta-keyword to $defs by renaming any key named definitions anywhere in the tree — including keys inside a properties dict, which are user-facing parameter names, not schema keywords. A parameter renamed to $defs violates the provider property-name pattern ^[a-zA-Z0-9_.-]{1,64}$ ($ is illegal). Because the full tools array ships on every request, one such tool 400s every conversation, not just calls to that tool.

Changes

  • tools/mcp_tool.py: _rewrite_local_refs now descends into properties/patternProperties by iterating name→schema pairs directly, leaving property names verbatim. The definitions$defs rename and the #/definitions/...#/$defs/... $ref rewrite still apply everywhere else, so a legitimately-nested definitions meta-keyword inside a property's schema is still promoted.
  • tests/tools/test_mcp_tool.py: two regression tests — definitions as a sole property name (preserved), and both forms coexisting in one schema (property preserved, meta-keyword promoted, $ref rewritten).

Validation

Case Before After
definitions property name renamed to $defs → provider 400 preserved verbatim
definitions meta-keyword promoted to $defs promoted to $defs (unchanged)
nested meta-keyword inside a property promoted promoted (unchanged)
#/definitions/... $ref rewritten rewritten (unchanged)
  • scripts/run_tests.sh tests/tools/test_mcp_tool.py — 202 passed (incl. 2 new regression tests).
  • E2E: ran _normalize_mcp_input_schema against the three schema shapes above with real imports; all assertions pass.

Salvage of #30491 by @MattKotsenas — cherry-picked onto current main with authorship preserved.

Infographic

MCP definitions property-name fix

MattKotsenas and others added 2 commits July 1, 2026 00:42
The MCP input-schema normalizer in _normalize_mcp_input_schema promotes the
legacy JSON Schema 'definitions' meta-keyword to '$defs' (draft 2019-09+)
so local '$ref' resolution works downstream. The previous walk renamed
*any* key named 'definitions' anywhere in the tree, including inside
'properties' dicts. That turned user-facing parameter names into '$defs',
producing property keys that contain '$', which Anthropic and OpenAI
both reject with HTTP 400 (pattern '^[a-zA-Z0-9_.-]{1,64}$').

Real-world repro: an MCP server that exposes a CI/pipelines tool whose
'definitions' parameter is an array of pipeline-definition IDs. Such a tool
is enough on its own to break every conversation, because the full tools
array is sent on every request.

Fix: when descending into a 'properties' or 'patternProperties' mapping,
iterate property-name -> schema pairs directly, leaving the property names
verbatim. Ordinary JSON Schema semantics resume inside each property's
schema, so a legitimately nested 'definitions' meta-keyword inside a
property's schema is still promoted.

Adds two regression tests:
- test_definitions_as_property_name_is_preserved (the property-name case)
- test_definitions_property_and_meta_keyword_coexist (both forms in one
  schema; the property name stays, the meta-keyword promotes)
@alt-glitch alt-glitch added type/bug Something isn't working tool/mcp MCP client and OAuth P2 Medium — degraded but workaround exists labels Jul 1, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Salvage of #30491 (@mattko…), the earliest-open canonical fix — related, not a duplicate (this is the authoritative salvaged version). Also related to issue #55081 and the competing/dup PRs #55082 and #36955 (the latter a superset with an extra defensive property-key sanitize). A reviewer should close the community PRs in favor of this salvage.

@teknium1
teknium1 merged commit deb4629 into main Jul 1, 2026
30 of 31 checks passed
@teknium1
teknium1 deleted the hermes/hermes-6380f664 branch July 1, 2026 08:02
MaxFreedomPollard added a commit to MaxFreedomPollard/hermes-agent that referenced this pull request Sep 4, 2026
…tions to $defs

NousResearch#56150 gated properties/patternProperties, but a definitions MAP's keys are
member names too. A member literally named "definitions" was renamed to
$defs while the reference to it was rewritten to #/$defs/definitions, leaving
a dangling $ref that 400s the whole tool array.

Also fixes silent member loss when both spellings coexist on one node:
normalized["$defs" if key == "definitions" else key] let whichever key came
last overwrite the other's members outright. They now merge, with $defs
winning a name collision regardless of key order.

Rewritten against tools/mcp_tool_schema.py, where the helper now lives after
the Sep 2026 decomposition; the original branch targeted tools/mcp_tool.py.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P2 Medium — degraded but workaround exists tool/mcp MCP client and OAuth type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants