use std::sync::Arc; use forge_domain::{TitleFormat, ToolCallContext, ToolCallFull, ToolName, ToolOutput}; use crate::McpService; pub struct McpExecutor { services: Arc, } impl McpExecutor { pub fn new(services: Arc) -> Self { Self { services } } pub async fn execute( &self, input: ToolCallFull, context: &ToolCallContext, ) -> anyhow::Result { context .send_tool_input(TitleFormat::info("MCP").sub_title(input.name.as_str())) .await?; self.services.execute_mcp(input).await } pub async fn contains_tool(&self, tool_name: &ToolName) -> anyhow::Result { let mcp_servers = self.services.get_mcp_servers().await?; // Convert Claude Code format (mcp__{server}__{tool}) to the internal legacy // format (mcp_{server}_tool_{tool}) before checking, so both name styles match. let legacy = tool_name.to_legacy_mcp_name(); let found = mcp_servers.get_servers().values().any(|tools| { tools .iter() .any(|tool| tool.name == *tool_name || legacy.as_ref() == Some(&tool.name)) }); Ok(found) } }