1use crate::{Result, RuntimeError, Tool, ToolContext};
3use serde_json::Value;
4use std::sync::Arc;
5use tokio::sync::Mutex;
6
7use super::connection::McpConnection;
8
9pub struct McpTool {
12 pub(super) tool_name: String,
13 pub(super) server_tool_name: String,
15 pub(super) server_name: String,
16 pub(super) description: String,
17 pub(super) input_schema: Value,
18 pub(super) connection: Arc<Mutex<McpConnection>>,
19}
20
21#[async_trait::async_trait]
22impl Tool for McpTool {
23 fn origin(&self) -> crate::tools::ToolOrigin {
24 crate::tools::ToolOrigin::Mcp {
25 server_id: self.server_name.clone(),
26 server_tool_name: self.server_tool_name.clone(),
27 }
28 }
29
30 fn name(&self) -> &str {
31 &self.tool_name
32 }
33
34 fn description(&self) -> &str {
35 &self.description
36 }
37
38 fn parameters(&self) -> Value {
39 self.input_schema.clone()
40 }
41
42 async fn execute(&self, params: Value, ctx: ToolContext) -> Result<String> {
43 let binding = ctx
44 .capabilities
45 .memory_backend
46 .unwrap_or_else(crate::memory_backend::MemoryBinding::configured_current);
47 if binding.exclusive() && crate::memory_backend::competing_note_tool(&self.server_tool_name)
48 {
49 return Err(RuntimeError::Tool("independent MCP memory is disabled by the host-selected backend; use short memory tools".into()));
50 }
51 let mut conn = self.connection.lock().await;
52 conn.call_tool(&self.server_tool_name, params)
53 .await
54 .map_err(|e| {
55 RuntimeError::Tool(format!(
56 "MCP tool '{}' (server '{}') failed: {}",
57 self.tool_name, self.server_name, e
58 ))
59 })
60 }
61}