MCP tool ran twice: idempotency_key saves your Sume render
Claude Code fixed MCP tool calls that sometimes ran twice on large results. Sume's paid MCP tools require an idempotency_key so a repeat does not bill twice.

A Claude Code release note (v2.1.288) lists a fix for "MCP tool calls sometimes running twice when a remote server's result was over 16 MB or could not be parsed". A tool that can run twice is a billing risk if the tool spends money. Sume's write and paid MCP tools require an idempotency_key, so send a stable key per intent and a repeat call is a duplicate, not a second render.
The upstream fix
The line is from the Claude Code releases page, read on 2026-10-03. This post does not claim to know which clients or versions were affected beyond that note. The general point stands for any client: assume a tool call can be delivered twice.
What the key does on Sume
On hosted MCP, idempotency_key is required on write and paid tools. The docs describe it as a stable key for transport and dedup, not human approval. On the REST video route the docs are explicit: send Idempotency-Key to make retries safe, and a replay returns the original job. Reuse the same key only for the same operation and payload.
| Gate | Required? | Meaning |
|---|---|---|
| idempotency_key | Yes, on write and paid tools | Stable key for transport and dedup |
| dry_run=true | Optional | Cost and admission preview, no job |
| max_spend_usd | Optional | Enforced only when provided |
Make the key stable, not random
A key generated fresh on every call defeats the purpose, because a duplicate delivery of the same call would carry the same key only if it is derived from the intent. Build it from something that identifies the work, such as a project id, a scene number and a version.
{
"idempotency_key": "launch-video-scene-03-v1",
"max_spend_usd": 5,
"payload": {
"prompt": "A slow push-in on a matte black bottle on marble"
}
}If you think it ran twice
Call jobs_list and look at recent jobs before resubmitting, and use jobs_wait or jobs_status on the id you have. Do not resubmit a paid create because a wait failed: a 524 on jobs_wait is a transport failure, not a job outcome. Pair this with dry_run=true and max_spend_usd on bursts so one mistake stays small.
Sources
Related posts
More in Developers
- MCP TS SDK 2.3 enforces one server per request: where state lives
TypeScript SDK 2.3.0 enforces one server instance per request. For a media tool that means job state belongs in job ids, as Sume's jobs_wait does.
- Grok image model retires Nov 2: migrate safely
A pricing tracker says xAI retires legacy grok-imagine-image-quality on Nov 2, 2026. Migrate by pinning model ids and checking the live catalog.
- MiniMax H3 reference mix: why 9 + 3 + 3 fails the 12 cap
H3 and H3 Max allow 9 images, 3 videos and 3 audios, but only 12 inputs in total. A Python preflight counter and the cost of images past five.
- Music 1.0 is retiring: moving to the Music Router in one line
Sume Music 1.0 routes keep working but resolve through the Music Router. New code should call POST /v1/music-router/generate. What changes and what does not.
Written by Sume