Skip to main content
Glama
README.md
![codex-image-mcp — image generation in Claude Code, paid for by the ChatGPT subscription you already have](samples/social-preview.png)

# codex-image-mcp

No API key. No credits. No third-party service holding your prompts. This is an
MCP server that drives the Codex CLI already bundled inside ChatGPT.app, which
authenticates from your own `~/.codex/auth.json` and calls OpenAI's built-in
`gpt-image-2`. Every image on this page, banner included, came out of the tool
while I was building it.

## Why I built it

I wanted Claude to make images for me. Every option was wrong.
The hosted MCP servers — Pixa, ImagineArt, Claude Imagine — are someone else's
service with a credit tier attached. The OpenAI-key servers bill you per image
for a model your subscription already covers. Local diffusion on a 16 GB M1
Pro is slow and nowhere near `gpt-image-2` on quality.

Then I noticed my ChatGPT app ships a full Codex binary, that Codex has image
generation switched on by default, and that it signs in as me. The bridge turned
out to be one command. Getting that command to behave took considerably longer,
and the rest of this README is what went wrong along the way.

## Install

You need the ChatGPT desktop app and a logged-in Codex session. Then:

```bash
git clone https://github.com/Equallogic/codex-image-mcp.git
cd codex-image-mcp && npm install
claude mcp add --scope user codex-image -- node "$(pwd)/server.js"
```

Restart Claude Code. One tool appears:

```
generate_image(prompt, output_path, [reference_images])
```

It writes the file and hands back the path, format, dimensions, elapsed time and
tokens spent. Roughly 45 seconds an image.

## What I learned making it reliable

This is the part worth reading, because all three of these cost me real money to
find out.

**Phrasing decides whether you get an image at all.** Ask for "Generate an
image: X. Just generate the image." and Codex replies with the image tool's own
prompt-writing guidance instead of calling it. Seventy-eight seconds, 22,739 tokens, no
picture. The server sends an imperative that names the destination file instead,
and that has worked every time since.

**Codex reports success whether or not a file appeared.** It prints "Created with built-in ImageGen" and a
plausible path. That means nothing. So the server ignores the prose entirely and
goes to the disk: magic bytes to confirm it is an image at all, the PNG header
for dimensions, and an mtime guard so that a stale file already sitting at the
target path cannot quietly pass itself off as a fresh result. No image, no
success. You get an error.

**The overhead was never the tool.** The `image_gen` schema is 435 tokens. What
costs you is that an image request makes the agent read 17,763 bytes of
`imagegen/SKILL.md` first, then take several more passes to generate, copy and
verify. Suppressing that skill removes the read and a whole model pass — 80,049
aggregate input tokens down to 61,197. That single override is worth more than
every other flag combined.

## Do not trust the token count Codex prints

It is cache-discounted. Identical requests were measured taking anywhere from 0
to 17,664 cached tokens, so the figure moves with cache warmth and can go *up*
when a change makes the prompt smaller. I chased that number for an afternoon. Every
conclusion I drew from it was wrong, including a confident 24% improvement that
never existed.

Parse `--json` and sum `input_tokens` across the `turn.completed` events
instead. This server does, and reports input, cached and billed separately on
every call.

Two more traps in `codex-cli 0.154.0-alpha.6.2`. `-c 'plugins."x".enabled=false'`
is accepted, even under `--strict-config`, and silently does nothing —
`--ignore-user-config` is the only isolation that works. And `model_reasoning_effort`
is *not* ignored in `exec`, whatever the input token counts suggest: low and high
are identical on input because effort is a request parameter rather than prompt
text.

## Cost

About 8,000 to 12,000 billed tokens an image, out of roughly 50,000 to 75,000
aggregate input, most of which comes back as a cache hit. That is subscription
quota, not dollars.

There is no lighter route on a subscription. `codex exec` always runs the full
agent, and Codex CLI has no command that calls `image_gen` on its own. If you
want cheap single images and you have API billing, use `/v1/images/generations`
directly and skip all of this.

## What it will not do

`gpt-image-2` cannot produce transparent backgrounds. True transparency needs
`gpt-image-1.5` through the paid API. Ask for a flat uniform background and key
it out afterwards with the `remove_chroma_key.py` that ships inside Codex.

It is also the wrong tool for icons and logotype. Draw those as SVG.

## Configuration

| variable | default |
|---|---|
| `CODEX_BIN` | `/Applications/ChatGPT.app/Contents/Resources/codex` |
| `CODEX_HOME` | `~/.codex` |
| `CODEX_IMAGE_MODEL` | `gpt-5.6-sol` (the agent, not the image model) |
| `CODEX_IMAGE_TIMEOUT_MS` | `300000` |

macOS only, because the Codex binary lives inside the Mac app.

## Licence

MIT.