Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/kimi_cli/soul/toolset.py
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 MCP tool approval action_name not namespaced by server, causing cross-server auto-approval

The PR prefixes tool names with server_name to avoid collisions (f"{server_name}_{mcp_tool.name}"), but _action_name at line 715 is still f"mcp:{mcp_tool.name}" without the server prefix. When two MCP servers expose a tool with the same name (e.g. read_file), both MCPTool instances share the same _action_name = "mcp:read_file". If the user selects "approve for session" for one server's tool, the action is added to auto_approve_actions (src/kimi_cli/soul/approval.py:248), which then auto-approves the identically-named tool from the other server (src/kimi_cli/soul/approval.py:195). Additionally, all pending approvals with the same action are batch-resolved (src/kimi_cli/soul/approval.py:250-252). Before this PR, this couldn't happen because only one tool with a given name existed in _tool_dict (the second overwrote the first). Now that both tools coexist with distinct names, the shared _action_name creates an unintended cross-server approval bypass.

(Refers to line 715)

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Original file line number Diff line number Diff line change
Expand Up @@ -698,8 +698,9 @@ def __init__(
runtime: Runtime,
**kwargs: Any,
):
tool_name = f"{server_name}_{mcp_tool.name}"
super().__init__(
name=mcp_tool.name,
name=tool_name,
description=(
f"This is an MCP (Model Context Protocol) tool from MCP server `{server_name}`.\n\n"
f"{mcp_tool.description or 'No description provided.'}"
Expand All @@ -711,7 +712,7 @@ def __init__(
self._client = client
self._runtime = runtime
self._timeout = timedelta(milliseconds=runtime.config.mcp.client.tool_call_timeout_ms)
self._action_name = f"mcp:{mcp_tool.name}"
self._action_name = f"mcp:{tool_name}"

async def __call__(self, *args: Any, **kwargs: Any) -> ToolReturnValue:
description = f"Call MCP tool `{self._mcp_tool.name}`."
Expand Down