LibreChat/api/server
Danny Avila 6c36d8038c
fix: Sanitize MCP Tool Schemas for Gemini/Vertex Compatibility (#13623)
* 🧰 fix: Flatten union schemas for Gemini/Vertex MCP tool compatibility

`@langchain/google-common`'s `zod_to_gemini_parameters` throws "Gemini cannot
handle union types" on any genuine `anyOf`/`oneOf` (e.g. discriminated unions),
so MCP tools shipping union-typed schemas crash on the Google endpoint while
working fine on OpenAI/Claude.

Add `flattenJsonSchemaUnions` (packages/api) to collapse unions to their first
non-null member and multi-entry `type` arrays to a single nullable type, and
apply it in `createToolInstance`'s existing `isGoogle` branch so only the
Google/Vertex path is affected. Lossy by design, mirroring the existing
empty-object fallback.

Closes #13612

* 🩹 fix: Address Codex review — preserve fields, strip null enums, cover definitions path

- Preserve parent-level `properties`/`required` when collapsing a union: merge the
  chosen branch into the parent instead of overwriting, so args declared outside the
  union (e.g. always-required fields) still reach Gemini.
- Drop the `null` member from `enum` when a union/type-array makes a field nullable,
  keeping Gemini's required homogeneous-enum invariant.
- Propagate the Google-flattened schema to the definitions/deferred-tool path:
  thread `provider` into `loadToolDefinitions` and flatten there, and store the
  flattened schema on `mcpJsonSchema` so `extractMCPToolDefinition` no longer emits
  raw unions on Google/Vertex.

* 🎨 style: Sort imports in tools/definitions per import-order check

*  feat: Broaden union flatten into a full Gemini schema sanitizer

The union flatten alone wasn't enough — real GitHub MCP tools on Gemini also 400
with `Invalid value ... (TYPE_STRING), true`, because Gemini's function-calling
Schema (https://ai.google.dev/api/caching#Schema) accepts only a restricted JSON
Schema subset, and `enum` is `Type.STRING`-only.

Rename `flattenJsonSchemaUnions` → `sanitizeGeminiSchema` and broaden it (one pass,
Gemini-gated) to cover the documented subset:

- Keep only string `enum` values; drop the keyword for non-string types (fixes the
  reported boolean-enum 400, incl. boolean `const` normalized to `enum: [true]`).
- `const` → single-value string enum, or drop if non-string.
- Merge `allOf` intersections; fold `exclusiveMinimum`/`exclusiveMaximum` into
  `minimum`/`maximum`.
- Strip unsupported keywords: `additionalProperties`, `default`, `$schema`, `$id`.
- (Existing) collapse `anyOf`/`oneOf`, multi-entry `type` arrays, nullable.

Grounded in Google's Schema docs rather than reverse-engineered from 400s. Verified
end-to-end against the real `@langchain/google-common` converter. Complements
danny-avila/agents#232 (langchain bump), which defers schema flattening to LibreChat.

* 🩹 fix: Gate enum retention on the effective (collapsed) type

Codex review: a mixed-type enum like `type: ['integer','string'], enum: [1,'auto']`
collapsed the type to `integer` but still kept the string value `'auto'`, yielding
`{type:'integer', enum:['auto']}` — a non-string type with an enum, which Gemini
rejects. Keep `enum` only when the effective collapsed type is string (or unset),
and stamp `type: 'string'` on a surviving typeless enum (e.g. a string `const`
discriminator) so it satisfies Gemini's Type.STRING enum requirement.
2026-06-09 14:16:25 -04:00
..
controllers 🧵 fix: Reject Preliminary Parent Follow-Ups (#13619) 2026-06-09 12:06:51 -04:00
middleware 📌 fix: Preserve Project Scope Through Enforced Model Specs (#13586) 2026-06-08 08:41:27 -04:00
routes 🪞 fix: Preserve Model Spec Icons Across Stream Resume and Abort (#13603) 2026-06-08 17:14:21 -04:00
services fix: Sanitize MCP Tool Schemas for Gemini/Vertex Compatibility (#13623) 2026-06-09 14:16:25 -04:00
utils
cleanup.js
experimental.js 🗂️ feat: Add Private Chat Projects (#13467) 2026-06-03 15:29:18 -04:00
index.js 🗂️ feat: Add Deployment Skill Directory (#13523) 2026-06-05 10:24:28 -04:00
index.metrics.spec.js ⚖️ feat: Add Operational Prometheus Metrics (#13265) 2026-05-22 20:47:41 -04:00
index.spec.js 🚦 fix: Gate Chat Starts During Readiness (#13502) 2026-06-04 00:09:10 -04:00
socialLogins.js feat: Make OpenID Token Reuse Window Configurable (#13546) 2026-06-06 15:15:58 -04:00
socialLogins.spec.js feat: Make OpenID Token Reuse Window Configurable (#13546) 2026-06-06 15:15:58 -04:00
telemetry.js
telemetry.spec.js