rust_agent/mcp/
adapter.rs

1// Tool adapter definition
2use anyhow::Error;
3use std::collections::HashMap;
4use std::sync::Arc;
5use serde_json::Value;
6use crate::tools::Tool;
7use super::client::{McpClient, McpTool};
8use log::info;
9// MCP tool adapter
10pub struct McpToolAdapter {
11    mcp_client: Arc<dyn McpClient>,
12    mcp_tool: McpTool,
13}
14
15impl McpToolAdapter {
16    pub fn new(mcp_client: Arc<dyn McpClient>, mcp_tool: McpTool) -> Self {
17        Self {
18            mcp_client,
19            mcp_tool,
20        }
21    }
22    
23    // Constructor method to convert from Box to Arc
24    pub fn new_from_box(mcp_client: Box<dyn McpClient>, mcp_tool: McpTool) -> Self {
25        Self {
26            mcp_client: Arc::from(mcp_client),
27            mcp_tool,
28        }
29    }
30    
31    // Get reference to the client
32    pub fn get_client(&self) -> Arc<dyn McpClient> {
33        self.mcp_client.clone()
34    }
35    
36    // Get clone of the MCP tool
37    pub fn get_mcp_tool(&self) -> McpTool {
38        self.mcp_tool.clone()
39    }
40}
41
42impl Tool for McpToolAdapter {
43    fn name(&self) -> &str {
44        &self.mcp_tool.name
45    }
46    
47    fn description(&self) -> &str {
48        &self.mcp_tool.description
49    }
50    
51    fn invoke(&self, input: &str) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<String, Error>> + Send + '_>> {
52        let client = self.mcp_client.clone();
53        let tool_name = self.mcp_tool.name.clone();
54        let input_str = input.to_string();
55        info!("Invoking MCP tool {} with input: {}", tool_name, input_str);
56        Box::pin(async move {
57            // Try to parse input as JSON parameters, add fault tolerance
58            let parameters: HashMap<String, Value> = match serde_json::from_str(&input_str) {
59                Ok(params) => params,
60                Err(_) => {
61                    // Simple handling, use input as default parameter
62                    let mut map = HashMap::new();
63                    map.insert("query".to_string(), Value::String(input_str.clone()));
64                    map
65                },
66            };
67            
68            // Call the tool on the MCP server
69            let result_future = client.call_tool(&tool_name, parameters);
70            let result = result_future.await?;
71            
72            // Convert result to string
73            Ok(serde_json::to_string_pretty(&result)?)
74        })
75    }
76    
77    // Implement as_any method to support runtime type checking
78    fn as_any(&self) -> &dyn std::any::Any {
79        self
80    }
81}