Pixio-MCP
This server provides a complete MCP interface to 550+ Pixio generative AI models (text-to-image, image-to-video, text-to-video, video-to-video, lipsync, text-to-audio), with built-in spend guardrails and full job lifecycle management. Key capabilities:
Discover Models (
list_models): Browse and filter Pixio's catalog by type or keyword, with pagination support.Inspect Model Schemas (
get_model_params): Fetch live input parameter schemas — required fields, types, defaults, allowed values — pulled at call time so new models are supported the day they ship.Estimate Costs (
estimate_cost): Price a job in credits before spending anything.Upload Media (
upload_media): Convert local files or remote URLs into permanent Pixio-hosted public URLs required by media-consuming models.Run Generations (
generate): Submit jobs with automatic spend guardrails (per-job cap viaPIXIO_MAX_CREDITS_PER_JOB, cumulative session budget viaPIXIO_SESSION_BUDGET, and explicitconfirm=truefor jobs exceeding caps), with optional polling until completion.Check Job Status (
get_generation): Snapshot a generation's current status and output URLs.Resume/Wait for Jobs (
wait_for_generation): Block-poll any in-flight or timed-out job until it succeeds or fails — jobs are never lost on timeout.Download Outputs (
download_output): Save completed generation files to local disk.Check Credit Balance (
get_credits): View current balance and recent spend/top-up history.
It integrates with Claude Desktop, LM Studio, Cursor, Continue, Zed, and custom agents via Python SDK, supporting stdio, streamable-http, and SSE transports. A 9-code error taxonomy enables structured, programmatic error handling.
Stores uploaded media and generated outputs on DigitalOcean Spaces, providing permanent public URLs for use in media generation.
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., "@Pixio-MCPgenerate an image of a sunset over mountains"
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.
⚡ pixio-mcp ⚡
554+ generative models. One MCP server. Zero chances to nuke your credit balance.
Prompt in. File on disk. Four tool calls. Every model Pixio ships — the day it ships.
🔥 What is this
pixio-mcp hands any MCP client — Claude Desktop, Claude Code, or your own agent swarm — the entire Pixio media generation arsenal: text-to-image, image-to-video, text-to-video, video-to-video, lipsync, text-to-audio, and a stack of utility ops. All of it metered in credits, all of it behind guardrails that make it safe to hand the keys to a fully autonomous agent and walk away.
discover → inspect schema → price it → generate → poll → download. done. 💅The cheat code: this server hardcodes zero model knowledge. Every parameter schema is pulled live from the API at call time. Pixio drops 50 new models tomorrow? They work here tomorrow. No update. No redeploy. No waiting on anybody.
Related MCP server: universal-image-mcp
🧨 Why it goes hard
The old way | The | |
Coverage | Hand-rolled HTTP for a handful of models | All 554+ models, discovery-driven |
New models | Wait for someone to update the wrapper | Day-zero support, automatically |
Spend control | Vibes 💸 | Two hard caps + estimate-before-spend |
Long video jobs | Hang or lose the job | Resumable ids — timeout ≠ dead job |
Local files | Figure out uploads yourself |
|
Errors | A stack trace and a prayer | 9-code machine-actionable taxonomy |
Battle-tested: 121 offline tests, two full multi-agent validation rounds (security audit, adversarial review, live protocol checks), and a real end-to-end run — prompt → generated image → verified bytes on disk.
🚀 Quick start
You need: Python 3.11+, uv, and a Pixio API key (pxio_live_...).
git clone https://github.com/RealDealCPA-VR/Pixio-MCP.git
cd Pixio-MCP
uv sync# PowerShell — fire it up (stdio transport; it waits for an MCP client)
$env:PIXIO_API_KEY = "pxio_live_..."
uv run pixio-mcp# bash / zsh — same thing
export PIXIO_API_KEY="pxio_live_..."
uv run pixio-mcpYou'll almost never run it by hand — register it with your client (next section) and let your agent cook. 👨🍳 No key set? The server still boots (warning on stderr) and every tool politely returns an AUTH error until you feed it one.
🔌 Plug it in
🌍 Any MCP host
One JSON shape rules them all:
{
"mcpServers": {
"pixio": {
"command": "uv",
"args": ["run", "--directory", "<path-to-repo>", "pixio-mcp"],
"env": { "PIXIO_API_KEY": "pxio_live_..." }
}
}
}This exact block works in Claude Desktop, LM Studio (~/.lmstudio/mcp.json), Cursor (.cursor/mcp.json), Windsurf, Cline (cline_mcp_settings.json), and LibreChat (librechat.yaml, mcpServers section). Swap <path-to-repo> for wherever you cloned this — and once pixio-mcp hits PyPI, swap the whole command for "command": "uvx", "args": ["pixio-mcp"].
Claude Desktop
Drop the block above into %APPDATA%\Claude\claude_desktop_config.json (Windows) or ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) under mcpServers, restart Claude Desktop. Done.
Claude Code
One-liner. That's it. That's the setup.
# <path-to-repo> = your clone, e.g. C:\Users\you\projects\Pixio-MCP
claude mcp add pixio -e PIXIO_API_KEY=pxio_live_... -- uv run --directory <path-to-repo> pixio-mcp
# Published package
claude mcp add pixio -e PIXIO_API_KEY=pxio_live_... -- uvx pixio-mcpOr drop the same JSON block into your project's .mcp.json.
Continue
In config.yaml, add a stdio entry under mcpServers:
mcpServers:
- name: pixio
command: uv
args: ["run", "--directory", "<path-to-repo>", "pixio-mcp"]
env:
PIXIO_API_KEY: pxio_live_...Zed
In settings.json, under context_servers:
{
"context_servers": {
"pixio": {
"command": {
"path": "uv",
"args": ["run", "--directory", "<path-to-repo>", "pixio-mcp"],
"env": { "PIXIO_API_KEY": "pxio_live_..." }
}
}
}
}Open WebUI
Open WebUI speaks OpenAPI, not MCP — bridge with mcpo:
export PIXIO_API_KEY="pxio_live_..."
uvx mcpo --port 8000 --api-key <secret> -- uvx pixio-mcpThen add http://localhost:8000 as an OpenAPI tool server in Open WebUI (Settings → Tools), using <secret> as the bearer token.
🐍 Roll your own agent
No host at all? The vanilla mcp SDK gets you a working client in ~15 lines:
import asyncio
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
async def main() -> None:
server = StdioServerParameters(
command="uv",
args=["run", "--directory", "<path-to-repo>", "pixio-mcp"],
env={"PIXIO_API_KEY": "pxio_live_..."},
)
async with stdio_client(server) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
tools = await session.list_tools()
print([t.name for t in tools.tools])
result = await session.call_tool("list_models", {"query": "flux", "limit": 5})
print(result.content[0].text)
asyncio.run(main())🏠 Built for local models too
This server isn't just tuned for frontier models — it's deliberately friendly to a 7B running on your laptop:
Self-describing schemas. Every tool parameter carries its own description in the MCP schema — small models don't have to guess what
confirmoroffsetmean.Lenient inputs. String numbers, string bools,
paramspassed as a JSON string, backtick-wrapped ids — all quietly normalized instead of rejected. Local models fumble formats; the server doesn't punish them for it.Compact by default.
list_modelsreturns 20 models per call unless you ask for more, and descriptions are truncated — a 554-model catalog never floods a small context window. Filter withtype/queryinstead of paging.HTTP transport built in. LM Studio, Ollama-backed hosts, or anything that prefers HTTP over stdio — see Transports below.
🎛️ Configuration
Everything tunes through env vars:
Env var | Required | Default | Purpose |
| yes | — | Bearer token ( |
| no |
| Override if the API moves off beta. Trailing slash / missing |
| no |
| Per-job credit cap. Estimates above this get refused without |
| no |
| Cumulative credit ceiling per server process. |
| no |
| Default wait for |
| no |
| Where |
| no |
| Logs go to stderr as JSON lines (stdout carries the MCP protocol). |
| no |
|
|
| no |
| Bind address for the HTTP transports. |
| no |
| Bind port for the HTTP transports. |
Fat-finger an integer (PIXIO_SESSION_BUDGET=lots)? The server refuses to boot — one clean stderr line naming the exact variable, no traceback. No silent misconfigs.
🚦 Transports
Default is stdio — the classic spawn-me-as-a-subprocess mode every desktop host uses. For hosts that talk HTTP instead (web UIs, remote agents, LM Studio-style local stacks), flip one env var:
export PIXIO_TRANSPORT=streamable-http # or "sse" for legacy SSE hosts
uv run pixio-mcp # serves on http://127.0.0.1:8000⚠️ SECURITY: this server holds a spending API key. Anyone who can reach the port can burn your credits. Keep it bound to 127.0.0.1 (the default) — if you must expose it beyond localhost via PIXIO_HOST, put it behind a reverse proxy with auth, a firewall rule, or a VPN. Never bind 0.0.0.0 on an untrusted network.
🧰 The toolkit — 9 tools, full lifecycle
Tool | What it does | Key inputs |
| Filterable catalog of all 554+ models (cached 10 min). Id, name, type, per-run credits, company, description. |
|
| The exact live input schema for one model — names, types, required flags, defaults, allowed |
|
| Price the job before a single credit moves. Falls back to catalog cost if the estimate endpoint flakes. |
|
| Local file or remote URL → permanent public Pixio URL ( |
|
| The main event: rejects local paths, estimates, enforces caps, submits, waits for the result. |
|
| One-shot status + output URLs. |
|
| Poll to |
|
| Every output file of a succeeded job → your disk. Returns absolute paths. |
|
| Balance breakdown ( |
|
Every tool returns clean JSON. Failures come back as structured error dicts (see taxonomy) — tools never throw raw exceptions at your agent.
🎯 The three-call contract
The server ships knowing nothing about any model. Your LLM discovers everything at runtime:
list_models— find the weapon 🎯get_model_params— read the manual 📖generate— send it 🚀
Add download_output and a text prompt becomes a file on your machine in four calls flat:
>>> list_models(type="text-to-image", query="flux")
{
"models": [
{"id": "pixio/flux-1/schnell", "name": "FLUX.1 Schnell", "type": "text-to-image",
"credits": 1, "company": "Black Forest Labs", "description": "Fast text-to-image..."},
...
],
"total_matching": 6, "returned": 6, "offset": 0
}
>>> get_model_params(model_id="pixio/flux-1/schnell")
{
"model": {"id": "pixio/flux-1/schnell", ...},
"params": [
{"name": "prompt", "type": "string", "label": "Prompt", "required": true, "defaultValue": ""},
{"name": "image_size", "type": "select", "label": "Image size", "required": false,
"defaultValue": "landscape_4_3",
"options": [{"value": "square_hd", "label": "Square HD"},
{"value": "landscape_4_3", "label": "Landscape 4:3"}, ...]}
]
}
>>> generate(model_id="pixio/flux-1/schnell",
params={"prompt": "a crimson arc reactor on black velvet, studio lighting",
"image_size": "square_hd"})
{
"generation_id": "b7e2f9c1-4a06-4d2e-9c1e-0f3a7d5e8b21",
"status": "succeeded",
"output_urls": ["https://pixiomedia.nyc3.digitaloceanspaces.com/outputs/...png?X-Amz-Expires=3600&..."],
"outputs": {"imageUrl": "https://pixiomedia.nyc3.digitaloceanspaces.com/outputs/...png?..."},
"model_id": "pixio/flux-1/schnell",
"credits_spent": 1,
"remaining_balance": 999,
"elapsed_s": 6.4,
"error": null
}
>>> download_output(generation_id="b7e2f9c1-4a06-4d2e-9c1e-0f3a7d5e8b21")
{
"generation_id": "b7e2f9c1-4a06-4d2e-9c1e-0f3a7d5e8b21",
"files": ["~/pixio-outputs/b7e2f9c1-0.png"],
"dest_dir": "~/pixio-outputs"
}Models that eat media (image-to-video, lipsync, ...)? upload_media first, pass the returned URL in params. generate is URLs-only and swats local paths before a single credit is spent.
🛡️ Spend safety (the flex)
This is the part that lets you point an autonomous agent at a credit balance and sleep at night. All guardrails are server-side and on by default:
💰 Estimate before spend. Every job is priced first (estimate endpoint, catalog fallback). Nothing submits until the price is known — or explicitly flagged unknown via a
warning.🧱 Per-job cap (
PIXIO_MAX_CREDITS_PER_JOB, default 60). One job over the line →BUDGET_EXCEEDED. Denied.🏦 Session budget (
PIXIO_SESSION_BUDGET, default 300). Cumulative ceiling for the whole server process. The meter never lies.🔑 Explicit override only. A refusal tells you the estimate, which cap tripped, and the cap value — and only a re-call with
confirm=truegets through. The server never overrides itself.📊 Balance on every receipt. Every terminal result reports
credits_spent+remaining_balance. Spend drift has nowhere to hide.🚫 Zero auto-retry on submission.
POST /generatefires exactly once — a network blip can never double-spend you. (Reads and estimates retry 3x, because those are free.)
🚨 Error taxonomy
Failed tool calls return {"error": {"code": ..., "message": ..., "details": {...}}}. Nine codes, all machine-actionable:
⚠️ Telling failures apart from successes: successful job results also carry an
errorkey — it's the provider's failure reason,nullon success (see thegenerateexample above). Don't test"error" in result; test whetherresult["error"]is a dict with acode(failure envelope) vsnull/string (job-result field).
Code | Meaning | Your move |
| 401, or | Set a valid |
| 402 — balance can't cover the job. | Top up, or pick a cheaper model ( |
| Bad/missing param — or a local file path in | Re-read |
| The server's own guardrail said no (per-job cap or session budget). Nothing was spent. | If the estimate's acceptable, re-call with |
| 429 — account's in-flight limit reached. | Wait for in-flight jobs ( |
| Terminal | Read the reason, adjust, submit fresh (a retry spends credits again). |
| Wait window elapsed but the job is still cooking — not cancelled. |
|
| 404 — unknown model or generation id. | Check the id; discover real ones via |
| 5xx, network failure, or unparseable response. | Retry later — GETs/estimates already retried 3x with backoff before this surfaced. |
💀 Gotchas (learned so you don't have to)
Hard-won quirks of the live Pixio gateway. The server stays schema-agnostic and does not enforce these — your agent must respect them:
Select values are strings. Send
options[].valueexactly as given."5", not5. Even when it looks numeric. Especially when it looks numeric."Optional" is sometimes a lie. Some optional-with-default params get rejected when omitted. First attempt: send every param from
get_model_paramsat itsdefaultValue.Output URLs can die in ~1 hour.
outputUrlmay be signed with a short fuse.download_outputpromptly; never stash URLs for later. (upload_mediaURLs are the exception — permanent and public.)Concurrency is account-wide. 1 in-flight by default, 3 on Maker — across all your API keys. Parallel fan-outs will eat
CONCURRENCYerrors; serialize your jobs.There is no cancel button. Once submitted, a job runs to the end;
DELETE /generations/{id}isn't a thing. ATIMEOUT_PENDINGjob keeps holding a concurrency slot until it finishes — budgettimeout_saccordingly and resume, don't resubmit.No list-generations endpoint. The
generation_idfrom every submission is the only handle you get. Guard it with your life.
🧪 Development
uv sync
uv run pytest121 tests, fully offline — a mocked Pixio gateway, no API key, no network, zero credits harmed. 🌱
📜 License
MIT — go build something loud.
Built for agents. Guarded like a vault. Fresh models on day zero. ⚡
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
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/RealDealCPA-VR/Pixio-MCP'
If you have feedback or need assistance with the MCP directory API, please join our Discord server