use std::sync::Arc;
use futures::future::BoxFuture;
use super::client::McpClient;
use super::types::McpTool;
use echo_core::error::Result;
use echo_core::tools::{Tool, ToolParameters, ToolResult};
pub struct McpToolAdapter {
client: Arc<McpClient>,
tool: McpTool,
}
impl McpToolAdapter {
pub fn new(client: Arc<McpClient>, tool: McpTool) -> Self {
Self { client, tool }
}
}
impl Tool for McpToolAdapter {
fn name(&self) -> &str {
&self.tool.name
}
fn description(&self) -> &str {
self.tool.description.as_deref().unwrap_or("")
}
fn parameters(&self) -> serde_json::Value {
self.tool.input_schema.clone()
}
fn execute(&self, parameters: ToolParameters) -> BoxFuture<'_, Result<ToolResult>> {
Box::pin(async move {
let args = serde_json::Value::Object(parameters.into_iter().collect());
let result = self.client.call_tool(&self.tool.name, args).await?;
let mut text = McpClient::content_to_text(&result.content);
if let Some(ref structured) = result.structured_content {
let structured_str = serde_json::to_string_pretty(structured).unwrap_or_default();
text = format!("{text}\n\n结构化数据:\n{structured_str}");
}
if !result.extra.is_empty() {
let extra_str = serde_json::to_string_pretty(&result.extra).unwrap_or_default();
text = format!("{text}\n\n附加字段:\n{extra_str}");
}
if result.is_error {
Ok(ToolResult::error(text))
} else {
Ok(ToolResult::success(text))
}
})
}
}