Skip to content

Instantly share code, notes, and snippets.

@u1-liquid
Created November 12, 2025 22:30
Show Gist options
  • Select an option

  • Save u1-liquid/fc8deb951bd0611261d46c78599f712a to your computer and use it in GitHub Desktop.

Select an option

Save u1-liquid/fc8deb951bd0611261d46c78599f712a to your computer and use it in GitHub Desktop.
fixup Codex MCP handling problem (connection closed: initialize response / transport closed)
#!/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