mirror of
https://github.com/openai/codex.git
synced 2026-11-13 14:46:14 +00:00
[codex] Remove string-keyed MCP tool maps (#21454)
## Summary This PR removes the synthetic `HashMap<String, ToolInfo>` keys from MCP tool discovery. `McpConnectionManager::list_all_tools()` now returns normalized `Vec<ToolInfo>`, and downstream code derives identity from `ToolInfo::canonical_tool_name()`. The motivation is to keep model-visible tool identity on `ToolName`/`ToolInfo` instead of parallel string map keys, so future namespace changes do not have to preserve otherwise-unused lookup keys. ## Changes - Rename the MCP normalization path from `qualify_tools` to `normalize_tools_for_model` and return tool values directly. - Flow MCP tool lists through connectors, plugin injection, router/spec building, code mode, and tool search as vectors/slices. - Keep direct/deferred subtraction local to `mcp_tool_exposure`, using `ToolName` values. - Update tests to compare `ToolName` instances where MCP identity matters. ## Validation - `cargo test -p codex-mcp test_normalize_tools` - `cargo test -p codex-core mcp_tool_exposure` - `cargo test -p codex-core direct_mcp_tools_register_namespaced_handlers` - `cargo test -p codex-core search_tool_registers_namespaced_mcp_tool_aliases` - `just fix -p codex-mcp` - `just fix -p codex-core`
This commit is contained in:
1 parent
114bac1409
commit
857e731478
20 files changed
+459
-471
No files matched your search
@@ -1,4 +1,4 @@
|
||||
//! MCP tool metadata, filtering, schema shaping, and name qualification.
|
||||
//! MCP tool metadata, filtering, schema shaping, and name normalization.
|
||||
//!
|
||||
//! Raw MCP tool identities must be preserved for protocol calls, while
|
||||
//! model-visible tool names must be sanitized, deduplicated, and kept within API
|
||||
@@ -130,12 +130,12 @@ pub(crate) fn filter_tools(tools: Vec<ToolInfo>, filter: &ToolFilter) -> Vec<Too
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Returns a qualified-name lookup for MCP tools.
|
||||
/// Returns MCP tools with model-visible names normalized.
|
||||
///
|
||||
/// Raw MCP server/tool names are kept on each [`ToolInfo`] for protocol calls, while
|
||||
/// `callable_namespace` / `callable_name` are sanitized and, when necessary, hashed so
|
||||
/// every model-visible `mcp__namespace__tool` name is unique and <= 64 bytes.
|
||||
pub(crate) fn qualify_tools<I>(tools: I) -> HashMap<String, ToolInfo>
|
||||
/// every model-visible name is unique and <= 64 bytes.
|
||||
pub(crate) fn normalize_tools_for_model<I>(tools: I) -> Vec<ToolInfo>
|
||||
where
|
||||
I: IntoIterator<Item = ToolInfo>,
|
||||
{
|
||||
@@ -213,9 +213,9 @@ where
|
||||
candidates.sort_by(|left, right| left.raw_tool_identity.cmp(&right.raw_tool_identity));
|
||||
|
||||
let mut used_names = HashSet::new();
|
||||
let mut qualified_tools = HashMap::new();
|
||||
let mut model_tools = Vec::new();
|
||||
for mut candidate in candidates {
|
||||
let (callable_namespace, callable_name, qualified_name) = unique_callable_parts(
|
||||
let (callable_namespace, callable_name) = unique_callable_parts(
|
||||
&candidate.callable_namespace,
|
||||
&candidate.callable_name,
|
||||
&candidate.raw_tool_identity,
|
||||
@@ -223,9 +223,9 @@ where
|
||||
);
|
||||
candidate.tool.callable_namespace = callable_namespace;
|
||||
candidate.tool.callable_name = callable_name;
|
||||
qualified_tools.insert(qualified_name, candidate.tool);
|
||||
model_tools.push(candidate.tool);
|
||||
}
|
||||
qualified_tools
|
||||
model_tools
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -345,10 +345,10 @@ fn unique_callable_parts(
|
||||
tool_name: &str,
|
||||
raw_identity: &str,
|
||||
used_names: &mut HashSet<String>,
|
||||
) -> (String, String, String) {
|
||||
let qualified_name = format!("{namespace}{tool_name}");
|
||||
if qualified_name.len() <= MAX_TOOL_NAME_LENGTH && used_names.insert(qualified_name.clone()) {
|
||||
return (namespace.to_string(), tool_name.to_string(), qualified_name);
|
||||
) -> (String, String) {
|
||||
let model_name = format!("{namespace}{tool_name}");
|
||||
if model_name.len() <= MAX_TOOL_NAME_LENGTH && used_names.insert(model_name) {
|
||||
return (namespace.to_string(), tool_name.to_string());
|
||||
}
|
||||
|
||||
let mut attempt = 0_u32;
|
||||
@@ -360,9 +360,9 @@ fn unique_callable_parts(
|
||||
};
|
||||
let (namespace, tool_name) =
|
||||
fit_callable_parts_with_hash(namespace, tool_name, &hash_input);
|
||||
let qualified_name = format!("{namespace}{tool_name}");
|
||||
if used_names.insert(qualified_name.clone()) {
|
||||
return (namespace, tool_name, qualified_name);
|
||||
let model_name = format!("{namespace}{tool_name}");
|
||||
if used_names.insert(model_name) {
|
||||
return (namespace, tool_name);
|
||||
}
|
||||
attempt = attempt.saturating_add(1);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user