[GH-ISSUE #2813] inputSchema nesting depth exceeds 10 on 24 tools (max 19: compare_web_captures) — breaks strict-depth MCP clients #1005

Closed
opened 2026-10-15 18:30:16 +00:00 by bsakaguchi · 3 comments
Owner

Originally created by @amikishiyev on GitHub (Oct 13, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/2813

Summary

MCP clients that enforce a maximum JSON-schema nesting depth of 10 reject rea because 24 of 170 inputSchema objects exceed that limit. Worst offender is compare_web_captures at depth 19. Reproduced with rea-agents@6.4.0.

Observed client error:

JSON schema exceeds the maximum nesting depth of 10 levels

This makes the whole MCP server unusable in those clients, even though 146 of 170 tools would be fine.

Reproduction

npx -y rea-agents@6.4.0 mcp   # stdio MCP
# then: initialize, notifications/initialized, tools/list
# walk each inputSchema JSON tree; root = depth 0

Measured with rea-agents@6.4.0:

metric value
tools 170
max depth 19 (compare_web_captures)
tools with depth > 10 7
tools with depth == 10 17
puppeteer-mcp-server (control) 8 tools, max depth 3

Tools at depth >= 10

depth=19 bytes=57175 compare_web_captures
   at .$defs.__schema67.properties.items.items.anyOf[7].properties.headers.anyOf[2].properties.items.items.properties.value.anyOf[0].type
depth=15 bytes=16647 build_reconstruction_obligation_ledger
   at .$defs.__schema46.properties.bindings.items.properties.verifier.anyOf[0].properties.nondeterminism.properties.mode.enum[0]
depth=14 bytes=19679 evaluate_reconstruction_coverage
   at .$defs.__schema0.properties.owners.items.properties.ownership.oneOf[0].properties.owner_export.anyOf[0].type
depth=12 bytes=13354 compare_source_to_bundle
depth=12 bytes=7003 correlate_static_and_runtime
depth=11 bytes=9078 trace_javascript_semantics
depth=11 bytes=8730 compare_process_captures
depth=10  x17  (shared __schemaN.anyOf[0].properties.architecture.anyOf[0].type / .enum[0] pattern)

Root cause

Two generator patterns compound:

  1. Deep anyOf/oneOf wrapper chains around leaf scalars. The recurring offender is:

    "architecture": {
      "anyOf": [ { "enum": ["x86", "x86_64", "arm", "arm64", "mips"] }, { "type": "null" } ]
    }
    

    Each of these sits inside another anyOf/oneOf wrapper, so the leaf type/enum token lands 10 levels down. 17 tools share this exact shape via $defs.__schemaN.

  2. compare_web_captures nests a second full event union inside the first: events.items.anyOf[7] is a network-content event whose headers is again anyOf[0|1|2], whose items.value is again anyOf[...]. Three stacked nullable-union layers produce depth 19.

Note: depths above are raw JSON-tree depth without resolving $ref. With $ref expansion the real depth is the same or worse, because $defs.__schema67 etc. are themselves deeply nested.

Suggested fix

Flatten the leaf wrappers rather than dropping semantic information:

  1. Collapse "anyOf": [{"enum": [...]}, {"type": "null"}] into "enum": [..., null] (JSON Schema draft 2020-12 allows null in enum). Same for nullable string/boolean leaves: "type": ["string", "null"]. This alone removes 2 levels on ~17 tools and drops them under the limit.

  2. For compare_web_captures, hoist the per-event-kind field sets to named $defs and reference them with a single-level discriminator instead of stacking items.anyOf[N] inside items.anyOf[M]. A oneOf + if/then on kind, or a flat properties bag with kind enum, keeps the same validation surface at roughly half the depth.

  3. Optionally add a CI check that fails the build when any inputSchema tree depth exceeds a chosen budget (10 is a common client limit). Rough guard:

    const depth = (n, d = 0) =>
      !n || typeof n !== 'object' ? d
      : Math.max(...(Array.isArray(n) ? n : Object.values(n))
          .map(v => depth(v, d + 1)));
    // fail if depth(tool.inputSchema) > 10
    

Environment

  • rea-agents@6.4.0 via npx, macOS, stdio transport
  • Client: OpenCode, model provider rejecting the tools/list payload

Happy to test a candidate release against the same repro script.

Originally created by @amikishiyev on GitHub (Oct 13, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/2813 ## Summary MCP clients that enforce a **maximum JSON-schema nesting depth of 10** reject `rea` because 24 of 170 `inputSchema` objects exceed that limit. Worst offender is `compare_web_captures` at **depth 19**. Reproduced with `rea-agents@6.4.0`. Observed client error: ``` JSON schema exceeds the maximum nesting depth of 10 levels ``` This makes the whole MCP server unusable in those clients, even though 146 of 170 tools would be fine. ## Reproduction ```bash npx -y rea-agents@6.4.0 mcp # stdio MCP # then: initialize, notifications/initialized, tools/list # walk each inputSchema JSON tree; root = depth 0 ``` Measured with `rea-agents@6.4.0`: | metric | value | |---|---| | tools | 170 | | max depth | 19 (`compare_web_captures`) | | tools with depth > 10 | 7 | | tools with depth == 10 | 17 | | puppeteer-mcp-server (control) | 8 tools, max depth 3 | ## Tools at depth >= 10 ``` depth=19 bytes=57175 compare_web_captures at .$defs.__schema67.properties.items.items.anyOf[7].properties.headers.anyOf[2].properties.items.items.properties.value.anyOf[0].type depth=15 bytes=16647 build_reconstruction_obligation_ledger at .$defs.__schema46.properties.bindings.items.properties.verifier.anyOf[0].properties.nondeterminism.properties.mode.enum[0] depth=14 bytes=19679 evaluate_reconstruction_coverage at .$defs.__schema0.properties.owners.items.properties.ownership.oneOf[0].properties.owner_export.anyOf[0].type depth=12 bytes=13354 compare_source_to_bundle depth=12 bytes=7003 correlate_static_and_runtime depth=11 bytes=9078 trace_javascript_semantics depth=11 bytes=8730 compare_process_captures depth=10 x17 (shared __schemaN.anyOf[0].properties.architecture.anyOf[0].type / .enum[0] pattern) ``` ## Root cause Two generator patterns compound: 1. **Deep `anyOf`/`oneOf` wrapper chains** around leaf scalars. The recurring offender is: ```json "architecture": { "anyOf": [ { "enum": ["x86", "x86_64", "arm", "arm64", "mips"] }, { "type": "null" } ] } ``` Each of these sits inside another `anyOf`/`oneOf` wrapper, so the leaf `type`/`enum` token lands 10 levels down. 17 tools share this exact shape via `$defs.__schemaN`. 2. **`compare_web_captures`** nests a second full event union inside the first: `events.items.anyOf[7]` is a network-content event whose `headers` is again `anyOf[0|1|2]`, whose `items.value` is again `anyOf[...]`. Three stacked nullable-union layers produce depth 19. Note: depths above are raw JSON-tree depth **without** resolving `$ref`. With `$ref` expansion the real depth is the same or worse, because `$defs.__schema67` etc. are themselves deeply nested. ## Suggested fix Flatten the leaf wrappers rather than dropping semantic information: 1. Collapse `"anyOf": [{"enum": [...]}, {"type": "null"}]` into `"enum": [..., null]` (JSON Schema draft 2020-12 allows `null` in `enum`). Same for nullable string/boolean leaves: `"type": ["string", "null"]`. This alone removes 2 levels on ~17 tools and drops them under the limit. 2. For `compare_web_captures`, hoist the per-event-kind field sets to named `$defs` and reference them with a single-level discriminator instead of stacking `items.anyOf[N]` inside `items.anyOf[M]`. A `oneOf` + `if/then` on `kind`, or a flat `properties` bag with `kind` enum, keeps the same validation surface at roughly half the depth. 3. Optionally add a CI check that fails the build when any `inputSchema` tree depth exceeds a chosen budget (10 is a common client limit). Rough guard: ```js const depth = (n, d = 0) => !n || typeof n !== 'object' ? d : Math.max(...(Array.isArray(n) ? n : Object.values(n)) .map(v => depth(v, d + 1))); // fail if depth(tool.inputSchema) > 10 ``` ## Environment - `rea-agents@6.4.0` via `npx`, macOS, stdio transport - Client: OpenCode, model provider rejecting the `tools/list` payload Happy to test a candidate release against the same repro script.
Author
Owner

@ylwl1997 commented on GitHub (Oct 13, 2026):

Thanks for the depth walk — this matches what some strict MCP clients do beyond byte-size caps.

Reproduced the symptom class on rea-agents@6.4.0: clients that reject schemas deeper than ~10 fail at tools/list even when most tools are fine. Note that REA_MCP_INPUT_SCHEMA_PROFILE=compact reduces annotation/size, not necessarily tree depth, so it is not a substitute for flattening the anyOf/oneOf wrappers you described.

Happy to re-run your depth script against a candidate PR / nightly if maintainers want an external confirmation.

Workaround for operators today: use a client that tolerates deep schemas, or drive heavy tools via CLI while the catalog fix lands.

<!-- gh-comment-id:6147473767 --> @ylwl1997 commented on GitHub (Oct 13, 2026): Thanks for the depth walk — this matches what some strict MCP clients do beyond byte-size caps. Reproduced the symptom class on `rea-agents@6.4.0`: clients that reject schemas deeper than ~10 fail at `tools/list` even when most tools are fine. Note that `REA_MCP_INPUT_SCHEMA_PROFILE=compact` reduces **annotation/size**, not necessarily **tree depth**, so it is not a substitute for flattening the `anyOf`/`oneOf` wrappers you described. Happy to re-run your depth script against a candidate PR / nightly if maintainers want an external confirmation. Workaround for operators today: use a client that tolerates deep schemas, or drive heavy tools via CLI while the catalog fix lands.
bsakaguchi 2026-10-31 00:29:48 +00:00
Author
Owner

@Cyb3rDrunk3n commented on GitHub (Oct 18, 2026):

Also affected: Claude desktop app (Windows), still present in rea-agents 6.5.0

Same root cause seen in the Claude desktop app. REA connects and all other tools load, but compare_web_captures is dropped and the app shows:

"Claude can't use Compare Web Captures from REA because of a problem with that connector. Update or reinstall REA."

Reinstalling doesn't help, so this seems to be the schema depth issue described here. Looking forward to #2905 landing. Happy to test a candidate release.

Environment: rea-agents 6.5.0, Windows, Claude desktop app

Related: #4081 (same symptom reported for Claude Desktop on Windows)

<!-- gh-comment-id:6251102729 --> @Cyb3rDrunk3n commented on GitHub (Oct 18, 2026): **Also affected: Claude desktop app (Windows), still present in rea-agents 6.5.0** Same root cause seen in the Claude desktop app. REA connects and all other tools load, but `compare_web_captures` is dropped and the app shows: "Claude can't use Compare Web Captures from REA because of a problem with that connector. Update or reinstall REA." Reinstalling doesn't help, so this seems to be the schema depth issue described here. Looking forward to #2905 landing. Happy to test a candidate release. Environment: rea-agents 6.5.0, Windows, Claude desktop app Related: #4081 (same symptom reported for Claude Desktop on Windows)
Author
Owner

@morluto commented on GitHub (Oct 25, 2026):

The requested compact-schema depth bound is now present on main. Commit 80de3145e4 caps expanded compact schemas at ten levels, the MCP boundary test checks every advertised tool schema, and the docs describe the bound: github.com/morluto/rea@80de3145e4/src/contracts/compactInputSchema.ts ; github.com/morluto/rea@80de3145e4/tests/boundary/mcp/compactInputSchemaMcp.test.ts . Source-derived; no OpenCode or other client runtime verification was performed in this closure review.

<!-- gh-comment-id:6392730550 --> @morluto commented on GitHub (Oct 25, 2026): The requested compact-schema depth bound is now present on main. Commit 80de3145e458474319f160d2d2c09586e7a282a4 caps expanded compact schemas at ten levels, the MCP boundary test checks every advertised tool schema, and the docs describe the bound: https://github.com/morluto/rea/blob/80de3145e458474319f160d2d2c09586e7a282a4/src/contracts/compactInputSchema.ts ; https://github.com/morluto/rea/blob/80de3145e458474319f160d2d2c09586e7a282a4/tests/boundary/mcp/compactInputSchemaMcp.test.ts . Source-derived; no OpenCode or other client runtime verification was performed in this closure review.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#1005
No description provided.