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 <noreply@anthropic.com>
This commit is contained in:
+9
-1
@@ -97,7 +97,15 @@ internal class McpClient(
|
|||||||
*/
|
*/
|
||||||
suspend fun spawn(serverId: String, command: List<String>, env: Map<String, String>): McpClient {
|
suspend fun spawn(serverId: String, command: List<String>, env: Map<String, String>): McpClient {
|
||||||
val process = withContext(Dispatchers.IO) {
|
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))
|
val client = McpClient(serverId, StdioTransport(process))
|
||||||
client.initialize()
|
client.initialize()
|
||||||
|
|||||||
Reference in New Issue
Block a user