set_model_response is missing from the MCP _RESERVED_TOOL_NAMES guard

オープン 初心者向け
#7,144 コメント 1 件 リアクション 0 件 担当者 1 名 GitHub で見る

@sanketpatil06 がすでに取り組んでいます。

2026年9月17日 から。

評価

難易度
2/5
見積もり時間
1〜3時間
初心者へのやさしさ
88/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
python
領域
tooling

調査の方向性

src/google/adk/tools/mcp_tool/mcp_tool.py から始めて _RESERVED_TOOL_NAMES ガードを確認し、その後 test_mcp_tool.py の関連テストを読んでください。予約名に set_model_response を追加し、その名前を通知する MCP サーバーを対象にしてください。完了条件は、他の予約済みツール名と同様に、登録時に一貫して ValueError が発生することです。

索引モデルが issue の本文から書いたものです。

説明

mcp

_RESERVED_TOOL_NAMES in src/google/adk/tools/mcp_tool/mcp_tool.py omits set_model_response, even though it is a tool name the framework itself puts on the wire. The guard added in #6796 states its own invariant in the comment above the set:

# Tool names the framework itself puts on the wire. A server advertising one of
# these would have its tool dispatched in place of the framework's own, so the
# name is refused at registration.
_RESERVED_TOOL_NAMES = frozenset({
    REQUEST_EUC_FUNCTION_CALL_NAME,             # adk_request_credential
    REQUEST_CONFIRMATION_FUNCTION_CALL_NAME,    # adk_request_confirmation
    REQUEST_INPUT_FUNCTION_CALL_NAME,           # adk_request_input
    transfer_to_agent.__name__,                 # transfer_to_agent
})

set_model_response satisfies that description but is not in the set, so an MCP server advertising it is accepted where the other four are refused.

set_model_response is a framework-owned tool name
  • Defined as def set_model_response() -> str: in src/google/adk/tools/set_model_response_tool.py (self.func = set_model_response), so that is its declaration name.
  • Injected into the request whenever output_schema is set alongside other tools:
    src/google/adk/flows/llm_flows/prompt/_schema.py:54
    set_response_tool = SetModelResponseTool(agent.output_schema)
    llm_request.append_tools([set_response_tool])
    
  • The framework then instructs the model to use it by name: "you must provide your final response using the set_model_response tool" (_schema.py:57-64).
  • And it reads the answer back by that name — get_structured_model_response() (_schema.py:97) is reached from base_llm_flow.py:710 with the comment "Check if this is a set_model_response function response".
Why that matters at an MCP boundary

LlmRequest.append_tools resolves a duplicate name by last-wins with only a warning (src/google/adk/models/llm_request.py):

if tool.name in self.tools_dict:
    # Both declarations are still advertised to the model, but only one
    # tool can hold the name, so calls land on the survivor.
    logging.warning(
        "Duplicate tool name %r: the previously registered tool is shadowed ...",
        tool.name,
    )
self.tools_dict[tool.name] = tool

So if an MCP server advertises set_model_response, one of the two tools holds the name and the model's set_model_response call is dispatched there. If the server's tool is the survivor, the agent's structured final answer is delivered to the third-party MCP server and the framework never sees it — which is the outcome the reserved-name check exists to prevent. If the framework's tool is the survivor, the duplicate is still advertised and callable by name, so calls can land on the wrong one.

Either way the invariant stated in the #6796 comment is violated: the name is never refused at registration.

Reproduction sketch
agent = LlmAgent(
    model=..., tools=[McpToolset(connection_params=<server that advertises
                                 a tool named "set_model_response">)],
    output_schema=MySchema,
)
# Expected: ValueError, as for transfer_to_agent / adk_request_confirmation
# Actual:   accepted; a warning is logged at request build time
Suggested fix

Add the name to the set:

_RESERVED_TOOL_NAMES = frozenset({
    REQUEST_EUC_FUNCTION_CALL_NAME,
    REQUEST_CONFIRMATION_FUNCTION_CALL_NAME,
    REQUEST_INPUT_FUNCTION_CALL_NAME,
    transfer_to_agent.__name__,
    'set_model_response',
})

If it is useful, the same reasoning may apply to other in-model names the framework injects (google_search, google_maps, url_context, vertex_ai_search, code_execution, load_artifacts, load_memory) — I have not verified each of those reaches tools_dict, so I have deliberately kept this report to the one name I traced end to end.

Happy to send the set change plus a unit test alongside test_mcp_tool.py if that is the preferred route.

主要言語
Python
スター
21.6k
フォーク
4k
平均マージ
13時間 49分
マージ済み PR(30日)
10

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

google/adk-python のほかの issue

google/adk-python の issue をすべて見る

似ている issue

Python の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。