Skip to content

Google Realtime API fails with MCP tools due to $schema field in parametersΒ #4334

@muhammadkhalid-03

Description

@muhammadkhalid-03

Bug Description

The to_fnc_ctx function in livekit/plugins/google/utils.py only uses _GeminiJsonSchema.simplify() for regular FunctionTool definitions, but not for RawFunctionTool definitions (which MCP tools use).

For context, I have an MCP endpoint in a separate API service. This API service has some MCP tools defined which use Zod schemas. When these tools are served via MCP, the Zod schemas are automatically converted to JSON Schema by the MCP SDK. When my LiveKit agent (self-hosted) connects to the MCP server and forwards these tools to Google's Realtime API, Gemini rejects them due to an unsupported $schema field in the raw tool definition that isn't being removed before being passed onto Gemini due to which the agent fails to speak.

Current MCP tool schema:

{
  'type': 'object',
  'properties': {...},
  'additionalProperties': False,
  '$schema': 'http://json-schema.org/draft-07/schema#'
}

Expected Behavior

Both FunctionTool and RawFunctionTool should have their schemas cleaned up to remove unsupported fields when passing them onto Gemini. For example:

{
  'type': 'object',
  'properties': {...},
  'additionalProperties': False,
  '$schema': 'http://json-schema.org/draft-07/schema#'              <- This shouldn't be here
}

Reproduction Steps

1. Start a livekit session with a google realtime model (e.g. `google.realtime.RealtimeModel(model="gemini-2.5-flash-native-audio-preview-12-2025", voice="Kore")`) that has access to an MCP tool and that uses `RawFunctionTool`
2. The agent should fail fast without you being able to talk to it.
3.
...
- Sample code snippet, or a GitHub Gist link -

Operating System

macOS Sequoia 15.6.1

Models Used

gemini-2.5-flash-native-audio-preview-12-2025

Package Versions

livekit-agents=1.3.6

Session/Room/Call IDs

No response

Proposed Solution

Apply `_GeminiJsonSchema.simplify()` to `RawFunctionTool` parameters in the `else` branch of `to_fnc_ctx()`:

else:
    json_schema = _GeminiJsonSchema(info.raw_schema.get("parameters", {})).simplify()
    fnc_kwargs["parameters"] = types.Schema.model_validate(json_schema)

Additional Context

No response

Screenshots and Recordings

Image Image

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions