Skip to content

Stdio MCP servers can trigger terminal job-control suspension during startup on macOS #18656

@spqw

Description

@spqw

What version of Codex CLI is running?

codex-cli 0.121.0

What subscription do you have?

Enterprise

Which model were you using?

gpt-5.4

What platform is your computer?

Darwin 25.4.0 arm64 arm

What terminal emulator and version are you using (if applicable)?

Ghostty, Terminal.app

What issue are you seeing?

On macOS, starting Codex with a stdio MCP server can result in terminal job-control failure during startup, observed as zsh: suspended (tty input).

After tracing this locally, the issue appears to be in how stdio MCP child processes are spawned: they are moved into a separate process group, but remain attached to the controlling terminal session. If anything in that server process tree touches
the terminal, the shell can suspend it as a background TTY reader.

What steps can reproduce the bug?

Environment

  • Platform: macOS
  • Shell: zsh
  • Codex CLI: codex-cli 0.121.0
  • MCP transport: stdio
  • Example server that exposed the issue: npx -y @blitzdev/iphone-mcp
  1. Configure a stdio MCP server, for example:
     [mcp_servers.blitz-iphone]
     command = "npx"
     args = ["-y", "@blitzdev/iphone-mcp"]
  1. Start interactive Codex normally.
  2. During MCP startup, Codex may get suspended by the shell with:
     zsh: suspended (tty input) codex ...

What is the expected behavior?

Expected behavior

Codex should be able to start stdio MCP servers without exposing them to terminal job-control interactions.
stdio MCP children are pipe-based helpers and should not depend on or inherit a controlling TTY.

Actual behavior

A stdio MCP child can remain in the terminal session while being placed in a separate process group. That creates a job-control hazard on macOS/zsh if the child process tree performs terminal I/O.

The visible user symptom is shell suspension during Codex startup rather than a clean MCP startup or a clean MCP failure.

Additional information

Impact

  • Interactive Codex startup can fail when specific stdio MCP servers are enabled.
  • The failure is confusing because it appears shell-related or MCP-specific rather than a Codex process-launch issue.
  • Optional MCP tools may silently disappear if users work around this by disabling servers.
  • Required MCP servers can block the entire session.

Why this seems like a Codex-side issue

From inspection, Codex already treats stdio MCP servers as non-interactive, pipe-based children. There is also already precedent in the codebase for detaching non-interactive child processes from the controlling TTY before exec. The risky behavior appears to be specific to the stdio MCP spawn path rather than a general requirement of MCP servers.

Proposed fix

In the stdio MCP spawn path, detach the child from the controlling TTY/session before exec rather than only assigning a new process group.
That makes the child behave like a normal non-interactive helper process and avoids terminal job-control suspension.
I have a candidate implementation plus a regression test in my fork:
https://github.com/spqw/codex/pull/1

Validation

Locally, the candidate fix:

  • detaches stdio MCP children from the controlling TTY
  • preserves normal pipe-based stdio operation
  • passes crate tests including a focused regression test for detached-session behavior

Additional info

I’m happy to reshape the PR if you’d prefer this handled in a different layer, but I wanted to open the issue first since docs/contributing.md suggests discussing behavior changes before expecting a PR review.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingmcpIssues related to the use of model context protocol (MCP) servers

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions