Skip to content

Gemini API rejects MCP tool schemas with $defs references #13326

@krasmussen37

Description

@krasmussen37

What happened?

When using Gemini CLI with MCP servers that have JSON schemas containing $defs references (Snowflake MCP, BEADS MCP, Basic Memory MCP), the Gemini API returns a 400 error:

API Error: {
  "error": {
    "code": 400,
    "message": "reference to undefined schema at properties.target_object.anyOf.1",
    "status": "INVALID_ARGUMENT"
  }
}

Additionally, during MCP discovery, tools are skipped with errors:

✕ Error discovering tools from beads: can't resolve reference #/$defs/Issue from id #
✕ Error discovering tools from basic-memory: can't resolve reference #/$defs/ContextResult from id #

The MCP servers connect successfully (gemini mcp list shows all as "Connected"), but the Gemini API rejects tool calls.

What did you expect to happen?

The Gemini API should accept valid JSON Schema with:

  • $defs references
  • anyOf with nested type references
  • Complex nested schemas

These schemas are:

  1. Valid per JSON Schema specification (draft 2020-12)
  2. Generated by official MCP Python SDK
  3. Work perfectly with Claude Code CLI, MCP Inspector, and other AI CLIs

Example Problematic Schema

From Snowflake MCP's create_object tool:

{
  "inputSchema": {
    "type": "object",
    "properties": {
      "target_object": {
        "anyOf": [
          {"type": "string"},
          {"$ref": "#/$defs/SnowflakeDatabase"},
          {"$ref": "#/$defs/SnowflakeSchema"}
        ]
      }
    },
    "$defs": {
      "SnowflakeDatabase": {
        "type": "object",
        "properties": {...}
      }
    }
  }
}

Client information

╭────────────────────────────────────────────────────────────────────────────────╮
│ About Gemini CLI                                                               │
│ CLI Version                 0.16.0                                             │
│ OS                          linux (Debian 12 in container)                     │
│ Auth Method                 OAuth                                              │
╰────────────────────────────────────────────────────────────────────────────────╯

Affected MCP Servers

  1. Snowflake MCP (Snowflake-Labs/mcp)

    • Error: "reference to undefined schema at properties.target_object.anyOf.1"
  2. BEADS MCP (steveyegge/beads)

    • Error: "can't resolve reference #/$defs/Issue from id #"
  3. Basic Memory MCP (basicmachines-co/basic-memory)

    • Error: "can't resolve reference #/$defs/ContextResult from id #"

Working MCP Servers

These work fine (simpler schemas without $defs):

  • exa (HTTP-based)
  • firecrawl (stdio)
  • probe (stdio)

Current Workaround

gemini --allowed-mcp-server-names exa firecrawl probe

Related Issues

Note: Issue #9574 removed CLI-side schema validation, but the Gemini API backend still rejects these schemas at the HTTP API level.


Solutions Found (Not Yet in Gemini CLI)

Solution 1: Google's Own Schema Processor

Source: Stack Overflow - Gemini AI Structured Output

Google has an internal function that flattens schemas for Gemini compatibility:

from google import genai
from google.genai._transformers import process_schema
from pydantic import BaseModel

def normalize_schema_for_gemini(response_format: type[BaseModel]) -> dict[str, object]:
    # Convert Pydantic model to JSON schema
    json_schema: dict[str, object] = response_format.model_json_schema()

    # Use Google's own schema processing function
    googleFakeClient = genai.Client(api_key="fake")._api_client
    process_schema(json_schema, googleFakeClient, order_properties=True)

    # Return flattened schema
    return {
        "type": "json_schema",
        "json_schema": {
            "schema": json_schema,
            "name": response_format.__name__,
            "strict": True,
        },
    }

Action Required: Gemini CLI should use process_schema to transform MCP tool schemas before sending to API.

Solution 2: Python Function to Flatten $defs

Source: Stack Overflow - Remove $defs from Pydantic

def remove_defs_and_refs(schema: dict):
    schema = schema.copy()
    defs = schema.pop('$defs', {})

    def resolve(subschema):
        if isinstance(subschema, dict):
            ref = subschema.get('$ref', None)
            if ref:
                _def = ref.split('/')[-1]
                return resolve(defs[_def])
            return {
                _def: resolve(_ref)
                for _def, _ref in subschema.items()
            }
        if isinstance(subschema, list):
            return [resolve(ss) for ss in subschema]
        return subschema

    return resolve(schema)

Solution 3: FastMCP Fixed This

Source: jlowin/fastmcp#1372

FastMCP had the same issue and fixed it in PR #1426:

  • Problem: Nested $refs weren't being included in $defs
  • Fix: Recursively collect all transitive dependencies
  • Status: Fixed in FastMCP 2.12+

This means: If affected MCP servers update to FastMCP 2.12+, they should work.


Recommended Actions

For Gemini CLI Team (Priority P1)

  1. Integrate process_schema from google.genai._transformers into MCP tool loading

    • This is Google's own solution for schema compatibility
    • Apply it to all MCP tool schemas before sending to API
  2. OR implement schema flattening using the pattern from Solution 2

  3. Document schema restrictions if flattening is not possible


Technical Details

Root Cause

The error is from Google's Gemini API backend, not the CLI:

Why This Matters

Many MCP servers use $defs for:

  • Type reuse (DRY principle)
  • Polymorphic parameters
  • Complex nested data structures

The MCP Python SDK (FastMCP, official Anthropic SDK) generates these schemas automatically.


Reproduction Steps

  1. Configure any MCP server using $defs in tool schemas
  2. Add to ~/.config/gemini/mcp.json
  3. Launch gemini
  4. Observe discovery errors in startup
  5. Attempt any query: gemini "test message"
  6. Observe 400 API error

Impact

Severity: P1 - Blocks using many popular MCP servers with Gemini

Ecosystem Impact: Affects entire MCP ecosystem since official SDKs generate these schemas

Workaround Available: Yes, but requires excluding valuable tools

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions