claude_agent/tools/
mcp.rs1use std::sync::Arc;
4
5use async_trait::async_trait;
6use serde_json::Value;
7
8use super::{ExecutionContext, Tool};
9use crate::mcp::{McpManager, McpToolDefinition, make_mcp_name, parse_mcp_name};
10use crate::types::{ToolDefinition, ToolResult};
11
12pub struct McpToolWrapper {
17 manager: Arc<McpManager>,
18 qualified_name: String,
19 server_name: String,
20 tool_name: String,
21 definition: McpToolDefinition,
22}
23
24impl McpToolWrapper {
25 pub fn new(
26 manager: Arc<McpManager>,
27 server_name: impl Into<String>,
28 tool: McpToolDefinition,
29 ) -> Self {
30 let server_name = server_name.into();
31 let qualified_name = make_mcp_name(&server_name, &tool.name);
32 Self {
33 manager,
34 qualified_name,
35 server_name,
36 tool_name: tool.name.clone(),
37 definition: tool,
38 }
39 }
40
41 pub fn qualified_name(&self) -> &str {
42 &self.qualified_name
43 }
44
45 pub fn server_name(&self) -> &str {
46 &self.server_name
47 }
48
49 pub fn tool_name(&self) -> &str {
50 &self.tool_name
51 }
52}
53
54#[async_trait]
55impl Tool for McpToolWrapper {
56 fn name(&self) -> &str {
57 &self.qualified_name
58 }
59
60 fn description(&self) -> &str {
61 &self.definition.description
62 }
63
64 fn input_schema(&self) -> Value {
65 self.definition.input_schema.clone()
66 }
67
68 fn definition(&self) -> ToolDefinition {
69 ToolDefinition::new(
70 &self.qualified_name,
71 &self.definition.description,
72 self.definition.input_schema.clone(),
73 )
74 }
75
76 async fn execute(&self, input: Value, _context: &ExecutionContext) -> ToolResult {
77 match self.manager.call_tool(&self.qualified_name, input).await {
78 Ok(result) => {
79 if result.is_error {
80 ToolResult::error(result.to_string_content())
81 } else {
82 ToolResult::success(result.to_string_content())
83 }
84 }
85 Err(e) => ToolResult::error(e.to_string()),
86 }
87 }
88}
89
90pub async fn create_mcp_tools(manager: Arc<McpManager>) -> Vec<Arc<dyn Tool>> {
92 let tools_list = manager.list_tools().await;
93 let mut wrappers: Vec<Arc<dyn Tool>> = Vec::with_capacity(tools_list.len());
94
95 for (qualified_name, definition) in tools_list {
96 if let Some((server, _tool)) = parse_mcp_name(&qualified_name) {
97 let wrapper = McpToolWrapper::new(Arc::clone(&manager), server, definition);
98 wrappers.push(Arc::new(wrapper));
99 }
100 }
101
102 wrappers
103}