hermes - ✅(Solved) Fix MCP tool schema normalization should repair string additionalProperties values [2 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
NousResearch/hermes-agent#14927Fetched 2026-04-24 10:44:16
View on GitHub
Comments
0
Participants
1
Timeline
7
Reactions
0
Author
Participants
Timeline (top)
labeled ×4cross-referenced ×2referenced ×1

Error Message

Observed Error

Root Cause

A single malformed MCP tool schema can prevent an otherwise unrelated model request from starting, because tool registration fails before inference.

Fix Action

Fixed

PR fix notes

PR #14870: fix: repair malformed MCP additionalProperties schemas

Description (problem / solution / changelog)

Summary

  • Normalize malformed MCP schemas where additionalProperties is emitted as a scalar string shorthand, e.g. "object".
  • Convert the shorthand into a provider-valid JSON Schema object before tool registration.
  • Add a regression test covering the broken MCP schema shape.

Fixes #14927.

Problem

Some MCP servers expose tool schemas that contain:

{
  "type": "object",
  "additionalProperties": "object"
}

OpenAI-compatible providers reject that during tool registration with HTTP 400:

Invalid schema for function 'mcp_notion_notion_create_pages': 'object' is not of type 'object', 'boolean'.
param: tools[122].parameters
code: invalid_function_parameters

This breaks requests before any model turn runs when the malformed tool is present.

Root Cause

Hermes already repairs several malformed MCP object schemas, but additionalProperties was only preserved when it was already a valid schema object or boolean. A scalar string type shorthand survived normalization and was passed through to the provider.

Fix

When repairing object-shaped MCP schemas, coerce scalar string additionalProperties values into equivalent schema objects. For example:

"additionalProperties": "object"

becomes:

"additionalProperties": {
  "type": "object",
  "properties": {}
}

This keeps the MCP tool usable while producing a provider-valid JSON Schema.

Test Plan

  • ./venv/bin/pytest tests/tools/test_mcp_tool.py -q -k 'string_additional_properties_is_coerced_to_schema_object or missing_type_on_object_is_coerced or required_pruned_when_property_missing'

Note: the full tests/tools/test_mcp_tool.py -q file currently has an unrelated pre-existing timing failure in TestShutdown.test_shutdown_is_parallel on my local checkout; the new targeted regression and adjacent schema-repair tests pass.

Changed files

  • tests/tools/test_mcp_tool.py (modified, +16/-0)
  • tools/mcp_tool.py (modified, +9/-0)

PR #14977: fix(tools): schema-aware MCP normalization preserves property names

Description (problem / solution / changelog)

What changed and why

_normalize_mcp_input_schema in tools/mcp_tool.py recursed blindly into every dict, treating the properties map itself as a schema node. When a tool parameter happens to share a name with a JSON Schema keyword — properties, required, or definitions — the heuristics misfire. The most visible symptom: Anthropic 400s on tool-use requests with

tools.N.custom.input_schema: JSON schema is invalid.
It must match JSON Schema draft 2020-12.
('object' is not of type 'object', 'boolean')

because Hermes had injected a stray "type": "object" sibling into the properties map. The existing check

if not repaired.get("type") and ("properties" in repaired or "required" in repaired):
    repaired["type"] = "object"

was meant to say "this node looks like an object schema" but triggers equally on a property-map whose keys happen to include properties or required. Similarly the definitions → $defs rewrite applied to a user-named property rather than only the JSON Schema keyword.

The fix replaces the two structure-blind passes (_rewrite_local_refs + _repair_object_shape) with a single schema-aware walk that recurses only into positions holding JSON Schema values:

  • Single schema: items, additionalProperties, contains, not, if/then/else, propertyNames, unevaluatedItems/unevaluatedProperties, contentSchema, additionalItems (draft-07 compat).
  • List of schemas: allOf, anyOf, oneOf, prefixItems.
  • Map of name→schema: properties, patternProperties, dependentSchemas, $defs, definitions.

Everything else (including type, required, enum, const, description, and unknown keywords) is treated as a leaf and copied verbatim. Boolean schemas (true, additionalProperties: false) pass through unchanged. No public API change; return shape is identical and walk order is still post-order.

Repro

Trivial with any Notion-shaped MCP server. The official @notionhq/notion-mcp-server defines tools like API_post_page / API_patch_page / API_create_a_data_source / API_update_a_data_source whose schemas include a top-level properties field mirroring the Notion REST API. User-authored Notion MCP servers (anywhere with z.object({ ..., properties: z.string() })) hit the same trap. In my local setup, 7 tools across two Notion MCP servers all produced schemas Anthropic rejected before this fix.

How to test it

./venv/bin/pytest tests/tools/test_mcp_tool.py -q -k "schema or normali or definitions_refs or missing_type or null_type or required_pruned or required_removed or nested_objects or array_items or property_named or additionalproperties"

New regression tests cover:

  • Parameter literally named properties — property-map stays clean (no injected type).
  • Parameter named required — not pruned / not rewritten.
  • Parameter named definitions — not renamed to $defs.
  • additionalProperties: false preserved.

Platforms tested

  • macOS 15 (Darwin 25.4.0, arm64), Python 3.11.13
  • Full tests/tools/test_mcp_tool.py: 177 of 178 pass. The one failure (TestShutdown::test_shutdown_is_parallel) is a pre-existing timing-flake unrelated to this change.
  • End-to-end: live 138-tool payload (including previously-broken Notion tools) validates clean via jsonschema.Draft202012Validator.check_schema for every tool, and a real claude-opus-4-7 request with the full tools list returns successfully.

No platform-specific code paths are touched — the change is pure Python dict/list manipulation — so Linux impact is expected to be identical.

Related issues

  • Related to #14927 / #14870: same function, adjacent but distinct root cause. That issue concerns an MCP server emitting a malformed additionalProperties: "object" string shorthand; this PR concerns a Hermes-side heuristic misfire on a valid server schema. The two fixes do not overlap textually and can land independently.

🤖 Generated with Claude Code

Changed files

  • tests/tools/test_mcp_tool.py (modified, +83/-0)
  • tools/mcp_tool.py (modified, +84/-42)

Code Example

{
  "type": "object",
  "additionalProperties": "object"
}

---

Invalid schema for function 'mcp_notion_notion_create_pages': 'object' is not of type 'object', 'boolean'.
param: tools[122].parameters
code: invalid_function_parameters

---

{
  "type": "object",
  "properties": {}
}
RAW_BUFFERClick to expand / collapse

Bug Description

Some MCP servers can expose tool input schemas where additionalProperties is emitted as a scalar string type shorthand instead of a JSON Schema object or boolean, for example:

{
  "type": "object",
  "additionalProperties": "object"
}

OpenAI-compatible providers reject this schema during tool registration before any model turn runs.

Observed Error

When a Notion MCP tool with this schema is registered, the request fails with HTTP 400:

Invalid schema for function 'mcp_notion_notion_create_pages': 'object' is not of type 'object', 'boolean'.
param: tools[122].parameters
code: invalid_function_parameters

Expected Behavior

Hermes should normalize MCP-provided schemas into provider-valid JSON Schema before registering tools. A string shorthand like additionalProperties: "object" should be coerced to a schema object such as:

{
  "type": "object",
  "properties": {}
}

Actual Behavior

The malformed additionalProperties value is passed through as a raw string, causing OpenAI-compatible providers to reject the entire tool list.

Impact

A single malformed MCP tool schema can prevent an otherwise unrelated model request from starting, because tool registration fails before inference.

Proposed Fix

Normalize scalar string additionalProperties values in the MCP schema repair path, and add a regression test for the observed shorthand.

A PR with the fix is available at #14870.

extent analysis

TL;DR

The issue can be fixed by normalizing the additionalProperties value in the MCP schema to a JSON Schema object.

Guidance

  • Review the MCP schema for any additionalProperties values that are scalar strings and convert them to JSON Schema objects.
  • Verify that the schema is correctly normalized by checking the output of the schema repair path.
  • Test the registration of tools with the normalized schema to ensure that it is accepted by OpenAI-compatible providers.
  • Consider adding a regression test to prevent similar issues in the future.

Example

// Before normalization
{
  "type": "object",
  "additionalProperties": "object"
}

// After normalization
{
  "type": "object",
  "additionalProperties": {
    "type": "object"
  }
}

Notes

The proposed fix is to normalize the additionalProperties value in the MCP schema repair path, and a PR with the fix is available at #14870. However, the exact implementation details are not provided in the issue.

Recommendation

Apply the workaround by normalizing the additionalProperties value in the MCP schema, as this is a targeted fix for the specific issue described.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

hermes - ✅(Solved) Fix MCP tool schema normalization should repair string additionalProperties values [2 pull requests, 1 participants]