33import asyncio
44import copy
55import functools
6+ import hashlib
67import inspect
78import json
89from collections .abc import Awaitable
@@ -212,6 +213,9 @@ async def get_all_function_tools(
212213 """Get all function tools from a list of MCP servers."""
213214 tools = []
214215 tool_names : set [str ] = set ()
216+ server_tool_name_prefixes = (
217+ cls ._server_tool_name_prefixes (servers ) if include_server_in_tool_names else {}
218+ )
215219 for server in servers :
216220 server_tools = await cls .get_function_tools (
217221 server ,
@@ -220,6 +224,7 @@ async def get_all_function_tools(
220224 agent ,
221225 failure_error_function = failure_error_function ,
222226 include_server_in_tool_names = include_server_in_tool_names ,
227+ tool_name_prefix = server_tool_name_prefixes .get (id (server )),
223228 )
224229 server_tool_names = {tool .name for tool in server_tools }
225230 if len (server_tool_names & tool_names ) > 0 :
@@ -241,16 +246,18 @@ async def get_function_tools(
241246 agent : AgentBase ,
242247 failure_error_function : ToolErrorFunction | None = default_tool_error_function ,
243248 include_server_in_tool_names : bool = False ,
249+ tool_name_prefix : str | None = None ,
244250 ) -> list [Tool ]:
245251 """Get all function tools from a single MCP server."""
246252
247253 with mcp_tools_span (server = server .name ) as span :
248254 tools = await server .list_tools (run_context , agent )
249255 span .span_data .result = [tool .name for tool in tools ]
250256
251- tool_name_prefix = (
252- cls ._server_tool_name_prefix (server .name ) if include_server_in_tool_names else ""
253- )
257+ if tool_name_prefix is None :
258+ tool_name_prefix = (
259+ cls ._server_tool_name_prefix (server .name ) if include_server_in_tool_names else ""
260+ )
254261 return [
255262 cls .to_function_tool (
256263 tool ,
@@ -273,6 +280,30 @@ def _server_tool_name_prefix(server_name: str) -> str:
273280 normalized = "server"
274281 return f"{ normalized } _"
275282
283+ @classmethod
284+ def _server_tool_name_prefixes (cls , servers : list [MCPServer ]) -> dict [int , str ]:
285+ normalized_to_servers : dict [str , list [MCPServer ]] = {}
286+ for server in servers :
287+ normalized_prefix = cls ._server_tool_name_prefix (server .name )[:- 1 ]
288+ normalized_to_servers .setdefault (normalized_prefix , []).append (server )
289+
290+ prefixes : dict [int , str ] = {}
291+ for normalized_prefix , grouped_servers in normalized_to_servers .items ():
292+ if len (grouped_servers ) == 1 :
293+ prefixes [id (grouped_servers [0 ])] = f"{ normalized_prefix } _"
294+ continue
295+
296+ seen_prefixes : set [str ] = set ()
297+ for index , server in enumerate (grouped_servers , start = 1 ):
298+ hash_suffix = hashlib .sha1 (server .name .encode ("utf-8" )).hexdigest ()[:8 ]
299+ prefix = f"{ normalized_prefix } _{ hash_suffix } "
300+ if prefix in seen_prefixes :
301+ prefix = f"{ prefix } _{ index } "
302+ seen_prefixes .add (prefix )
303+ prefixes [id (server )] = f"{ prefix } _"
304+
305+ return prefixes
306+
276307 @classmethod
277308 def to_function_tool (
278309 cls ,
0 commit comments