rust_agent/mcp/
adapter.rs1use 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;
9pub 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 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 pub fn get_client(&self) -> Arc<dyn McpClient> {
33 self.mcp_client.clone()
34 }
35
36 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 let parameters: HashMap<String, Value> = match serde_json::from_str(&input_str) {
59 Ok(params) => params,
60 Err(_) => {
61 let mut map = HashMap::new();
63 map.insert("query".to_string(), Value::String(input_str.clone()));
64 map
65 },
66 };
67
68 let result_future = client.call_tool(&tool_name, parameters);
70 let result = result_future.await?;
71
72 Ok(serde_json::to_string_pretty(&result)?)
74 })
75 }
76
77 fn as_any(&self) -> &dyn std::any::Any {
79 self
80 }
81}