codex mcp-server: transient "Auth(AuthorizationRequired)" when spawning multiple concurrent stdio server instances
Summary
Running codex mcp-server (ChatGPT-subscription login, no API key) as a stdio MCP server, spawned as independent child processes (each invocation does spawn("codex", ["mcp-server"]), fresh process per task, no shared state between them), I observe intermittent transport failures:
ERROR rmcp::transport::worker: worker quit with fatal: Transport channel closed, when Auth(AuthorizationRequired)
Observed evidence (from real logs tonight, timestamps included)
Two codex mcp-server processes were spawned within the same second, dispatched from two separate tools/call requests issued almost simultaneously:
- Process A: failed at
2026-07-05T21:06:33.754284Zwith the error above - Process B: succeeded, dispatched at essentially the same wall-clock moment
Across one evening of usage I logged 4 failures out of 23 total codex mcp-server invocations (17.4%), so this is not a rare one-off.
What I've ruled out
- Not a bug in my client: my stdio client is a minimal NDJSON wrapper (
initialize→notifications/initialized→tools/call), it does not touch auth at all. - Not a permanently-expired session:
codex login statusandcodex doctorboth show a healthy, currently-valid ChatGPT auth (stored ChatGPT tokens: true) immediately after the failures. codex doctorshows the ChatGPT backend auth path is a WebSocket connection (wss://chatgpt.com/backend-api/..., handshakeHTTP 101 Switching Protocols) — this may be relevant to why concurrent process spawns racing for auth could produce a transient channel-closed error.
Environment
codex-cli 0.142.5(installed viabrew)- macOS 26.5.1 (Apple Silicon)
- Auth mode: ChatGPT subscription (not API key)
Question for maintainers
Is there a known race condition when multiple codex mcp-server processes are spawned concurrently and each performs its own auth handshake against the shared ChatGPT session/token store? Is there a recommended way to avoid this (e.g., serializing server startup, a shared auth-refresh lock, or a codex config flag to increase auth-handshake retry tolerance) rather than the caller having to retry externally?
I don't have a minimal concurrent-only repro isolated from my larger workflow yet — happy to try to produce one if useful. Filing this now with the real evidence I have, since the failure mode is disruptive enough (17% of invocations) that it seemed worth reporting even without a fully isolated repro.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗