Merge pull request #2077 from yousifa/mcp-http-gemini-support

Mcp http gemini support
This commit is contained in:
Vanessa Pyne
2025-07-02 11:47:25 -05:00
committed by GitHub
5 changed files with 82 additions and 3 deletions

View File

@@ -18,8 +18,8 @@ from pipecat.pipeline.task import PipelineParams, PipelineTask
from pipecat.processors.aggregators.openai_llm_context import OpenAILLMContext
from pipecat.services.cartesia.tts import CartesiaTTSService
from pipecat.services.deepgram.stt import DeepgramSTTService
from pipecat.services.google.llm import GoogleLLMService
from pipecat.services.mcp_service import MCPClient
from pipecat.services.openai.llm import OpenAILLMService
from pipecat.transports.base_transport import BaseTransport, TransportParams
from pipecat.transports.network.fastapi_websocket import FastAPIWebsocketParams
from pipecat.transports.services.daily import DailyParams
@@ -58,7 +58,7 @@ async def run_example(transport: BaseTransport, _: argparse.Namespace, handle_si
voice_id="71a7ad14-091c-4e8e-a314-022ece01c121", # British Reading Lady
)
llm = OpenAILLMService(api_key=os.getenv("OPENAI_API_KEY"), model="gpt-4o-mini")
llm = GoogleLLMService(api_key=os.getenv("GOOGLE_API_KEY"), model="gemini-2.0-flash")
try:
# Github MCP docs: https://github.com/github/github-mcp-server

View File

@@ -583,6 +583,17 @@ class GeminiMultimodalLiveLLMService(LLMService):
"""
return True
def needs_mcp_alternate_schema(self) -> bool:
"""Check if this LLM service requires alternate MCP schema.
Google/Gemini has stricter JSON schema validation and requires
certain properties to be removed or modified for compatibility.
Returns:
True for Google/Gemini services.
"""
return True
def set_audio_input_paused(self, paused: bool):
"""Set the audio input pause state.

View File

@@ -717,6 +717,17 @@ class GoogleLLMService(LLMService):
"""
return True
def needs_mcp_alternate_schema(self) -> bool:
"""Check if this LLM service requires alternate MCP schema.
Google/Gemini has stricter JSON schema validation and requires
certain properties to be removed or modified for compatibility.
Returns:
True for Google/Gemini services.
"""
return True
def _create_client(self, api_key: str):
self._client = genai.Client(api_key=api_key)

View File

@@ -355,6 +355,17 @@ class LLMService(AIService):
return True
return function_name in self._functions.keys()
def needs_mcp_alternate_schema(self) -> bool:
"""Check if this LLM service requires alternate MCP schema.
Some LLM services have stricter JSON schema validation and require
certain properties to be removed or modified for compatibility.
Returns:
True if MCP schemas should be cleaned for this service, False otherwise.
"""
return False
async def run_function_calls(self, function_calls: Sequence[FunctionCallFromLLM]):
"""Execute a sequence of function calls from the LLM.

View File

@@ -53,6 +53,7 @@ class MCPClient(BaseObject):
super().__init__(**kwargs)
self._server_params = server_params
self._session = ClientSession
self._needs_alternate_schema = False
if isinstance(server_params, StdioServerParameters):
self._client = stdio_client
@@ -80,9 +81,48 @@ class MCPClient(BaseObject):
Returns:
A ToolsSchema containing all successfully registered tools.
"""
# Check once if the LLM needs alternate strict schema
self._needs_alternate_schema = llm and llm.needs_mcp_alternate_schema()
tools_schema = await self._register_tools(llm)
return tools_schema
def _get_alternate_schema_for_strict_validation(self, schema: Dict[str, Any]) -> Dict[str, Any]:
"""Get an alternate JSON schema to be compatible with LLMs that have strict validation.
Some LLMs have stricter validation and don't allow certain schema properties
that are valid in standard JSON Schema.
Args:
schema: The JSON schema to get an alternate schema for
Returns:
An alternate schema compatible with strict validation
"""
if not isinstance(schema, dict):
return schema
alternate_schema = {}
for key, value in schema.items():
# Skip additionalProperties as some LLMs don't like additionalProperties: false
if key == "additionalProperties":
continue
# Recursively get alternate schema for nested objects
if isinstance(value, dict):
alternate_schema[key] = self._get_alternate_schema_for_strict_validation(value)
elif isinstance(value, list):
alternate_schema[key] = [
self._get_alternate_schema_for_strict_validation(item)
if isinstance(item, dict)
else item
for item in value
]
else:
alternate_schema[key] = value
return alternate_schema
def _convert_mcp_schema_to_pipecat(
self, tool_name: str, tool_schema: Dict[str, Any]
) -> FunctionSchema:
@@ -100,6 +140,11 @@ class MCPClient(BaseObject):
properties = tool_schema["input_schema"].get("properties", {})
required = tool_schema["input_schema"].get("required", [])
# Only get alternate schema for LLMs that need strict schema validation
if self._needs_alternate_schema:
logger.debug("Getting alternate schema for strict validation")
properties = self._get_alternate_schema_for_strict_validation(properties)
schema = FunctionSchema(
name=tool_name,
description=tool_schema["description"],
@@ -280,7 +325,8 @@ class MCPClient(BaseObject):
try:
# Convert the schema
function_schema = self._convert_mcp_schema_to_pipecat(
tool_name, {"description": tool.description, "input_schema": tool.inputSchema}
tool_name,
{"description": tool.description, "input_schema": tool.inputSchema},
)
# Register the wrapped function