vestige/crates/vestige-mcp/src/protocol/stdio.rs
Sam Valladares f9c60eb5a7 Initial commit: Vestige v1.0.0 - Cognitive memory MCP server
FSRS-6 spaced repetition, spreading activation, synaptic tagging,
hippocampal indexing, and 130 years of memory research.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 01:31:03 -06:00

84 lines
2.5 KiB
Rust

//! stdio Transport for MCP
//!
//! Handles JSON-RPC communication over stdin/stdout.
use std::io::{self, BufRead, BufReader, Write};
use tracing::{debug, error, warn};
use super::types::{JsonRpcError, JsonRpcRequest, JsonRpcResponse};
use crate::server::McpServer;
/// stdio Transport for MCP server
pub struct StdioTransport;
impl StdioTransport {
pub fn new() -> Self {
Self
}
/// Run the MCP server over stdio
pub async fn run(self, mut server: McpServer) -> Result<(), io::Error> {
let stdin = io::stdin();
let stdout = io::stdout();
let reader = BufReader::new(stdin.lock());
let mut stdout = stdout.lock();
for line in reader.lines() {
let line = match line {
Ok(l) => l,
Err(e) => {
error!("Failed to read line: {}", e);
break;
}
};
if line.is_empty() {
continue;
}
debug!("Received: {}", line);
// Parse JSON-RPC request
let request: JsonRpcRequest = match serde_json::from_str(&line) {
Ok(r) => r,
Err(e) => {
warn!("Failed to parse request: {}", e);
let error_response = JsonRpcResponse::error(None, JsonRpcError::parse_error());
match serde_json::to_string(&error_response) {
Ok(response_json) => {
writeln!(stdout, "{}", response_json)?;
stdout.flush()?;
}
Err(e) => {
error!("Failed to serialize error response: {}", e);
}
}
continue;
}
};
// Handle the request
if let Some(response) = server.handle_request(request).await {
match serde_json::to_string(&response) {
Ok(response_json) => {
debug!("Sending: {}", response_json);
writeln!(stdout, "{}", response_json)?;
stdout.flush()?;
}
Err(e) => {
error!("Failed to serialize response: {}", e);
}
}
}
}
Ok(())
}
}
impl Default for StdioTransport {
fn default() -> Self {
Self::new()
}
}