MCP server that wraps the Claude Code and Gemini CLI so any MCP client (e.g. codex) can call it as a tool.
Overview
⚡ mcp-agents exposes Claude Code and Codex CLI as MCP tools, so either agent can delegate work to the other, request a second opinion, or run an independent review without custom glue for each CLI. ⚠️ OpenAI has deprecated codex mcp-server. The default codex provider keeps MCP at the mcp-agents boundary and uses codex app-server privately underneath. codex-legacy is a temporary compatibility lane while supported Codex CLI releases still ship the deprecated command—not a foundation for new setups. Install one package, then add one MCP server entry per agent you want to expose. Each provider has its own tool surface. A client can start it over stdio or connect to an operator-run HTTP daemon; one process never dynamically routes every backend. - Ask the other agent to implement, review, investigate, or challenge a plan without leaving your current client. - Install one executable and select the agent behind each server entry with --provider.
README
mcp-agents
Use Codex from Claude Code. Use Claude Code from Codex. One MCP bridge, either direction.
TL;DR
⚡
mcp-agentsexposes Claude Code and Codex CLI as MCP tools, so either agent can delegate work to the other, request a second opinion, or run an independent review without custom glue for each CLI.
⚠️ OpenAI has deprecated
codex mcp-server. The defaultcodexprovider keeps MCP at themcp-agentsboundary and usescodex app-serverprivately underneath.codex-legacyis a temporary compatibility lane while supported Codex CLI releases still ship the deprecated command—not a foundation for new setups.
Install one package, then add one MCP server entry per agent you want to expose. Each provider has its own tool surface. A client can start it over stdio or connect to an operator-run HTTP daemon; one process never dynamically routes every backend.
Table of contents
- Why mcp-agents?
- Quickstart
- Transport modes
- Providers
- Client configuration
- Provider reference
- Development
- How it works
- License
Why mcp-agents?
- Claude ↔ Codex, both ways. Ask the other agent to implement, review, investigate, or challenge a plan without leaving your current client.
- One MCP integration pattern. Install one executable and select the agent
behind each server entry with
--provider. - Long-running work without wishful thinking. Claude reviews and Codex turns have background jobs, bounded result paging, cancellation, and privacy-safe progress.
- A migration path off native Codex MCP. MCP clients keep a closed, wrapper-owned interface while the default Codex provider adapts to App Server.
- Durable Codex sessions. Threads, goals, recovery state, leases, and liveness survive clean bridge reconnects.
- Optional remote browser access. The browser provider can proxy Chrome DevTools MCP through an operator-owned, fail-closed browser lease.
Quickstart
🚀 Install the bridge once, then configure either or both directions.
Prerequisites
- Node.js 26 or newer
- For Claude Code → Codex:
Codex CLI 0.149.1 or newer,
authenticated and available on Claude Code’s
PATH - For Codex → Claude Code:
Claude Code, authenticated
and available on Codex’s
PATH
Only configured providers need their corresponding CLI. The browser provider has separate lease-helper requirements described in its advanced reference.
Install with Mise (recommended)
Add mcp-agents to the project’s .tool-versions:
npm:mcp-agents latest
Then install it through the project’s normal Mise setup:
mise install
mcp-agents --version
This keeps the installation and update policy in the project while MCP clients
still launch the direct mcp-agents executable. The latest value
intentionally tracks the newest published release.
Make sure the MCP client inherits the activated Mise PATH. If a GUI client
cannot resolve the shim, use the absolute path reported by
command -v mcp-agents.
Claude Code calls Codex
Add mcp-agents to the project’s .mcp.json:
{
"mcpServers": {
"codex": {
"command": "mcp-agents",
"args": ["--provider", "codex"],
"timeout": 7500000
}
}
}
Restart Claude Code, then verify the server is connected:
claude mcp list
Ask Claude to use Codex for a task, for example:
Ask Codex to review this implementation plan and identify the riskiest assumption.
The codex tool starts a durable thread. Its returned threadId can be used
with codex-reply for follow-up work.
Codex calls Claude Code
Add the Claude provider to ~/.codex/config.toml:
[mcp_servers.claude-code]
command = "mcp-agents"
args = ["--provider", "claude"]
tool_timeout_sec = 960
Restart Codex, then verify the server is listed:
codex mcp list
Ask Codex for an independent Claude review, for example:
Ask Claude for a second opinion on this diff. Focus on correctness and regressions.
For substantial reviews, Codex should use claude-start →
claude-status → claude-result. The blocking claude_code tool is intended
for small prompts.
This quickstart uses the default client-managed stdio transport. The optional shared HTTP mode avoids one bridge process per client.
Transport modes
Both modes expose the same MCP tools. The difference is process ownership and lifetime.
| Mode | Process lifecycle | Trade-off |
|---|---|---|
| Client-managed stdio (default) | Each MCP client starts and stops its own provider process. | No service setup; every concurrent connection pays its own process, memory, and startup cost. |
| Shared HTTP daemon (optional) | The operator keeps one provider daemon running and clients connect to http://127.0.0.1:/mcp. |
Faster reconnects and fewer adapter processes; requires service and local-auth configuration. |
Stdio uses
JSON-RPC over stdio.
Because the protocol era is chosen by the opening exchange, the bridge logs
twice to stderr: [mcp-agents] listening (provider: , awaiting protocol era) once the transport accepts input, then [mcp-agents] ready (provider: , era=) once an era is pinned. The codex provider
logs the same pair as [mcp-agents] Codex MCP adapter listening and
[mcp-agents] Codex MCP adapter ready. Wait for the listening line, not the
ready line, to know the bridge accepts traffic. stdout remains MCP-only.
Every provider first logs [mcp-agents] starting (mcp_agents=, provider=, transport=, node=), and the Codex ready
line carries mcp_agents= and codex=. The claude and gemini providers
run claude --version / agy --version once in the background and log
[mcp-agents] provider CLI version (=); the probe never
delays the transport and reports unknown with a reason within four seconds
(a three-second timeout plus a one-second grace). The codex provider also
logs one [mcp-agents] Codex turn started (tool=…, thread=…, reported_by=…, requested_model=…, reported_model=…, model_status=…, requested_effort=…, reported_effort=…, effort_status=…) line for every turn it starts, prefixed
WARNING: when Codex reports a different model or effort than requested, and
[mcp-agents] WARNING: Codex rerouted the model (…) when Codex reroutes the
model of such a turn. Turns Codex starts on its own, such as goal
continuations, are not logged.
Use the Quickstart configuration above if you prefer this mode.
Shared HTTP daemon
HTTP is additive and opt-in. Each daemon serves one of the codex, claude,
or gemini providers. Use a separate port and service for each additional
provider. The raw browser and codex-legacy providers remain stdio-only.
Test the Codex daemon in a terminal first:
mcp-agents --provider codex --transport http --http-port 8765
It listens only on loopback at http://127.0.0.1:8765/mcp and creates a
private bearer-token file. Point Claude Code at it with:
{
"mcpServers": {
"codex": {
"type": "http",
"url": "http://127.0.0.1:8765/mcp",
"headers": {
"X-Mcp-Agents-Project-Root": "${PWD}"
},
"headersHelper": "/absolute/path/to/mcp-agents http-auth-headers",
"timeout": 7500000
}
}
}
Use the same mcp-agents installation for the daemon and headersHelper.
Claude Code runs the helper on every connection; it reads the token file and
returns the Authorization header without storing the token in .mcp.json.
The project-root header is required by the Codex provider so one daemon can
isolate and pool runtimes by canonical project path.
The root is also a boundary: a Codex call, reply, or review whose workspace
resolves outside it is refused with codex_workspace_outside_project. Request
bodies over 10 MiB, the same limit as a stdio frame, are refused with 413. A
blocking claude or gemini call is canceled, and its CLI process group
killed, when its client disconnects. An idle runtime is reaped only after every
finished background job has been read with codex-status or codex-result, or
has passed its one-hour retention. --http-runtime-idle-timeout 0 disables
reaping entirely, so a runtime whose App Server child died mid-turn keeps its
thread leases until the daemon stops.
Service managers do not load interactive shell initialization. The examples
below use the absolute path from command -v mise and a working directory
whose .tool-versions contains mcp-agents and its provider CLI. Without
Mise, invoke the absolute mcp-agents path directly and set PATH for Node.js
and the provider CLI in the service definition.
Providers
Primary providers
| Provider | Best for | Under the hood | State model |
|---|---|---|---|
codex |
Implementation, reviews, steering, goals, and resumable sessions | Wrapper-owned MCP adapter over codex app-server --stdio |
Durable threads and native goals |
claude |
One-shot help and independent read-only reviews | Claude Code CLI, Fable 5.1 at xhigh effort with Opus 5 availability fallback and guarded default-model quota retry |
Blocking calls and connection-local review jobs |
Also supported
| Provider | What it does | Under the hood |
|---|---|---|
gemini |
Runs a Gemini-backed agent prompt | Google Antigravity CLI: agy --sandbox -p |
browser |
Proxies Chrome DevTools MCP to an operator-leased remote browser | chrome-devtools-mcp --browserUrl |
codex-legacy |
Temporary compatibility with the former Codex bridge | Deprecated codex mcp-server |
The browser provider is an advanced operational capability, not part of the
normal Claude ↔ Codex setup. codex-legacy is not a recommended fallback and is
never selected automatically.
Client configuration
Mise, npm, or npx
The Mise installation is recommended. It
keeps the shared tool and its update policy in .tool-versions without adding a
Mise wrapper to every MCP process launch. If you do not use Mise,
npm install -g mcp-agents works just as well at runtime and launches the same
executable.
Claude Code configuration
The quickstart is the recommended project configuration. To override Codex defaults at server startup:
{
"mcpServers": {
"codex": {
"command": "mcp-agents",
"args": [
"--provider",
"codex",
"--model",
"gpt-6-astra",
"--model_reasoning_effort",
"xhigh",
"--codex-workspace-network=false"
],
"timeout": 7500000
}
}
}
Every initial codex call may select gpt-6-astra or gpt-5.6-terra and
medium, high, xhigh, or max. Omitted selectors use the server defaults;
replies inherit the thread’s model, effort, sandbox, and subagent policy. Other
models, raw config, and per-call approval-policy arguments are rejected before
Codex runs. Add "--goal", "" to the server args to provide a default
native durable objective.
Claude Code interprets the per-server timeout in milliseconds as a hard
wall-clock cap; progress does not extend it. Keep it above the wrapper’s
--timeout, which defaults to 7,200 seconds for Codex, including response
headroom. A project .mcp.json entry can override a user-level entry of the
same name, so configure the timeout on the project entry.
OpenAI Codex configuration
The quickstart is enough for blocking Claude calls. For frictionless background reviews, explicitly approve the connection-local review tools:
[mcp_servers.claude-code]
command = "mcp-agents"
args = ["--provider", "claude"]
tool_timeout_sec = 960
[mcp_servers.claude-code.tools.claude-start]
approval_mode = "approve"
[mcp_servers.claude-code.tools.claude-status]
approval_mode = "approve"
[mcp_servers.claude-code.tools.claude-result]
approval_mode = "approve"
[mcp_servers.claude-code.tools.claude-cancel]
approval_mode = "approve"
The 960-second client timeout preserves compatibility with the blocking
900-second claude_code tool. Background reviews do not keep one MCP request
open: claude-start returns immediately, and each claude-status poll lasts at
most 60 seconds.
Run from a source checkout
For a personal bridge launched directly from a checkout:
{
"mcpServers": {
"codex": {
"type": "stdio",
"command": "node",
"args": [
"/absolute/path/to/mcp-agents/server.js",
"--provider",
"codex",
"--codex_idle_timeout",
"0"
],
"env": {},
"timeout": 3600000
}
}
}
Bare node resolves against the MCP client’s PATH. If the client does not
initialize nvm, fnm, asdf, or another version manager, use the absolute Node path
reported by command -v node.
Provider reference
codex: App Server-backed MCP
The default Codex provider is a wrapper-owned MCP server backed internally by
the documented stdio JSONL interface of codex app-server. It requires Codex
CLI 0.149.1 or newer. OpenAI currently labels App Server experimental and
unsupported for production workloads, so the adapter treats it as a
version-gated private dependency instead of exposing its protocol to MCP
clients.
The outer MCP connection owns initialization, discovery, validation, progress, jobs, and results; App Server stays lazy. There is no automatic fallback to native MCP because the providers have different durability, goal, recovery, and error semantics.
initialize, tools/list, ping, and wrapper-local status tools do not depend
on a healthy Codex child. If a child exits, a later safe operation starts a new
generation against the same durable sessions. A dispatched turn is reported as
codex_outcome_unknown and is never replayed automatically because it may
already have changed the workspace.
App Server frames are capped at 10 MiB. With Codex 0.151.0 or later the bridge asks for metadata only when it resumes or forks a thread, since a long thread’s full history alone can exceed the cap. A frame over the cap fails only what it belongs to: the request it answers, or the turn whose answer it carried. Progress-only frames are dropped, and an approval request over the cap is refused, which interrupts its turn. Only a frame that cannot be attributed safely, or the answer to a dispatched mutation, still restarts the child.
codex-legacy: temporary native compatibility
codex-legacy preserves the complete 0.28 native MCP bridge and runs the
deprecated codex mcp-server command directly. It is a migration escape hatch,
not a fallback. It receives security and compatibility fixes but no App
Server-only capabilities, and any later removal will be called out as a
breaking change.
claude: blocking help and background reviews
For substantial second opinions and code reviews:
- Call
claude-startwith the complete review prompt and an absolutecwd. - Call
claude-statuswith the returnedjobIdandcursor, repeating with each new cursor until the state is terminal. - When the state is
completed, callclaude-resultand continue fromnextOffsetuntildoneistrue. - Call
claude-cancelif the verdict is no longer needed.
Use the blocking claude_code tool only for small prompts that can comfortably
finish inside one MCP request.
gemini: Antigravity prompt runner
The gemini provider invokes Google’s Gemini-backed Antigravity CLI, agy. It
is intentionally a small blocking provider:
| Parameter | Type | Required | Description |
|---|---|---|---|
prompt |
string |
yes | Prompt sent to agy |
timeout_ms |
integer |
no | Timeout in milliseconds; default 300,000 / 5 minutes |
Additional arguments are ignored. agy always runs with --sandbox; there is
no per-call sandbox toggle.
browser: advanced remote Chrome pass-through
The browser provider starts a local chrome-devtools-mcp process and lazily
acquires a remote Chrome lease on the first browser tool call. The MCP server
and every file it writes remain local; only Chrome DevTools Protocol traffic
crosses the operator-provided loopback tunnel.
There are no wrapper-owned acquire, status, release, job, or cancellation tools. Calls arriving during acquisition share one provisioning attempt and remain in FIFO order.
Development
npm install
npm link
npm link symlinks mcp-agents into the active Node installation. Edits to
server.js or codex-legacy.js then take effect immediately without a rebuild
or reinstall.
Benchmark launch through real temporary-project MCP configurations:
npm run bench:mcp-startup
The benchmark measures initialize through tools/list and does not call an
agent model or tool.
Run the deterministic suite without real CLI calls:
SKIP_INTEGRATION=1 ./test.sh
For a real Claude background smoke check, call claude-start with a short
review prompt and this repository as cwd, poll claude-status with every new
cursor, and read the verdict with claude-result. For the inverse direction,
have Claude Code call codex-start, poll codex-status, and read
codex-result.
How it works
- An MCP client either starts
mcp-agentsover stdio or connects to an authenticated loopback HTTP daemon. - The server selects one
--providerat startup; the default iscodex. - The selected provider registers its own tools:
- Claude exposes one blocking tool plus one-shot review jobs.
- Codex exposes a wrapper-owned MCP surface and lazily starts App Server.
- Antigravity exposes one blocking prompt tool.
- Browser proxies a downstream Chrome DevTools MCP server.
codex-legacyruns the sealed native MCP bridge.
- The client calls a tool with provider-specific arguments.
- The bridge normalizes lifecycle and results without leaking vendor protocols onto MCP stdout.
Claude review jobs parse stream JSON. The Codex adapter correlates documented thread, turn, and item events into privacy-safe progress, durable thread IDs, and retained result pages. The legacy provider transforms and observes native MCP frames. The browser provider validates every result against its lease generation.
A small keepalive prevents a stdio bridge from exiting when stdin reaches EOF before an asynchronous subprocess registers an active handle. When that MCP connection closes, active Claude and Codex work receives a native interrupt where available, followed by bounded TERM/KILL fallback. Remaining tracked detached process groups are reaped before the bridge exits. The HTTP Codex host instead pools one lazy App Server runtime per canonical project root and reaps it after the configured idle period.
License
MIT
Install
npx -y mcp-agents --provider codexConfiguration
{
"mcpServers": {
"codex": {
"command": "mcp-agents",
"args": ["--provider", "codex"],
"timeout": 7500000
}
}
}