Siray Image MCP
This MCP server lets AI agents generate project-ready images and backdrops via the Siray API, plus list available models.
generate_image: Create an image from a text prompt (optional model, size, aspect ratio, seed, reference image for i2i/edit models) and save it to a specified project folder.
generate_backdrop: Create a UI-safe background plate from a prompt, using a project's actual color palette and overlay text color; the result is locally graded (contrast, busyness, palette drift, seam) with a PASS/FAIL verdict.
list_models: Fetch the live catalog of Siray image models, with the default highlighted and t2i/i2i suffix meanings.
Click on "Deploy 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., "@Siray Image MCP generate a 1920x1080 hero image of a mountain landscape into public/images"
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.
Siray Image MCP
Image generation backed by the Siray API (Flux, Nano Banana, Seedream, GPT-Image, and 50+ other models behind one key), wired up two ways:
An MCP server — any MCP-capable AI agent (Claude Code, Codex, Antigravity, Cursor, Windsurf, VS Code, Claude Desktop, Gemini CLI...) can generate images and backdrops directly into your project.
A local web page —
uv run web.pyfor a prompt box, model picker and gallery.
Built for generating real project assets (hero images, icons, product shots, UI backdrops) without burning API credits on doomed or unusable generations — see Not wasting credits and Backdrops below.
Quickstart
git clone https://github.com/Paramrk/siray-image-mcp.git
cd siray-image-mcp
uv sync
cp .env.example .env # then paste your Siray key into it
uv run test_core.py # sanity check, no networkGet a key at siray.ai → console → API keys.
Related MCP server: ShotFlow MCP Server
Use from an AI agent
See INSTALL.md for the exact config for Claude Code, Codex, Antigravity,
Cursor, Windsurf, VS Code, Claude Desktop and Gemini CLI, plus the two mistakes that break
most pastes (a relative uv command GUI agents can't find; VS Code's config using
servers instead of mcpServers).
Once connected, the agent has three tools:
tool | for |
| any image, saved straight into your project |
| a background plate that won't clash with your UI — see Backdrops |
| the live model catalogue |
In any project, just ask: "generate a 1920x1080 hero image of X into public/images".
Backdrops
generate_backdrop requires palette and overlay_text_color — the agent has to read
your project's actual colours (CSS variables, tailwind config, theme file) and decide what
text goes on top before it can call this tool. That decision is what makes the backdrop
match the first time instead of costing a second generation.
The prompt is rewritten with background-plate rules (no text, no logos, no centre subject, calm negative space, tone forced opposite the overlay colour), then the saved file is graded locally — no API call:
measure | means | fails above/below |
| WCAG contrast against your overlay colour, on a 6×6 grid | below 4.5 |
| edge energy; clutter that fights overlaid text | above 12 |
| 0–100 distance of the image's dominant colours from your palette | above 30 |
| difference between opposing edges, only checked if | above 8 |
Calibrated against real generations: a purpose-built backdrop measured 7.13 / 2.0 / 7.6.
Ordinary images used as backdrops measured ~1.0 contrast and 25–39 drift. The thresholds
sit in that gap — they're judgement calls, tune them in backdrop.py.
A FAILED verdict never deletes the file and never auto-retries — it's already paid for,
so it's kept, and the report says exactly what to change if you regenerate.
Not wasting credits
core.preflight() refuses requests that are certain to fail or hang, before anything is
submitted — every rule below is something observed failing against the live API:
an unknown model id (the API answers
503) — suggests the closest real idsa
-t2imodel given a referenceimage, or an-i2imodel given nonesizeonbytedance/seedream-*, which accepts the parameter and then never finishesa malformed
sizestring, a bad palette hex, or a reference file that doesn't exist
Refusals return as REFUSED (nothing was generated, no credit spent): <what to change> in
under a second — both the MCP tools and the web UI surface the reason, not just "error",
because an opaque failure is what causes an agent to retry blindly and waste the credit
this exists to save.
Usage tracking
Siray's API has no credits/balance endpoint, so core.py keeps its own count: every
successful generation (refusals don't count — nothing was spent) increments a per-model
counter for the life of the server process. generate_image and generate_backdrop both
append a line to their output:
credits used this session — google/nano-banana-pro-t2i: 2, openai/gpt-image-2-t2i: 1 (total: 3)An MCP server process is started fresh per conversation, so "this session" is "this conversation". The counter resets when the server restarts — it's a running tally, not a persisted ledger.
Dimensions
Pass size="1920x1080" and you get exactly that, on any model — how it gets there differs
by family, handled automatically:
model family | what happens |
| rendered at that exact size by the API |
| nearest aspect ratio requested, then resized locally to your exact pixels |
| ignores size and aspect ratio entirely (always 2048²) — |
Security: no key reaches the browser or the agent's context
The Siray API key lives in .env (gitignored) and is read once, server-side, by
core._key(). Nothing else touches it:
Web UI: the browser only ever calls this project's own local server (
/generate,/models,/gallery).index.htmlnever talks toapi.siray.aiand contains no key, token, or Authorization header —web.pydoes that server-side, in Python, and returns only file paths and text back to the page.MCP server: the agent talks to
server.pyover a local stdio pipe — no network endpoint, no browser, nothing an agent's own context window or a webpage could read the key out of. The key never appears in a tool's input, output, or error text (checked: seecore.explain()and everyraiseincore.py— they carry paths and model ids, never headers or the key itself)..gitignoreexcludes.env,.venv/,output/,__pycache__/anduv.lock. Only.env.example(empty) is committed.
If you fork this and add a hosted deployment (not local), put the key behind your own backend the same way — never ship it in client-side JS.
Models
Ids end in -t2i (text-to-image) or -i2i / -edit / -ref2i (image-to-image, needs
image). Default is google/nano-banana-pro-t2i. A few worth knowing:
openai/gpt-image-2-t2i,openai/gpt-image-2.5-flare-t2i— exact sizes, ChatGPT's modelsblack-forest-labs/flux-1.1-pro-ultra-t2i— very high resolutionbytedance/seedream-4.5-t2i— square onlygoogle/nano-banana-pro-i2i— best for editing an existing image
list_models() (tool or core.list_models()) always reflects the live catalogue.
Local web UI
uv run web.py→ http://127.0.0.1:8765. Prompt box, live model picker, exact size, aspect ratio, seed,
optional reference image, and a gallery of everything in output/.
Testing
uv run test_core.pyNo network. Covers filename slugging, extension sniffing, size parsing, aspect snapping, preflight refusals, palette normalisation (agents send arrays, comma strings, and JSON strings — all three are accepted), contrast math, and the seedream size guard.
Project layout
file | purpose |
Siray API client: submit, poll, download, preflight | |
prompt composition + local image grading for backdrops | |
MCP server — the three tools above | |
local web UI | |
the test suite | |
per-agent connection config |
API notes (learned the hard way)
Async only:
POST /v1/images/generations/async→task_id, then pollGET .../async/{task_id}.statuscan flip toSUCCESSa beat beforeoutputsis populated — poll until both.On success,
fail_reason(confusingly) contains the image URL. Ignore it.Output URLs are
api.siray.ai/redirect/...; redirects are followed by hand incore._http_fetchbecause httpx's own follower choked on one.
Contributing
Issues and PRs welcome. Keep additions to the same shape: a rule in core.preflight() or
backdrop.py should trace back to something actually observed failing against the live
API, with a test in test_core.py.
License
Available Tools
3 toolsgenerate_backdropA
Generate a background plate that the project's UI can sit on top of.
STOP: before calling this, read the project's actual colours — the CSS custom
properties, tailwind.config, theme file, or an existing screenshot — and pass
them as palette. Do not guess them, and do not invent a palette from the
prompt. Whatever text or UI will sit on this backdrop determines
overlay_text_color. Getting these two right is what stops the backdrop from
clashing and needing a second paid generation.
The prompt is rewritten to enforce background-plate discipline (no text, no
logos, no centre subject, calm negative space, tone set opposite the overlay
colour), then the saved file is measured locally: worst-region contrast against
overlay_text_color, clutter, drift from palette, and edge seam if tileable.
The file is ALWAYS kept — it is already paid for. A FAILED verdict tells you exactly what to change if you choose to regenerate; it is not an automatic retry.
Args: prompt: The scene or texture, e.g. "soft abstract mesh gradient". out_dir: Absolute path to save into. Created if missing. palette: Hex colours from the project, e.g. ["#0f1115", "#6ea8fe"]. A single comma-separated string works too. overlay_text_color: Hex colour of the text/UI going on top, e.g. "#e7e9ee". size: Exact dimensions, e.g. "1920x1080". model: Omit for the default. Do not use bytedance/seedream-* for a non-square backdrop — it only renders 2048x2048. tileable: True for a repeating pattern; the edge seam is then measured. seed: Integer for reproducible output.
Returns the saved path, the measurements, and a PASS/FAILED verdict.
Inputs: prompt (required), out_dir (required), palette (required), overlay_text_color (required), +4 more. Returns: result
generate_imageA
Generate an image with Siray and save it into the current project.
Args: prompt: What to draw. Be specific about subject, style, lighting, background. out_dir: Absolute path of the folder to save into, e.g. the project's assets/images folder. Created if missing. model: Siray model id, e.g. "bytedance/seedream-4.5-t2i", "google/nano-banana-pro-t2i", "black-forest-labs/flux-1.1-pro-ultra-t2i". Omit for the default. Call list_models() for the live list. image: Optional reference image for image-to-image / editing — a URL or a local file path. When you pass this you MUST also pass an -i2i / -edit model (e.g. "google/nano-banana-pro-i2i"); -t2i models reject it. Note: bytedance/seedream-* ignores size and aspect ratio entirely. size: exact output dimensions, e.g. "1920x1080". Use this whenever the user names dimensions. openai/* models render at that size natively; for other models the nearest aspect ratio is requested and the file is resized to exactly this. aspect_ratio: e.g. "16:9", "1:1", "9:16". Ignore when passing size. seed: Integer for reproducible output.
Returns the saved file path(s).
Inputs: prompt (required), out_dir (required), seed, size, +3 more. Returns: result
list_modelsA
List Siray's active image models, live from the API. Default is marked.
Ids ending in -t2i are text-to-image; -i2i / -edit / -ref2i need an image.
Inputs: no named parameters. Returns: result
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 3 tools
The two generation tools are clearly separated by purpose: generate_image handles general image creation/editing, while generate_backdrop is a specialized, measurement-driven operation for background plates. list_models is entirely distinct, so an agent can confidently select the right tool by name and description.
All tool names follow the same verb_noun snake_case pattern: generate_image, generate_backdrop, and list_models. There are no mixed conventions, vague single-word names, or inconsistent prefixes.
Three tools is well-scoped for a narrow image-generation MCP: one general generation tool, one specialized backdrop tool, and one model discovery tool. Each tool earns its place, and the count is within the ideal range.
The server covers the core image-generation lifecycle: discovering available models, generating images from prompts, supporting image-to-image/editing via the image argument, and providing a dedicated backdrop workflow with built-in validation. There are no obvious dead ends or missing critical operations for an image generation domain.
Maintenance
Related MCP Connectors
Create images & video from any MCP agent — 17 models, spend limits, one URL.
Direct AI video, image, music and storyboard production from any MCP client.
AI video, image and audio generation with 140+ AI models from any MCP agent
Generate images with any major model — one API key, one prepaid balance, one MCP.
Related MCP Servers
- AlicenseAqualityBmaintenanceEnables AI image and video generation using Midjourney through the AceDataCloud API. It supports comprehensive features including image creation, transformation, blending, editing, and video generation directly within MCP-compatible clients.16605 PyPI18MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI agents to generate professional storyboards and videos from scripts or creative descriptions via MCP-compatible clients.34 npmMIT

@callirra/mcpofficial
AlicenseCqualityAmaintenanceEnables MCP-compatible agents to discover models, generate images and videos, use Prompt Studio, upload references, poll tasks, and check balances via the Callirra API.70619 npm1MIT- AlicenseNot gradedqualityBmaintenanceEnables AI agents to generate and manage bulk AI images locally through the app's engine, including batches, reference images, LoRAs, upscaling, and OpenAI-compatible API operations. It connects MCP clients such as Claude Code, Codex, Antigravity, and Hermes to a self-hosted Windows image-generation workflow without cloud accounts.MIT