Skip to content

Gemini: sanitizeGemini doesn't handle anyOf/const patterns in MCP tool schemas #12908

Closed

Description

@nxxxsooo

Bug Description

When using Google Gemini models (both via @ai-sdk/google API key and antigravity OAuth), MCP tools with anyOf/const patterns in their JSON Schema cause Gemini API to reject the request with errors like:

GenerateContentRequest.tools[0].function_declarations[32].parameters.properties[format].any_of[0].enum: only allowed for STRING type

Root Cause

ProviderTransform.schema() in packages/opencode/src/provider/transform.ts has a sanitizeGemini function (line 772) that converts integer enums to string enums, but does not flatten anyOf/const patterns that Gemini API rejects.

MCP servers (notably Obsidian Local REST API) generate tool schemas like:

{
  "format": {
    "anyOf": [
      { "const": "json" },
      { "const": "markdown" }
    ]
  }
}

Gemini expects this to be:

{
  "format": {
    "type": "string",
    "enum": ["json", "markdown"]
  }
}

The same issue affects fields with anyOf + enum patterns:

{
  "operation": {
    "anyOf": [
      { "const": "append", "description": "..." },
      { "const": "prepend", "description": "..." },
      { "const": "replace", "description": "..." }
    ]
  }
}

Affected Tools

All Obsidian REST API MCP tools with enum-like fields:

  • GetActiveFile / GetVaultFile → format field
  • PatchActiveFile / PatchVaultFile → contentType, operation, targetType fields
  • SearchVault → queryType field
  • ExecuteTemplate → createFile field

Suggested Fix

In sanitizeGemini, add handling for anyOf/oneOf arrays of const values:

// Flatten anyOf/oneOf with const values into enum
for (const keyword of ['anyOf', 'any_of', 'oneOf', 'one_of']) {
  if (Array.isArray(result[keyword])) {
    const constants = result[keyword]
      .filter((item: any) => item && typeof item === 'object' && 'const' in item)
    if (constants.length === result[keyword].length && constants.length > 0) {
      result.type = 'string'
      result.enum = constants.map((item: any) => String(item.const))
      delete result[keyword]
    }
  }
}

Environment

  • OpenCode version: 1.1.53
  • Provider: @ai-sdk/google (both API key and antigravity plugin)
  • MCP server: Obsidian Local REST API
  • OS: macOS (Apple Silicon)

Workaround

Currently the only workaround is to disable the problematic MCP server's tools using permissions, but this affects all providers — not just Gemini.

Activity

  1. added a commit that references this issue on Feb 15, 2026
    5954f2c
  2. github-actions commented on Apr 12, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 90 days of no activity. If the issue is still relevant please open a new one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions