use langchainrust::mcp::{MCPClient, MCPConfig};
use serde_json::json;
fn filesystem_config() -> MCPConfig {
let npx_cmd = if cfg!(target_os = "windows") {
"npx.cmd"
} else {
"npx"
};
MCPConfig::stdio(
npx_cmd,
vec![
"@modelcontextprotocol/server-filesystem".to_string(),
std::env::temp_dir().to_string_lossy().to_string(),
],
)
}
#[tokio::test]
#[ignore = "需要 npx 和 @anthropic/mcp-server-filesystem"]
async fn test_mcp_stdio_list_tools() {
let client = MCPClient::connect(filesystem_config())
.await
.expect("连接 MCP Server 失败");
let tools = client.list_tools().await.expect("列出工具失败");
assert!(!tools.is_empty(), "filesystem server 应暴露工具");
println!("工具数量: {}", tools.len());
for t in &tools {
println!(" - {}: {}", t.name, t.description);
}
client.close().await.unwrap();
}
#[tokio::test]
#[ignore = "需要 npx 和 @anthropic/mcp-server-filesystem"]
async fn test_mcp_as_tools() {
let client = MCPClient::connect(filesystem_config())
.await
.expect("连接失败");
let tools: Vec<_> = client.as_tools().await.expect("as_tools 失败");
assert!(!tools.is_empty(), "应转换出 BaseTool");
println!("BaseTool 数量: {}", tools.len());
}
#[tokio::test]
#[ignore = "需要 npx 和 @anthropic/mcp-server-filesystem"]
async fn test_mcp_call_tool() {
let client = MCPClient::connect(filesystem_config())
.await
.expect("连接失败");
client.list_tools().await.expect("列出工具失败");
let result = client
.call_tool(
"list_directory",
json!({"path": std::env::temp_dir().to_string_lossy()}),
)
.await;
if let Ok(r) = result {
println!("工具结果: {}", r.text());
assert!(!r.is_error, "list_directory 不应返回错误");
}
client.close().await.unwrap();
}
#[tokio::test]
async fn test_mcp_tools_load_into_agent_tools_in_process() {
use langchainrust::mcp::{InMemoryTransport, MCPClient, MCPServer};
use langchainrust::{AgentExecutor, BaseTool, Calculator};
use std::sync::Arc;
let server = Arc::new(
MCPServer::new()
.with_server_info("calc-mcp", "0.1.0")
.with_tool(Arc::new(Calculator::new()) as Arc<dyn BaseTool>),
);
let client = MCPClient::with_transport(Box::new(InMemoryTransport::new(server)))
.await
.expect("进程内连接 MCP Server 失败");
let mcp_tools: Vec<Arc<dyn BaseTool>> = client.as_tools().await.expect("as_tools 失败");
assert_eq!(mcp_tools.len(), 1, "MCPServer 应暴露 1 个工具");
let calc = &mcp_tools[0];
assert_eq!(calc.name(), "calculator");
assert!(calc.description().contains("math"));
assert!(calc.args_schema().is_some());
let out = calc
.run(r#"{"expression": "2 + 3 * 4"}"#.to_string())
.await
.expect("调用 MCP 工具失败");
assert!(out.contains("= 14"), "计算结果应正确, 实际: {}", out);
fn agent_tools(tools: Vec<Arc<dyn BaseTool>>) -> Vec<Arc<dyn BaseTool>> {
tools
}
let _kept: Vec<Arc<dyn BaseTool>> = agent_tools(mcp_tools);
let _assert_type: fn(
Arc<dyn langchainrust::BaseAgent>,
Vec<Arc<dyn BaseTool>>,
) -> AgentExecutor = AgentExecutor::new;
let _ = _assert_type;
}