提交前确认 · Pre-submission checklist
问题类别 · Category
工具调用 / MCP · Tool use / MCP
涉及的 Agent 框架 · Agent framework
ZCode Agent(自研)
严重程度 · Severity
Blocking for affected MCP tools: valid calls are rejected before reaching the MCP server.
复现频率 · Reproducibility
Always in the deterministic cases below.
问题描述 · Description
ZCode's tool-input validator counts unresolved local $ref branches as successful matches. When a property uses oneOf with two such branches, an input that should match exactly one branch is rejected as matching both. Replacing the references with their definitions makes the same input pass.
This is client-side argument validation, not a model-generation failure or a remote API error. All references in the example are local JSON Pointers; no external schema retrieval is needed.
Related but different: #387 reports an API failure when a property is literally named $ref. This report concerns actual schema references inside oneOf in the ZCode validator.
复现步骤 · Steps to reproduce
- Expose a harmless MCP tool named
ref_demo, whose handler simply echoes its arguments, with the following inputSchema:
{
"type": "object",
"properties": {
"job": {
"oneOf": [
{ "$ref": "#/$defs/ByText" },
{ "$ref": "#/$defs/ById" }
]
}
},
"required": ["job"],
"additionalProperties": false,
"$defs": {
"ByText": {
"type": "object",
"properties": {
"kind": { "const": "text" },
"text": { "type": "string" }
},
"required": ["kind", "text"],
"additionalProperties": false
},
"ById": {
"type": "object",
"properties": {
"kind": { "const": "id" },
"id": { "type": "integer" }
},
"required": ["kind", "id"],
"additionalProperties": false
}
}
}
- Invoke it with either of these inputs:
{ "job": { "kind": "text", "text": "example" } }
{ "job": { "kind": "id", "id": 1 } }
- For a model-independent reproduction in the source tree, pass each input and the schema above to the existing helper:
validateJsonSchemaValue(input, schema);
- As a control, replace the two
$ref objects in properties.job.oneOf with the contents of $defs.ByText and $defs.ById, leaving the input and all constraints unchanged. Both inputs then validate successfully.
期望表现 · Expected behavior
Each input matches exactly one branch and reaches the echo handler. Local references should be resolved before evaluating oneOf.
If a schema feature is deliberately unsupported, an explicit unsupported-schema error would be preferable to interpreting its reference branches as successful matches and blaming valid input.
实际表现 · Actual behavior
For both inputs, the minimized source-helper reproduction returns:
{
"valid": false,
"errors": [
"$.job must match exactly one oneOf schema, matched 2"
],
"issues": [
{
"code": "invalid_union",
"errors": [[], []],
"path": ["job"],
"message": "Invalid input"
}
]
}
The inlined control returns:
{ "valid": true, "errors": [], "issues": [] }
ZCode 版本 · ZCode version
- Windows Desktop: 3.14.4.7912.
- Bundled engine: 0.16.9.
- Public source inspected:
29628c9acdb81b703bbd4080c207a0e7ce5e276e.
设备 / 系统 / 浏览器 · Device / OS / Browser
Windows x64. Installed-runtime integration verification used a deterministic local model endpoint and a real local echo MCP subprocess, so it did not depend on a cloud model, account, or paid provider.
截图 / 录屏 / 日志 · Verification and source evidence
- In a controlled run of the unmodified installed engine using
--prompt --surface desktop, the referenced-schema fixture was rejected with InputValidationError / invalid_union before its MCP handler ran. Its equivalent inlined-schema control reached the MCP handler successfully. This is running-engine integration evidence, not a fresh Desktop GUI replay of the minimized example.
- The exact two-branch example above was separately executed against the public
validateJsonSchemaValue implementation. Both inputs failed with references and passed with equivalent inline definitions. The displayed JSON is the minimal reproduction output, not a user log.
- In
packages/core/src/tool/json-schema.ts, validateNode evaluates each oneOf candidate and counts candidates without errors. It does not resolve $ref; reference-only candidate objects therefore contribute no validation errors.
This report concerns the concrete false rejection. It does not assume a particular negotiated MCP protocol version or make a broader protocol-conformance claim.
中文摘要
ZCode 的工具参数校验器没有解析本地 $ref。当 oneOf 的分支只有引用时,各分支都被当作校验成功,导致本来只匹配一个分支的合法输入被拒绝。上面的两个分支完全使用虚构数据,不需要外部 schema、账户或网络服务。
已分别验证两种输入:使用引用时均返回 matched 2 和两个空错误列表;展开相同定义后均校验成功。另有未修改的已安装引擎与本地模型/MCP 子进程的集成验证,确认同类问题会在到达 MCP handler 前阻断调用。最小示例的验证属于源码函数验证,不声称已重新完成 Desktop GUI 验证。
期望先解析本地引用,再按 oneOf 语义校验;如果有意不支持该 schema 特性,也应明确报告不支持,而不是误报合法参数匹配多个分支。此问题与 #387 的远程 API 崩溃不同。
提交前确认 · Pre-submission checklist
问题类别 · Category
工具调用 / MCP · Tool use / MCP
涉及的 Agent 框架 · Agent framework
ZCode Agent(自研)
严重程度 · Severity
Blocking for affected MCP tools: valid calls are rejected before reaching the MCP server.
复现频率 · Reproducibility
Always in the deterministic cases below.
问题描述 · Description
ZCode's tool-input validator counts unresolved local
$refbranches as successful matches. When a property usesoneOfwith two such branches, an input that should match exactly one branch is rejected as matching both. Replacing the references with their definitions makes the same input pass.This is client-side argument validation, not a model-generation failure or a remote API error. All references in the example are local JSON Pointers; no external schema retrieval is needed.
Related but different: #387 reports an API failure when a property is literally named
$ref. This report concerns actual schema references insideoneOfin the ZCode validator.复现步骤 · Steps to reproduce
ref_demo, whose handler simply echoes its arguments, with the followinginputSchema:{ "type": "object", "properties": { "job": { "oneOf": [ { "$ref": "#/$defs/ByText" }, { "$ref": "#/$defs/ById" } ] } }, "required": ["job"], "additionalProperties": false, "$defs": { "ByText": { "type": "object", "properties": { "kind": { "const": "text" }, "text": { "type": "string" } }, "required": ["kind", "text"], "additionalProperties": false }, "ById": { "type": "object", "properties": { "kind": { "const": "id" }, "id": { "type": "integer" } }, "required": ["kind", "id"], "additionalProperties": false } } }{ "job": { "kind": "text", "text": "example" } }{ "job": { "kind": "id", "id": 1 } }$refobjects inproperties.job.oneOfwith the contents of$defs.ByTextand$defs.ById, leaving the input and all constraints unchanged. Both inputs then validate successfully.期望表现 · Expected behavior
Each input matches exactly one branch and reaches the echo handler. Local references should be resolved before evaluating
oneOf.If a schema feature is deliberately unsupported, an explicit unsupported-schema error would be preferable to interpreting its reference branches as successful matches and blaming valid input.
实际表现 · Actual behavior
For both inputs, the minimized source-helper reproduction returns:
{ "valid": false, "errors": [ "$.job must match exactly one oneOf schema, matched 2" ], "issues": [ { "code": "invalid_union", "errors": [[], []], "path": ["job"], "message": "Invalid input" } ] }The inlined control returns:
{ "valid": true, "errors": [], "issues": [] }ZCode 版本 · ZCode version
29628c9acdb81b703bbd4080c207a0e7ce5e276e.设备 / 系统 / 浏览器 · Device / OS / Browser
Windows x64. Installed-runtime integration verification used a deterministic local model endpoint and a real local echo MCP subprocess, so it did not depend on a cloud model, account, or paid provider.
截图 / 录屏 / 日志 · Verification and source evidence
--prompt --surface desktop, the referenced-schema fixture was rejected withInputValidationError/invalid_unionbefore its MCP handler ran. Its equivalent inlined-schema control reached the MCP handler successfully. This is running-engine integration evidence, not a fresh Desktop GUI replay of the minimized example.validateJsonSchemaValueimplementation. Both inputs failed with references and passed with equivalent inline definitions. The displayed JSON is the minimal reproduction output, not a user log.packages/core/src/tool/json-schema.ts,validateNodeevaluates eachoneOfcandidate and counts candidates without errors. It does not resolve$ref; reference-only candidate objects therefore contribute no validation errors.This report concerns the concrete false rejection. It does not assume a particular negotiated MCP protocol version or make a broader protocol-conformance claim.
中文摘要
ZCode 的工具参数校验器没有解析本地
$ref。当oneOf的分支只有引用时,各分支都被当作校验成功,导致本来只匹配一个分支的合法输入被拒绝。上面的两个分支完全使用虚构数据,不需要外部 schema、账户或网络服务。已分别验证两种输入:使用引用时均返回
matched 2和两个空错误列表;展开相同定义后均校验成功。另有未修改的已安装引擎与本地模型/MCP 子进程的集成验证,确认同类问题会在到达 MCP handler 前阻断调用。最小示例的验证属于源码函数验证,不声称已重新完成 Desktop GUI 验证。期望先解析本地引用,再按
oneOf语义校验;如果有意不支持该 schema 特性,也应明确报告不支持,而不是误报合法参数匹配多个分支。此问题与 #387 的远程 API 崩溃不同。