1use anyhow::Result;
4
5pub use crate::core::provider::Tool;
7
8pub async fn fetch_mcp_tools(tools_str: &str) -> Result<(Option<Vec<Tool>>, Vec<String>)> {
10 use crate::services::mcp::McpConfig;
11 use crate::services::mcp_daemon::DaemonClient;
12
13 let server_names: Vec<&str> = tools_str.split(',').map(|s| s.trim()).collect();
14 let mut all_tools = Vec::new();
15 let mut valid_server_names = Vec::new();
16
17 let config = McpConfig::load().await?;
19
20 let daemon_client = DaemonClient::new()?;
22
23 for server_name in server_names {
24 if server_name.is_empty() {
25 continue;
26 }
27
28 crate::debug_log!("Fetching tools from MCP server '{}'", server_name);
29
30 if config.get_server(server_name).is_some() {
32 match daemon_client.ensure_server_connected(server_name).await {
34 Ok(_) => {
35 crate::debug_log!("Successfully connected to MCP server '{}'", server_name);
36 valid_server_names.push(server_name.to_string());
37 }
38 Err(e) => {
39 eprintln!(
40 "Warning: Failed to connect to MCP server '{}': {}",
41 server_name, e
42 );
43 continue;
44 }
45 }
46 } else {
47 eprintln!(
48 "Warning: MCP server '{}' not found in configuration",
49 server_name
50 );
51 continue;
52 }
53 }
54
55 for server_name in &valid_server_names {
57 match daemon_client.list_tools(server_name).await {
58 Ok(server_tools) => {
59 if let Some(tools) = server_tools.get(server_name) {
60 crate::debug_log!(
61 "Retrieved {} tools from server '{}'",
62 tools.len(),
63 server_name
64 );
65
66 for tool in tools {
67 let mut simplified_schema = serde_json::Map::new();
70
71 if let Some(properties) = tool.input_schema.get("properties") {
73 simplified_schema.insert("type".to_string(), serde_json::json!("object"));
74 simplified_schema.insert("properties".to_string(), properties.clone());
75
76 if let Some(required) = tool.input_schema.get("required") {
77 simplified_schema.insert("required".to_string(), required.clone());
78 }
79 } else {
80 simplified_schema.insert("type".to_string(), serde_json::json!("object"));
82 simplified_schema.insert("properties".to_string(), serde_json::json!({}));
83 }
84
85 let openai_tool = crate::core::provider::Tool {
86 tool_type: "function".to_string(),
87 function: crate::core::provider::Function {
88 name: tool.name.to_string(),
89 description: tool
90 .description
91 .as_ref()
92 .map(|s| s.to_string())
93 .unwrap_or_else(|| "No description".to_string()),
94 parameters: serde_json::Value::Object(simplified_schema),
95 },
96 };
97
98 all_tools.push(openai_tool);
99 crate::debug_log!(
100 "Added tool '{}' from server '{}'",
101 tool.name,
102 server_name
103 );
104 }
105 }
106 }
107 Err(e) => {
108 eprintln!(
109 "Warning: Failed to list tools from MCP server '{}': {}",
110 server_name, e
111 );
112 }
113 }
114 }
115
116 if all_tools.is_empty() {
119 crate::debug_log!("No tools found from any specified MCP servers");
120 Ok((None, valid_server_names))
121 } else {
122 crate::debug_log!("Total {} tools fetched from MCP servers", all_tools.len());
123 Ok((Some(all_tools), valid_server_names))
124 }
125}
126
127pub async fn execute_mcp_tool(
129 server_name: &str,
130 tool_name: &str,
131 arguments: serde_json::Value,
132) -> Result<serde_json::Value> {
133 use crate::services::mcp_daemon::DaemonClient;
134
135 let daemon_client = DaemonClient::new()?;
136
137 crate::debug_log!(
138 "Executing tool '{}' on server '{}' with arguments: {}",
139 tool_name,
140 server_name,
141 arguments
142 );
143
144 match daemon_client.call_tool(server_name, tool_name, arguments).await {
145 Ok(result) => {
146 crate::debug_log!("Tool execution successful");
147 Ok(result)
148 }
149 Err(e) => {
150 crate::debug_log!("Tool execution failed: {}", e);
151 Err(e)
152 }
153 }
154}