[PR #2877] [CLOSED] fix(mcp): keep Gemini-rejected dependency keywords out of input schemas #5462

Closed
opened 2026-10-31 01:06:50 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/2877
Author: @thefolahan
Created: 10/13/2026
Status: ❌ Closed

Base: main ← Head: fix/gemini-schema-keywords


📝 Commits (4)

  • 27e140a fix(mcp): keep Gemini-rejected dependency keywords out of input schemas
  • 5447a5d fix(mcp): keep partner guidance in compact schemas and correct the contract
  • ea4cfc9 test(mcp): expect partner fields to be enforced by the canonical parser only
  • 2807b99 Merge origin/main into fix/gemini-schema-keywords

📊 Changes

1 file changed (+12 additions, -7 deletions)

View changed files

📝 docs/mcp-contracts.md (+12 -7)

📄 Description

Summary

Fixes #2832. Advertised tool input schemas no longer contain dependentRequired or dependencies. Gemini function declarations reject both, and one unknown keyword in one tool fails the request for the whole catalog, so every REA tool became unavailable on Gemini-backed clients.

Problem and expected behavior

Two tools carried the keyword in the advertised catalog on current main:

  • compare_web_captures, from flattenRootObjectUnion in src/contracts/inputSchemaPresentation.ts, which turned "a field unique to a group needs that group's required partners" into dependentRequired (or dependencies for draft-07). This is the one reported in #2832.
  • inspect_sqlite_database, from .meta({ dependentRequired: { row_limit: ["table"], columns: ["table"] } }) in src/domain/sqlite/sqliteDatabase.ts. It landed in #2271 after the issue was filed, and the new test below found it.

Change and scope

  • flattenRootObjectUnion no longer computes or emits the partner map. The group description it already writes ("Provide a complete input group: before + after; before_scenario + after_scenario + [normalization].") still tells callers which fields go together, and minProperties is kept.
  • The SQLite input drops dependentRequired from its metadata. The table requirement is now in the input schema's root description, which the compact profile keeps (field descriptions are stripped there), and row_limit's own description says it too. Its superRefine checks are unchanged.
  • Both rules are still enforced by the canonical Zod parsers, as cross-group exclusion already was. What changes is that a client validating the advertised form alone now accepts an optional field without its partners, for example { before_scenario: 1, normalization: true }, and the server rejects it. toolInputReferences.test.ts now states that expectation explicitly, next to the existing cross-group case.

docs/mcp-contracts.md now describes partner fields as guidance enforced by the canonical parser, not by the advertised schema.

I kept $schema. MCP clients rely on it to tell draft-07 from 2020-12, and the reporter's capture shows gateways already strip it. compactInputSchema.ts is unchanged: it preserves whatever validation keywords it receives, and nothing upstream emits these two any more.

Regression guard

tests/boundary/mcp/compactInputSchemaMcp.test.ts lists the whole catalog over an in-memory MCP transport, with both the full and compact profiles, and walks every advertised input schema for dependentRequired and dependencies in keyword position. It skips property names and literal const/enum/default/examples data, so a field that happens to be called dependencies is fine. Against the old code it fails with:

+   "inspect_sqlite_database/dependentRequired",
+   "compare_web_captures/dependentRequired",

Contract and boundary impact

  • Semantic owner and earliest changed stage: MCP input schema presentation (inputSchemaPresentation.ts), plus the SQLite input contract's advertised metadata.
  • CLI and MCP/tool-catalog contract: the advertised input schemas lose one keyword in two tools, and one field description gains "requires table". Accepted and rejected inputs at the server are unchanged.
  • Provider, bridge, target-format, or platform compatibility: no provider changes.

Verification

Node 24.21.0 on macOS (Apple silicon):

  • vitest run for tests/boundary/mcp/compactInputSchemaMcp.test.ts, src/contracts/toolInputReferences.test.ts, src/contracts/compactInputSchema.test.ts, tests/conformance/contracts/mcpInputSchemaProfile.test.ts, src/application/sqlite and tests/boundary/sqlite: 11 files, 128 passed, 1 skipped.
  • tests/boundary/mcp/toolSchemaValidity.test.ts with the compact test: 21 passed. Building the catalog artifact it needs requires compile, which fails on current main at src/android/JadxAnalysis.ts:366 (#2852, fix in #2850). I ran it with a local, uncommitted workaround for that line only.
  • tsc --noEmit: no errors in the changed files. The errors it does report are already on main (JadxAnalysis.ts, analysisView.test.ts, IdaSessionClient.test.ts).
  • verify:gemini-client was not run: no Gemini CLI on this host.

Observation, not changed here: the catalog also advertises if/then (inspect_sqlite_database) and not (compare_web_captures), which are also outside Gemini's strict Schema message. The reporter's gateway strips those, so they did not break the request. I am happy to follow up if you would rather the advertised catalog avoid them too.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/2877 **Author:** [@thefolahan](https://github.com/thefolahan) **Created:** 10/13/2026 **Status:** ❌ Closed **Base:** `main` ← **Head:** `fix/gemini-schema-keywords` --- ### 📝 Commits (4) - [`27e140a`](https://github.com/morluto/rea/commit/27e140a232362c9d59d65e42fe19380dc10e1d06) fix(mcp): keep Gemini-rejected dependency keywords out of input schemas - [`5447a5d`](https://github.com/morluto/rea/commit/5447a5d5ddfffe171c34ecce6641fdb5628d7290) fix(mcp): keep partner guidance in compact schemas and correct the contract - [`ea4cfc9`](https://github.com/morluto/rea/commit/ea4cfc9f11fb002923c999839df3bba6984d0b23) test(mcp): expect partner fields to be enforced by the canonical parser only - [`2807b99`](https://github.com/morluto/rea/commit/2807b99ec407886d1a3bd1e910471467cb691f63) Merge origin/main into fix/gemini-schema-keywords ### 📊 Changes **1 file changed** (+12 additions, -7 deletions) <details> <summary>View changed files</summary> 📝 `docs/mcp-contracts.md` (+12 -7) </details> ### 📄 Description ## Summary Fixes #2832. Advertised tool input schemas no longer contain `dependentRequired` or `dependencies`. Gemini function declarations reject both, and one unknown keyword in one tool fails the request for the whole catalog, so every REA tool became unavailable on Gemini-backed clients. ## Problem and expected behavior Two tools carried the keyword in the advertised catalog on current `main`: * `compare_web_captures`, from `flattenRootObjectUnion` in `src/contracts/inputSchemaPresentation.ts`, which turned "a field unique to a group needs that group's required partners" into `dependentRequired` (or `dependencies` for draft-07). This is the one reported in #2832. * `inspect_sqlite_database`, from `.meta({ dependentRequired: { row_limit: ["table"], columns: ["table"] } })` in `src/domain/sqlite/sqliteDatabase.ts`. It landed in #2271 after the issue was filed, and the new test below found it. ## Change and scope * `flattenRootObjectUnion` no longer computes or emits the partner map. The group description it already writes ("Provide a complete input group: before + after; before_scenario + after_scenario + [normalization].") still tells callers which fields go together, and `minProperties` is kept. * The SQLite input drops `dependentRequired` from its metadata. The table requirement is now in the input schema's root description, which the compact profile keeps (field descriptions are stripped there), and `row_limit`'s own description says it too. Its `superRefine` checks are unchanged. * Both rules are still enforced by the canonical Zod parsers, as cross-group exclusion already was. What changes is that a client validating the advertised form alone now accepts an optional field without its partners, for example `{ before_scenario: 1, normalization: true }`, and the server rejects it. `toolInputReferences.test.ts` now states that expectation explicitly, next to the existing cross-group case. `docs/mcp-contracts.md` now describes partner fields as guidance enforced by the canonical parser, not by the advertised schema. I kept `$schema`. MCP clients rely on it to tell draft-07 from 2020-12, and the reporter's capture shows gateways already strip it. `compactInputSchema.ts` is unchanged: it preserves whatever validation keywords it receives, and nothing upstream emits these two any more. ## Regression guard `tests/boundary/mcp/compactInputSchemaMcp.test.ts` lists the whole catalog over an in-memory MCP transport, with both the full and compact profiles, and walks every advertised input schema for `dependentRequired` and `dependencies` in keyword position. It skips property names and literal `const`/`enum`/`default`/`examples` data, so a field that happens to be called `dependencies` is fine. Against the old code it fails with: ``` + "inspect_sqlite_database/dependentRequired", + "compare_web_captures/dependentRequired", ``` ## Contract and boundary impact - Semantic owner and earliest changed stage: MCP input schema presentation (`inputSchemaPresentation.ts`), plus the SQLite input contract's advertised metadata. - CLI and MCP/tool-catalog contract: the advertised input schemas lose one keyword in two tools, and one field description gains "requires table". Accepted and rejected inputs at the server are unchanged. - Provider, bridge, target-format, or platform compatibility: no provider changes. ## Verification Node 24.21.0 on macOS (Apple silicon): - `vitest run` for `tests/boundary/mcp/compactInputSchemaMcp.test.ts`, `src/contracts/toolInputReferences.test.ts`, `src/contracts/compactInputSchema.test.ts`, `tests/conformance/contracts/mcpInputSchemaProfile.test.ts`, `src/application/sqlite` and `tests/boundary/sqlite`: 11 files, 128 passed, 1 skipped. - `tests/boundary/mcp/toolSchemaValidity.test.ts` with the compact test: 21 passed. Building the catalog artifact it needs requires `compile`, which fails on current `main` at `src/android/JadxAnalysis.ts:366` (#2852, fix in #2850). I ran it with a local, uncommitted workaround for that line only. - `tsc --noEmit`: no errors in the changed files. The errors it does report are already on `main` (`JadxAnalysis.ts`, `analysisView.test.ts`, `IdaSessionClient.test.ts`). - `verify:gemini-client` was not run: no Gemini CLI on this host. Observation, not changed here: the catalog also advertises `if`/`then` (`inspect_sqlite_database`) and `not` (`compare_web_captures`), which are also outside Gemini's strict `Schema` message. The reporter's gateway strips those, so they did not break the request. I am happy to follow up if you would rather the advertised catalog avoid them too. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-31 01:06:50 +00:00
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#5462
No description provided.