1use mcp_client::{
2 client::{ClientCapabilities, ClientInfo, McpClient, McpClientTrait},
3 transport::{SseTransport, StdioTransport, Transport},
4 McpService,
5};
6use rand::Rng;
7use rand::SeedableRng;
8use std::time::Duration;
9use std::{collections::HashMap, sync::Arc};
10use tracing_subscriber::EnvFilter;
11
12#[tokio::main]
13async fn main() -> Result<(), Box<dyn std::error::Error>> {
14 tracing_subscriber::fmt()
16 .with_env_filter(
17 EnvFilter::from_default_env().add_directive("mcp_client=debug".parse().unwrap()),
18 )
19 .init();
20
21 let transport1 = StdioTransport::new("uvx", vec!["mcp-server-git".to_string()], HashMap::new());
22 let handle1 = transport1.start().await?;
23 let service1 = McpService::with_timeout(handle1, Duration::from_secs(30));
24 let client1 = McpClient::new(service1);
25
26 let transport2 = StdioTransport::new("uvx", vec!["mcp-server-git".to_string()], HashMap::new());
27 let handle2 = transport2.start().await?;
28 let service2 = McpService::with_timeout(handle2, Duration::from_secs(30));
29 let client2 = McpClient::new(service2);
30
31 let transport3 = SseTransport::new("http://localhost:8000/sse", HashMap::new());
32 let handle3 = transport3.start().await?;
33 let service3 = McpService::with_timeout(handle3, Duration::from_secs(10));
34 let client3 = McpClient::new(service3);
35
36 let mut clients: Vec<Box<dyn McpClientTrait>> =
38 vec![Box::new(client1), Box::new(client2), Box::new(client3)];
39
40 for (i, client) in clients.iter_mut().enumerate() {
42 let info = ClientInfo {
43 name: format!("example-client-{}", i + 1),
44 version: "1.0.0".to_string(),
45 };
46 let capabilities = ClientCapabilities::default();
47
48 println!("\nInitializing client {}", i + 1);
49 let init_result = client.initialize(info, capabilities).await?;
50 println!("Client {} initialized: {:?}", i + 1, init_result);
51 }
52
53 for (i, client) in clients.iter_mut().enumerate() {
55 let tools = client.list_tools(None).await?;
56 println!("\nClient {} tools: {:?}", i + 1, tools);
57 }
58
59 println!("\n\n----------------------------------\n\n");
60
61 let clients = Arc::new(clients);
63 let mut handles = vec![];
64
65 for i in 0..20 {
66 let clients = Arc::clone(&clients);
67 let handle = tokio::spawn(async move {
68 let mut rng = rand::rngs::StdRng::from_entropy();
70 tokio::time::sleep(Duration::from_millis(rng.gen_range(5..50))).await;
71
72 match rng.gen_range(0..4) {
74 0 => {
75 println!("\n{i}: Listing tools for client 1 (stdio)");
76 match clients[0].list_tools(None).await {
77 Ok(tools) => {
78 println!(" {i}: -> Got tools, first one: {:?}", tools.tools.first())
79 }
80 Err(e) => println!(" {i}: -> Error: {}", e),
81 }
82 }
83 1 => {
84 println!("\n{i}: Calling tool for client 2 (stdio)");
85 match clients[1]
86 .call_tool("git_status", serde_json::json!({ "repo_path": "." }))
87 .await
88 {
89 Ok(result) => println!(
90 " {i}: -> Tool execution result, is_error: {:?}",
91 result.is_error
92 ),
93 Err(e) => println!(" {i}: -> Error: {}", e),
94 }
95 }
96 2 => {
97 println!("\n{i}: Listing tools for client 3 (sse)");
98 match clients[2].list_tools(None).await {
99 Ok(tools) => {
100 println!(" {i}: -> Got tools, first one: {:?}", tools.tools.first())
101 }
102 Err(e) => println!(" {i}: -> Error: {}", e),
103 }
104 }
105 3 => {
106 println!("\n{i}: Calling tool for client 3 (sse)");
107 match clients[2]
108 .call_tool(
109 "echo_tool",
110 serde_json::json!({ "message": "Client with SSE transport - calling a tool" }),
111 )
112 .await
113 {
114 Ok(result) => println!(" {i}: -> Tool execution result, is_error: {:?}", result.is_error),
115 Err(e) => println!(" {i}: -> Error: {}", e),
116 }
117 }
118 _ => unreachable!(),
119 }
120 Ok::<(), Box<dyn std::error::Error + Send + Sync>>(())
121 });
122 handles.push(handle);
123 }
124
125 for handle in handles {
127 handle.await.unwrap().unwrap();
128 }
129
130 Ok(())
131}