Empty job_id next to job_ids: how Sume MCP treats placeholders
Some agent clients fill every optional tool field with empty strings, zeros and empty arrays. What Sume's MCP drops, what it keeps, and what still errors.

If your agent calls Sume's jobs_result or jobs_wait with job_id: "" next to a real job_ids array, or a real job_id next to job_ids: [], the hosted MCP server treats the empty one as "not set" and runs the call. Two real selectors at once is still an error, so a client that sends both a job id and a non-empty list gets a refusal that says to pick one, not both.
This comes from Sume's own server code and its tests, which I read for this post. It matters because it explains a class of errors you will not see on Sume, and it tells you which empty values are safe to leave in a payload.
The problem the server code describes
A comment in the server's placeholder module describes the pattern: Codex on gpt-6-sol fills every optional property of an MCP tool schema, with an empty string for a string, 0 for a number and [] for an array, and means "not set". Tools read presence, so each placeholder arrives as a value the tool's own schema never allowed. An empty job_id beside job_ids fails the "exactly one of" rule, and each rejection costs the model a round trip.
Sume's answer is to drop the placeholder before the tool runs. Sume's MCP dispatch removes a present, optional, top-level argument when it is an empty value and the advertised schema rejects that exact value. That is a narrow rule, and the narrowness is the point.
What counts as empty, and what is never touched
Per the code, an empty value is an empty or whitespace-only string, a spelled-out null (null, undefined, . or -), 0, or []. The word none is deliberately not on the list, because against an enum without it, none can mean "no transition" and an error serves that better than a default.
Three kinds of value stay exactly as sent. Empty values the schema admits are real values, so false stays, and 0 stays where the schema allows a minimum of 0. Required arguments stay, and the handler names what is wrong. Limits stay too: a zero on max_calls, max_paid_calls, max_spend_usd, generation_spend_cap_usd or timeout_seconds is never widened, because the default it would fall back to allows more work and more spend.
| Call sent | What the server does | Result |
|---|---|---|
| jobs_result with job_id set, job_ids [] | Drops the empty list | Reads the one job |
| jobs_result with job_id "", job_ids of two ids | Drops the empty string | Reads both ids in request order |
| jobs_result with job_id and a non-empty job_ids | Keeps both | Error: not both |
| A limit field set to 0 | Keeps it | Call fails, no wider default |
| A boolean false or a 0 under minimum 0 | Keeps it | Treated as a real value |
What to do in your own client
You do not need to strip empty fields before calling Sume, but you also should not rely on the drop for anything that affects spend. A budget you left at zero will fail loudly rather than quietly become the default, which is the safer behavior for a paid tool.
Sume's jobs docs say both jobs_wait and jobs_result take 1 to 20 ids. Send one selector, job_id for a single job and job_ids for a wave, and the question of placeholders never comes up.
- Prefer one batch
jobs_waitwithjob_idsafter a fan-out, then one batchjobs_result. - Treat an "exactly one of" or "not both" error as a payload bug on your side, not a job failure.
- Never retry a paid create because a read call errored. The create already registered a job.
Why this is worth knowing
The server logs an info line with the field names it dropped, so if you suspect a client is sending placeholders, that is where it shows. The same logic is why a model that never sees the error cannot learn from it: the call just works.
Behavior can change with the server version, and the schema from tools_schema is the contract for what each field accepts. Check it when a client you do not control starts sending fields you did not write.
Sources
Related posts
More in Developers
- On a 402, try a cheaper rung: a Python ladder with fresh keys
A 402 on Sume means nothing was reserved, so a cheaper request can go straight through. Python ladder: Seedance 720p, 480p, then Wan 480p, one key per rung.
- Sume failed job says [redacted_url]: what was removed
A [redacted_url] in a Sume job error is by design: URLs, provider ids, env names and secrets are masked, and the provider reason is capped at 300 characters.
- Is there a lipsync-1.0 endpoint on Sume? Old paths 404; use Fabric
Sume's old /v1/lipsync-1.0 paths return 404 and its model ids return model_not_found. Send the same still and audio to veed/fabric-1.0 or H3 Max lip-sync.
- Make a vertical Short clip with curl and jq: submit, poll, download
A 20-line shell script that asks Sume for an 8-second 9:16 clip at 1080p, polls the job, and saves short.mp4, matched to YouTube's Shorts page.
Written by Sume