Skip to content

Commit fa89ea5

Browse files
committed
fix(mcp): prevent stdout pollution in MCP stdio protocol
Root Cause: Lines 1133-1135 (dual transport) and 1140-1142 (daemon mode) wrote directly to stdout without checking if stdout is attached to a TTY. This violated the MCP protocol specification which requires stdout to contain ONLY JSON-RPC messages when in stdio mode. Impact: - MCP clients couldn't connect: "Failed to reconnect to codegraph" - JSON-RPC parsing failed due to text preceding JSON messages - Protocol violation prevented any MCP communication Detection: Dual transport: println!("✓ MCP server started with dual transport"); Daemon mode: println!("Running in daemon mode"); Fix: Wrapped all println! calls in handle_start() with atty::is(Stream::Stdout) checks, matching the pattern used elsewhere in the codebase (handle_stop, etc.). Messages now only appear when stdout is a terminal, not when it's being used for MCP JSON-RPC communication. Verified: - Build successful - Follows existing pattern from lines 1154-1155 (handle_stop) - Only affects dual transport and daemon mode startup messages - Other println! calls are in CLI-only commands (status, config, index)
1 parent ebd3e7a commit fa89ea5

File tree

1 file changed

+10
-6
lines changed

1 file changed

+10
-6
lines changed

crates/codegraph-mcp/src/bin/codegraph.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1130,16 +1130,20 @@ async fn handle_start(
11301130
pid_file.clone(),
11311131
)
11321132
.await?;
1133-
println!("✓ MCP server started with dual transport");
1134-
println!(" STDIO: buffer size {} (PID: {})", buffer_size, stdio_pid);
1135-
println!(" HTTP: http://{}:{} (PID: {})", host, port, http_pid);
1133+
if atty::is(Stream::Stdout) {
1134+
println!("✓ MCP server started with dual transport");
1135+
println!(" STDIO: buffer size {} (PID: {})", buffer_size, stdio_pid);
1136+
println!(" HTTP: http://{}:{} (PID: {})", host, port, http_pid);
1137+
}
11361138
}
11371139
}
11381140

11391141
if daemon {
1140-
println!("Running in daemon mode");
1141-
if let Some(ref pid_file) = pid_file {
1142-
println!("PID file: {:?}", pid_file);
1142+
if atty::is(Stream::Stdout) {
1143+
println!("Running in daemon mode");
1144+
if let Some(ref pid_file) = pid_file {
1145+
println!("PID file: {:?}", pid_file);
1146+
}
11431147
}
11441148
}
11451149

0 commit comments

Comments
 (0)