feat(mcp): #1167 add include_server_in_tool_names option to avoid duplicate name collisions#2830
feat(mcp): #1167 add include_server_in_tool_names option to avoid duplicate name collisions#2830hashwnath wants to merge 2 commits intoopenai:mainfrom
Conversation
… name collisions When multiple MCP servers expose tools with the same name, the agent currently raises a UserError. This adds an opt-in MCPConfig option `include_server_in_tool_names` that prefixes tool names with the sanitized server name (e.g. `my_server__run`), allowing tools from different servers to coexist. The original MCP tool name is preserved for server invocation via functools.partial. Fixes openai#1167
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 214e19efe2
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| if include_server_in_tool_names: | ||
| prefix = _sanitize_server_name(server.name) | ||
| for tool in server_tools: | ||
| if isinstance(tool, FunctionTool): | ||
| tool.name = f"{prefix}__{tool.name}" |
There was a problem hiding this comment.
Detect collisions after server-name prefixing
When include_server_in_tool_names is enabled, tool names are rewritten using a sanitized server prefix but this branch never validates that the rewritten names are unique. For example, servers named a-b and a_b both sanitize to a_b, so run becomes a_b__run for both servers. Downstream function-tool lookup is last-wins, so one tool silently shadows the other and dispatch can target the wrong server instead of raising a UserError like the default path does.
Useful? React with 👍 / 👎.
Move the duplicate-name check so it runs after prefixing as well. Servers whose names sanitize to the same prefix (e.g. "a-b" and "a_b") now correctly raise UserError instead of silently shadowing tools. Addresses Codex review feedback on PR openai#2830.
Summary
When multiple MCP servers expose tools with the same name, the SDK raises a
UserErrorand the agent cannot proceed. This is a common scenario in production multi-server deployments where different MCP servers may independently define tools with generic names likerun,search, orexecute.This PR adds an opt-in
include_server_in_tool_namesoption toMCPConfigthat prefixes each tool's name with its originating server name (e.g.my_server__run), allowing tools from different servers to coexist without collisions. Key design decisions:UserErroron duplicates) is preserved. Users enable prefixing explicitly viamcp_config={"include_server_in_tool_names": True}."server"for empty/all-special-character names. This ensures the prefixed name is always a valid tool identifier.MCPToolobject captured in thefunctools.partialclosure retains the original name, soserver.call_tool()always receives the correct MCP tool name regardless of the display prefix.include_server_in_tool_namesas suggested by @seratch in the review of the prior PR feat(mcp): optional server-name prefix for colliding tool names #2442.This follows up on the closed PR #2442 by @weiguangli-io, which implemented the same feature but went stale awaiting re-review.
Test plan
test_duplicate_tool_names_raises_by_default: verifies the existingUserErrorbehavior is unchanged.test_include_server_in_tool_names_avoids_collision: two servers with same tool name → no error, both tools available with prefixed names.test_include_server_in_tool_names_invokes_with_original_name: verifies the MCP server receives the original (unprefixed) tool name during invocation.test_include_server_in_tool_names_sanitizes_server_name: verifies special characters in server names are sanitized (e.g.my-cool.server/v2→my_cool_server_v2).test_include_server_in_tool_names_empty_server_name_fallback: verifies fallback to"server"prefix for degenerate names.make format,make lint,make typecheckall pass clean (only pre-existing mypy error in unrelated file).Issue number
Fixes #1167
Checks
make lintandmake format