Frontmatter
| id | 10064 |
| title | MCP: OpenApiValidator emits array schemas without items, crashing strict validators (Copilot) |
| state | Closed |
| labels | bugai |
| assignees | tobiu |
| createdAt | Apr 18, 2026, 7:46 PM |
| updatedAt | May 15, 2026, 2:42 PM |
| githubUrl | https://github.com/neomjs/neo/issues/10064 |
| author | tobiu |
| commentsCount | 0 |
| parentIssue | null |
| subIssues | [] |
| subIssuesCompleted | 0 |
| subIssuesTotal | 0 |
| contentTrust | |
| projected | |
| quarantined | 0 |
| signals | [] |
| blockedBy | [] |
| blocking | [] |
| closedAt | Apr 18, 2026, 7:58 PM |
MCP: OpenApiValidator emits array schemas without items, crashing strict validators (Copilot)
tobiu cross-referenced by PR #10065 on Apr 18, 2026, 7:51 PM
tobiu assigned to @tobiu on Apr 18, 2026, 7:53 PM
tobiu closed this issue on Apr 18, 2026, 7:58 PM
tobiu cross-referenced by PR #10066 on Apr 18, 2026, 8:42 PM
tobiu cross-referenced by #9837 on Apr 18, 2026, 9:08 PM
tobiu cross-referenced by PR #10067 on Apr 18, 2026, 9:18 PM
tobiu cross-referenced by PR #10071 on Apr 18, 2026, 10:50 PM
Problem
GitHub Copilot (via its Neural Link bridge) crashes when listing
neo.mjs-neural-linktools:Claude Desktop / Cursor tolerate the malformed schema; Copilot's validator is strictly draft-compliant and rejects any
{"type":"array"}lackingitems.Architectural Reality
Three-stage pipeline produces the defect:
ai/mcp/server/neural-link/openapi.yamlatCallMethodRequest.properties.args(and three/data/store/inspectresponse properties) declarestype: arraywith noitems— permitted by OpenAPI 3.x but ambiguous.ai/mcp/validation/OpenApiValidator.mjs:115-116fallback producesz.array(z.any())(correct Zod behavior).zod-to-json-schemawithtarget: 'openApi3'serializesz.array(z.any())as{"type":"array"}— silently stripsitems. Verified:zodToJsonSchema(z.array(z.any()), {target:'openApi3'}) === {"type":"array"} // bug zodToJsonSchema(z.array(z.unknown()), {target:'openApi3'}) === {"type":"array","items":{}} // fixThis is orthogonal to prior fixes:
z.array(z.string())regression.itemsat all — the residual third case.Blast Radius (audited)
Only
neural-link/openapi.yamlis affected. Four locations:.components.schemas.CallMethodRequest.properties.args— breakscall_methodon Copilot/data/store/inspectresponse:.properties.filters,.properties.sorters,.properties.items— breaksinspect_storeoutput schema (if validated)The other four MCP servers are clean.
Proposed Fix (Two Layers)
Layer 1 — defense-in-depth in
ai/mcp/validation/OpenApiValidator.mjs:116:- zodSchema = z.array(z.any()); + zodSchema = z.array(z.unknown());z.unknown()round-trips throughzod-to-json-schemaasitems: {}, forcing a compliant emission regardless of YAML quality.Layer 2 — source-of-truth in
ai/mcp/server/neural-link/openapi.yaml:CallMethodRequest.args→ additems: {}(heterogeneous method args, intentionally untyped)/data/store/inspectresponsefilters,sorters,items→ additems: {type: object}Avoided "Gold Standards" / Traps
z.array(z.string())fallback. That was the regression #10043 fixed — would break typed args.items: {}. Adds a second serialization layer;z.unknown()achieves the same outcome natively in Zod.Verification
Permanent Playwright regression test (per
AGENTS.md§10 rule 3) that callslistToolson the neural-link server and asserts every array-typed schema node includes anitemsproperty.Origin Session ID
97343e6e-9d1c-4170-b3a5-6e58d41511b6