From 0a89fafd459b6f583bffde065d54e0617e58f9e4 Mon Sep 17 00:00:00 2001 From: kami Date: Thu, 16 Jul 2026 19:49:57 +0400 Subject: [PATCH] fix(tools): restore stdin pipe for MCP stdio transport ChildProcess defaults stdin to /dev/null (scaffolders fail fast rather than hang). MCP stdio is the inverse: the server reads requests from stdin and sees EOF then exits immediately without a live pipe. spawn() now restores Redirect.PIPE. Verified end-to-end: Correx spawns the real codebase-memory-mcp v0.9.0 and mounts its 8 tools as mcp__codebase-memory__*. Co-Authored-By: Claude Opus 4.8 --- .../correx/infrastructure/tools/mcp/McpStdioClient.kt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/infrastructure/tools/src/main/kotlin/com/correx/infrastructure/tools/mcp/McpStdioClient.kt b/infrastructure/tools/src/main/kotlin/com/correx/infrastructure/tools/mcp/McpStdioClient.kt index 6c959db1..d71fecf1 100644 --- a/infrastructure/tools/src/main/kotlin/com/correx/infrastructure/tools/mcp/McpStdioClient.kt +++ b/infrastructure/tools/src/main/kotlin/com/correx/infrastructure/tools/mcp/McpStdioClient.kt @@ -97,7 +97,15 @@ internal class McpClient( */ suspend fun spawn(serverId: String, command: List, env: Map): McpClient { val process = withContext(Dispatchers.IO) { - ChildProcess.builder(command).apply { environment().putAll(env) }.start() + ChildProcess.builder(command) + .apply { + environment().putAll(env) + // ChildProcess defaults stdin to /dev/null (so scaffolders fail fast instead of + // hanging). MCP stdio is the opposite: the server READS requests from stdin, so + // it needs a live pipe or it sees EOF and exits immediately. Restore the pipe. + redirectInput(ProcessBuilder.Redirect.PIPE) + } + .start() } val client = McpClient(serverId, StdioTransport(process)) client.initialize()