fix: add missing items field to two array schemas (Gemini Pro strict JSON Schema compat)#910
Open
DmitryBMsk wants to merge 2 commits into
Open
fix: add missing items field to two array schemas (Gemini Pro strict JSON Schema compat)#910DmitryBMsk wants to merge 2 commits into
DmitryBMsk wants to merge 2 commits into
Conversation
… Schema compat)
Two array properties were declared with type: 'array' but no items field, which
Gemini Pro's strict JSON Schema validator rejects:
Invalid schema for function 'gbrain__extract_facts': In context=('properties',
'entity_hints'), array schema missing items.
Effect on real deployments: when OpenClaw 2026.5.4 (or any host that uses Gemini
Pro as the chat model) registers gbrain via stdio MCP, the daemon spawns
'gbrain serve', enumerates tools, and forwards their JSON Schemas to the LLM
API. The schema is rejected on every request, blocking the entire gbrain__*
tool surface (60 tools) for that session.
Fixes:
- src/core/operations.ts: entity_hints (extract_facts input) gets items: { type: 'string' }
— matches the existing description ('canonical entity slugs') and runtime
cast 'p.entity_hints as string[]'.
- src/core/resolvers/builtin/x-api/handle-to-tweet.ts: candidates output gets
items matching XTweetCandidate interface (tweet_id, text, created_at, score, url).
No runtime behavior change. Schema metadata only.
…chemas
Adds invariant tests that walk every operation inputSchema and every builtin
resolver inputSchema/outputSchema, collecting paths where { type: 'array' }
lacks an items field. The arrays.length === 0 assertion is the regression
guard — it would have caught both schemas fixed in the previous commit, and
will catch any future drift on the same class of bug.
- test/mcp-tool-defs.test.ts: walks buildToolDefs(operations). Catches input
schema arrays missing items (e.g. extract_facts.entity_hints).
- test/resolvers.test.ts: walks xHandleToTweetResolver and urlReachableResolver
schemas. Catches output schema arrays missing items (e.g. handle-to-tweet
outputSchema.candidates), which buildToolDefs doesn't cover.
Pure unit tests, no network/db required. Local run: 6 pass mcp-tool-defs, 55
pass resolvers.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Two array properties in
src/core/are declared withtype: 'array'but noitemsfield, which strict JSON Schema validators reject. Most notably, Gemini Pro's tool-call schema validator throws:Repro
gbrain serveas a stdio MCP child of any host that uses Gemini Pro as its chat model (OpenClaw 2026.5.4 withmcp.servers.<name>.commandconfig is one example; ChatGPT Tool calls and other strict-schema LLM gateways behave the same).End-to-end repro on my live OpenClaw deployment:
bundle-mcplogs showfailed to start server "gbrain": McpError: MCP error -32000: Connection closed, and the Telegram bot returns theInvalid schema for function 'gbrain__extract_facts'message verbatim. After the patch is applied locally and the stdio child is restarted, the bot enumerates all 60gbrain__*tools and successfully calls e.g.gbrain__get_statsreturning real numbers from Supabase.Fix
Add the missing
itemsfield to both schemas. Behavior unchanged — these are JSON Schema metadata, not runtime contracts.src/core/operations.ts—extract_facts.params.entity_hintsThe description already says "canonical entity slugs" and the handler casts the value via
p.entity_hints as string[]. Schema now matches:src/core/resolvers/builtin/x-api/handle-to-tweet.ts—outputSchema.candidatesThe TypeScript interface
XTweetCandidatealready defines the per-element shape; the JSON Schema now spells the same fields out for any consumer that runs a JSON Schema validator on the resolver output:Why not a typedef-driven generator?
Could be a future improvement (run the same TS interface through a
to-json-schemastep) — out of scope for this fix. Both schemas now match the TypeScript types that already exist alongside them.Test plan
gbrain__extract_factsrejection on a live OpenClaw 2026.5.4 + Gemini Pro deployment (private OCI setup).bundle-mcpno longer errors and all 60gbrain__*tools are surfaced into the LLM tool inventory.gbrain__get_statsandgbrain__searchround-trip successfully end-to-end (host → MCP → Supabase) after the patch.Notes
type: 'array'declarations withoutitemsinsrc/; only these two showed up in master at the time of writing (commit 17b190e).Need help on this PR? Tag
@codesmithwith what you need.