mirror of
https://github.com/samvallad33/vestige.git
synced 2026-04-25 00:36:22 +02:00
85 lines
2.5 KiB
Rust
85 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()
|
||
|
|
}
|
||
|
|
}
|