diff --git a/src-tauri/src/mcp/stdio_transport.rs b/src-tauri/src/mcp/stdio_transport.rs new file mode 100644 index 0000000..3447cf6 --- /dev/null +++ b/src-tauri/src/mcp/stdio_transport.rs @@ -0,0 +1,31 @@ +//! stdio transport (FR-MCP-6) — "a thin adapter the agent spawns". A coding +//! agent's MCP client config spawns `whispassist.exe --mcp-stdio` and talks +//! JSON-RPC over that child process's stdin/stdout; `main.rs` checks for that +//! flag before building the Tauri window and calls `serve_once` here instead. +//! +//! There is no bearer-token header to check here (unlike HTTP): the ability +//! to spawn this process at all already requires the same OS-level privilege +//! as running any other local command as the signed-in user, so process-spawn +//! capability is the trust boundary for stdio, same as other local-only MCP +//! servers. `set_mcp_enabled` still mints/stores a token (`mcp::token`) for +//! parity with the HTTP transport and in case a future stdio client wants to +//! pass it, but this transport does not require presenting it. + +use crate::mcp::handler::WaMcpHandler; +use crate::mcp::McpError; +use rmcp::ServiceExt; + +/// Serves one MCP session over the current process's stdin/stdout until the +/// peer disconnects, then returns. +pub async fn serve_once(handler: WaMcpHandler) -> Result<(), McpError> { + let transport = rmcp::transport::io::stdio(); + let running = handler + .serve(transport) + .await + .map_err(|e| McpError::Server(e.to_string()))?; + running + .waiting() + .await + .map_err(|e| McpError::Server(e.to_string()))?; + Ok(()) +}