Skip to main content
Glama

Image MCP Server

Production MCP server for image generation, editing, and local background removal. Cursor connects over a public HTTPS URL. Cursor does not send an API key, Bearer token, OAuth login, or password.

The Kie AI key stays on the server in .env.

What this is

A FastAPI process that exposes:

  • Streamable HTTP MCP at /mcp

  • GET /, GET /health, GET /health/ready

  • GET /files/{filename} for generated assets

MCP tools:

  • generate_image — Kie AI text-to-image with automatic model fallback

  • edit_image — Kie AI Seedream V4 Edit

  • remove_background — local rembg + birefnet-general-lite (no Kie call)

Related MCP server: Photo AI Studio MCP Server

Architecture

Cursor
  → HTTPS
  → Cloudflare Tunnel
  → FastAPI / MCP (127.0.0.1:8000)
       ├── generate_image → Kie AI
       │     nano-banana-pro → gpt-image-2-text-to-image → other models by cost_rank
       ├── edit_image → bytedance/seedream-v4-edit
       └── remove_background → rembg / birefnet-general-lite (local ONNX)

Public MCP endpoint:

https://PUBLIC_DOMAIN/mcp

Capabilities

  • Nano Banana Pro first, then GPT Image 2, then automatic fallback

  • Results downloaded from Kie, converted to WebP, and re-hosted on /files

  • Local free background removal

  • Rate limits, concurrency semaphore, daily caps

  • SSRF protection on inbound image URLs

  • systemd + Cloudflare Tunnel installers for Ubuntu 22.04/24.04

Installation

On Ubuntu 22.04 or 24.04:

sudo bash install.sh

The installer:

  1. Installs Python 3.11+, venv, cloudflared

  2. Copies the app to /opt/image-mcp-server

  3. Creates system user image-mcp

  4. Installs dependencies

  5. Tries to preload birefnet-general-lite

  6. Enables image-mcp.service

  7. Checks http://127.0.0.1:8000/health

  8. Offers Cloudflare Quick Tunnel, Named Tunnel, or skip

If model preload fails because of network, installation still succeeds. The next process start retries the download.

Configure KIE_API_KEY

sudo nano /opt/image-mcp-server/.env

Set:

KIE_API_KEY=your_real_key

Restart:

sudo systemctl restart image-mcp

Never put this key in Cursor, in the MCP URL, or in git.

Quick Cloudflare Tunnel

Use this if you do not have a domain. The installer can start it, or:

sudo systemctl enable --now cloudflared-image-mcp
sudo bash /opt/image-mcp-server/get-mcp-url.sh

You get a URL like:

https://xxxxx.trycloudflare.com/mcp

Quick Tunnel URLs change after every cloudflared restart. After reboot or systemctl restart cloudflared-image-mcp, run get-mcp-url.sh again and update Cursor.

Also set:

PUBLIC_BASE_URL=https://xxxxx.trycloudflare.com

so /files links are absolute HTTPS URLs that Kie and Cursor can fetch.

Stable Cloudflare Tunnel

Recommended production setup:

Internet → mcp.example.com → Cloudflare Tunnel → 127.0.0.1:8000
sudo cloudflared tunnel login
sudo cloudflared tunnel create image-mcp
sudo cloudflared tunnel route dns image-mcp mcp.example.com

Copy and edit the example config. Do not hardcode a tunnel ID from this repo:

sudo mkdir -p /etc/cloudflared
sudo cp /opt/image-mcp-server/deploy/cloudflared-config.example.yml /etc/cloudflared/config.yml
sudo nano /etc/cloudflared/config.yml

Replace IMAGE_MCP_TUNNEL_ID and mcp.example.com, then:

sudo cloudflared tunnel run image-mcp

Or install Cloudflare's cloudflared systemd unit and enable it.

Then:

PUBLIC_BASE_URL=https://mcp.example.com
ENABLE_DNS_REBINDING_PROTECTION=true
MCP_ALLOWED_HOSTS=mcp.example.com,127.0.0.1,localhost
sudo systemctl restart image-mcp

Connect Cursor

No authentication from Cursor.

User MCP config (~/.cursor/mcp.json or Cursor Settings → MCP):

{
  "mcpServers": {
    "image-mcp": {
      "url": "https://mcp.example.com/mcp"
    }
  }
}

Authentication: none. Do not add headers, Bearer, API key, or OAuth.

After a Quick Tunnel restart, replace the URL with the new get-mcp-url.sh value.

MCP tools

Tool

When the model should call it

generate_image

Create / draw / generate a new image from text

edit_image

There is a source image and the user wants it changed

remove_background

Transparent background / cutout / remove background

The user does not pick Kie model IDs. The server does.

Model fallback

generate_image always starts with nano-banana-pro. If that attempt succeeds, it stops.

If Nano Banana Pro fails for a retryable reason (timeout, HTTP 429/5xx, task fail, empty result, overload), the server tries gpt-image-2-text-to-image, then the remaining enabled text-to-image models sorted by cost_rank in config/models.yaml:

nano-banana-pro
→ gpt-image-2-text-to-image
→ z-image
→ bytedance/seedream-v4-text-to-image
→ qwen3/pro-text-to-image
→ seedream/5-pro-text-to-image

Pinned models run first by priority. The rest use cost_rank. Kie public pricing changes; this repo does not invent live dollar prices.

Fallback does not continue on:

  • missing prompt

  • invalid Kie API key (401/403)

  • insufficient Kie credits (402)

  • fatal server configuration errors

Adapters translate the common MCP input (prompt, aspect_ratio, quality, output_format) into each model's real Kie payload. Edit uses only bytedance/seedream-v4-edit and is never used as a text-to-image fallback.

Kie Market API used here (docs.kie.ai):

  • POST /api/v1/jobs/createTask

  • GET /api/v1/jobs/recordInfo?taskId=

WebP output

Public /files URLs are WebP. Kie may return PNG or JPEG; the server converts them locally before hosting. Background removal keeps transparency in lossless WebP.

Background removal

Local only:

rembg + birefnet-general-lite + onnxruntime CPU

The rembg session is created once at startup and reused. BRIA RMBG is not the default and is not used.

Security

Public MCP has no Cursor credential, so the server enforces:

  • RATE_LIMIT_PER_MINUTE

  • MAX_CONCURRENT_GENERATIONS (asyncio.Semaphore)

  • MAX_GENERATIONS_PER_DAY

  • MAX_GENERATIONS_PER_IP_PER_DAY

Image URL fetch:

  • HTTP/HTTPS only

  • blocks localhost, loopback, private IPv4/IPv6, link-local, metadata endpoints

  • re-validates redirect targets

  • checks magic bytes with Pillow, not the filename

/files/{filename} only serves UUID-style names from data/outputs. Path traversal is rejected.

KIE_API_KEY is never returned in MCP results, logs, or URLs.

Logs

JSON logs include request_id, tool, model, duration_ms, success, fallback, http_status, task_id.

They do not include the API key, Authorization headers, base64 bodies, or full prompts.

sudo journalctl -u image-mcp -f

Usage rows are stored in SQLite (METRICS_DB_PATH). There is no public billing dashboard.

Update

cd /path/to/this/repo
sudo rsync -a --exclude '.venv' --exclude '.env' --exclude 'data' ./ /opt/image-mcp-server/
sudo -u image-mcp /opt/image-mcp-server/.venv/bin/pip install -r /opt/image-mcp-server/requirements.txt
sudo systemctl restart image-mcp
curl -fsS http://127.0.0.1:8000/health

Local development

Python 3.11+:

python -m venv .venv
.venv\Scripts\activate
pip install -r requirements.txt
copy .env.example .env
python -m pytest
uvicorn app.main:app --host 127.0.0.1 --port 8000

Health: http://127.0.0.1:8000/health

A public Cloudflare URL is not created in a local Windows checkout. After Ubuntu install, run:

sudo bash /opt/image-mcp-server/get-mcp-url.sh

Troubleshooting

Symptom

What to check

/health fails

sudo systemctl status image-mcp and journal logs

Cursor cannot connect

Confirm HTTPS /mcp, Cloudflare is up, get-mcp-url.sh

421 from MCP

Hostname not allowed; set MCP_ALLOWED_HOSTS or keep DNS rebinding off for Quick Tunnel

generate_image says key missing

KIE_API_KEY in /opt/image-mcp-server/.env, then restart

402 / insufficient credits

Top up Kie; fallback will not help

remove_background not ready

First-time ONNX download; check disk and network, restart service

edit from base64 fails

PUBLIC_BASE_URL must be a URL Kie can fetch

Files 404 after a few days

OUTPUT_TTL_HOURS cleanup (default 72h)

Uninstall:

sudo bash uninstall.sh
sudo bash uninstall.sh --purge

License notes

Application code is provided for this project. Third-party licenses are listed in LICENSES.md. BiRefNet code is MIT; confirm current weight terms before commercial deployment.

Related MCP Connectors

Related MCP Servers