#[cfg(feature = "mcp-client")]
use crate::core::{McpClientError, McpClientManager};
#[cfg(feature = "mcp-client")]
use rmcp::model::CallToolResult;
#[cfg(feature = "mcp-client")]
use serde_json::Value;
#[cfg(feature = "mcp-client")]
#[allow(async_fn_in_trait)]
pub trait McpToolsExt {
fn mcp_client(&self) -> &McpClientManager;
async fn call_mcp_tool(
&self,
server_name: &str,
tool_name: &str,
arguments: Option<Value>,
) -> Result<CallToolResult, McpClientError> {
self.mcp_client()
.call_tool(server_name, tool_name, arguments)
.await
}
async fn call_mcp_tool_simple(
&self,
server_name: &str,
tool_name: &str,
) -> Result<CallToolResult, McpClientError> {
self.call_mcp_tool(server_name, tool_name, None).await
}
async fn list_mcp_tools(&self) -> Vec<(String, String)> {
self.mcp_client()
.list_all_tools()
.await
.iter()
.map(|(server, tool)| (server.clone(), tool.name.to_string()))
.collect()
}
async fn is_mcp_server_connected(&self, server_name: &str) -> bool {
self.mcp_client().is_connected(server_name).await
}
}
#[cfg(feature = "mcp-client")]
pub fn extract_tool_result_text(result: &CallToolResult) -> String {
result
.content
.iter()
.filter_map(|content| {
if let rmcp::model::RawContent::Text(text) = &**content {
Some(text.text.clone())
} else {
None
}
})
.collect::<Vec<_>>()
.join("\n")
}
#[cfg(feature = "mcp-client")]
pub fn is_tool_call_successful(result: &CallToolResult) -> bool {
!result.is_error.unwrap_or(false)
}
#[cfg(not(feature = "mcp-client"))]
pub trait McpToolsExt {}