use anyhow::Error;
use std::collections::HashMap;
use std::sync::Arc;
use serde_json::Value;
use crate::tools::Tool;
use super::client::{McpClient, McpTool};
use log::info;
pub struct McpToolAdapter {
mcp_client: Arc<dyn McpClient>,
mcp_tool: McpTool,
}
impl McpToolAdapter {
pub fn new(mcp_client: Arc<dyn McpClient>, mcp_tool: McpTool) -> Self {
Self {
mcp_client,
mcp_tool,
}
}
pub fn new_from_box(mcp_client: Box<dyn McpClient>, mcp_tool: McpTool) -> Self {
Self {
mcp_client: Arc::from(mcp_client),
mcp_tool,
}
}
pub fn get_client(&self) -> Arc<dyn McpClient> {
self.mcp_client.clone()
}
pub fn get_mcp_tool(&self) -> McpTool {
self.mcp_tool.clone()
}
}
impl Tool for McpToolAdapter {
fn name(&self) -> &str {
&self.mcp_tool.name
}
fn description(&self) -> &str {
&self.mcp_tool.description
}
fn invoke(&self, input: &str) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<String, Error>> + Send + '_>> {
let client = self.mcp_client.clone();
let tool_name = self.mcp_tool.name.clone();
let input_str = input.to_string();
info!("Invoking MCP tool {} with input: {}", tool_name, input_str);
Box::pin(async move {
let parameters: HashMap<String, Value> = match serde_json::from_str(&input_str) {
Ok(params) => params,
Err(_) => {
let mut map = HashMap::new();
map.insert("query".to_string(), Value::String(input_str.clone()));
map
},
};
let result_future = client.call_tool(&tool_name, parameters);
let result = result_future.await?;
Ok(serde_json::to_string_pretty(&result)?)
})
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
}