[GH-ISSUE #7123] [Bug] Advertised input schema normalization and literal constraint checks skip contentSchema and array-valued tuple items #4281

Open
opened 2026-10-31 00:48:27 +00:00 by bsakaguchi · 2 comments
Owner

Originally created by @carcraze on GitHub (Oct 25, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/7123

Before submitting

  • I searched the open and closed issues for a related report.
  • I removed credentials, tokens, private paths, and sensitive target data.

Area

MCP or agent integration

Observed behavior

Two schema positions are currently skipped during advertised input-schema literal normalization and client-constraint validation:

  1. contentSchema (draft 2020-12) is absent from schemaChildren in src/contracts/jsonSchemaKeywords.ts, so presentInputJsonSchema leaves contentSchema: { const: "" } un-widened, and localInputReferences / unsupportedInputLiteralSchemaError skip contentSchema subschemas.
  2. In tests/fixtures/mcpClientSchemaConstraints.ts, unsupportedInputLiteralSchemaError only iterates array-valued children for schemaArrays keywords, whereas arrayItemSchemaError checks (schemaArrays.has(key) || schemaChildren.has(key)) && Array.isArray(value). Array-valued tuple items: [{ type: "string" }, { const: "" }] are therefore skipped by unsupportedInputLiteralSchemaError.
  3. In src/contracts/inputSchemaPresentation.ts, widening a mixed enum containing "" (such as enum: ["", 1]) drops enum without preserving the primitive member types as anyOf.

Fixed in PR #7122.

Reproduction

  1. Call presentInputJsonSchema({ type: "object", properties: { value: { type: "string", contentSchema: { const: "" } }, mixed: { enum: ["", 1] } } }, () => undefined).
  2. Call unsupportedInputLiteralSchemaError({ type: "array", items: [{ type: "string" }, { const: "" }] }, "tuple").
  3. Observe contentSchema.const === "" remains in the advertised schema, mixed loses its string | integer member types, and unsupportedInputLiteralSchemaError returns undefined on the tuple items array.

Expected behavior

  • contentSchema is included in schemaChildren and traversed by literal normalization, reference checks, and client-constraint checks.
  • unsupportedInputLiteralSchemaError shares child traversal with arrayItemSchemaError so array-valued tuple items are checked.
  • Mixed primitive enums containing "" widen to anyOf of their primitive member types.

Impact and scope

Affecting advertised schema normalization and catalog-wide client-constraint guards in src/contracts/ and tests/fixtures/mcpClientSchemaConstraints.ts.

REA version

6.8.0

Runtime and platform

Node v24.22.1; Ubuntu Linux x86_64

Target and artifact context

not applicable

Interface

MCP

Earliest failure stage

Transport or result projection

Relevant output or evidence

Covered by unit and boundary regressions in PR #7122.

Originally created by @carcraze on GitHub (Oct 25, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/7123 ### Before submitting - [x] I searched the open and closed issues for a related report. - [x] I removed credentials, tokens, private paths, and sensitive target data. ### Area MCP or agent integration ### Observed behavior Two schema positions are currently skipped during advertised input-schema literal normalization and client-constraint validation: 1. `contentSchema` (draft 2020-12) is absent from `schemaChildren` in [`src/contracts/jsonSchemaKeywords.ts`](https://github.com/morluto/rea/blob/rea-agents-6.8.0/src/contracts/jsonSchemaKeywords.ts#L10-L22), so `presentInputJsonSchema` leaves `contentSchema: { const: "" }` un-widened, and `localInputReferences` / `unsupportedInputLiteralSchemaError` skip `contentSchema` subschemas. 2. In [`tests/fixtures/mcpClientSchemaConstraints.ts`](https://github.com/morluto/rea/blob/rea-agents-6.8.0/tests/fixtures/mcpClientSchemaConstraints.ts#L58-L78), `unsupportedInputLiteralSchemaError` only iterates array-valued children for `schemaArrays` keywords, whereas `arrayItemSchemaError` checks `(schemaArrays.has(key) || schemaChildren.has(key)) && Array.isArray(value)`. Array-valued tuple `items: [{ type: "string" }, { const: "" }]` are therefore skipped by `unsupportedInputLiteralSchemaError`. 3. In [`src/contracts/inputSchemaPresentation.ts`](https://github.com/morluto/rea/blob/rea-agents-6.8.0/src/contracts/inputSchemaPresentation.ts#L263-L274), widening a mixed `enum` containing `""` (such as `enum: ["", 1]`) drops `enum` without preserving the primitive member types as `anyOf`. Fixed in PR #7122. ### Reproduction 1. Call `presentInputJsonSchema({ type: "object", properties: { value: { type: "string", contentSchema: { const: "" } }, mixed: { enum: ["", 1] } } }, () => undefined)`. 2. Call `unsupportedInputLiteralSchemaError({ type: "array", items: [{ type: "string" }, { const: "" }] }, "tuple")`. 3. Observe `contentSchema.const === ""` remains in the advertised schema, `mixed` loses its `string | integer` member types, and `unsupportedInputLiteralSchemaError` returns `undefined` on the tuple `items` array. ### Expected behavior - `contentSchema` is included in `schemaChildren` and traversed by literal normalization, reference checks, and client-constraint checks. - `unsupportedInputLiteralSchemaError` shares child traversal with `arrayItemSchemaError` so array-valued tuple `items` are checked. - Mixed primitive `enum`s containing `""` widen to `anyOf` of their primitive member types. ### Impact and scope Affecting advertised schema normalization and catalog-wide client-constraint guards in `src/contracts/` and `tests/fixtures/mcpClientSchemaConstraints.ts`. ### REA version 6.8.0 ### Runtime and platform Node v24.22.1; Ubuntu Linux x86_64 ### Target and artifact context not applicable ### Interface MCP ### Earliest failure stage Transport or result projection ### Relevant output or evidence Covered by unit and boundary regressions in PR #7122.
Author
Owner

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

三个问题都确认是真实且相互关联的:contentSchema 漏进 schemaChildren 会让 advertised schema 保留 const: "" 这种无法被 Gemini 类客户端消费的字面量;unsupportedInputLiteralSchemaError 只遍历 schemaArrays 关键字导致 tuple 形式 [{type:"string"},{const:""}] 逃过校验,和 arrayItemSchemaError 的判定标准不一致;mixed enum 去重空串后丢弃原始成员类型则会让工具参数能力被静默缩小。认可 PR #7122 的收敛方向——特别是让 unsupportedInputLiteralSchemaError 与 arrayItemSchemaError 共享同一套 child 遍历逻辑,能避免两处判定再次分叉。建议补两类回归:1) contentSchema 嵌套在 properties/items 深层时的递归遍历;2) enum 中含 "" 且同时有对象的场景,确认展开成 anyOf 后各成员类型都保留。对 6.8.0 默认 compact 目录来说这种校验正是防止广告 schema 与真实约束漂移的关键。

<!-- gh-comment-id:6396646075 --> @XinwangTao commented on GitHub (Oct 25, 2026): 三个问题都确认是真实且相互关联的:contentSchema 漏进 schemaChildren 会让 advertised schema 保留 `const: ""` 这种无法被 Gemini 类客户端消费的字面量;unsupportedInputLiteralSchemaError 只遍历 schemaArrays 关键字导致 tuple 形式 `[{type:"string"},{const:""}]` 逃过校验,和 arrayItemSchemaError 的判定标准不一致;mixed enum 去重空串后丢弃原始成员类型则会让工具参数能力被静默缩小。认可 PR #7122 的收敛方向——特别是让 unsupportedInputLiteralSchemaError 与 arrayItemSchemaError 共享同一套 child 遍历逻辑,能避免两处判定再次分叉。建议补两类回归:1) contentSchema 嵌套在 properties/items 深层时的递归遍历;2) enum 中含 `""` 且同时有对象的场景,确认展开成 anyOf 后各成员类型都保留。对 6.8.0 默认 compact 目录来说这种校验正是防止广告 schema 与真实约束漂移的关键。
Author
Owner

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

Good catch — skipping contentSchema means clients that rely on the advertised schema will widen const constraints incorrectly (or fail the literal check) for draft 2020-12 schemas, and the array-valued literal constraint case has the same blind spot. Suggestion: extend the keyword set in jsonSchemaKeywords.ts to cover contentSchema (and the annotation-only siblings like deprecated/description are already handled elsewhere, so scope is small), then add a regression test that feeds a 2020-12 schema with contentSchema + an array-valued literal and asserts normalization and the client-side constraint error path behave identically to plain string schemas.

<!-- gh-comment-id:6399583336 --> @XinwangTao commented on GitHub (Oct 25, 2026): Good catch — skipping contentSchema means clients that rely on the advertised schema will widen const constraints incorrectly (or fail the literal check) for draft 2020-12 schemas, and the array-valued literal constraint case has the same blind spot. Suggestion: extend the keyword set in jsonSchemaKeywords.ts to cover contentSchema (and the annotation-only siblings like deprecated/description are already handled elsewhere, so scope is small), then add a regression test that feeds a 2020-12 schema with contentSchema + an array-valued literal and asserts normalization and the client-side constraint error path behave identically to plain string schemas.
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#4281
No description provided.