pub use crate::lsp::transport::{encode_message, read_message};
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn test_mcp_encode_decode_roundtrip() {
let request = json!({
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": {
"name": "xcodeai",
"version": "1.1.0"
}
}
});
let encoded = encode_message(&request);
let text = String::from_utf8(encoded).unwrap();
assert!(
text.starts_with("Content-Length: "),
"Expected Content-Length header"
);
assert!(text.contains("\r\n\r\n"), "Expected CRLF header separator");
}
#[tokio::test]
async fn test_mcp_tools_list_framing() {
let tools_response = json!({
"jsonrpc": "2.0",
"id": 2,
"result": {
"tools": [
{
"name": "read_file",
"description": "Read a file",
"inputSchema": {
"type": "object",
"properties": {
"path": { "type": "string" }
}
}
}
]
}
});
let encoded = encode_message(&tools_response);
let mut stream = tokio::io::BufReader::new(std::io::Cursor::new(encoded));
let decoded = read_message(&mut stream).await.unwrap();
assert_eq!(decoded["result"]["tools"][0]["name"], "read_file");
}
#[tokio::test]
async fn test_mcp_notification_framing() {
let notification = json!({
"jsonrpc": "2.0",
"method": "notifications/initialized",
"params": {}
});
let encoded = encode_message(¬ification);
let mut stream = tokio::io::BufReader::new(std::io::Cursor::new(encoded));
let decoded = read_message(&mut stream).await.unwrap();
assert_eq!(decoded["method"], "notifications/initialized");
assert!(
decoded.get("id").is_none(),
"Notification must not have an id"
);
}
}