Skip to content

fix(mcp): keep Gemini-rejected dependency keywords out of input schemas - #2877

Closed
thefolahan wants to merge 4 commits into
morluto:mainfrom
thefolahan:fix/gemini-schema-keywords
Closed

thefolahan wants to merge 4 commits into
morluto:mainfrom
thefolahan:fix/gemini-schema-keywords

Conversation

@thefolahan

@thefolahan thefolahan commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

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:

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 (Main compile: optional Jadx schema output is incompatible with JsonValue #2852, fix in fix(android): require explicit invoke coverage state #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.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-13T22:23:53.923203Z ea4cfc9 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@greptile-apps

greptile-apps Bot commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 5/5

[Low impact] This documentation-only change appears safe to merge.

Summary

Updates docs/mcp-contracts.md to explain how advertised input schemas differ from server checks.

  • MCP docs explain that related input fields are checked at runtime.

No actionable issues were found. GitHub status was unavailable, so whether another PR supersedes this one could not be confirmed.

Reviews (8) · Last reviewed commit: "Merge origin/main into fix/gemini-schema..." · Reviewed by Greptile

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 67430914e7

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/domain/sqlite/sqliteDatabase.ts Resolved
@morluto

morluto commented Oct 13, 2026

Copy link
Copy Markdown
Owner

Source fixes and publication evidence for the review findings below. Tests and executable checks were skipped at the maintainer's request. Findings that still require a decision or execution evidence remain open.

review thread, review thread

The schema owner moves table-dependency guidance to root text retained by compact projection, and the public contract now states that compact clients cannot rely on omitted partner validation. The changes are live at 16b7a16. Source inspection and git diff --check only; tests were not run.

@morluto
morluto force-pushed the fix/gemini-schema-keywords branch from a9f9bab to aca7106 Compare October 13, 2026 18:10

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: aca7106961

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 197 to 200
// Partner fields stay in the group description rather than in
// dependentRequired or dependencies: Gemini function declarations reject
// both, and one unknown keyword fails the client's whole tool catalog.
...(fewestRequired > 0 ? { minProperties: fewestRequired } : {}),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Update the browser boundary's incomplete-group expectations

npm run test:mcp now fails in tests/boundary/mcp/browserComparisonInput.test.ts: its invalid table still assigns advertisedValid: false to { ...passive, normalization } and the two scenario-plus-normalization cases (lines 113-121 and 144-147). After partner dependencies stop being emitted here, all three inputs contain only known, correctly typed properties and satisfy minProperties, so Ajv returns true while the assertion at line 155 expects false; move these cases into the advertised-valid/runtime-invalid coverage so the affected boundary test matches the new server-side-only enforcement.

AGENTS.md reference: AGENTS.md:L25-L25

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in ea4cfc9. The three inputs that carry normalization without both scenario captures (with the passive pair, or with only one scenario side) are now in the group the advertised schema accepts and the canonical parser rejects, next to the mixed families case. A lone before or before_scenario is still rejected by the advertised schema, so those stay in the fully invalid list. The test passes locally on Node 24.21.0.

@morluto
morluto force-pushed the fix/gemini-schema-keywords branch from aca7106 to 5ffd3ef Compare October 13, 2026 18:26

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5ffd3ef766

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread docs/mcp-contracts.md
Comment on lines +628 to +630
enforces the exact union, including partner fields and exclusions that the
advertised projection does not express, so a client must not rely on the
advertised schema to reject an incomplete group. Tests validate the schemas

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Correct the remaining incomplete-pair promise

Although this general paragraph was corrected, the fresh evidence is the unchanged “Comparison input shapes” paragraph at lines 697–700, which still promises that the advertised compare_web_captures schema rejects incomplete pairs. This commit's test at src/contracts/toolInputReferences.test.ts:350-363 now establishes that { before_scenario: 1, normalization: true } passes advertised validation while the canonical parser rejects it, so users following the concrete tool documentation can incorrectly assume the client schema will catch such calls; update that section to match the new server-side-only partner enforcement.

AGENTS.md reference: AGENTS.md:L25-L25

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in ea4cfc9. "Comparison input shapes" now says that mixed families, and normalization without both scenario captures, can pass advertised validation and are rejected by the SDK against the canonical schema. Incomplete pairs themselves are still rejected by the advertised schema, so that sentence stays.

Gemini function declarations reject dependentRequired and dependencies,
and one unknown keyword fails the client's whole tool catalog. Flattened
root unions no longer advertise the partner map, and the SQLite input
states its table requirement in its descriptions instead. The canonical
parsers still enforce both rules; a boundary test now checks every
advertised schema in the full and compact profiles.

Fixes morluto#2832
…ntract

The compact profile strips field descriptions, so the SQLite table
requirement moved to the root description, which it keeps; a boundary
assertion checks it in both profiles. docs/mcp-contracts.md no longer
promises that advertised root unions express group dependencies: partner
fields are guidance there and enforced by the canonical parser.
@morluto
morluto force-pushed the fix/gemini-schema-keywords branch from 5ffd3ef to 5447a5d Compare October 13, 2026 18:38
@morluto morluto added area: mcp MCP server, transport, and tool registration bug Something isn't working labels Oct 14, 2026
morluto added a commit that referenced this pull request Oct 14, 2026
Use one named input-schema projection for clients and catalog identity, preserve dialect declarations, and bound compact schema depth. Keep canonical SDK output validation when output advertisements are disabled. Release request-owned state on cancellation and carry upstream limitations through composed workflows. Preserve doctor full-output envelopes and validate navigation facts at their owner.

Reviewed fixes: #2088, #2108, #2513, #2684, #2693, #2695, #2836, #2864, #2868, #2877, #2933, #2998, #3002, #3015.

Validation: focused schema, SDK output-validation, context, and workflow tests passed; no schema dialect or canonical output validation was relaxed.
To3akaRin added a commit to To3akaRin/rea that referenced this pull request Oct 14, 2026
Assert SAZ expansion-limit code and byte constraint through stdio MCP as well as CLI, without partial results or source mutation. Align schema presentation guidance with canonical runtime partner validation. The general MCP documentation paragraph preserves the upstream explanation from 5447a5d in PR morluto#2877.

Co-authored-by: Omisakin Joshua <117924167+thefolahan@users.noreply.github.com>
(cherry picked from commit 5d906ecbe1ef7e6ca9e2129dd9dbc25d6145d1e9)
@kaoru0822-kitauji kaoru0822-kitauji added the ci-fix-wip Claimed by the CI-fix track label Oct 14, 2026
Main (80de314) already strips dependentRequired/dependencies from every
advertised input schema, states partner fields as root description guidance
(for example the SQLite "When row_limit is provided, also provide table."),
and tests both catalog profiles for those keywords. Keep main's SQLite schema,
presentation, and tests instead of this branch's hand-written SQLite
description and duplicate keyword walker. Keep this branch's docs update: main's
contract text still said the projection retains group-specific field
dependencies.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Repo admins can enable using credits for code reviews in their settings.

@kaoru0822-kitauji

Copy link
Copy Markdown
Collaborator

CI-fix track: I merged current main and resolved the conflicts (2807b99). The failing Static checks, Source tests and shard jobs reflected main's state at the time. Main already took the core of this fix in 80de314 (which lists #2877): advertised input schemas no longer carry dependentRequired or dependencies, partner fields become root description guidance (SQLite: "When row_limit is provided, also provide table."), and compactInputSchemaMcp tests both catalog profiles for those keywords. This PR's hand-written SQLite description replaced that generated guidance and failed main's test, so I kept main's SQLite schema and test and dropped the duplicate keyword walker. What's left is this PR's docs/mcp-contracts.md update, which corrects main's text that still says the projection retains group-specific field dependencies. docs:check passes, as do the MCP schema boundary tests (9).

@thefolahan

Copy link
Copy Markdown
Contributor Author

Closing this, since the core of the fix landed on main in 80de314. Thank you @kaoru0822-kitauji for the merge and the summary.

The only part left is the docs/mcp-contracts.md correction: main's text still says the projection retains group specific field dependencies, while the advertised schema no longer carries them. The corrected wording is in this PR's diff if a maintainer wants to fold it in.

I am closing it partly to stay within the open pull request limit for contributors, so I can open a small fix for the real Ghidra Swift verifier, which currently fails on main.

@thefolahan thefolahan closed this Oct 14, 2026
@morluto

morluto commented Oct 15, 2026

Copy link
Copy Markdown
Owner

@thefolahan, thanks for identifying that a single unsupported dependency keyword could make an entire Gemini tool catalog unavailable. The catalog projection now explains field-group relationships in guidance text and leaves exact enforcement to the canonical runtime schema (main).

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

Labels

area: mcp MCP server, transport, and tool registration bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Gemini-backed clients reject the whole tool catalog: advertised schemas emit dependentRequired / dependencies / $schema

3 participants