codex-cli-mcp-slim
A thin, auditable MCP server wrapping the Codex CLI (codex exec).
Why
codex mcp-server, the command that let other MCP clients call Codex, is
deprecated, and its removal has been merged upstream
(openai/codex#42993): releases up
to 0.153.x still ship it, later ones will not. Its replacement, the Codex app
server, speaks its own JSON-RPC protocol rather than MCP. This server keeps the old
integration point alive: it exposes the same two tools, codex and
codex-reply, and runs codex exec underneath. codex exec is the Codex CLI's
non-interactive mode: one prompt in, the agent works on its own, one final
message out.
When you add an MCP server to your AI coding tool, every prompt and code snippet
you send flows through that wrapper. Most CLI-wrapping MCP servers are small,
individually maintained packages, and recent supply-chain incidents
(xz-utils, postmark-mcp, the npm chalk/debug compromise) show that
"small and useful" is not the same as "safe to trust blindly."
This project takes the opposite stance: instead of asking you to trust it, it tries to be easy to audit.
- Single file — the whole server is
src/codex_cli_mcp_slim/server.py, readable end-to-end in one sitting - One third-party dependency (
mcp) — minimal supply-chain surface - Faithful CLI mapping — every typed parameter mirrors a real
codex execflag by name, so it is obvious which flags an invocation actually sets - Prompt over stdin — the prompt never appears in the process list and is not bounded by the argv size limit
- Forward-compatible — any new or uncommon
codex execflag is reachable viaextra_argswithout touching this server - Configurable binary path —
$CODEX_CMDlets you swap or wrap thecodexbinary - Transparent — every invocation logs the exact argv to stderr
Read server.py before you install. That is the point.
Prerequisites
- The
codexCLI installed and on$PATH(or pointed to via$CODEX_CMD). See the official Codex CLI repository. This server always passes--jsonand reads the prompt from stdin (codex exec -), both of whichcodex execdocuments. codexalready authenticated — this wrapper does not manage login; it surfacescodex's own error output if the CLI is not ready.
Installation
# Run directly without installing
uvx codex-cli-mcp-slim
# Install from PyPI
pip install codex-cli-mcp-slim
# Run from GitHub HEAD
uvx --from git+https://github.com/tksfjt1024/codex-cli-mcp-slim codex-cli-mcp-slim
Usage as an MCP server
Claude Code
claude mcp add codex uvx codex-cli-mcp-slim
Or manually in ~/.claude.json:
{
"mcpServers": {
"codex": {
"type": "stdio",
"command": "uvx",
"args": ["codex-cli-mcp-slim"]
}
}
}
If codex is not on the launching process's $PATH, point $CODEX_CMD at it:
{
"mcpServers": {
"codex": {
"type": "stdio",
"command": "uvx",
"args": ["codex-cli-mcp-slim"],
"env": { "CODEX_CMD": "/absolute/path/to/codex" }
}
}
}
Replacing codex mcp-server
An entry that used to launch codex mcp-server keeps its server name and its
tool names; only command and args change. Before:
{
"mcpServers": {
"codex": {
"type": "stdio",
"command": "codex",
"args": ["mcp-server"]
}
}
}
After:
{
"mcpServers": {
"codex": {
"type": "stdio",
"command": "uvx",
"args": ["codex-cli-mcp-slim"]
}
}
}
Parameter names differ from the old server where codex exec names the flag
differently: cwd is now cd (the -C/--cd flag), and codex-reply takes
thread_id instead of threadId. The result's structuredContent field keeps
the shape the old server returned, {"threadId": ..., "content": ...}.
Other MCP clients
Any MCP-compatible client can launch the server via stdio:
uvx codex-cli-mcp-slim
Server-level flags
Everything on the server's own command line is placed right after codex exec
on every invocation. One MCP-client entry can therefore pin a reasoning effort, a
model or a working directory for all of its calls. Two entries that differ only
in reasoning effort look like this:
{
"mcpServers": {
"codex-medium": {
"type": "stdio",
"command": "uvx",
"args": ["codex-cli-mcp-slim", "-c", "model_reasoning_effort=medium"]
},
"codex-high": {
"type": "stdio",
"command": "uvx",
"args": ["codex-cli-mcp-slim", "-c", "model_reasoning_effort=high"]
}
}
}
A call to codex-high runs
codex exec -c model_reasoning_effort=high [per-call flags] --json -. Per-call
flags come after the server-level ones, and -c may repeat with the last one
winning, so a per-call config entry overrides a server-level -c. Single-value
flags such as -m and -C may not repeat: codex rejects the second one, and
the tool result carries that error. Keep server-level flags and per-call
parameters disjoint for those.
Tool: codex
Runs a single non-interactive Codex session (codex exec). codex is an
agentic assistant: it reads and, depending on the sandbox, edits files in the
working directory to fulfil the request, then prints its final message.
The tool returns that final message followed by one metadata line:
[codex] thread_id=019a2b3c-1d4e-7f60-8a9b-0c1d2e3f4a5b status=completed input_tokens=13894 cached_input_tokens=11904 output_tokens=612
thread_id and status are always present; the token fields appear when the
run reported them. isError is the flag on an MCP tool result that tells the
client a call failed. This server sets it when codex exited non-zero, when the
subprocess timed out, and when the turn itself failed. The last case matters
because codex exec exits 0 after a failure inside the model API; the tool
result then carries the error text instead of coming back as a successful call:
[ERROR] codex failed
returncode=0
errors:
Unsupported value: 'none' is not supported with the ... model.
[codex] thread_id=019a2b3c-... status=failed
argv: ['codex', 'exec', '--json', '-']
Pass the thread_id to codex-reply to continue the same session.
| Parameter | Type | Description |
|---|---|---|
prompt (required) |
string | Prompt sent verbatim to codex on stdin |
cd |
string | Pass -C <DIR>: the working directory; defaults to the server's own |
model |
string | Pass -m <MODEL> |
config |
string[] | key=value overrides; each maps to one -c (repeatable, last wins) |
sandbox |
string | Pass --sandbox: read-only, workspace-write or danger-full-access. See note below |
add_dir |
string[] | Extra writable directories; each maps to one --add-dir (repeatable, not comma-joined) |
profile |
string | Pass -p <PROFILE> |
ephemeral |
bool | Pass --ephemeral (do not write the session transcript codex keeps under $CODEX_HOME/sessions) |
skip_git_repo_check |
bool | Pass --skip-git-repo-check (allow a working directory outside a git repository) |
extra_args |
string[] | Raw CLI flags appended verbatim. Do not pass --json or a prompt; the server adds both |
env |
object | Extra environment variables for the codex subprocess |
timeout_seconds |
int | Hard wall-clock timeout for the subprocess, 30 to 3600 (default 1800) |
Unknown parameters are refused rather than ignored, so a call that still uses
the old server's cwd gets an error naming cd instead of running in the
wrong directory.
Security note: sandbox
codex exec reads its sandbox mode from its own configuration file
(~/.codex/config.toml by default) unless --sandbox is given.
danger-full-access removes the filesystem and network sandbox entirely;
workspace-write makes the working directory (and any add_dir) writable.
--sandbox overrides only the mode; whether workspace-write gets network
access still follows the [sandbox_workspace_write] section of config.toml.
The parameter mirrors the flag so that whichever mode a call runs
under is visible in the arguments and in the logged argv. This server does not
pass --dangerously-bypass-approvals-and-sandbox; reach it via extra_args if
you really mean it.
Tool: codex-reply
Continues a previous session (codex exec resume <THREAD_ID>) with a follow-up
prompt and returns the new final message. Only the flags codex exec resume
accepts are exposed, so cd, sandbox, add_dir and profile are refused
here. The working directory and sandbox of a reply come from the current
configuration, that is, the server-level flags and config.toml, not from the
original session.
| Parameter | Type | Description |
|---|---|---|
thread_id (required) |
string | The thread_id from a previous result's [codex] line |
prompt (required) |
string | Follow-up prompt, sent on stdin |
model |
string | Pass -m <MODEL> |
config |
string[] | key=value overrides; each maps to one -c |
ephemeral |
bool | Pass --ephemeral |
skip_git_repo_check |
bool | Pass --skip-git-repo-check |
extra_args |
string[] | Raw CLI flags appended verbatim |
env |
object | Extra environment variables for the codex subprocess |
timeout_seconds |
int | Hard wall-clock timeout for the subprocess, 30 to 3600 (default 1800) |
Timeout configuration
timeout_seconds is this wrapper's hard wall-clock limit (default 1800, or
$CODEX_CLI_MCP_SLIM_TIMEOUT). On timeout, the wrapper kills the subprocess's
whole process group and then waits up to 20 additional seconds to collect any
buffered output and reap the process, so the effective ceiling is
timeout_seconds + 20. A timed-out call is flagged isError and carries
whatever codex had printed so far.
Forward-compatibility example
If a future codex exec release adds a new flag (say --super-mode), use it
immediately without updating this server:
{
"name": "codex",
"arguments": {
"prompt": "...",
"extra_args": ["--super-mode"]
}
}
Configuration
| Environment variable | Default | Purpose |
|---|---|---|
CODEX_CMD |
codex |
Path to the codex CLI binary |
CODEX_CLI_MCP_SLIM_TIMEOUT |
1800 |
Default subprocess timeout in seconds |
CODEX_CLI_MCP_SLIM_LOG_LEVEL |
INFO |
Logging level for stderr diagnostics |
codex itself reads its configuration file and credentials from $CODEX_HOME
(~/.codex by default), so an MCP-client entry can point a server at a
dedicated configuration directory through its env block.
Development
# Install dev dependencies
pip install -e ".[test,dev]"
# Lint
ruff check .
# Test
pytest
License
MIT © tksfjt1024
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file codex_cli_mcp_slim-0.1.0.tar.gz.
File metadata
- Download URL: codex_cli_mcp_slim-0.1.0.tar.gz
- Upload date:
- Size: 27.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4daa95519283b3da3647d6b865fa209df8a2135c7dea0d71e040a18e4f327d99
|
|
| MD5 |
f85fbf1cdf29c9e36b20d261905028b6
|
|
| BLAKE2b-256 |
73be347e40afe45f8d25a7a3233daa433f4210356f107831f1b5dde8494c970f
|
Provenance
The following attestation bundles were made for codex_cli_mcp_slim-0.1.0.tar.gz:
Publisher:
publish.yml on tksfjt1024/codex-cli-mcp-slim
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
codex_cli_mcp_slim-0.1.0.tar.gz -
Subject digest:
4daa95519283b3da3647d6b865fa209df8a2135c7dea0d71e040a18e4f327d99 - Sigstore transparency entry: 2728324463
- Sigstore integration time:
-
Permalink:
tksfjt1024/codex-cli-mcp-slim@a6f88a471abd7f1617ca93b1403bf2037ee28579 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/tksfjt1024
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@a6f88a471abd7f1617ca93b1403bf2037ee28579 -
Trigger Event:
push
-
Statement type:
File details
Details for the file codex_cli_mcp_slim-0.1.0-py3-none-any.whl.
File metadata
- Download URL: codex_cli_mcp_slim-0.1.0-py3-none-any.whl
- Upload date:
- Size: 16.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e6ea398e63aa3964dfd536cc0226b1a97a4ca04668773cce08ce785e7cbdce4c
|
|
| MD5 |
f1ff43df2016e179d666fe30775df1b7
|
|
| BLAKE2b-256 |
3228876c5dc1d7d84fa835732c83241a3cc681a0fd32956b371a45f3d4badf40
|
Provenance
The following attestation bundles were made for codex_cli_mcp_slim-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on tksfjt1024/codex-cli-mcp-slim
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
codex_cli_mcp_slim-0.1.0-py3-none-any.whl -
Subject digest:
e6ea398e63aa3964dfd536cc0226b1a97a4ca04668773cce08ce785e7cbdce4c - Sigstore transparency entry: 2728325643
- Sigstore integration time:
-
Permalink:
tksfjt1024/codex-cli-mcp-slim@a6f88a471abd7f1617ca93b1403bf2037ee28579 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/tksfjt1024
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@a6f88a471abd7f1617ca93b1403bf2037ee28579 -
Trigger Event:
push
-
Statement type: