From aa024bc9048a465f322100522eb24deb46970b5b Mon Sep 17 00:00:00 2001 From: Justin Barnett Date: Thu, 23 Apr 2026 14:48:32 -0400 Subject: [PATCH] fix(mcp): allow Claude Code names in tool validation --- crates/forge_app/src/tool_resolver.rs | 41 +++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/crates/forge_app/src/tool_resolver.rs b/crates/forge_app/src/tool_resolver.rs index 2f3d118a6a..a3b768a0ac 100644 --- a/crates/forge_app/src/tool_resolver.rs +++ b/crates/forge_app/src/tool_resolver.rs @@ -50,9 +50,16 @@ impl ToolResolver { pub fn is_allowed(agent: &Agent, tool_name: &ToolName) -> bool { let aliases = deprecated_tool_aliases(); - // Normalize the incoming tool name using aliases let normalized_tool_name = aliases.get(tool_name.as_str()).unwrap_or(tool_name); - Self::is_allowed_pattern(&Self::build_patterns(agent), normalized_tool_name) + let legacy_mcp_tool_name = normalized_tool_name.to_legacy_mcp_name(); + let patterns = Self::build_patterns(agent); + + Self::is_allowed_pattern(&patterns, normalized_tool_name) + || legacy_mcp_tool_name + .as_ref() + .is_some_and(|legacy_tool_name| { + Self::is_allowed_pattern(&patterns, legacy_tool_name) + }) } /// Builds glob patterns from the agent's tool patterns, deduplicating @@ -336,6 +343,36 @@ mod tests { assert_eq!(actual, expected); } + #[test] + fn test_exact_legacy_mcp_tool_allows_claude_code_name() { + let fixture = Agent::new( + AgentId::new("test-agent"), + ProviderId::ANTHROPIC, + ModelId::new("claude-3-5-sonnet-20241022"), + ) + .tools(vec![ToolName::new("mcp_github_tool_create_issue")]); + + assert!(ToolResolver::is_allowed( + &fixture, + &ToolName::new("mcp__github__create_issue"), + )); + } + + #[test] + fn test_glob_legacy_mcp_tool_allows_claude_code_name() { + let fixture = Agent::new( + AgentId::new("test-agent"), + ProviderId::ANTHROPIC, + ModelId::new("claude-3-5-sonnet-20241022"), + ) + .tools(vec![ToolName::new("mcp_github_tool_*")]); + + assert!(ToolResolver::is_allowed( + &fixture, + &ToolName::new("mcp__github__create_issue"), + )); + } + #[test] fn test_backward_compatibility_search_alias() { // Test that deprecated "search" name resolves to "fs_search"