fix: Propagate MCP tools output schema to FunctionDeclaration

PiperOrigin-RevId: 825380145
This commit is contained in:
Vishwa Murugan
2025-10-28 23:03:08 -07:00
committed by Copybara-Service
parent 1ee93c8bcb
commit c8e5340962
2 changed files with 54 additions and 3 deletions
+8 -3
View File
@@ -119,10 +119,15 @@ class McpTool(BaseAuthenticatedTool):
Returns:
FunctionDeclaration: The Gemini function declaration for the tool.
"""
schema_dict = self._mcp_tool.inputSchema
parameters = _to_gemini_schema(schema_dict)
input_schema = self._mcp_tool.inputSchema
parameters = _to_gemini_schema(input_schema)
output_schema = self._mcp_tool.outputSchema
response = _to_gemini_schema(output_schema)
function_decl = FunctionDeclaration(
name=self.name, description=self.description, parameters=parameters
name=self.name,
description=self.description,
parameters=parameters,
response=response,
)
return function_decl
@@ -36,6 +36,7 @@ try:
from google.adk.tools.mcp_tool.mcp_tool import MCPTool
from google.adk.tools.tool_context import ToolContext
from google.genai.types import FunctionDeclaration
from google.genai.types import Type
from mcp.types import CallToolResult
from mcp.types import TextContent
except ImportError as e:
@@ -49,6 +50,7 @@ except ImportError as e:
MCPTool = DummyClass
ToolContext = DummyClass
FunctionDeclaration = DummyClass
Type = DummyClass
CallToolResult = DummyClass
TextContent = DummyClass
else:
@@ -70,6 +72,7 @@ class MockMCPTool:
},
"required": ["param1"],
}
self.outputSchema = None
class TestMCPTool:
@@ -145,6 +148,49 @@ class TestMCPTool:
assert declaration.name == "test_tool"
assert declaration.description == "Test tool description"
assert declaration.parameters is not None
assert declaration.response is None
def test_get_declaration_with_output_schema(self):
"""Test function declaration generation with an output schema."""
self.mock_mcp_tool.outputSchema = {
"type": "object",
"properties": {
"status": {
"type": "string",
"description": "The status of the operation",
},
},
}
tool = MCPTool(
mcp_tool=self.mock_mcp_tool,
mcp_session_manager=self.mock_session_manager,
)
declaration = tool._get_declaration()
assert isinstance(declaration, FunctionDeclaration)
assert declaration.response is not None
assert declaration.response.type == Type.OBJECT
assert "status" in declaration.response.properties
assert declaration.response.properties["status"].type == Type.STRING
assert (
declaration.response.properties["status"].description
== "The status of the operation"
)
def test_get_declaration_with_empty_output_schema(self):
"""Test function declaration with an empty output schema."""
self.mock_mcp_tool.outputSchema = {}
tool = MCPTool(
mcp_tool=self.mock_mcp_tool,
mcp_session_manager=self.mock_session_manager,
)
declaration = tool._get_declaration()
assert declaration.response is not None
assert declaration.response.type == Type.OBJECT
assert declaration.response.properties is None
@pytest.mark.asyncio
async def test_run_async_impl_no_auth(self):