From 29a2b4f3b774654cea09a50839c97c1ec0c43c19 Mon Sep 17 00:00:00 2001 From: MUHAMMAD SALMAN HUSSAIN <160324527+mshsheikh@users.noreply.github.com> Date: Mon, 1 Jun 2026 18:18:40 +0500 Subject: [PATCH] Detect and reject duplicate tool names within individual MCP servers ## Problem The existing duplicate tool name validation only checked for conflicts across multiple MCP servers. It collected names from a single server using a set comprehension, which inherently discards duplicates. When a misconfigured or buggy MCP server returned multiple tools with identical names, the later entry would silently overwrite the earlier one. This caused non-deterministic tool registration, unpredictable agent behavior, and made it extremely difficult to trace the root cause of tool routing failures. ## Solution Introduced an explicit intra-server duplicate detection step before the existing cross-server validation. The updated logic uses collections.Counter to track the frequency of each tool name returned by a server. If any name appears more than once, the system raises a UserError with a precise message identifying the offending server and the duplicated names. The original cross-server duplicate check remains fully intact and operates on the deduplicated set of names. ## Technical Implementation - Replaced the initial set comprehension with a Counter to capture name frequencies per server response - Added a filtered iteration to identify names with a count greater than one - Introduced a targeted UserError for intra-server duplicates that includes the server name for immediate troubleshooting - Converted the Counter keys back to a set to preserve the existing cross-server intersection logic - Leveraged the already-imported collections.Counter, requiring zero new dependencies - Maintains full backward compatibility with no changes to public method signatures, error types, or external APIs ## Code Changes Location: MCPUtil.get_all_function_tools() inside the for server in servers: loop ### Before: ```python server_tool_names = {tool.name for tool in server_tools} duplicate_tool_names = sorted(server_tool_names & tool_names) if duplicate_tool_names: raise UserError( "Duplicate tool names found across MCP servers: " f"{', '.join(duplicate_tool_names)}" ) ``` ### After: ```python server_tool_name_counts = Counter(tool.name for tool in server_tools) intra_server_duplicate_tool_names = sorted( name for name, count in server_tool_name_counts.items() if count > 1 ) if intra_server_duplicate_tool_names: raise UserError( "Duplicate tool names found within MCP server " f"'{server.name}': {', '.join(intra_server_duplicate_tool_names)}" ) server_tool_names = set(server_tool_name_counts) duplicate_tool_names = sorted(server_tool_names & tool_names) if duplicate_tool_names: raise UserError( "Duplicate tool names found across MCP servers: " f"{', '.join(duplicate_tool_names)}" ) ``` ## Impact and Verification - Prevents silent tool overwrites when an MCP server returns duplicate tool definitions - Provides clear, actionable error messages that immediately identify the source of naming conflicts - Preserves all existing cross-server validation behavior and error formatting - Verified against the existing test suite, which passes without modification - Introduces no new dependencies or runtime overhead - Safe for immediate merge as a backward-compatible stability improvement --- src/agents/mcp/util.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/agents/mcp/util.py b/src/agents/mcp/util.py index bf00cb2b79..22250f027b 100644 --- a/src/agents/mcp/util.py +++ b/src/agents/mcp/util.py @@ -277,7 +277,17 @@ async def get_all_function_tools( agent, failure_error_function=failure_error_function, ) - server_tool_names = {tool.name for tool in server_tools} + server_tool_name_counts = Counter(tool.name for tool in server_tools) + intra_server_duplicate_tool_names = sorted( + name for name, count in server_tool_name_counts.items() if count > 1 + ) + if intra_server_duplicate_tool_names: + raise UserError( + "Duplicate tool names found within MCP server " + f"'{server.name}': {', '.join(intra_server_duplicate_tool_names)}" + ) + + server_tool_names = set(server_tool_name_counts) duplicate_tool_names = sorted(server_tool_names & tool_names) if duplicate_tool_names: raise UserError(