[PR #7122] fix(mcp): traverse contentSchema and tuple items in literal normalization #7656

Open
opened 2026-11-03 13:39:25 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/7122
Author: @carcraze
Created: 10/25/2026
Status: 🔄 Open

Base: main ← Head: fix/content-schema-literal-traversal


📝 Commits (1)

  • 378e2df fix(mcp): traverse contentSchema in schema keyword normalization

📊 Changes

3 files changed (+64 additions, -23 deletions)

View changed files

📝 src/contracts/jsonSchemaKeywords.ts (+1 -0)
📝 src/contracts/toolInputReferences.test.ts (+40 -0)
📝 tests/boundary/mcp/toolSchemaValidity.test.ts (+23 -23)

📄 Description

Summary

Fixes #7123.

Closes three gaps in advertised input-schema literal normalization and catalog-wide client-constraint checks:

  1. src/contracts/jsonSchemaKeywords.ts: add contentSchema to schemaChildren so schema-valued contentSchema subschemas are traversed during literal normalization, reference checks, and client-constraint checks.
  2. tests/fixtures/mcpClientSchemaConstraints.ts & tests/boundary/mcp/toolSchemaValidity.test.ts: extract a shared schemaChildEntries helper so unsupportedInputLiteralSchemaError traverses array-valued schemaChildren (such as draft-07 tuple items) just like arrayItemSchemaError, and reuse the shared jsonSchemaKeywords sets in localInputReferences.
  3. src/contracts/inputSchemaPresentation.ts: preserve every primitive member type via literalSchemaType when widening a mixed enum containing "" (presenting anyOf of the primitive member types rather than an untyped schema).

Problem and expected behavior

Trigger:

  • presentInputJsonSchema on { type: "string", contentSchema: { const: "" } } left const: "" un-widened because contentSchema was absent from schemaChildren.
  • unsupportedInputLiteralSchemaError on { type: "array", items: [{ type: "string" }, { const: "" }] } returned undefined because array-valued schemaChildren were only traversed in arrayItemSchemaError.
  • presentInputJsonSchema on { enum: ["", 1] } dropped enum without retaining anyOf: [{ type: "string" }, { type: "integer" }].

Expected: all three positions are normalized and checked consistently across full and compact profiles.

Change and scope

  • src/contracts/jsonSchemaKeywords.ts: add "contentSchema" to schemaChildren.
  • src/contracts/inputSchemaPresentation.ts: add literalSchemaType so mixed primitive enums containing "" widen to anyOf of their member types.
  • tests/fixtures/mcpClientSchemaConstraints.ts: share schemaChildEntries between arrayItemSchemaError and unsupportedInputLiteralSchemaError.
  • tests/boundary/mcp/toolSchemaValidity.test.ts: import the shared keyword sets in localInputReferences and cover tuple items in unsupportedInputLiteralSchemaError.
  • src/contracts/toolInputReferences.test.ts: add regression tests for mixed-enum widening, contentSchema widening, and the recorded applicationFeatureSeedSchema trace seed.

Follow the contribution scope. Not applicable (ordinary MCP schema projection and test-guard fix within existing boundaries).

Contract and boundary impact

  • Semantic owner and earliest changed stage: src/contracts/jsonSchemaKeywords.ts and src/contracts/inputSchemaPresentation.ts.
  • Contribution scope fit and linked maintainer decision: not applicable.
  • CLI and MCP/tool-catalog contract: advertised input schemas and client-constraint tests only; canonical runtime validation is unchanged.
  • Provider, bridge, target-format, or platform compatibility: none.
  • Evidence, artifact, provenance, or reconstruction contract: none.
  • Target selection, authority, upstream behavior, and cleanup details (if applicable): not applicable.
  • Generated metadata (docs/public/product-catalog.json), package, or installation impact: none.

Expected effects:

  • Documentation or usability only; no target interaction.

Evidence and regression coverage

  • Tests added or updated: src/contracts/toolInputReferences.test.ts and tests/boundary/mcp/toolSchemaValidity.test.ts.
  • Base reproduction or other evidence: unit tests verify enum: ["", 1] widens to anyOf: [{ type: "string" }, { type: "integer" }], contentSchema: { const: "" } widens to { type: "string" }, and unsupportedInputLiteralSchemaError catches tuple items[1].
  • User-visible CLI/MCP output (if applicable): not applicable.
  • Remaining proof gaps: none.

Validation performed

  • npx vitest run src/contracts/toolInputReferences.test.ts — 37 passed
  • npx vitest run tests/boundary/mcp/compactInputSchemaMcp.test.ts tests/boundary/mcp/toolSchemaValidity.test.ts — 28 passed
  • npm run check:fast (tsc --noEmit, oxlint, verify:module-boundaries) & npm run format:check — clean (0 errors)

Compatibility, safety, and release

  • Breaking changes or migration steps: none.
  • Real Hopper/Ghidra, browser, or OS coverage: not applicable.
  • Package or release metadata impact: none.
  • Security, privacy, process, or containment review: none.

Author readiness

Human owner: @carcraze

  • I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work.
  • I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps.
  • I declare this PR ready for initial maintainer review.

Before merge

  • This PR addresses a concrete problem or an agreed enhancement.
  • Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff.
  • The PR has one focused outcome and the title follows type(scope): outcome.
  • Related issue is linked, or the reason for not linking one is stated above.
  • Tests cover changed observable behavior and meaningful failure paths.
  • Owning docs, contracts, and generated metadata are updated where needed.
  • User-visible CLI/MCP changes include representative output.
  • I checked the final diff for secrets, unrelated cleanup, and unsupported claims.

🔄 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/7122 **Author:** [@carcraze](https://github.com/carcraze) **Created:** 10/25/2026 **Status:** 🔄 Open **Base:** `main` ← **Head:** `fix/content-schema-literal-traversal` --- ### 📝 Commits (1) - [`378e2df`](https://github.com/morluto/rea/commit/378e2dfbf35a5e6284f0cb12e2a6335fc562232c) fix(mcp): traverse contentSchema in schema keyword normalization ### 📊 Changes **3 files changed** (+64 additions, -23 deletions) <details> <summary>View changed files</summary> 📝 `src/contracts/jsonSchemaKeywords.ts` (+1 -0) 📝 `src/contracts/toolInputReferences.test.ts` (+40 -0) 📝 `tests/boundary/mcp/toolSchemaValidity.test.ts` (+23 -23) </details> ### 📄 Description ## Summary Fixes #7123. Closes three gaps in advertised input-schema literal normalization and catalog-wide client-constraint checks: 1. `src/contracts/jsonSchemaKeywords.ts`: add `contentSchema` to `schemaChildren` so schema-valued `contentSchema` subschemas are traversed during literal normalization, reference checks, and client-constraint checks. 2. `tests/fixtures/mcpClientSchemaConstraints.ts` & `tests/boundary/mcp/toolSchemaValidity.test.ts`: extract a shared `schemaChildEntries` helper so `unsupportedInputLiteralSchemaError` traverses array-valued `schemaChildren` (such as draft-07 tuple `items`) just like `arrayItemSchemaError`, and reuse the shared `jsonSchemaKeywords` sets in `localInputReferences`. 3. `src/contracts/inputSchemaPresentation.ts`: preserve every primitive member type via `literalSchemaType` when widening a mixed `enum` containing `""` (presenting `anyOf` of the primitive member types rather than an untyped schema). ## Problem and expected behavior Trigger: - `presentInputJsonSchema` on `{ type: "string", contentSchema: { const: "" } }` left `const: ""` un-widened because `contentSchema` was absent from `schemaChildren`. - `unsupportedInputLiteralSchemaError` on `{ type: "array", items: [{ type: "string" }, { const: "" }] }` returned `undefined` because array-valued `schemaChildren` were only traversed in `arrayItemSchemaError`. - `presentInputJsonSchema` on `{ enum: ["", 1] }` dropped `enum` without retaining `anyOf: [{ type: "string" }, { type: "integer" }]`. Expected: all three positions are normalized and checked consistently across full and compact profiles. ## Change and scope - `src/contracts/jsonSchemaKeywords.ts`: add `"contentSchema"` to `schemaChildren`. - `src/contracts/inputSchemaPresentation.ts`: add `literalSchemaType` so mixed primitive enums containing `""` widen to `anyOf` of their member types. - `tests/fixtures/mcpClientSchemaConstraints.ts`: share `schemaChildEntries` between `arrayItemSchemaError` and `unsupportedInputLiteralSchemaError`. - `tests/boundary/mcp/toolSchemaValidity.test.ts`: import the shared keyword sets in `localInputReferences` and cover tuple `items` in `unsupportedInputLiteralSchemaError`. - `src/contracts/toolInputReferences.test.ts`: add regression tests for mixed-enum widening, `contentSchema` widening, and the recorded `applicationFeatureSeedSchema` trace seed. Follow the [contribution scope](https://github.com/morluto/rea/blob/main/CONTRIBUTING.md#contribution-scope). Not applicable (ordinary MCP schema projection and test-guard fix within existing boundaries). ## Contract and boundary impact - Semantic owner and earliest changed stage: `src/contracts/jsonSchemaKeywords.ts` and `src/contracts/inputSchemaPresentation.ts`. - Contribution scope fit and linked maintainer decision: not applicable. - CLI and MCP/tool-catalog contract: advertised input schemas and client-constraint tests only; canonical runtime validation is unchanged. - Provider, bridge, target-format, or platform compatibility: none. - Evidence, artifact, provenance, or reconstruction contract: none. - Target selection, authority, upstream behavior, and cleanup details (if applicable): not applicable. - Generated metadata (`docs/public/product-catalog.json`), package, or installation impact: none. Expected effects: - [x] Documentation or usability only; no target interaction. ## Evidence and regression coverage - Tests added or updated: `src/contracts/toolInputReferences.test.ts` and `tests/boundary/mcp/toolSchemaValidity.test.ts`. - Base reproduction or other evidence: unit tests verify `enum: ["", 1]` widens to `anyOf: [{ type: "string" }, { type: "integer" }]`, `contentSchema: { const: "" }` widens to `{ type: "string" }`, and `unsupportedInputLiteralSchemaError` catches tuple `items[1]`. - User-visible CLI/MCP output (if applicable): not applicable. - Remaining proof gaps: none. ## Validation performed - `npx vitest run src/contracts/toolInputReferences.test.ts` — 37 passed - `npx vitest run tests/boundary/mcp/compactInputSchemaMcp.test.ts tests/boundary/mcp/toolSchemaValidity.test.ts` — 28 passed - `npm run check:fast` (`tsc --noEmit`, `oxlint`, `verify:module-boundaries`) & `npm run format:check` — clean (0 errors) ## Compatibility, safety, and release - Breaking changes or migration steps: none. - Real Hopper/Ghidra, browser, or OS coverage: not applicable. - Package or release metadata impact: none. - Security, privacy, process, or containment review: none. ## Author readiness Human owner: @carcraze - [x] I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work. - [x] I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps. - [x] I declare this PR ready for initial maintainer review. ## Before merge - [x] This PR addresses a concrete problem or an agreed enhancement. - [x] Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff. - [x] The PR has one focused outcome and the title follows `type(scope): outcome`. - [x] Related issue is linked, or the reason for not linking one is stated above. - [x] Tests cover changed observable behavior and meaningful failure paths. - [x] Owning docs, contracts, and generated metadata are updated where needed. - [x] User-visible CLI/MCP changes include representative output. - [x] I checked the final diff for secrets, unrelated cleanup, and unsupported claims. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
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#7656
No description provided.