MCP: read image-models_get, then dry-run generate_image first
An agent checklist for hosted Sume MCP: read the model with image-models_get, dry-run generate_image with a spend cap, then submit with a new idempotency key.

Before a paid image call over hosted MCP, an agent should read the model with image-models_get, then call generate_image with dry_run: true and an idempotency_key, and submit only after the estimate looks right. The dry run previews admission and cost and does not submit a job.
The hosted MCP URL is https://mcp.sume.com/mcp. Under OAuth with only mcp:read, the write and paid tools are hidden, so a session needs mcp:write or an API key to see generate_image at all.
Step 1: read the model
image-models_list returns the catalog and image-models_get returns one model's endpoint row. Its single required argument is model_id, such as openai/gpt-image-2.5. Read the supported sizes, qualities and reference limits there instead of guessing, and call tools_schema with name: "generate_image" for the exact call contract. The Sume docs add that the catalog does not list sume/auto.
| Gate | Required | What it does |
|---|---|---|
| idempotency_key | Yes, on paid tools | Stable key for dedup, not a human approval |
| dry_run=true | Optional | Cost and admission preview, no job submitted |
| max_spend_usd | Optional | Enforced only when you send it |
| payload.model | Optional | Omitted routes to sume/auto |
| mcp:write or API key | Yes, to see paid tools | mcp:read alone hides them |
Step 2: dry run with a cap
Send the same arguments you plan to submit, with dry_run true. Name the model in payload.model when the user asked for a specific family, and omit it otherwise.
{
"idempotency_key": "banner-draft-2026-10-05-001",
"dry_run": true,
"max_spend_usd": 1,
"payload": {
"model": "openai/gpt-image-2.5",
"prompt": "Flat teal banner with a white paper plane",
"image_size": "1920x640",
"quality": "medium"
}
}Step 3: submit and wait
Read the preview. If it matches, call again with dry_run omitted or false and a fresh idempotency_key, then follow the job with jobs_wait and read the output. Retry a transport failure with the same key, so the same create is not paid twice. For a burst of calls, run generation_admission_preview once first to see balance and queue behavior.
What a dry run does not prove
A preview is an estimate at the moment you ask. Balance, queue and model availability can change before the real call, so keep max_spend_usd on the submit as well if you want a hard cap.
A rule for agent instructions
These four lines fit in a system prompt and cover the cases where an agent spends money by accident. The gates are in the docs, but an agent follows them only if its instructions say so. Test the instructions once with a dry run on a cheap model and read the preview aloud in the agent's own report, so a human can see the estimate before the real call.
- Call
tools_schemaforgenerate_imagebefore the first create in a session. - Always dry run first when the user has not confirmed a price.
- Keep one
idempotency_keyper intended image, and reuse it only on a retry of that same call. - Report the Sume job id and the result URL, and never paste a token or signed URL into chat.
Sources
Related posts
More in Developers
- A 4K image request returns 202: poll the job and fetch the result
POST /v1/images waits 30 seconds. Slow 4K or high-quality calls return 202 with a job envelope. Python that handles both and polls to completion.
- Imagen 4 Fast has no 4:5: generate 3:4 and crop to 1080x1350 in Pillow
Imagen 4 Fast and Grok skip 4:5 on Sume. Request 3:4, then crop to 1080x1350 with ImageOps.fit and a top-biased centering so heads and product tops survive.
- Instagram 4:5 feed video from a 3:4 Sume render: the crop fractions
Sume models list 3:4 but not 4:5. Render 3:4, then crop 3.125% off the top and bottom with video-filter. Check the program free before the $0.02 encode.
- Timeline invalid_fit 400: fit must be cover, contain, stretch or blur
invalid_fit means video[].fit is not cover, contain, stretch or blur. Cover is the default, so omit the field if you want it. details.allowed lists values.
Written by Sume