use mcpkit::protocol::{Message, Response};
use mcpkit_client::ClientBuilder;
use mcpkit_transport::{MemoryTransport, Transport};
use serde_json::json;
use std::sync::Arc;
use tokio::sync::Mutex;
#[tokio::test]
async fn test_client_request_response_correlation() -> Result<(), Box<dyn std::error::Error>> {
let (client_transport, server_transport) = MemoryTransport::pair();
let server_transport = Arc::new(Mutex::new(server_transport));
let server_clone = Arc::clone(&server_transport);
let server_handle = tokio::spawn(async move {
let transport = server_clone.lock().await;
let msg = transport.recv().await?.ok_or("No message received")?;
let request = msg.as_request().ok_or("Expected request")?;
assert_eq!(request.method, "initialize");
let init_response = Response::success(
request.id.clone(),
json!({
"protocolVersion": "2025-11-25",
"capabilities": {"tools": {}},
"serverInfo": {"name": "test-server", "version": "1.0.0"}
}),
);
transport.send(Message::Response(init_response)).await?;
let msg = transport.recv().await?.ok_or("No message received")?;
assert!(msg.is_notification());
let msg = transport.recv().await?.ok_or("No message received")?;
let request = msg.as_request().ok_or("Expected request")?;
assert_eq!(request.method, "tools/list");
let tools_response = Response::success(
request.id.clone(),
json!({
"tools": [{"name": "test_tool", "description": "A test tool", "inputSchema": {"type": "object"}}]
}),
);
transport.send(Message::Response(tools_response)).await?;
let msg = transport.recv().await?.ok_or("No message received")?;
let request = msg.as_request().ok_or("Expected request")?;
assert_eq!(request.method, "tools/call");
let call_response = Response::success(
request.id.clone(),
json!({
"content": [{"type": "text", "text": "result"}],
"isError": false
}),
);
transport.send(Message::Response(call_response)).await?;
let msg = transport.recv().await?.ok_or("No message received")?;
let request = msg.as_request().ok_or("Expected request")?;
assert_eq!(request.method, "tools/call");
let call_response2 = Response::success(
request.id.clone(),
json!({
"content": [{"type": "text", "text": "result2"}],
"isError": false
}),
);
transport.send(Message::Response(call_response2)).await?;
Ok::<_, Box<dyn std::error::Error + Send + Sync>>(())
});
let client = ClientBuilder::new()
.name("test-client")
.version("1.0.0")
.build(client_transport)
.await
.expect("Client should connect successfully");
let tools = client
.list_tools()
.await
.expect("list_tools should succeed");
assert_eq!(tools.len(), 1);
assert_eq!(tools[0].name, "test_tool");
let result1 = client
.call_tool("test_tool", json!({"arg": "value1"}))
.await
.expect("call_tool should succeed");
assert!(!result1.is_error.unwrap_or(false));
let result2 = client
.call_tool("test_tool", json!({"arg": "value2"}))
.await
.expect("call_tool should succeed");
assert!(!result2.is_error.unwrap_or(false));
match server_handle.await {
Ok(Ok(())) => Ok(()),
Ok(Err(e)) => Err(format!("Server error: {e}").into()),
Err(e) => Err(format!("Server task panicked: {e}").into()),
}
}
#[tokio::test]
async fn test_sequential_requests() -> Result<(), Box<dyn std::error::Error>> {
let (client_transport, server_transport) = MemoryTransport::pair();
let server_transport = Arc::new(Mutex::new(server_transport));
let server_clone = Arc::clone(&server_transport);
let server_handle = tokio::spawn(async move {
let transport = server_clone.lock().await;
let msg = transport.recv().await?.ok_or("No message received")?;
let request = msg.as_request().ok_or("Expected request")?;
transport
.send(Message::Response(Response::success(
request.id.clone(),
json!({
"protocolVersion": "2025-11-25",
"capabilities": {"tools": {}},
"serverInfo": {"name": "test", "version": "1.0"}
}),
)))
.await?;
let _ = transport.recv().await?.ok_or("No message received")?;
for _ in 0..10 {
let msg = transport.recv().await?.ok_or("No message received")?;
let request = msg.as_request().ok_or("Expected request")?;
transport
.send(Message::Response(Response::success(
request.id.clone(),
json!({"tools": []}),
)))
.await?;
}
Ok::<_, Box<dyn std::error::Error + Send + Sync>>(())
});
let client = ClientBuilder::new()
.name("test")
.version("1.0")
.build(client_transport)
.await?;
for _ in 0..10 {
let tools = client.list_tools().await.expect("request should succeed");
assert!(tools.is_empty());
}
match server_handle.await {
Ok(Ok(())) => Ok(()),
Ok(Err(e)) => Err(format!("Server error: {e}").into()),
Err(e) => Err(format!("Server task panicked: {e}").into()),
}
}