From 6ea82ee7dc97e64dbad0136676c5ec5fc1816c23 Mon Sep 17 00:00:00 2001 From: Sehastrajit Date: Wed, 16 Sep 2026 18:51:21 -0700 Subject: [PATCH] fix(tools): guard set_model_response as a reserved MCP tool name An MCP server exposing a tool literally named set_model_response could shadow the built-in SetModelResponseTool, since _RESERVED_TOOL_NAMES in mcp_tool.py never accounted for it. Add the dispatch name as a shared constant on SetModelResponseTool and register it in the reserved set, matching how the other framework-reserved names are handled. --- src/google/adk/tools/mcp_tool/mcp_tool.py | 2 ++ src/google/adk/tools/set_model_response_tool.py | 8 +++++++- tests/unittests/tools/mcp_tool/test_mcp_tool.py | 1 + 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/google/adk/tools/mcp_tool/mcp_tool.py b/src/google/adk/tools/mcp_tool/mcp_tool.py index 09c4c9fe33f..e77bbf475ff 100644 --- a/src/google/adk/tools/mcp_tool/mcp_tool.py +++ b/src/google/adk/tools/mcp_tool/mcp_tool.py @@ -54,6 +54,7 @@ # part of the ADK public API; consumers flip the env var, not the symbol. from .._gemini_schema_util import _to_gemini_schema from ..base_authenticated_tool import BaseAuthenticatedTool +from ..set_model_response_tool import SET_MODEL_RESPONSE_FUNCTION_CALL_NAME from ..tool_context import ToolContext from ..transfer_to_agent_tool import transfer_to_agent from .mcp_session_manager import _http_debug_var @@ -70,6 +71,7 @@ REQUEST_EUC_FUNCTION_CALL_NAME, REQUEST_CONFIRMATION_FUNCTION_CALL_NAME, REQUEST_INPUT_FUNCTION_CALL_NAME, + SET_MODEL_RESPONSE_FUNCTION_CALL_NAME, transfer_to_agent.__name__, }) diff --git a/src/google/adk/tools/set_model_response_tool.py b/src/google/adk/tools/set_model_response_tool.py index c03392935c2..140f7c8063e 100644 --- a/src/google/adk/tools/set_model_response_tool.py +++ b/src/google/adk/tools/set_model_response_tool.py @@ -39,6 +39,12 @@ from .base_tool import BaseTool from .tool_context import ToolContext +# Name the framework dispatches this tool under. Exposed as a module-level +# constant (mirroring functions.py's REQUEST_*_FUNCTION_CALL_NAME) so other +# modules -- e.g. the MCP reserved-name guard -- can refer to it without +# hardcoding the literal. +SET_MODEL_RESPONSE_FUNCTION_CALL_NAME = 'set_model_response' + def _merge_json_schema_descriptions( target: dict[str, Any], source: dict[str, Any] @@ -215,7 +221,7 @@ def set_model_response() -> str: self.func = set_model_response super().__init__( - name=self.func.__name__, + name=SET_MODEL_RESPONSE_FUNCTION_CALL_NAME, description=self.func.__doc__.strip() if self.func.__doc__ else '', ) diff --git a/tests/unittests/tools/mcp_tool/test_mcp_tool.py b/tests/unittests/tools/mcp_tool/test_mcp_tool.py index 57856043cac..f7355c06e22 100644 --- a/tests/unittests/tools/mcp_tool/test_mcp_tool.py +++ b/tests/unittests/tools/mcp_tool/test_mcp_tool.py @@ -343,6 +343,7 @@ def test_init_with_empty_description(self): "adk_request_credential", "adk_request_confirmation", "adk_request_input", + "set_model_response", "transfer_to_agent", ], )