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. ⚡
Available Tools
9 toolsdownload_outputA
Download every output file of a succeeded generation to a local directory.
Call this after generate(wait=true) or wait_for_generation reports
status succeeded. Output URLs may be signed and expire (~1 hour), so
download promptly. If the generation is still processing this returns a
VALIDATION error — call wait_for_generation(generation_id) first and
retry once it succeeds. Any non-succeeded status (including failed)
returns a VALIDATION error stating the current status; for a failed
generation the provider's reason is included in the details.
Args:
generation_id: The id returned by generate.
dest_dir: Target directory, created if missing (~ is expanded).
Defaults to the server's configured download directory
(PIXIO_DOWNLOAD_DIR, default ~/pixio-outputs).
Returns:
{"generation_id": str, "files": [absolute file paths], "dest_dir": str}
— files are named {generation_id[:8]}-{index}{ext} (id prefix
sanitized to filesystem-safe characters) with the extension inferred
from each URL or the downloaded content.
| Name | Required | Description | Default |
|---|---|---|---|
| dest_dir | No | ||
| generation_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description carries full burden. It discloses that output URLs may be signed and expire, behavior for error states (processing vs failed), that dest_dir is created if missing, ~ expansion, default directory, and file naming convention. Comprehensive behavioral disclosure.
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?
Description is multi-paragraph but well-structured: starts with main purpose, then usage instructions, then parameter details, then return value. Every sentence provides value. No fluff.
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 output schema exists (context: true), description explains return format with example and file naming convention. It also provides enough context for an agent to use correctly with siblings. Complete for this tool's complexity.
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 describes parameters but without descriptions (coverage 0%). Description adds critical meaning: generation_id is 'id returned by generate', dest_dir is 'Target directory, created if missing (~ expanded), defaults to server's configured download directory'. Fully compensates for lack of schema descriptions.
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 states the tool downloads every output file of a succeeded generation. It specifies the verb 'download', resource 'output files', and context 'after generation succeeds', distinguishing it from siblings like generate, wait_for_generation, etc.
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?
Explicitly states when to use: after generate(wait=true) or wait_for_generation reports succeeded. Provides warnings about URL expiration (~1 hour) and explains error conditions (VALIDATION error if processing, failed status with details). Gives clear guidance on when not to use and what alternatives to use (wait_for_generation).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
estimate_costA
Estimate the credit cost of a generation BEFORE spending anything.
Call this after get_model_params and before generate (the three-call contract is list_models -> get_model_params -> generate; this tool is the recommended pre-flight between steps 2 and 3). Costs come from the gateway estimate endpoint when available ("source": "estimate"), else from the catalog-listed per-generation cost ("source": "catalog"), else the cost is reported as unknown.
Args: model_id: Catalog model id, e.g. "pixio/flux-1/schnell". params: The exact params object you intend to pass to generate(), built from the get_model_params response.
Returns: {"model_id": str, "estimated_credits": int | null, "source": "estimate" | "catalog" | "unknown"}, plus a "warning" string only when the cost could not be determined ("estimated_credits" is null and "source" is "unknown").
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes | ||
| model_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description carries full burden. Details cost determination logic, return structure, and warning conditions. Lacks some side-effect info, but as a read-only estimation tool, this is sufficient.
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?
Well-structured with paragraphs and bullet points. Front-loaded with purpose. Every sentence adds value, though slightly verbose in cost source enumeration.
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 no output schema and low schema coverage, description thoroughly explains return format, three cost sources, and warning conditions. Covers workflow context and parameter details completely.
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 coverage is 0%, but description provides clear explanations: model_id with example, params as the intended generate object. This adds significant meaning beyond the bare 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?
Clearly states the tool estimates credit cost before spending. Positions it in a workflow between get_model_params and generate, distinguishing it from siblings like generate and list_models.
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?
Explicitly says to call after get_model_params and before generate, referencing the three-call contract. Explains cost source hierarchy (estimate > catalog > unknown) and when warning appears.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
generateA
Run a media generation job on Pixio, with spend guardrails.
This is the final step of the 3-call discovery contract:
list_models -> get_model_params -> generate. Build params
from the live get_model_params(model_id) response — this server
embeds no model schemas. On a first attempt send EVERY param the schema
lists, at its default value (some params marked optional are actually
required by the gateway), and send select-option values as STRINGS
(e.g. "5", not 5).
URLs-only contract: every media input inside params must be an
http(s) or data: URL. Any value that looks like a local filesystem path
(~, ./, ../, file://, X:\, UNC \\, or an
existing file) is rejected with a VALIDATION error naming the offending
field(s) — before any credits are spent. Call upload_media first and
pass the permanent URL it returns.
Spend guardrails: the job cost is estimated up front and refused with
BUDGET_EXCEEDED if it exceeds the per-job cap or would exceed the
session budget — no credits are spent on a refusal. Pass confirm=true
to explicitly override both caps for this one job.
Waiting: with wait=true (default) this call polls until the job is
terminal or timeout_s elapses (default: PIXIO_DEFAULT_TIMEOUT_S,
180s). On timeout you get a TIMEOUT_PENDING error whose details carry
the generation_id — the job KEEPS RUNNING server-side; resume with
wait_for_generation(generation_id). With wait=false the call
returns immediately (status "processing", plus estimated_credits);
check later with get_generation or wait_for_generation.
Output URLs may be signed and expire after roughly an hour — call
download_output(generation_id) promptly.
Args:
model_id: Pixio model id, e.g. "pixio/flux-1/schnell".
params: Generation inputs built from get_model_params (URLs only
for media fields).
wait: Poll to completion (True, default) or return immediately.
timeout_s: Max seconds to wait when wait=true; None uses the
server default.
confirm: Set True to override the per-job and session credit caps.
Returns:
On success: {"generation_id", "status", "output_urls", "outputs",
"model_id", "credits_spent", "remaining_balance", "elapsed_s",
"error"}. With wait=false: the same shape with status
"processing", credits_spent None, and estimated_credits
added. On failure: {"error": {"code", "message", "details"}} with
code VALIDATION, BUDGET_EXCEEDED, INSUFFICIENT_CREDITS, CONCURRENCY,
GENERATION_FAILED, TIMEOUT_PENDING, NOT_FOUND, AUTH, or
UPSTREAM_ERROR. NOTE: success results also contain an "error" key
(the provider reason, null on success) — a call failed only when
result["error"] is a dict carrying a "code".
| Name | Required | Description | Default |
|---|---|---|---|
| wait | No | ||
| params | Yes | ||
| confirm | No | ||
| model_id | Yes | ||
| timeout_s | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Despite no annotations, the description thoroughly discloses behavioral traits: spend guardrails (BUDGET_EXCEEDED), URL-only input requirement, validation errors, waiting/polling mechanisms, timeout handling, output URL expiration, and error codes. No contradictions with annotations since none exist.
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 with a summary, step-by-step instructions, parameter details, and return format. While it's fairly long, every sentence adds value given the tool's complexity. A slight reduction could improve conciseness, but it remains efficient.
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 (5 parameters, nested objects, no output schema), the description is remarkably complete. It explains return values for success and failure, all possible error codes, and the behavior of wait=true/false, leaving no major 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 description compensates fully with an 'Args:' section explaining each parameter's purpose, defaults, and constraints. For 'params', it provides critical context about building from get_model_params and URL-only media fields, which the schema lacks.
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 states that the tool runs a media generation job on Pixio with spend guardrails. It distinguishes itself from siblings by being the final step of a 3-call discovery contract (list_models -> get_model_params -> generate), making its purpose very specific.
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 explicitly explains when to use the tool (as the final step of the discovery contract) and provides alternatives for waiting behavior (e.g., using wait_for_generation if timeout occurs). It also gives detailed instructions on how to build params from get_model_params and URL requirements.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_creditsA
Report the Pixio account's current credit balance.
Use to check affordability before a job or to audit spend after one. Every terminal generate / wait_for_generation result already includes "remaining_balance", so this tool is mainly for standalone balance checks and recent-spend review.
Args: include_ledger_tail: When true, also return the most recent credit ledger entries (spend and top-up history). ledger_limit: Maximum ledger entries to include (default 10; only used when include_ledger_tail is true; negative values are treated as 0).
Returns: {"total": , "recurring": {"current", "quota", "lastTopOffAt"}, "permanent": }, plus "ledger_tail": [{"id", "reason", "deltaRecurring", "deltaPermanent", "sourceId", "createdAt"}, ...] when include_ledger_tail is true.
| Name | Required | Description | Default |
|---|---|---|---|
| ledger_limit | No | ||
| include_ledger_tail | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description fully discloses behavior: it returns a detailed JSON structure, explains the effect of arguments, and specifies how ledger_limit handles negative values. No contradictions present.
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-organized with a summary, usage context, args, and returns sections. Every sentence adds value without redundancy, achieving efficiency and clarity.
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 tool with two optional parameters and no output schema, the description covers all necessary aspects: purpose, usage, parameters, and return format. It is fully complete.
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 has 0% description coverage, but the description thoroughly explains both parameters: include_ledger_tail triggers ledger entries, ledger_limit controls count with default 10 and negative treated as 0.
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 states 'Report the Pixio account's current credit balance' and distinguishes the tool from siblings like 'estimate_cost' and mentions that other generation tools include 'remaining_balance', making its unique purpose evident.
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?
Explicitly provides when to use (check affordability before a job, audit spend after) and when not to use (since generation results already include remaining_balance), with clear alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_generationA
Fetch the current status and outputs of one generation (no polling).
A single GET /generations/{id} snapshot. Use this to check on a job
started with generate(wait=false) or after a TIMEOUT_PENDING; use
wait_for_generation instead if you want to block until it finishes.
Statuses: "processing" -> "succeeded" | "failed". remaining_balance
is only fetched (best-effort) once the job is terminal; while
processing it is None, as is credits_spent.
Args:
generation_id: Id returned by generate.
Returns:
{"generation_id", "status", "output_urls", "outputs", "model_id",
"credits_spent", "remaining_balance", "elapsed_s", "error"} —
error carries the provider reason when status is "failed".
On failure: {"error": {"code", "message", "details"}} (e.g.
NOT_FOUND for an unknown id).
| Name | Required | Description | Default |
|---|---|---|---|
| generation_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Despite no annotations, description discloses that remaining_balance is best-effort and None while processing, explains error structure, and notes it's a snapshot. Fully transparent.
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?
Concise but complete. Every sentence adds value, front-loaded with purpose. Structured with use case, status info, args, returns.
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?
No output schema, but description provides detailed return fields including error structure. For a single-param tool, it's fully complete.
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?
Only one parameter, and the description adds meaning by stating that generation_id is the Id returned by generate, which is beyond the schema's minimal 'Generation Id'.
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 states the tool fetches status and outputs of a generation (snapshot). It uses specific verb 'Fetch' and resource 'generation', and distinguishes from sibling 'wait_for_generation' by stating no polling.
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?
Explicitly says when to use this tool (check on job with wait=false or after timeout) and when to use alternative (wait_for_generation for blocking). Also explains status progression.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_model_paramsA
Fetch the exact input schema for one Pixio model.
Step 2 of the three-call contract: list_models -> get_model_params ->
generate. Build the params object for generate() strictly from this
response — the server embeds no per-model knowledge.
Critical gotchas when building params for generate():
For select-type params the allowed values are
options[].value(there is no ".values" array). Send select values as STRINGS even when they look numeric — e.g. "5", not 5.Some params marked optional-with-default are still required by the gateway. On your first attempt send EVERY listed param, using each param's
defaultValuewhere you have no better value.
Args: model_id: Catalog model id from list_models, e.g. "pixio/flux-1/schnell".
Returns: The gateway /params response verbatim: {"model": {...}, "params": [{"name", "type", "label", "required", "defaultValue", "placeholder"?, "options"?: [{"value", "label"}]}, ...]}. An unknown model id yields a NOT_FOUND error dict.
| Name | Required | Description | Default |
|---|---|---|---|
| model_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description carries full burden. It describes the return format verbatim, gotchas about select-type params and optional-with-default params, and error condition. It does not mention destructive actions or auth, but as a read-only fetch, that is implied.
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 with overview, step context, gotchas, args, and returns. It is slightly verbose but each sentence adds value given the need to explain gotchas and contract.
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 no output schema, the description provides return structure. One param is well explained. The tool is part of a sequence, and the description explains its role fully. No missing critical information.
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?
Only one parameter (model_id) with 0% schema description coverage. The description adds meaning: 'Catalog model id from list_models, e.g. "pixio/flux-1/schnell".' This provides useful context beyond the 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 description clearly states 'Fetch the exact input schema for one Pixio model' and positions it as step 2 of a three-call contract (list_models -> get_model_params -> generate). This distinguishes it from siblings like list_models and generate.
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 explicitly says 'Step 2 of the three-call contract' and provides critical gotchas for building params for generate(). It does not explicitly state when not to use it, but the contract implies its specific role. It also mentions error behavior for unknown model_id.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_modelsA
Browse the Pixio model catalog (550+ models) with optional filters.
Step 1 of the three-call contract for running any generation:
list_models — find a model id (filter by type and/or query).
get_model_params(model_id) — fetch that model's exact input schema.
generate(model_id, params) — run the job.
Args: type: Exact model type to match, e.g. "text-to-image", "image-to-image", "image-to-video", "text-to-video", "video-to-video", "text-to-audio". query: Case-insensitive substring matched against each model's id, name, and description (e.g. "flux", "background removal"). limit: Maximum number of models to return; clamped to 1..200 (default 50). offset: Number of matching models to skip, for pagination (negative values are treated as 0).
Returns: {"models": [{"id", "name", "type", "credits", "company", "description"}, ...], "total_matching": , "returned": <len of "models">, "offset": }. "credits" is the catalog-listed cost per generation; descriptions are truncated to 200 characters. The catalog is cached for ~10 minutes.
| Name | Required | Description | Default |
|---|---|---|---|
| type | No | ||
| limit | No | ||
| query | No | ||
| offset | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses caching behavior (~10 minutes), truncation of descriptions to 200 characters, clamping on limit parameter, and handling of negative offset. Provides detailed return structure without contradicting any annotations (none provided).
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?
Well-structured: summary sentence, contract overview, bulleted Args, Returns section. Every sentence adds value without unnecessary verbosity. Ideal length for an AI agent.
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?
Comprehensive for a tool with 4 parameters, no output schema, and no annotations. Covers parameter constraints, return format, caching, and positions within the tool ecosystem (sibling tools). No 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?
Despite 0% schema description coverage, the description thoroughly explains each parameter: type examples, query as case-insensitive substring matching with examples, limit clamped to 1-200 with default 50, offset with negative handling. Adds significant meaning beyond the bare 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 description clearly states the tool browses the Pixio model catalog with optional filters. It identifies the resource and action, and distinguishes itself from siblings by being step 1 of a three-call contract.
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?
Explicitly describes the three-call contract for running generations, positioning list_models as the first step to find a model ID. Provides clear when-to-use guidance with alternatives (get_model_params and generate) listed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
upload_mediaA
Upload a local file or mirror a remote URL to Pixio, returning a permanent public media URL.
Use this before generate whenever a model parameter needs media
(image_url, video_url, audio_url, ...): generate accepts
http(s) URLs only and rejects local filesystem paths. The returned
url (hosted on pixiomedia.nyc3.digitaloceanspaces.com) is permanent
and publicly readable, and is exactly what generate's media params
(e.g. image_url) expect — pass it through verbatim.
Args:
source: An http(s) URL (mirrored server-side into Pixio storage) or a
local file path (~ is expanded; uploaded as multipart).
Directories are rejected.
Returns:
{"url": str, "source_kind": "local_file" | "remote_url", "file_name": str, "size_bytes": int | None} — size_bytes is
None for remote URLs (the file never transits this machine).
| Name | Required | Description | Default |
|---|---|---|---|
| source | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description fully handles transparency. Discloses behavior: source can be URL (mirrored) or local file (uploaded with ~ expansion), directories rejected, returns a detailed dict. Notes that size_bytes is None for remote URLs.
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?
Well-structured: brief intro, usage context, then clearly formatted Args and Returns sections. Every sentence is informative and earns its place.
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?
With one parameter and an output schema present, the description fully covers what the tool does, when to use it, input details, and output structure. No 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 coverage is 0%, so description must compensate. It thoroughly explains the 'source' parameter: accepts http(s) URL or local file path, with ~ expansion, and that directories are rejected. Adds significant value beyond the schema's minimal type info.
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 states the tool's purpose: uploading a local file or mirroring a remote URL to Pixio for a permanent public media URL. It distinguishes itself by explaining why it's necessary before the 'generate' tool, which only accepts http(s) URLs.
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?
Explicitly states to use this tool before 'generate' when media parameters like image_url, video_url, audio_url are needed. Provides clear context on what it returns and how to pass the result to generate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wait_for_generationA
Block until a generation reaches a terminal status, or time out.
Resumes waiting on any in-flight job — most usefully after generate
returned TIMEOUT_PENDING, or for a job started with wait=false.
Polls with backoff (2s growing to a 10s cap, jittered) until the job is
"succeeded" or "failed", or until timeout_s elapses (default:
PIXIO_DEFAULT_TIMEOUT_S, 180s). Budget actuals are reconciled from the
job's real creditsCost when it completes.
On timeout the TIMEOUT_PENDING error again carries the
generation_id — the job keeps running server-side and this tool can
be called as many times as needed.
Args:
generation_id: Id returned by generate.
timeout_s: Max seconds to wait; None uses the server default.
Returns: On success the job-result shape: {"generation_id", "status", "output_urls", "outputs", "model_id", "credits_spent", "remaining_balance", "elapsed_s", "error"}. On failure: {"error": {"code", "message", "details"}} with code GENERATION_FAILED (details include the provider reason), TIMEOUT_PENDING (details include generation_id and a resume hint), NOT_FOUND, AUTH, or UPSTREAM_ERROR.
| Name | Required | Description | Default |
|---|---|---|---|
| timeout_s | No | ||
| generation_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description fully covers behavioral traits: polling with backoff (2s to 10s jittered), timeout handling, credit reconciliation, and return shapes on success and failure. No contradictions.
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-organized into logical sections (purpose, usage, behavior, Args, Returns) with no unnecessary words. Every sentence provides 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 (polling, timeout, error handling), the description covers return types, error codes, and usage patterns comprehensively. No output schema exists, but the description includes the return shape.
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 description's 'Args' section adds clear meaning: 'generation_id' is the ID from 'generate', and 'timeout_s' is max wait with server default. This fully compensates for missing schema descriptions.
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 states 'Block until a generation reaches a terminal status, or time out,' providing a specific verb and resource. It distinguishes from siblings by mentioning its use after 'generate' returns TIMEOUT_PENDING or for jobs with 'wait=false'.
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 explicitly notes when to use the tool (after TIMEOUT_PENDING or wait=false) and explains that it can be called multiple times on timeout. However, it does not explicitly contrast with alternatives like 'get_generation' for non-blocking scenarios.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
TDQS
Each tool targets a distinct action (listing, param fetching, cost estimation, generation, status polling, download, upload, credit checking) with no overlap. The descriptions clearly differentiate their purposes.
All tool names follow a consistent verb_noun pattern using snake_case (e.g., list_models, get_model_params, upload_media). No mixing of conventions.
With 9 tools covering the full generation workflow (discovery, parameter retrieval, cost estimation, run, status, download, upload, credits), the count is well-scoped and each tool serves a necessary role.
The tool surface covers the essential lifecycle: list, params, estimate, generate, poll, download, upload, and credit check. A minor gap is the absence of cancel or delete operations, but these are not critical for the core use case.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
MCP server for Google Veo AI video generation
Multi-model AI image and video generator. 14 models behind one OAuth-secured MCP endpoint.
MCP server for building and testing AI agents with multi-model experimentation and insights.
AI image, video, voice and music generation over MCP, routed to Veo 3.1, Seedance 2.0 and more.
Related MCP Servers
- AlicenseAqualityDmaintenanceAn MCP server that enables AI applications to access 20+ model providers (including OpenAI, Anthropic, Google) through a unified interface for text and image generation.230MIT
- AlicenseAqualityDmaintenanceMCP server for multi-provider AI image generation (AWS Bedrock, OpenAI, Google Gemini) enabling image generation, transformation, and editing through a unified interface.41MIT
- AlicenseNot gradedqualityAmaintenanceMCP server for generating images and videos using Google Gemini and VEO models, with support for multiple AI models and credential modes.1Apache 2.0
- AlicenseNot gradedqualityDmaintenanceMCP server for fal model discovery, execution, pricing, and local media processing, enabling AI model workflows via natural language.125MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- 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