Siray Image MCP
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 MCPgenerate 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: WujieAI 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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| seed | No | ||
| size | No | ||
| model | No | ||
| prompt | Yes | ||
| out_dir | Yes | ||
| palette | Yes | ||
| tileable | No | ||
| overlay_text_color | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full burden for behavior, and it delivers: it discloses that the prompt is rewritten to enforce background-plate rules, that the saved file is locally measured for contrast/clutter/drift/edge seam, that the file is always kept because it is already paid for, and that a FAILED verdict is not an automatic retry. This gives the agent important externally invisible behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well structured and not wasteful: a one-line purpose, a prioritized STOP instruction block, then a plain-language behavior block, then a compact Args list. The all-caps/STOP stands out without being noise, and every sentence adds operational or behavioral value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (8 params, 4 required, no annotations), the description is complete enough: it explains all parameters, return values (saved path, measurements, PASS/FAILED verdict), failure handling, and important warnings. The presence of an output schema covers shape details, so the description fills the remaining contextual gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the Args section documents all 8 parameters with concrete examples and caveats: palette accepts an array or single string, seed gives reproducible output, tileable triggers seam measurement, out_dir is created if missing, size is exact dimensions, and model should be omitted by default. This fully compensates for the sparse schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence states a specific verb and resource: 'Generate a background plate that the project's UI can sit on top of.' The rest of the description scopes the tool further by mentioning background-plate discipline, avoiding text/logos/centre subject, and measuring contrast for overlay text, which clearly distinguishes it from a general image generator like generate_image.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The STOP block gives strong contextual guidance: read actual project colors before calling, pass them as palette, never invent palette from the prompt, derive overlay_text_color from UI text, avoid seedream models for non-square backdrops, and treat FAILED as a diagnostic rather than a retry trigger. It does not explicitly mention when to prefer generate_image instead, so it misses explicit exclusions/alternatives, but the usage context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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).
| Name | Required | Description | Default |
|---|---|---|---|
| seed | No | ||
| size | No | ||
| image | No | ||
| model | No | ||
| prompt | Yes | ||
| out_dir | Yes | ||
| aspect_ratio | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden and handles it well. It discloses side effects such as creating out_dir, model compatibility constraints, exact-size resizing behavior, seed reproducibility, and the return value of saved file paths.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with its core purpose and follows with a tight bulleted Args section. Every sentence adds operational value, and the length is justified by the complexity of seven parameters with conditional constraints.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a seven-parameter generation tool with no annotations, this is remarkably complete. It covers required inputs, optional customizations, model selection, image-to-image requirements, resizing behavior, and what the tool returns, leaving no critical gap for an agent to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must explain every parameter, and it does. Each parameter receives meaningful detail, including examples, defaults, conditional requirements, and interaction rules between image and model, and between size and aspect_ratio.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the action and target: 'Generate an image with Siray and save it into the current project.' It gives a specific verb and resource, but it does not explicitly distinguish itself from the sibling generate_backdrop tool, so it is clear without full sibling differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives strong parameter-level usage guidance: when to pass size, when to ignore aspect_ratio, and when an -i2i/-edit model is required. It references list_models() for the live model list, but it does not provide explicit when-to-use versus generate_backdrop guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the behavioral disclosure burden. It discloses that results are 'live from the API,' that a default is marked, and that ID suffixes encode whether an image input is required. These are useful operational details beyond the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two compact sentences with the core purpose front-loaded and the model ID convention provided as useful secondary context. Every sentence adds value and there is no filler or repetition of schema information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-argument listing tool with an output schema, the description adequately covers purpose, freshness, default marking, and ID semantics. It lacks an explicit connection to when to use it alongside the generation siblings, but the overall context is sufficient for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are zero parameters, so schema coverage is effectively 100% and the description has no parameter burden. The baseline for a zero-parameter tool is 4, and the description appropriately focuses on output behavior rather than arguments.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource: 'List Siray's active image models.' It clearly identifies a read-only catalog operation and distinguishes itself from the generate_* siblings by describing an informational listing rather than an image-generation action.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The usage is implied: an agent would call this tool when it needs to discover available model IDs or check the active/default model. However, the description does not explicitly say when to prefer list_models over generate_image or generate_backdrop, nor does it describe a discovery-before-generation workflow.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
3 tool updates
v0.1.0- First observed
generate_backdrop - First observed
generate_image - First observed
list_models
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.
Generate images with any major model — one API key, one prepaid balance, one MCP.
OCR, transcription, file extraction, and image generation for AI agents via MCP.
Generate on-brand images from your AI agent: design, edit, and render templates over MCP.
Related MCP Servers
- AlicenseAqualityAmaintenanceEnables 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.169MIT
- AlicenseBqualityDmaintenanceEnables AI image generation via MCP protocol, supporting dozens of models, customizable parameters, and multiple resolutions.37 npmISC
- AlicenseNot gradedqualityBmaintenanceEnables AI agents to generate professional storyboards and videos from scripts or creative descriptions via MCP-compatible clients.31 npmMIT
- AlicenseNot gradedqualityCmaintenanceEnables coding agents to generate AI images directly through MCP tools, handling payment via the x402 protocol with USDC on Base and no API keys.MIT