io.github.pvliesdonk/image-generation-mcp
Generates images using Google Gemini models like gemini-2.5-flash-image and gemini-3.x previews.
Generates images using OpenAI models such as gpt-image-1.5, gpt-image-1, and dall-e-3.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@io.github.pvliesdonk/image-generation-mcpGenerate a sci-fi cityscape at night, 16:9."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Image Generation MCP
Multi-provider image generation MCP server built on FastMCP. Generate images from Claude Desktop, Claude Code, or any MCP client using OpenAI, Google Gemini, Stable Diffusion (SD WebUI), or a zero-cost placeholder provider.
Documentation | Config wizard | PyPI | Docker
Features
Multi-provider: OpenAI (
gpt-image-2,gpt-image-1.5,dall-e-3), Google Gemini (gemini-3.1-flash-image,gemini-3-pro-image,gemini-3.1-flash-lite-image), SD WebUI (Stable Diffusion / Forge / reForge), and a zero-cost placeholder for testing.Per-model style metadata: every model carries a
style_profile(strengths, prompt grammar, lifecycle);list_providersincludes a top-levelwarningsarray for deprecated models. See Model Catalog.Keyword-based auto-selection:
provider="auto"routes by prompt content (text/logo → OpenAI, photoreal/anime → SD WebUI, draft → placeholder).CDN-style image transforms:
image://{id}/view?format=webp&width=512&crop_x=...resizes / re-encodes / crops on demand without re-generating.Hybrid background tasks: long-running SD generations run with
task=True(poll for status); short OpenAI calls stream progress in the foreground.MCP Apps gallery + viewer: interactive UI surfaces (browse generated images, edit / crop / rotate) for clients that support
app:resources.Production deployment: Docker (multi-arch),
.deb/.rpmwith hardened systemd, OIDC + bearer auth, persistent EventStore for HTTP session resumability.
Related MCP server: NanoBanana MCP
What you can do with it
With this server mounted in an MCP client, you can ask:
"Generate a coffee mug product photo on a worn oak table, 16:9, no text." Routes to
gpt-image-1.5for typography-aware photorealism."Create three concept-art variations of a cyberpunk alley at dusk." Composes
generate_imagewithprovider="sd_webui"and a stylised checkpoint likedreamshaperXL."Crop this image to a 1:1 square centred on the subject and resize to 512px." Uses
image://{id}/view?width=512&height=512&crop_x=...resource transforms."Show me my recent generations." Browses the gallery via the
image://listresource and the MCP Apps gallery viewer."Save this style as 'cyberpunk-night' so I can apply it to future requests." Uses the style library, whose markdown briefs the LLM interprets per-provider.
"Replace the background of my last photo with a sunset sky." Uses
transform_imagewith the galleryimage_idas a reference (image-to-image via Gemini).
Installation
From PyPI
pip install image-generation-mcpIf you add optional extras via the PROJECT-EXTRAS-START / PROJECT-EXTRAS-END sentinels in pyproject.toml, document them below:
Extra | Includes | Use when |
|
| Background-task support ( |
|
| Enables the OpenAI provider. |
|
| Enables the Gemini provider. |
|
| Everything except SD WebUI (which is HTTP-only, no extra needed). |
Example: pip install image-generation-mcp[all].
From source
git clone https://github.com/pvliesdonk/image-generation-mcp.git
cd image-generation-mcp
uv sync --all-extras --all-groupsDocker
docker pull ghcr.io/pvliesdonk/image-generation-mcp:latestA compose.yml ships at the repo root as a starting point. Copy .env.example to .env, edit, and docker compose up -d.
To attach a remote Python debugger (development only; the protocol is unauthenticated), see Remote debugging.
Linux packages (.deb / .rpm)
Download .deb or .rpm packages from the GitHub Releases page. Both install a hardened systemd unit; env configuration is sourced from /etc/image-generation-mcp/env (copy from the shipped /etc/image-generation-mcp/env.example).
Claude Desktop (.mcpb bundle)
Download the .mcpb bundle from the GitHub Releases page and double-click to install, or run:
mcpb install image-generation-mcp-<version>.mcpbClaude Desktop prompts for required env vars via a GUI wizard, with no manual JSON editing needed.
For manual Claude Desktop configuration and setup options, see Claude Desktop deployment.
Quick start
image-generation-mcp serve # stdio transport
image-generation-mcp serve --transport http --port 8000 # streamable HTTPFor library usage (embedding the domain logic without the MCP transport), import from the image_generation_mcp package directly. See the project's domain modules under src/image_generation_mcp/ for entry points.
Server info
The server registers a built-in get_server_info tool (via fastmcp_pvl_core.register_server_info_tool) so operators can confirm the deployed version with a single MCP call. The default response carries server_name, server_version, and core_version. Servers that talk to a remote upstream wire upstream version reporting inside the DOMAIN-UPSTREAM-START / DOMAIN-UPSTREAM-END sentinel in src/image_generation_mcp/server.py; see CLAUDE.md for the wiring pattern.
Configuration
Core environment variables shared across all fastmcp-pvl-core-based services:
Variable | Default | Description |
|
| Log level for FastMCP internals and app loggers ( |
|
| Set to |
|
| Persistent-state backend URL for pvl-core subsystems: |
Domain-specific variables go below under Domain configuration.
Authentication
Callers authenticate via a bearer token or OIDC (mutually exclusive). See the Authentication guide for setup, mapped multi-subject tokens, OIDC, and troubleshooting.
Post-scaffold checklist
After copier copy and gh repo create --push:
Fill in the DOMAIN blocks (every section marked with a
DOMAINsentinel comment) in this README and inCLAUDE.md.Configure GitHub secrets (see below).
Install dev + docs tooling:
uv sync --all-extras --all-groups.Install pre-commit hooks:
uv run pre-commit install.Run the gate locally:
uv run pytest -x -q && uv run ruff check --fix . && uv run ruff format . && uv run mypy src/ tests/.Push the first commit. CI should be green.
GitHub secrets
CI workflows reference three repository secrets. Configure them via Settings → Secrets and variables → Actions or with gh secret set:
Secret | Used by | How to generate |
|
| Fine-grained PAT at https://github.com/settings/personal-access-tokens/new with |
|
| https://codecov.io: sign in with GitHub and add the repo. The upload token is on the repo settings page. |
|
| Run |
gh secret set RELEASE_TOKEN
gh secret set CODECOV_TOKEN
gh secret set CLAUDE_CODE_OAUTH_TOKENGITHUB_TOKEN is auto-provided; no action needed.
Local development
The PR gate (matches CI):
uv run pytest -x -q # tests
uv run ruff check --fix . && uv run ruff format . # lint + format
uv run mypy src/ tests/ # type-checkPre-commit runs a subset of the gate on each commit; see .pre-commit-config.yaml for details, or CLAUDE.md for the full Hard PR Acceptance Gates.
Troubleshooting
Moving a scaffolded project
uv sync creates .venv/bin/* scripts with absolute shebangs pointing at the venv Python. If you move the repo after scaffolding (mv /old/path /new/path), uv run pytest fails with ModuleNotFoundError: No module named 'fastmcp' because the stale shebang resolves to a different interpreter than the venv's site-packages.
Fix:
rm -rf .venv
uv sync --all-extras --all-groupsuv run python -m pytest also works as a one-shot workaround (bypasses the stale entry-script shim).
uv.lock refresh after copier update
When copier update introduces new dependencies (such as a new extra added to pyproject.toml.jinja), CI runs uv sync --frozen which fails against a stale lockfile. Run uv lock locally and commit the refreshed uv.lock alongside accepting the copier-update PR.
Links
Domain configuration
All domain environment variables use the IMAGE_GENERATION_MCP_ prefix.
Core
Variable | Default | Required | Description |
|
| No | Directory for saved generated images. |
|
| No | Hide write-tagged tools ( |
|
| No | Default provider: |
Providers
Variable | Default | Required | Description |
| (none) | No | OpenAI API key; enables OpenAI provider when set. |
| (none) | No | Google API key with Gemini access; enables Gemini provider when set. |
| (none) | No | SD WebUI URL ( |
| (none) | No | SD WebUI checkpoint name for preset detection and override. Deprecated alias: |
Authentication
Variable | Default | Required | Description |
| (none) | No | Static bearer token; enables bearer auth when set. |
| (none) | No | Public base URL for OIDC and the capability-link transfer routes ( |
| (none) | No | OIDC discovery endpoint URL. |
| (none) | No | OIDC client ID. |
| (none) | No | OIDC client secret. |
| ephemeral | Yes on Linux/Docker | JWT signing key. |
| (none) | No | Expected JWT audience claim. |
|
| No | Comma-separated required scopes. |
|
| No | Verify access token as JWT instead of id token. |
Cost control & performance
Variable | Default | Required | Description |
|
| No | Comma-separated paid provider names. Triggers an elicitation cost-confirmation on capable clients. Gemini is omitted by default (generous free tier); add |
|
| No | Max cached transforms. Set to |
Reference image input (transform_image)
Variable | Default | Required | Description |
|
| No | Enable local filesystem paths as |
|
| No | Per-reference maximum byte size for input images (default 20 MiB). |
|
| No | HTTP fetch timeout in seconds, used when fetching remote image URLs. |
Capability-link transfer (HTTP downloads/uploads)
The create_download_link / create_upload_link tools and the /transfer/{token} route register only on an HTTP or SSE transport with BASE_URL set, and store link tokens in IMAGE_GENERATION_MCP_KV_STORE_URL. The knobs below tune link lifetime and upload limits.
Variable | Default | Required | Description |
|
| No | Link lifetime (seconds) when the caller omits |
|
| No | Ceiling (seconds); a caller-requested |
|
| No | Post-success grace window (seconds) for a stalled transfer to retry. |
|
| No | Reclaim window (seconds) for an in-flight reservation from a crashed handler. |
|
| No | Per-upload size cap in bytes for |
Server identity
Variable | Default | Required | Description |
|
| No | Server name shown to MCP clients. |
| (computed) | No | System instructions for LLM context. |
|
| No | HTTP endpoint mount path. |
| (auto) | No | MCP Apps widget sandbox domain. Auto-computed from |
Domain-config fields are composed inside src/image_generation_mcp/config.py between the CONFIG-FIELDS-START / CONFIG-FIELDS-END sentinels; env reads go through fastmcp_pvl_core.env(_ENV_PREFIX, "SUFFIX", default) so naming stays consistent.
For the full MCP tool / resource / prompt surface and per-provider setup notes, see the documentation site.
Key design decisions
Multi-provider with capability discovery, not feature flags. Each provider's
discover_capabilities()reports its actual supported aspect ratios / qualities / formats / negative-prompt support at startup; routing logic asks the capability surface, not a hard-coded enum. New providers slot in by satisfying the protocol, with no router edits needed. (Seedocs/decisions/0001-…,0002-…,0007-….)Per-model
style_profilemetadata, surfaced vialist_providers. Closed-list providers (OpenAI, Gemini, placeholder) use exact-key lookup; SD WebUI uses a regex-ordered pattern table. Profiles include lifecycle flags (current/legacy/deprecated) and feed an auto-built top-levelwarningsarray. (Seedocs/decisions/0009-….)Hybrid background tasks. Short calls (OpenAI ~5 s) stream progress in-line; long calls (SD WebUI 30-180 s) run as background tasks with
check_generation_statuspolling; clients pick the mode viatask=True. (Seedocs/decisions/0005-….)Image asset model: content-addressed registry + sidecar JSON metadata + on-demand transforms. Generated images keep their full-resolution original;
image://{id}/view?format=webp&width=512&crop_x=…resources do format conversion / resize / crop on demand without re-generating. Transforms are cached. (Seedocs/decisions/0006-….)Style library. User-saved markdown briefs (with YAML frontmatter for tags / aspect ratio / quality) that the LLM interprets per-provider, not copy-pasted verbatim. Distinct from per-model
style_profile: style library is the brief;style_profiledescribes the model. (Seedocs/decisions/0008-…and0009-…for disambiguation.)Composes
fastmcp_pvl_core.ServerConfig, never inherits. Domain config goes betweenCONFIG-FIELDS-START/CONFIG-FIELDS-ENDsentinels; env reads route throughfastmcp_pvl_core.env(...)to keep prefix naming consistent.
This server cannot be installed
Maintenance
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/pvliesdonk/image-generation-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server