Created
November 12, 2025 22:30
-
-
Save u1-liquid/fc8deb951bd0611261d46c78599f712a to your computer and use it in GitHub Desktop.
fixup Codex MCP handling problem (connection closed: initialize response / transport closed)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env node | |
| 'use strict'; | |
| import { spawn } from 'node:child_process'; | |
| import { createInterface } from 'node:readline'; | |
| if (process.argv.length < 3) { | |
| console.error('Usage: mcp-stdio-jsonrpc-guard <command...>'); | |
| process.exit(1); | |
| } | |
| // Build a POSIX-safe command string for sh -lc | |
| const args = process.argv.slice(2); | |
| const command = args.length === 1 | |
| ? args[0] | |
| : args.map((s) => s === '' ? "''" : `'${String(s).replace(/'/g, `'\\''`)}'`).join(' '); | |
| const child = spawn('sh', ['-lc', command], { | |
| stdio: ['pipe', 'pipe', 'pipe'], | |
| env: process.env, | |
| cwd: process.cwd(), | |
| windowsHide: false, | |
| shell: false, | |
| }); | |
| // stdin -> child stdin | |
| process.stdin.pipe(child.stdin); | |
| // child stderr -> parent stderr (verbatim) | |
| child.stderr.pipe(process.stderr); | |
| // child stdout -> line filter via readline: JSON lines -> stdout (with patch), others -> stderr | |
| const stdout = createInterface({ | |
| input: child.stdout, | |
| crlfDelay: Infinity, | |
| }); | |
| stdout.on('line', (line) => { | |
| const trimmed = line.trim(); | |
| if (!trimmed) { | |
| process.stderr.write(line + '\n'); | |
| return; | |
| } | |
| try { | |
| let out = line; // preserve original text by default | |
| let msg = JSON.parse(trimmed); | |
| // Patch: move params.message -> params.data when method matches and data is absent | |
| // https://github.com/openai/codex/issues/5671 | |
| if (msg && typeof msg === 'object' && msg.method === 'notifications/message' && msg.params) { | |
| const p = msg.params; | |
| if (Object.prototype.hasOwnProperty.call(p, 'message') && !('data' in p)) { | |
| msg.params = { ...p, data: p.message }; | |
| delete msg.params.message; | |
| out = JSON.stringify(msg); | |
| } | |
| } | |
| process.stdout.write(out + '\n'); | |
| } catch { | |
| process.stderr.write(line + '\n'); | |
| } | |
| }); | |
| // forward common signals to child | |
| [ | |
| 'SIGINT', 'SIGTERM', 'SIGHUP', 'SIGQUIT', 'SIGUSR1', 'SIGUSR2', 'SIGPIPE', 'SIGBREAK' | |
| ].forEach(sig => process.on(sig, () => child.kill(sig))); | |
| // ensure child is cleaned up if parent exits | |
| process.on('exit', () => { | |
| try { child.kill(); } catch {} | |
| }); | |
| // mirror child exit status | |
| child.on('exit', (code, signal) => { | |
| if (signal) { | |
| try { | |
| process.kill(process.pid, signal); | |
| } catch { | |
| process.exit(128); | |
| } | |
| } else { | |
| process.exit(code ?? 0); | |
| } | |
| }); | |
| child.on('error', (err) => { | |
| console.error(`Failed to start "${cmd}": ${err.message}`); | |
| process.exit(127); | |
| }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment