Disambiguate flattened MCP tool names

This commit is contained in:
Mitsuhiro Kotake
2026-06-23 13:58:49 +09:00
parent 0b7b2436bb
commit 18fecc6723
2 changed files with 30 additions and 4 deletions
@@ -481,6 +481,27 @@ fn test_normalize_tools_disambiguates_sanitized_tool_name_collisions() {
assert_eq!(callable_tool_names.len(), 2);
}
#[test]
fn test_normalize_tools_disambiguates_canonical_flat_name_collisions() {
let tools = vec![create_test_tool("a", "b__c"), create_test_tool("a__b", "c")];
let model_tools =
normalize_tools_for_model_with_prefix(tools, /*prefix_mcp_tool_names*/ true);
assert_eq!(model_tools.len(), 2);
assert_eq!(model_tool_names(&model_tools).len(), 2);
let canonical_flat_names = model_tools
.iter()
.map(|tool| {
tool.canonical_tool_name()
.canonical_flat_name()
.into_owned()
})
.collect::<HashSet<_>>();
assert_eq!(canonical_flat_names.len(), 2);
assert!(canonical_flat_names.contains("mcp__a__b__c"));
}
#[test]
fn tool_filter_allows_by_default() {
let filter = ToolFilter::default();
+9 -4
View File
@@ -376,8 +376,8 @@ fn unique_callable_parts(
used_names: &mut HashSet<String>,
reserved_len: usize,
) -> (String, String) {
let model_name = format!("{namespace}{tool_name}");
if model_name.len() + reserved_len <= MAX_TOOL_NAME_LENGTH && used_names.insert(model_name) {
let canonical_flat_name = canonical_flat_tool_name(namespace, tool_name);
if canonical_flat_name.len() <= MAX_TOOL_NAME_LENGTH && used_names.insert(canonical_flat_name) {
return (namespace.to_string(), tool_name.to_string());
}
@@ -390,10 +390,15 @@ fn unique_callable_parts(
};
let (namespace, tool_name) =
fit_callable_parts_with_hash(namespace, tool_name, &hash_input, reserved_len);
let model_name = format!("{namespace}{tool_name}");
if used_names.insert(model_name) {
if used_names.insert(canonical_flat_tool_name(&namespace, &tool_name)) {
return (namespace, tool_name);
}
attempt = attempt.saturating_add(1);
}
}
fn canonical_flat_tool_name(namespace: &str, tool_name: &str) -> String {
ToolName::namespaced(namespace, tool_name)
.canonical_flat_name()
.into_owned()
}