Skip to content

fix(mcp): fold non-string enums into descriptions for tools/list - #39

Merged
KristofersOzolinsMagebit merged 1 commit into
masterfrom
fix/gemini-non-string-enum-schemas
Aug 19, 2026
Merged

fix(mcp): fold non-string enums into descriptions for tools/list#39
KristofersOzolinsMagebit merged 1 commit into
masterfrom
fix/gemini-non-string-enum-schemas

Conversation

@KristofersOzolinsMagebit

Copy link
Copy Markdown
Member

Problem

Gemini errors out on every message when this MCP server is connected. Google validates every advertised tool schema on each request and rejected two of ours:

function_declarations[30].parameters.required[0..6]: property is not defined
function_declarations[36].parameters.properties[items].items.required[0]: property is not defined

Nothing is actually missing from our schemas. Google's function-declaration schema only accepts enum when the values are strings, and we emit integer ones (status, visibility, backorders, source-item status). When Google meets a numeric enum it discards the whole surrounding properties map, and required is then left naming properties it can no longer see — hence the misleading error.

Our schemas are correct: the MCP spec defines inputSchema as plain JSON Schema with no keyword subset, and draft-07 says enum elements "might be of any value". This is a Gemini limitation, but we're the ones getting the ticket, so the accommodation goes here. Claude and OpenAI ignore it, which is why it only ever showed up on Gemini.

Change

Split the two uses of SchemaSanitizer, because they are not the same job:

  • sanitize() — unchanged. Used by ToolsCallHandler to validate incoming arguments, so it keeps the integer enums and validation stays strict.
  • sanitizeForClient() — new. Used only by ToolsListHandler for what we advertise. Drops any enum holding non-string values and folds the allowed values into the property description.

The split matters: ToolsCallHandler validates against the sanitized schema, so folding the enum in one shared method would have silently dropped server-side enum validation as a side effect. The advertised schema is now looser than the validation schema, which is the safe direction.

The fold only fires on a JSON list, so a tool with a property literally named enum is not mangled. There is a test pinning that.

Verification

  • 15 sanitizer tests (9 new, written failing first), 860/860 core unit tests, PHPStan level 9 clean.
  • Live tools/list: 146 tools, 0 non-string enums, 0 orphan required.
  • Enum validation still enforced end to end — catalog_product_stock_set with backorders: 9 returns -32014 "The data should match one item from enum", while backorders: 1 passes schema and fails on the SKU. Used a non-existent SKU so nothing could be written.

Also fixes two latent cases in McpInventoryTools (inventory_source_item_set, inventory_stock_item_configuration_set) that would have failed the same way once that module met a Gemini client.

Pairs with magebitcom/magento2-mcp-catalog-tools — that side adds the value meanings to status / visibility, which had no description to fall back on once the enum was dropped.

🤖 Generated with Claude Code

@KristofersOzolinsMagebit
KristofersOzolinsMagebit merged commit 85637f5 into master Aug 19, 2026
2 checks passed
@KristofersOzolinsMagebit
KristofersOzolinsMagebit deleted the fix/gemini-non-string-enum-schemas branch August 31, 2026 16:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant