codex-mcp
README.md
# codex-mcp
**Expose the Codex engine as MCP tools, so any MCP-capable agent can use it — including teams that cannot use Codex directly.**
Codex is a strong coding engine: it plans, edits files, runs commands, and keeps a thread alive. But getting an OpenAI account, a payment method, and stable network access is not possible for everyone. Codex itself supports custom OpenAI-compatible providers, which means the engine can run on a domestic model (DeepSeek, Qwen, or any compatible endpoint).
This project wraps `codex app-server` in a local MCP server. Any agent that speaks MCP over stdio — DSH, WorkBuddy/CodeBuddy, Trae, Qoder, Claude Desktop, Cursor — can call Codex as tools, with approvals, resume, usage and event polling.
```
your agent ──MCP(stdio)──▶ codex-mcp ──JSON-RPC──▶ codex app-server ──▶ provider
```
---
## Why not just use Codex directly?
| Situation | Direct Codex | codex-mcp |
|---|---|---|
| You already live in another agent (DSH, WorkBuddy, Trae, Qoder) | Switch tools and lose the session | Codex becomes a tool inside your agent |
| OpenAI signup / payment / network is a blocker | Cannot start | Point Codex at a domestic provider and keep the engine |
| You need approvals before commands run | Terminal prompts only | `codex_start` + `codex_poll` + `codex_approve` over MCP |
| You want a long-running thread | One terminal session | Thread id persists; `codex_resume` continues it |
| You want usage and event progress | Terminal UI only | `codex_poll` returns items, commands, approvals, token usage |
It is not a replacement for the agent's own planning loop. It exposes the Codex execution engine as a tool.
---
## Tools
| Tool | Arguments | Purpose |
|---|---|---|
| `codex_run` | `prompt`, `cwd?`, `model?`, `sandbox?`, `context?`, `timeoutSec?` | Blocking run; auto-approves; returns final text, usage, thread id |
| `codex_start` | `prompt`, `cwd?`, `model?`, `sandbox?`, `approvalPolicy?`, `context?` | Start a thread/turn and return immediately |
| `codex_poll` | `threadId`, `cursor?` | Read new events, status, text, usage, pending approvals |
| `codex_approve` | `threadId`, `approvalId`, `decision` | Answer an approval: `accept`, `acceptForSession`, `decline`, `cancel` |
| `codex_interrupt` | `threadId` | Interrupt the running turn |
| `codex_resume` | `sessionId`, `prompt`, `cwd?`, `model?`, `sandbox?`, `timeoutSec?` | Continue an existing thread and wait |
`codex_run` is the simple path. `codex_start` → `codex_poll` → `codex_approve` is the interactive path: the host can show progress and let a human approve each command.
---
## Requirements
- Node.js 18 or newer
- Codex CLI installed and on `PATH` (or set `CODEX_EXE`)
- A Codex provider home (`CODEX_HOME`) with a `config.toml`
- An API key for that provider, passed through an environment variable
```bash
npm install -g @openai/codex
```
---
## Provider setup (DeepSeek example)
`CODEX_HOME/config.toml`:
```toml
model = "deepseek-chat"
model_provider = "deepseek"
[model_providers.deepseek]
name = "DeepSeek"
base_url = "https://api.deepseek.com/v1"
env_key = "DEEPSEEK_API_KEY"
wire_api = "chat"
```
Then export the key for the process that launches the MCP server:
```bash
export DEEPSEEK_API_KEY=... # macOS / Linux
$env:DEEPSEEK_API_KEY = "..." # Windows PowerShell
```
The server also falls back to `deepseekApiKey` in `~/.my-agent/credentials.json` if the environment variable is empty. It never logs or writes the key.
Any OpenAI-compatible provider works the same way; change `base_url`, `env_key`, and `model`.
---
## Environment variables
| Variable | Meaning |
|---|---|
| `CODEX_EXE` | Path or command for the Codex binary. Default: `codex` |
| `CODEX_HOME` | Provider home containing `config.toml`. Default: Codex's own default |
| `DEEPSEEK_API_KEY` | Optional; used when the provider requires it |
| `MY_AGENT_HOME` | Optional; overrides `~/.my-agent` for the credentials fallback |
---
## Client configuration
The server is a standard stdio MCP server. The only portable part of every config is:
```
command: node
args: ["<absolute-path>/server-appserver.mjs"]
```
### DSH
```yaml
- insert:
- id: codex-mcp
name: '@deepseek-ai/dsh-mcp-client'
config:
serverName: codex
transport: stdio
command: node
args:
- C:/path/to/codex-mcp/server-appserver.mjs
env:
CODEX_EXE: codex
CODEX_HOME: C:/path/to/your/codex-home
toolCallTimeoutMs: 1800000
failOnStartupError: true
```
`toolCallTimeoutMs` matters: a Codex turn can run far longer than the MCP client's default 60 seconds.
### WorkBuddy / CodeBuddy
Put this in the project root (or pass it with `--mcp-config`):
```json
{
"mcpServers": {
"codex": {
"command": "node",
"args": ["C:/path/to/codex-mcp/server-appserver.mjs"],
"env": {
"CODEX_EXE": "codex",
"CODEX_HOME": "C:/path/to/your/codex-home"
}
}
}
}
```
See `mcp.example.json`. WorkBuddy CLI does not auto-load a project-root `.mcp.json`; pass `--mcp-config` or configure the desktop connector.
### Trae / Qoder / Claude Desktop / Cursor
Add the same `command` / `args` / `env` block in the host's MCP settings. No server-side change is needed.
---
## Compatibility
- **Protocol:** MCP `2024-11-05` over stdio, verified with a handshake test.
- **Any stdio MCP client:** the server does not depend on DSH-specific APIs.
- **Tested hosts:** DSH and WorkBuddy/CodeBuddy. Trae, Qoder, Claude Desktop and Cursor use the same stdio contract, but each host has its own configuration surface.
- **Long turns:** set a tool timeout of at least 30 minutes; otherwise the client may kill a legitimate Codex run.
Run the protocol test without spending model tokens:
```bash
node test-handshake.mjs
# initialize ok, protocol 2024-11-05
# tools: codex_approve, codex_interrupt, codex_poll, codex_resume, codex_run, codex_start
```
Full tests (these do call the provider):
```bash
node test-appserver.mjs # codex_run + protocol
node test-start.mjs # start/poll/approve
```
---
## Project instructions and context
Before starting a thread, the server reads, in order:
- `~/.dsh/AGENTS.md`
- `~/.agents/AGENTS.md`
- `AGENTS.md` / `AGENTS.local.md` from the project root down to `cwd`
They are passed as Codex `developerInstructions`, capped at 32 KB. The optional `context` argument appends task-specific memory or a handoff brief.
---
## Security
- The API key is passed only to the Codex child process; it is never logged or written to disk.
- Sandbox mode per call: `read-only`, `workspace-write`, `danger-full-access`.
- Two approval layers remain: the host's approval for the MCP tool call, and Codex's own approval policy for commands. `codex_start` lets the host approve Codex commands, but the two models are not unified.
- Do not expose this server over a network transport without adding authentication.
---
## Limits
- **Tool-level, not a loop replacement.** Your agent still plans; Codex executes inside one thread.
- **No token-level streaming.** `codex_poll` gives event-level progress, not the native TUI stream.
- **No native Codex UI.** Rollout view, plan mode, and the TUI are not reproduced.
- **Two ecosystems.** Codex's own MCP servers and skills live in `CODEX_HOME`; your agent's tools are separate.
---
## License
MIT — see [LICENSE](LICENSE).
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues