Skip to content

Commit 9a2b4a9

Browse files
fix(mcp): make duplicate tool errors deterministic (#3136)
1 parent e22f25a commit 9a2b4a9

2 files changed

Lines changed: 29 additions & 4 deletions

File tree

src/agents/mcp/util.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -223,10 +223,11 @@ async def get_all_function_tools(
223223
failure_error_function=failure_error_function,
224224
)
225225
server_tool_names = {tool.name for tool in server_tools}
226-
if len(server_tool_names & tool_names) > 0:
226+
duplicate_tool_names = sorted(server_tool_names & tool_names)
227+
if duplicate_tool_names:
227228
raise UserError(
228-
f"Duplicate tool names found across MCP servers: "
229-
f"{server_tool_names & tool_names}"
229+
"Duplicate tool names found across MCP servers: "
230+
f"{', '.join(duplicate_tool_names)}"
230231
)
231232
tool_names.update(server_tool_names)
232233
tools.extend(server_tools)

tests/mcp/test_mcp_util.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,12 @@
1111

1212
import agents._debug as _debug
1313
from agents import Agent, FunctionTool, RunContextWrapper, default_tool_error_function
14-
from agents.exceptions import AgentsException, MCPToolCancellationError, ModelBehaviorError
14+
from agents.exceptions import (
15+
AgentsException,
16+
MCPToolCancellationError,
17+
ModelBehaviorError,
18+
UserError,
19+
)
1520
from agents.mcp import MCPServer, MCPUtil
1621
from agents.tool_context import ToolContext
1722

@@ -83,6 +88,25 @@ async def test_get_all_function_tools():
8388
assert all(tool.name in names for tool in tools)
8489

8590

91+
@pytest.mark.asyncio
92+
async def test_get_all_function_tools_duplicate_error_is_deterministic():
93+
server1 = FakeMCPServer(server_name="server_1")
94+
server1.add_tool("zeta", {})
95+
server1.add_tool("alpha", {})
96+
97+
server2 = FakeMCPServer(server_name="server_2")
98+
server2.add_tool("alpha", {})
99+
server2.add_tool("zeta", {})
100+
101+
run_context = RunContextWrapper(context=None)
102+
agent = Agent(name="test_agent", instructions="Test agent")
103+
104+
with pytest.raises(UserError) as exc_info:
105+
await MCPUtil.get_all_function_tools([server1, server2], False, run_context, agent)
106+
107+
assert str(exc_info.value) == "Duplicate tool names found across MCP servers: alpha, zeta"
108+
109+
86110
@pytest.mark.asyncio
87111
async def test_invoke_mcp_tool():
88112
"""Test that the invoke_mcp_tool function invokes an MCP tool and returns the result."""

0 commit comments

Comments
 (0)