refactor: Extract shared MCP Stdio NDJSON parsing loop into mcp-stdio library
This commit is contained in:
1 parent
f8c0d58415
commit
9009f127a9
8 files changed
+77
-80
No files matched your search
@@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "mcp-stdio"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
tokio = { version = "1.53.1", features = ["io-util"] }
|
||||
tracing = "0.1.44"
|
||||
@@ -0,0 +1,40 @@
|
||||
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;
|
||||
loop {
|
||||
let mut line = String::new();
|
||||
if stdin.read_line(&mut line).await.unwrap_or(0) == 0 {
|
||||
return None;
|
||||
}
|
||||
|
||||
if line.starts_with('{') {
|
||||
return Some(line.trim_end().to_string());
|
||||
}
|
||||
|
||||
let line = line.trim_end();
|
||||
if line.is_empty() {
|
||||
break;
|
||||
}
|
||||
|
||||
let lower_line = line.to_lowercase();
|
||||
if let Some(len_str) = lower_line.strip_prefix("content-length:") {
|
||||
length = len_str.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()
|
||||
}
|
||||
Reference in new issue
Block a user