Skip to main content
Glama
ahmadjz

codex-bridge

by ahmadjz

codex-bridge

An MCP server that gives Claude Code (or any MCP client) the current Codex CLI as a tool.

Upstream Codex removed codex mcp-server in 0.154.0. Its successor, codex app-server, speaks its own JSON-RPC protocol, which is not MCP. codex-bridge sits in between: it runs codex app-server and exposes the same codex and codex-reply tools the old server had, so existing callers keep working. To update Codex, you swap the binary.

Unofficial. Not affiliated with, endorsed by or supported by OpenAI. "Codex" is used only to describe what this tool talks to.

Why not just pin an old Codex?

You can, but on a ChatGPT login the backend gates models by client version. A client pinned to 0.153.4 (the last one with mcp-server) only gets the older models. Newer ones (at the time of writing gpt-6.1-sol, gpt-6-sol, gpt-6-luna) return 400 ... not supported when using Codex with a ChatGPT account on 0.153.4 and 0.154, but work on 0.163.0. Check what a given binary can see with:

/path/to/codex debug models

codex-bridge lets you run the newest binary through MCP, so you get the newest models.

Related MCP server: BoundedRelay

Requirements

  • Node.js 20 or newer

  • A Codex CLI that has codex app-server (built and tested against codex-cli 0.163.0)

  • An existing Codex login (codex login). codex-bridge never reads or touches your tokens. Codex uses its own login from ~/.codex, or from CODEX_HOME if set.

If you use a standalone release binary from GitHub, put codex-code-mode-host from the same release next to codex. Without it, 0.163.0 can't run shell commands ("execution host is missing"), and codex-bridge logs Codex's warning about it.

Install

Claude Code

claude mcp add codex-bridge -s user -e CODEX_BIN=/path/to/codex -- npx -y codex-bridge

Leave out -e CODEX_BIN=... to use whichever codex is on PATH.

Long reviews can run for many minutes. Claude Code's per-call MCP timeout is MCP_TOOL_TIMEOUT (milliseconds). Raise it in ~/.claude/settings.json:

{
  "env": {
    "MCP_TOOL_TIMEOUT": "1800000"
  }
}

or per launch: MCP_TOOL_TIMEOUT=1800000 claude. codex-bridge also sends MCP progress notifications (turn started, commands run, files edited, a heartbeat every 15 s) while Codex works.

Codex as the client

~/.codex/config.toml:

[mcp_servers.codex-bridge]
command = "npx"
args = ["-y", "codex-bridge"]
env = { CODEX_BIN = "/path/to/codex" }
tool_timeout_sec = 1800

Cursor

~/.cursor/mcp.json:

{
  "mcpServers": {
    "codex-bridge": {
      "command": "npx",
      "args": ["-y", "codex-bridge"],
      "env": { "CODEX_BIN": "/path/to/codex" }
    }
  }
}

From a clone

npm ci && npm run build
claude mcp add codex-bridge -s user -e CODEX_BIN=/path/to/codex -- node /abs/path/to/codex-bridge/dist/index.js

Tools

codex

Starts a new Codex thread and runs one turn.

Argument

Type

Notes

prompt

string, required

The first user prompt

model

string

e.g. gpt-6.1-sol

sandbox

read-only | workspace-write | danger-full-access

approval-policy

on-request | never

See Approvals

cwd

string

Relative paths resolve against the server's working directory

config

object

config.toml overrides, e.g. {"model_reasoning_effort": "high"}

base-instructions

string

Replaces the default instructions

developer-instructions

string

Injected as a developer message

compact-prompt

string

Prompt used when compacting the conversation

Any argument you leave out falls back to your Codex config.

codex-reply

Continues a thread: threadId (or the deprecated conversationId) plus prompt. The thread keeps its model, sandbox and approval settings. Threads are stored by Codex, so a reply works even after codex-bridge or app-server restarts.

Result

Both tools return

{ "threadId": "…", "content": "final agent message", "codexVersion": "0.163.0" }

as structuredContent, and the same JSON as the text content. content is the final answer of the turn. A failed or interrupted turn comes back with isError: true and the error text, starting with threadId: … when a thread exists.

Approvals

No human sits between codex-bridge and Codex, so:

  • approval-policy: never: Codex runs without asking, inside the sandbox you chose.

  • approval-policy: on-request: when Codex asks to run a command or change files, codex-bridge asks you through MCP elicitation if your client supports it. The prompt shows the command, cwd and reason, or the list of files. Only an explicit accept approves, and only that one request, with one exception: a file-change request can also ask for write access to a directory for the rest of the session (grantRoot). The prompt says so, and accepting grants it. codex-bridge never picks Codex's "accept for session" option itself. If the client has no elicitation support, or the prompt is dismissed, fails or goes stale, the request is declined.

  • Other Codex requests: permission escalations are granted nothing. Questions to the user and MCP elicitations from Codex's own MCP servers are declined. Token refresh and attestation requests are refused.

Configuration

Env var

Default

Meaning

CODEX_BIN

codex on PATH

The Codex binary to drive

CODEX_HOME

~/.codex

Passed through to Codex (login, config, threads)

CODEX_BRIDGE_DEBUG

unset

1 echoes app-server stderr to codex-bridge's stderr

The app-server child inherits codex-bridge's full environment, because Codex needs HOME, PATH, CODEX_HOME and any provider keys you normally give it. codex-bridge logs to stderr only. It logs the binary path and version at startup, crash exit codes, and Codex's own warnings verbatim. App-server stderr is logged only with CODEX_BRIDGE_DEBUG=1. Progress messages sent to your MCP client include the commands Codex runs and the files it edits.

On startup codex-bridge runs codex --version and codex app-server --help. It logs the version to stderr, or exits with a clear error if the binary is missing or has no app-server.

Updating Codex

  1. Download the new release (or npm i -g @openai/codex@latest). For standalone binaries, take codex and codex-code-mode-host from the same release.

  2. Replace the file CODEX_BIN points to (or update the env var).

  3. Restart the MCP server (in Claude Code, /mcp and reconnect, or start a new session) so a fresh app-server starts from the new file.

  4. Run codex debug models to see which models the new version unlocks.

You don't need to change anything in codex-bridge unless the app-server protocol changes in a way that breaks it. codexVersion in every result comes from the running app-server, so it shows what actually ran.

How it works

One codex app-server child per codex-bridge process, started on first use and reused. Each tool call maps to thread/start (or thread/resume) plus turn/start, and the answer is the last agentMessage with phase: "final_answer" from that turn. Calls on the same thread run one at a time. If the child crashes, in-flight calls fail and the next call starts a fresh child. If the client cancels, the call sends turn/interrupt. On stdin EOF or a signal, codex-bridge closes the child's stdin, then sends SIGTERM and finally SIGKILL to its process group. Details are in docs/design.md.

Protocol: built against codex app-server from codex-cli 0.163.0 (v2 API, non-experimental), with types generated by codex app-server generate-ts. To regenerate against another binary:

CODEX_BIN=/path/to/codex npm run gen:protocol

Limitations

  • codex app-server is marked experimental upstream. A future Codex release can change the protocol. Pin a known-good binary if that bites, and regenerate the types to see what changed.

  • Text prompts only. No images, audio or file attachments.

  • codex-reply can't change model, sandbox or approval settings mid-thread, matching the old server.

  • on-request approvals need a client with MCP elicitation support. Otherwise every approval is declined.

  • Progress notifications only flow if the client sends a progress token. Whether progress resets the client's timeout depends on the client, so set MCP_TOOL_TIMEOUT (or your client's equivalent) high for long runs.

  • A turn has no server-side time limit. A cancelled call returns right away. If the turn ignores turn/interrupt, its thread stays busy, so later replies to it wait until it ends.

  • All threads share one app-server child. If it crashes, or fails to answer a request within 120 s, codex-bridge restarts it, and every turn running at that moment fails, not only the one that hit the problem. The threads themselves survive and can be continued.

  • If codex-bridge is killed with SIGKILL, cleanup depends on app-server exiting on stdin EOF (it does as of 0.163.0).

  • Tested on Linux. macOS should work. Windows is untested.

Development

npm ci
npm run lint && npm run typecheck && npm test
CODEX_BIN=/path/to/codex npm run test:e2e   # opt-in, uses your real Codex login and quota

CODEX_BRIDGE_E2E_MODEL picks the e2e model (default gpt-6.1-sol).

License

MIT

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables MCP clients to spawn and control Codex CLI and Claude Code sessions on the host machine, with session management and filesystem access.
    4
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Enables MCP clients to run non-interactive Codex CLI sessions via codex and codex-reply tools, including resuming conversations by thread ID and passing codex exec flags.
    2
    36 PyPI
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    Enables MCP-compatible coding agents to execute the local Codex CLI as a coding agent, including code reviews, session resume/fork, and CLI diagnostics.
    9
    6 npm
    MIT