Skip to content

Commit 67184a2

Browse files
committed
fix: add namespace prefix to MCP tools to prevent conflicts with plugin tools
- Add namespace prefix format: mcp_<server_name>__<tool_name> to MCPTool - Store original tool name in MCPTool.original_tool_name for display and calling - Add backward compatibility in get_func() to support old persona tool references - Update tool list API to include display_name field showing original name - Update MCP server info to display original tool names without prefix - Fixes issue where MCP tools and plugin tools with same name would conflict
1 parent 10ceacf commit 67184a2

3 files changed

Lines changed: 44 additions & 4 deletions

File tree

astrbot/core/agent/mcp_client.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -379,20 +379,28 @@ class MCPTool(FunctionTool, Generic[TContext]):
379379
def __init__(
380380
self, mcp_tool: mcp.Tool, mcp_client: MCPClient, mcp_server_name: str, **kwargs
381381
) -> None:
382+
# Add namespace prefix to avoid conflicts with plugin tools
383+
# Format: mcp_<server_name>__<tool_name>
384+
namespaced_name = f"mcp_{mcp_server_name}__{mcp_tool.name}"
385+
382386
super().__init__(
383-
name=mcp_tool.name,
387+
name=namespaced_name,
384388
description=mcp_tool.description or "",
385389
parameters=mcp_tool.inputSchema,
386390
)
387391
self.mcp_tool = mcp_tool
388392
self.mcp_client = mcp_client
389393
self.mcp_server_name = mcp_server_name
394+
self.original_tool_name = (
395+
mcp_tool.name
396+
) # Store original name for display and calling
390397

391398
async def call(
392399
self, context: ContextWrapper[TContext], **kwargs
393400
) -> mcp.types.CallToolResult:
401+
# Use original tool name when calling MCP server
394402
return await self.mcp_client.call_tool_with_reconnect(
395-
tool_name=self.mcp_tool.name,
403+
tool_name=self.original_tool_name,
396404
arguments=kwargs,
397405
read_timeout_seconds=timedelta(seconds=context.tool_call_timeout),
398406
)

astrbot/core/provider/func_tool_manager.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,10 +311,31 @@ def remove_func(self, name: str) -> None:
311311
break
312312

313313
def get_func(self, name) -> FuncTool | None:
314+
# First try exact match
314315
for f in self.func_list:
315316
if f.name == name:
316317
return f
317318

319+
# Fallback: try to find MCP tool by original name for backward compatibility
320+
# This handles cases where personas reference tools by their original names
321+
mcp_matches = []
322+
for f in self.func_list:
323+
if isinstance(f, MCPTool) and f.original_tool_name == name:
324+
mcp_matches.append(f)
325+
326+
if len(mcp_matches) == 1:
327+
return mcp_matches[0]
328+
elif len(mcp_matches) > 1:
329+
# Multiple MCP servers provide the same tool name
330+
# Log warning and return the first one
331+
logger.warning(
332+
f"Multiple MCP tools found with original name '{name}': "
333+
f"{[f.name for f in mcp_matches]}. Using {mcp_matches[0].name}"
334+
)
335+
return mcp_matches[0]
336+
337+
return None
338+
318339
def get_full_tool_set(self) -> ToolSet:
319340
"""获取完整工具集"""
320341
tool_set = ToolSet(self.func_list.copy())

astrbot/dashboard/routes/tools.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,13 @@ async def get_mcp_servers(self):
104104
for name_key, runtime in self.tool_mgr.mcp_server_runtime_view.items():
105105
if name_key == name:
106106
mcp_client = runtime.client
107-
server_info["tools"] = [tool.name for tool in mcp_client.tools]
107+
# Display original tool names without namespace prefix
108+
server_info["tools"] = [
109+
tool.name.split("__", 1)[1]
110+
if tool.name.startswith(f"mcp_{name}__")
111+
else tool.name
112+
for tool in mcp_client.tools
113+
]
108114
server_info["errlogs"] = mcp_client.server_errlogs
109115
break
110116
else:
@@ -434,18 +440,23 @@ async def get_tool_list(self):
434440
if isinstance(tool, MCPTool):
435441
origin = "mcp"
436442
origin_name = tool.mcp_server_name
443+
# Add original tool name for MCP tools
444+
display_name = getattr(tool, "original_tool_name", tool.name)
437445
elif tool.handler_module_path and star_map.get(
438446
tool.handler_module_path
439447
):
440448
star = star_map[tool.handler_module_path]
441449
origin = "plugin"
442450
origin_name = star.name
451+
display_name = tool.name
443452
else:
444453
origin = "unknown"
445454
origin_name = "unknown"
455+
display_name = tool.name
446456

447457
tool_info = {
448-
"name": tool.name,
458+
"name": tool.name, # Keep namespaced name for internal use
459+
"display_name": display_name, # Original name for display
449460
"description": tool.description,
450461
"parameters": tool.parameters,
451462
"active": tool.active,

0 commit comments

Comments
 (0)