Skip to main content

qwencode_rs/mcp/
client.rs

1use anyhow::Result;
2use tracing::{debug, info};
3
4use crate::mcp::server::SdkMcpServer;
5use crate::types::mcp::McpToolResult;
6
7/// MCP Client for interacting with MCP servers
8pub struct McpClient {
9    server: SdkMcpServer,
10}
11
12impl McpClient {
13    /// Create a new MCP client for a server
14    pub fn new(server: SdkMcpServer) -> Self {
15        info!("Creating MCP client for server: {}", server.name);
16
17        McpClient { server }
18    }
19
20    /// Call a tool on the server
21    pub async fn call_tool(
22        &self,
23        tool_name: &str,
24        arguments: serde_json::Value,
25    ) -> Result<McpToolResult> {
26        debug!(
27            "Calling tool '{}' with arguments: {:?}",
28            tool_name, arguments
29        );
30
31        let result = self.server.execute_tool(tool_name, arguments).await?;
32
33        debug!(
34            "Tool '{}' returned {} content items",
35            tool_name,
36            result.content.len()
37        );
38        Ok(result)
39    }
40
41    /// List available tools
42    pub async fn list_tools(&self) -> Vec<String> {
43        self.server.get_tool_names().await
44    }
45
46    /// Check if a tool is available
47    pub async fn has_tool(&self, tool_name: &str) -> bool {
48        self.server.has_tool(tool_name).await
49    }
50
51    /// Get the server name
52    pub fn server_name(&self) -> &str {
53        &self.server.name
54    }
55}
56
57#[cfg(test)]
58mod tests {
59    use super::*;
60    use crate::mcp::tool::McpTool;
61    use crate::types::mcp::{McpToolResult, ToolContent};
62
63    fn create_test_server() -> SdkMcpServer {
64        let _tool = McpTool::new(
65            "test_tool",
66            "Test tool",
67            serde_json::json!({}),
68            |_input: serde_json::Value| async move {
69                Ok(McpToolResult {
70                    content: vec![ToolContent::Text {
71                        text: "test result".to_string(),
72                    }],
73                    is_error: false,
74                })
75            },
76        );
77
78        // Note: In real implementation, we'd add tools properly
79        // For now, testing client creation
80        SdkMcpServer::new("test-server")
81    }
82
83    #[test]
84    fn test_mcp_client_creation() {
85        let server = create_test_server();
86        let client = McpClient::new(server);
87
88        assert_eq!(client.server_name(), "test-server");
89    }
90
91    #[tokio::test]
92    async fn test_mcp_client_list_tools() {
93        let server = create_test_server();
94        let client = McpClient::new(server);
95
96        let tools = client.list_tools().await;
97        assert_eq!(tools.len(), 0); // No tools added
98    }
99
100    #[tokio::test]
101    async fn test_mcp_client_has_tool_check() {
102        let server = create_test_server();
103        let client = McpClient::new(server);
104
105        let has_tool = client.has_tool("nonexistent").await;
106        assert!(!has_tool);
107    }
108}