mirror of
https://github.com/openai/codex.git
synced 2026-11-13 22:47:20 +00:00
[mcp] Expand tool search to custom MCPs. (#16944)
- [x] Expand tool search to custom MCPs.
- [x] Rename several variables/fields to be more generic.
Updated tool & server name lifecycles:
**Raw Identity**
ToolInfo.server_name is raw MCP server name.
ToolInfo.tool.name is raw MCP tool name.
MCP calls route back to raw via parse_tool_name() returning
(tool.server_name, tool.tool.name).
mcpServerStatus/list now groups by raw server and keys tools by
Tool.name: mod.rs:599
App-server just forwards that grouped raw snapshot:
codex_message_processor.rs:5245
**Callable Names**
On list-tools, we create provisional callable_namespace / callable_name:
mcp_connection_manager.rs:1556
For non-app MCP, provisional callable name starts as raw tool name.
For codex-apps, provisional callable name is sanitized and strips
connector name/id prefix; namespace includes connector name.
Then qualify_tools() sanitizes callable namespace + name to ASCII alnum
/ _ only: mcp_tool_names.rs:128
Note: this is stricter than Responses API. Hyphen is currently replaced
with _ for code-mode compatibility.
**Collision Handling**
We do initially collapse example-server and example_server to the same
base.
Then qualify_tools() detects distinct raw namespace identities behind
the same sanitized namespace and appends a hash to the callable
namespace: mcp_tool_names.rs:137
Same idea for tool-name collisions: hash suffix goes on callable tool
name.
Final list_all_tools() map key is callable_namespace + callable_name:
mcp_connection_manager.rs:769
**Direct Model Tools**
Direct MCP tool declarations use the full qualified sanitized key as the
Responses function name.
The raw rmcp Tool is converted but renamed for model exposure.
**Tool Search / Deferred**
Tool search result namespace = final ToolInfo.callable_namespace:
tool_search.rs:85
Tool search result nested name = final ToolInfo.callable_name:
tool_search.rs:86
Deferred tool handler is registered as "{namespace}:{name}":
tool_registry_plan.rs:248
When a function call comes back, core recombines namespace + name, looks
up the full qualified key, and gets the raw server/tool for MCP
execution: codex.rs:4353
**Separate Legacy Snapshot**
collect_mcp_snapshot_from_manager_with_detail() still returns a map
keyed by qualified callable name.
mcpServerStatus/list no longer uses that; it uses
McpServerStatusSnapshot, which is raw-inventory shaped.
This commit is contained in:
1 parent
545f3daba0
commit
d7f99b0fa6
26 files changed
+1297
-737
No files matched your search
@@ -25,18 +25,12 @@ async fn js_repl_tools_only_blocks_direct_tool_calls() -> anyhow::Result<()> {
|
||||
.await
|
||||
.list_all_tools()
|
||||
.await;
|
||||
let app_tools = Some(mcp_tools.clone());
|
||||
let deferred_mcp_tools = Some(mcp_tools.clone());
|
||||
let router = ToolRouter::from_config(
|
||||
&turn.tools_config,
|
||||
ToolRouterParams {
|
||||
mcp_tools: Some(
|
||||
mcp_tools
|
||||
.into_iter()
|
||||
.map(|(name, tool)| (name, tool.tool))
|
||||
.collect(),
|
||||
),
|
||||
tool_namespaces: None,
|
||||
app_tools,
|
||||
deferred_mcp_tools,
|
||||
mcp_tools: Some(mcp_tools),
|
||||
discoverable_tools: None,
|
||||
dynamic_tools: turn.dynamic_tools.as_slice(),
|
||||
},
|
||||
@@ -84,18 +78,12 @@ async fn js_repl_tools_only_allows_js_repl_source_calls() -> anyhow::Result<()>
|
||||
.await
|
||||
.list_all_tools()
|
||||
.await;
|
||||
let app_tools = Some(mcp_tools.clone());
|
||||
let deferred_mcp_tools = Some(mcp_tools.clone());
|
||||
let router = ToolRouter::from_config(
|
||||
&turn.tools_config,
|
||||
ToolRouterParams {
|
||||
mcp_tools: Some(
|
||||
mcp_tools
|
||||
.into_iter()
|
||||
.map(|(name, tool)| (name, tool.tool))
|
||||
.collect(),
|
||||
),
|
||||
tool_namespaces: None,
|
||||
app_tools,
|
||||
deferred_mcp_tools,
|
||||
mcp_tools: Some(mcp_tools),
|
||||
discoverable_tools: None,
|
||||
dynamic_tools: turn.dynamic_tools.as_slice(),
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user