MCP toolset: in-model built-ins (e.g. google_search) can be shadowed by a server tool; a server tool named set_model_response aborts the run
Maintainers usually reply within 1 day
Assessment
This issue has not been assessed yet.
Description
Summary
Same two defects as the Go port, reproduced locally against adk-java (4ee155b2, core). No live service was contacted.
- In-model built-in tools do not occupy their name, so a server-provided tool can shadow them.
GoogleSearchTool(andGoogleMapsTool,UrlContextTool,VertexAiSearchTool,BuiltInCodeExecutionTool) overrideprocessLlmRequestto append only toconfig.Tools, never callingappendTools. So the duplicate-name guard inLlmRequest.Builder.appendToolsnever sees them, and a callable MCP tool advertisinggoogle_searchis accepted and wins dispatch —Functions.handleFunctionCallsresolves by name from a map where the MCP tool overwrote the built-in. - A server-provided tool named
set_model_responseaborts the whole run on an agent with an output schema (IllegalArgumentException: Duplicate tool name: set_model_response). Availability, not silent displacement — but a malicious/untrusted MCP server can deny service.
Evidence
- MCP tools take the server's name, unfiltered by default —
tools/mcp/McpToolset.java:260-279;tools/BaseToolset.java:60-64(if (toolFilter == null) return true;); name sourcetools/mcp/AbstractMcpTool.java:52-56. - Callable-vs-callable is fail-closed —
models/LlmRequest.java:204-222(appendTools, throwing merger); all tools enter viatools/BaseTool.java:187-193. set_model_responseis in the guarded class —flows/llmflows/OutputSchema.java:60-65;SetModelResponseTool.java:33-45(extendsBaseTool, does not overrideprocessLlmRequest). Processor order:SingleFlow.java:27-36,BaseLlmFlow.java:103-104.- Built-ins bypass the guard —
tools/GoogleSearchTool.java:45-76(override that appendsTool.builder().googleSearch(...)only); same inGoogleMapsTool.java:65,UrlContextTool.java:46,VertexAiSearchTool.java:60,BuiltInCodeExecutionTool.java:44. - Dispatch by name —
BaseLlmFlow.java:765-766;Functions.java:295(tools.get(functionCall.name().get())).
Local reproduction
[probe] registered tool map keys: [google_search]
[probe] config.Tool googleSearch=true functionDeclarations=[]
[probe] config.Tool googleSearch=false functionDeclarations=[google_search]
[probe] google_search: NO ERROR. dispatch map maps google_search -> FakeMcpTool
[probe] set_model_response: REJECTED -> Duplicate tool name: set_model_response
Suggested fix
Preferred (availability-first): reject the server-provided tool via a reserved-name check in AbstractMcpTool's constructor or in McpToolset.getTools / McpAsyncToolset.getTools, covering set_model_response, transfer_to_agent, google_search, google_maps, url_context, vertex_ai_search, code_execution, load_artifacts.
Alternative: make the in-model tools call appendTools so the existing duplicate guard applies (note: google_search would then need a clean-failing runAsync).
Same class as the Go port (google/adk-go#1605) and a separately-triaged adk-js report.
- Dominant language
- Java
- Stars
- 1.7k
- Forks
- 431
- Avg merge
- 3d 2h
- Merged PRs (30d)
- 46
Getting set up
Starts the project's dev container in your browser, under your own GitHub account.
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from google/adk-java
-
GeminiUtil placeholder user turn ("Continue output. DO NOT look at this line ...") is flagged by prompt injection filtersPossibly taken @innoprej claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
Maintainers usually reply within 1 day
-
[spring-ai] ToolConverter silently drops enum and items from tool parameter schemasPossibly taken @hirematha claimed this 3 days ago. Openneeds review
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
google/adk-java#1609 · 2 comments · 1 assignee ·
Maintainers usually reply within 1 day
-
[spring-ai] Streaming responses ending with CJK punctuation (。!?) are misclassified as partial and never persisted to the sessionPossibly taken @hirematha claimed this 3 days ago. Openwaiting on reporter
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
google/adk-java#1608 · 2 comments · 1 assignee ·
Maintainers usually reply within 1 day
-
[core] Client disconnects don't cancel the model stream (per-step flow is cached) — and there is no public API to cancel an in-flight runPossibly taken @hemasekhar-p claimed this 2 days ago. Openneeds review
google/adk-java#1618 · 6 comments · 1 assignee ·
Maintainers usually reply within 1 day
-
[spring-ai] Bridge drops reasoning_content (thinking) — surface it as partial events and/or persist itPossibly taken @hemasekhar-p claimed this 3 days ago. Openneeds review
google/adk-java#1616 · 1 comment · 1 assignee ·
Maintainers usually reply within 1 day
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
NationalSecurityAgency/ghidra#9748 ·
Maintainers usually reply within 1 day
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
Maintainers usually reply within 1 day
-
spring-mcp-tools
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
explyt/spring-plugin#591 ·
Maintainers usually reply within 1 day
-
waiting-for-triage
Difficulty 1/5 Under an hour Newbie friendliness 72/100
spring-cloud/spring-cloud-openfeign#1443 ·
Maintainers usually reply within 1 day
-
Difficulty 1/5 1-3 hours Newbie friendliness 84/100
ADORSYS-GIS/keycloak-oid4vp-plugin#221 ·
Maintainers usually reply within 2 days