The pain
Every blog post here now ships with an editorial cover — cartoon, 16:7, part of the robot-vacuum desk-scene series. Before this MCP, the flow looked like:
- Open a different tool: ChatGPT with image generation, Midjourney via Discord, web DALL·E, Leonardo, whatever. Each one with its own UI.
- Write the prompt from scratch. Each time, manually recall: what was the exact style of the last cover? Cartoon with which accents? Swiss-cartoon or just flat? Which character? — no history, no template you can hook into.
- Hit generate. Want variants — generate a few. Find one you like — download the PNG from the browser.
- Open Finder, drag the file into the project folder (
apps/blog/public/assets/posts/<slug>/). Or attach it in Claude Code and say "here's a cover, wire it up". - Claude copies it, updates the frontmatter, crops to 16:7 — if you have
sipsor ImageMagick locally. If not — yet another trip to another tool.
That's context-switching between two or three apps for a single image. And the bigger problem — you have to invent the style again every time, because ChatGPT/Midjourney doesn't remember between sessions that your blog has a cartoon series with a robot vacuum and a red accent at the bottom. You yourself are the only living memory of that style language.
I went looking for an existing MCP server that would work straight from Claude Code chat (no UI-switching, no manual file shuffling) and would also:
- generate + edit + crop in one package,
- be provider-agnostic (I want gpt-image-1.5 on OpenAI, sd3 on Stability, something on Replicate when the mood strikes),
- not hardcode a model enum (because
gpt-image-1is gone,gpt-image-1.5exists, somegpt-image-2will appear tomorrow).
Nothing in the community fit. The ones I found were either OpenAI-only with stale enums, or missing edits, or missing crop. So I built one.
What I open-sourced
imagegen-mcp — github.com/acrossoffwest/imagegen-mcp. MIT, TS + @modelcontextprotocol/sdk. Four tools:
generate_image— text-to-image. The model is just a string, no enum hardcode.edit_image— image edit / inpaint. Where a provider doesn't support it, the tool throwsnot_supported.list_image_models— query/v1/models(or a known list), filter to image-capable IDs.crop_image— sharp-based resize.cover/contain/fillmodes, any gravity.
Built-in providers:
- OpenAI native (gpt-image-1.5, dall-e-3, dall-e-2)
- OpenAI-compatible via a custom
baseUrl— handy for locally-hosted backends - Stability AI v2beta (
sd3,core,ultra) - Replicate (flux, sdxl, ideogram, and any
owner/name:version)
Config lives at ~/.config/imagegen-mcp/config.json. Per-provider env files:
{
"providers": {
"openai": {
"type": "openai",
"envFile": "~/.config/imagegen-mcp/openai.env",
"envVar": "OPENAI_API_KEY"
},
"local": {
"type": "openai",
"envFile": "~/.config/imagegen-mcp/local.env",
"envVar": "LOCAL_API_KEY",
"baseUrl": "http://localhost:8000/v1"
}
},
"defaultProvider": "openai",
"defaultModel": "gpt-image-1.5"
}Wire it into Claude Code:
claude mcp add imagegen -- npx -y tsx ~/projects/own-projects/imagegen-mcp/src/server.tsAfter a restart, mcp__imagegen__* tools show up inside Claude Code. That's the whole install.
What this changes for the blog flow
Before: open ChatGPT (or Midjourney via Discord), build a prompt from scratch by hand, mentally reconstruct what style the last cover had, hit generate, pick from variants, download the PNG into ~/Downloads, drag it into the project folder, and only then say in Claude Code "here, wire it up as a cover" — which would copy the file and update the frontmatter, but I'd still go cropping to 16:7 separately.
Now: in Claude Code chat, "generate a cover for the new post, keep the cartoon series" — and it:
- Calls
mcp__imagegen__generate_imagewith my standard prompt template, modelgpt-image-1.5, size1536x1024. - Follows up with
mcp__imagegen__crop_imagedown to 1536×672 (16:7), cover mode. - Writes
cover.pngtoapps/blog/public/assets/posts/<slug>/. - Updates frontmatter in both locales.
- If something looks off — re-generate with a tweaked prompt, never leaving the chat.
No UI switching, no dragging files between Finder and the project. And the bigger win — the style language for the series lives in docs/post-covers/ and in my blog-specific CLAUDE.md, so Claude itself proposes "continue the series" instead of me reciting the style from memory every single time. This post's cover got generated through the MCP while I was writing the text: "let's draw something fitting, keep the series" → done, in frontmatter, on disk, rendering locally.
Gotchas
gpt-image-1is gone,gpt-image-1.5is what you use. The originalgpt-image-1is no longer in production (existing projects getdoes not existfrom the API). Any third-party tool or MCP wrapper that hardcodesgpt-image-1will fail. Just putgpt-image-1.5everywhere.- dall-e-3 doesn't support edits. Text-to-image only. Edit/inpaint works on
gpt-image-1.5(and the legacydall-e-2). - No native 16:7 from any provider. gpt-image:
1024×1024 / 1024×1536 / 1536×1024. dall-e-3 adds1792×1024. Closest is1536×1024, thencrop_imageto 1536×672. - MCP-server enum hardcodes in popular wrappers. spartanz51's
imagegen-mcponly knowsgpt-image-1 / dall-e-3 / dall-e-2and dies ongpt-image-1.5. My version takes the model as a string — whatever you type goes straight to the API.
What I want to add
- Reference-image mode: for posts that have a source photo I want to pass it into
edit_imageas a reference instead of describing it in words. Already works ongpt-image-1.5through/v1/images/edits, but the tool-wrapper UX could be smoother. - Batch covers —
n: 4variants at once, pick visually. Right now defaults ton: 1, but the parameter does pass through. - Variations: dall-e-2's
/v1/images/variations— for "same scene, slightly different" iterations. Not inedit_imageyet, needs its own tool. - Spark imggen — my self-hosted Stable Diffusion on the home lab. The
openai-compatibleprovider type works via custom baseUrl in theory, still need to wire it up against the real backend.
If anyone wants the shape for their own cover pipeline — clone, edit the config, claude mcp add, done. A single ~/.config/imagegen-mcp/config.json file controls everything.
