loading…
Search for a command to run...
loading…
Local MCP server that wraps the codex CLI asynchronously, returning a job_id immediately to avoid MCP protocol timeouts, and providing tools to start, poll, lis
Local MCP server that wraps the codex CLI asynchronously, returning a job_id immediately to avoid MCP protocol timeouts, and providing tools to start, poll, list, and cancel codex jobs.
Local MCP server that wraps the codex CLI asynchronously — returns a job_id immediately instead of blocking, so Claude never hits the MCP protocol timeout (-32001).
codex CLI installed and on $PATH (v0.125.0+)cd ~/payroll-mcp # or wherever this repo lives
pip install -e ".[dev]"
Verify:
python -c "from codex_async_mcp.server import mcp; print(mcp.name)"
# → codex-async-mcp
claude mcp add codex-async -s user -- python -m codex_async_mcp.server
cd ~/payrollservice-thailand # or any project
claude mcp add codex-async -- python -m codex_async_mcp.server
claude mcp list
# codex-async: python -m codex_async_mcp.server - ✓ Connected
{
"permissions": {
"allow": [
"mcp__codex-async__codex_start",
"mcp__codex-async__codex_poll",
"mcp__codex-async__codex_list",
"mcp__codex-async__codex_cancel"
]
}
}
| Tool | Description |
|---|---|
codex_start(prompt, cwd, approval_policy?) |
Start codex in background → returns job_id instantly |
codex_poll(job_id, tail_lines?) |
Check status + output tail |
codex_list(limit?) |
List recent jobs (newest first) |
codex_cancel(job_id) |
Kill running job |
| Value | Codex flag | Behavior |
|---|---|---|
suggest |
-s read-only |
Read-only sandbox, no writes |
auto-edit |
--full-auto |
Auto-applies edits |
full-auto |
--dangerously-bypass-approvals-and-sandbox |
No prompts, no sandbox |
For Claude automation always use full-auto — suggest mode waits for interactive input which will never arrive inside a subprocess.
codex_start(
prompt="In app/services/prorate_calculation_service.rb line 96, change format(...) to number_to_currency(...)",
cwd="/Users/bbgummybear/payrollservice-thailand",
approval_policy="full-auto"
)
# → { job_id: "f3a9b2", status: "running", pid: 12345 }
codex_poll(job_id="f3a9b2")
# → { status: "running", output: "Reading file..." }
codex_poll(job_id="f3a9b2")
# → { status: "done", exit_code: 0, output: "Applied changes to prorate_calculation_service.rb" }
Jobs are stored in ~/.codex-async/jobs/{job_id}/:
~/.codex-async/jobs/f3a9b2/
meta.json ← status, pid, timestamps, exit_code
output.txt ← stdout + stderr from codex
meta.json structure:
{
"job_id": "f3a9b2",
"status": "running | done | error | cancelled",
"prompt": "...",
"cwd": "/path/to/repo",
"approval_policy": "full-auto",
"pid": 12345,
"started_at": "2026-04-29T10:00:00+00:00",
"finished_at": null,
"exit_code": null
}
codex-async: ... - ✗ Failed in claude mcp listPython can't be found or the package isn't installed in the right environment.
# Check which python Claude is using
which python
# If using conda, register with the full path
claude mcp add codex-async -s user -- /Users/bbgummybear/miniconda3/bin/python -m codex_async_mcp.server
# Verify the package is installed in that environment
/Users/bbgummybear/miniconda3/bin/python -c "import codex_async_mcp; print('ok')"
status: "error" immediately after codex_startCodex failed to start. Check the raw output:
cat ~/.codex-async/jobs/<job_id>/output.txt
Common causes:
| Output message | Fix |
|---|---|
command not found: codex |
codex not on PATH — add to shell profile or set CODEX_BIN in config.py |
unknown flag: --dangerously-bypass-approvals-and-sandbox |
Codex version < 0.125.0 — run npm install -g @openai/codex to upgrade |
permission denied |
cwd doesn't exist or Claude doesn't have access |
status: "running" forever, never finishesThe subprocess is hung (waiting for input or stuck in a loop).
# Check if the process is still alive
ps aux | grep codex
# Check live output
tail -f ~/.codex-async/jobs/<job_id>/output.txt
# Cancel the job
codex_cancel(job_id="<job_id>")
Most common cause: using approval_policy="suggest" which pauses for interactive approval. Use "full-auto" instead.
status: "running" after server restartThe MCP server lost the in-memory Popen registry on restart. The next codex_poll call will detect the PID is dead and update the status automatically.
codex_poll(job_id="<job_id>")
# → { status: "done", ... } ← auto-resolved on first poll
# View all jobs sorted by date
ls -lt ~/.codex-async/jobs/
# Delete jobs older than 7 days
find ~/.codex-async/jobs -maxdepth 1 -type d -mtime +7 -exec rm -rf {} +
codex-async-mcp/
├── README.md
├── pyproject.toml
├── src/
│ └── codex_async_mcp/
│ ├── __init__.py
│ ├── server.py # MCP entry point, tool definitions
│ ├── job_manager.py # spawn / poll / cancel / list
│ └── config.py # JOBS_DIR, CODEX_BIN, defaults
└── tests/
└── test_job_manager.py
pytest tests/ -v
Добавь это в claude_desktop_config.json и перезапусти Claude Desktop.
{
"mcpServers": {
"codex-async-mcp": {
"command": "npx",
"args": []
}
}
}