43 lines
1.1 KiB
Rust
43 lines
1.1 KiB
Rust
use tokio::io::{AsyncBufReadExt, AsyncReadExt, BufReader};
|
|
|
|
/// Reads an MCP (NDJSON or LSP Content-Length prefixed) message from a buffered async reader.
|
|
/// Returns the raw JSON string payload if successful, or None on EOF or error.
|
|
pub async fn read_mcp_message<R: tokio::io::AsyncRead + Unpin>(
|
|
stdin: &mut BufReader<R>,
|
|
) -> Option<String> {
|
|
let mut length = 0;
|
|
let mut line = String::new();
|
|
loop {
|
|
line.clear();
|
|
if stdin.read_line(&mut line).await.unwrap_or(0) == 0 {
|
|
return None;
|
|
}
|
|
|
|
if line.starts_with('{') {
|
|
let len = line.trim_end().len();
|
|
line.truncate(len);
|
|
return Some(line);
|
|
}
|
|
|
|
let line = line.trim_end();
|
|
if line.is_empty() {
|
|
break;
|
|
}
|
|
|
|
if line.len() >= 15 && line[..15].eq_ignore_ascii_case("content-length:") {
|
|
length = line[15..].trim().parse().unwrap_or(0);
|
|
}
|
|
}
|
|
|
|
if length == 0 {
|
|
return None;
|
|
}
|
|
|
|
let mut buffer = vec![0; length];
|
|
if stdin.read_exact(&mut buffer).await.is_err() {
|
|
return None;
|
|
}
|
|
|
|
String::from_utf8(buffer).ok()
|
|
}
|