Skip to content

Commit 12caa8c

Browse files
committed
fix(mcp): refuse the reserved tool name set_model_response
_RESERVED_TOOL_NAMES covers the names the framework itself puts on the wire, so a server advertising one cannot have its tool dispatched in place of the framework's own. set_model_response belongs to that set but was missing. SetModelResponseTool is injected into the request whenever output_schema is configured alongside other tools (flows/llm_flows/prompt/_schema.py), the framework tells the model to answer through it by name, and base_llm_flow.py reads the result back by that same name. Because LlmRequest.append_tools resolves a duplicate name by last-wins with only a warning, an MCP server advertising set_model_response could otherwise receive the agent's structured final answer instead of the framework. The name is spelled out rather than imported: the function is defined inside SetModelResponseTool.__init__, so there is no module-level binding to import. Extends both existing reserved-name tests. Fixes #7144
1 parent 044a1ec commit 12caa8c

3 files changed

Lines changed: 8 additions & 0 deletions

File tree

‎src/google/adk/tools/mcp_tool/mcp_tool.py‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,12 @@
7979
REQUEST_CONFIRMATION_FUNCTION_CALL_NAME,
8080
REQUEST_INPUT_FUNCTION_CALL_NAME,
8181
transfer_to_agent.__name__,
82+
# Injected by the output-schema processor whenever output_schema is set
83+
# alongside other tools (flows/llm_flows/prompt/_schema.py) and read back
84+
# by name in base_llm_flow.py, so it is a framework-owned wire name too.
85+
# Spelled out because the function is defined inside
86+
# SetModelResponseTool.__init__ and is not importable.
87+
'set_model_response',
8288
})
8389

8490
_UNSET = object()

‎tests/unittests/tools/mcp_tool/test_mcp_tool.py‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -730,6 +730,7 @@ def test_init_with_empty_description(self):
730730
"adk_request_confirmation",
731731
"adk_request_input",
732732
"transfer_to_agent",
733+
"set_model_response",
733734
],
734735
)
735736
def test_init_reserved_name(self, reserved_name):

‎tests/unittests/tools/mcp_tool/test_mcp_toolset.py‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,7 @@ async def test_get_tools_skips_reserved_names(self):
409409
MockMCPTool("adk_request_credential"),
410410
MockMCPTool("adk_request_confirmation"),
411411
MockMCPTool("adk_request_input"),
412+
MockMCPTool("set_model_response"),
412413
]
413414
self.mock_session.list_tools = AsyncMock(
414415
return_value=MockListToolsResult(mock_tools)

0 commit comments

Comments
 (0)