Agents

MCP tool call timeouts on long-running video jobs: use jobs_wait

On Sume's hosted MCP server, one jobs_wait call holds at most 55 seconds. Wait out long video jobs in slices, batch up to 20 ids, and never resubmit.

5 min readSume
All posts

On Sume's hosted MCP server at https://mcp.sume.com/mcp, a jobs_wait call holds at most 55 seconds, so an agent waits out a minutes-long video job in slices: call jobs_wait on the job id, or on up to 20 ids, and when a slice ends with wait_slice_expired, call it again on the same ids. Never resubmit the paid create. The job keeps running and billing whether or not anyone is watching.

The rules come from Sume's Jobs and results, Authentication, and MCP tools and gates pages, read on 2026-09-26. Response fields described as current come from the hosted server's code. The basics page says the CLI and hosted MCP still work but are not part of the primary integration path today; a backend polls GET /v1/jobs/{id}/status over HTTP instead. This is the MCP side of idempotency keys for AI video APIs.

Why does a long MCP tool call time out?

A wait is one HTTP request held open with nothing transferring, and every edge closes such a request eventually. When that happens the caller gets no tool result at all, while the job keeps running and billing. So for every remote POST /mcp caller, one jobs_wait holds at most 55 seconds. The server does not hold a wait for 600 seconds: a request held that long dies at the edge with 502 or Transport send error before it can answer.

Wait for a ten-minute render by repeating the wait, not by asking for a longer one. timeout_seconds defaults to 50 and is capped at 55. Values up to 600 are accepted but clamped, and the response says so in wait_slice_clamped, which currently reports requested_timeout_seconds and applied_timeout_seconds.

How do I call jobs_wait?

Send exactly one of two shapes:

  • job_id for one job. The response is object: "job_wait".
  • job_ids with 1–20 ids and an optional wait_for of all (the default) or any. The response is object: "job_wait_batch", with a status snapshot for every requested id.
  • timeout_seconds is optional: omit it for 50, or send up to 55.
  • A wait returns the moment its job is terminal: completed, failed, or canceled.
{
  "job_ids": ["job_123", "job_124", "job_125"],
  "wait_for": "all",
  "timeout_seconds": 50
}

What does a slice return, and what do I do next?

After a parallel fan-out, prefer one batch wait over N single waits. Here is what a wait can return, and what to do next:

From Jobs and results, read 2026-09-26; the outcome field is current server behavior.
You getWhat it meansNext step
outcome: "terminal"The wait condition was met: every id is terminal, or at least one with wait_for: "any".Read results with jobs_result. Keep waiting on any id still pending.
wait_slice_expiredYour polling window closed. The pending jobs are still running and billing.Call jobs_wait again with the same ids, currently listed in wait_slice_expired.pending_job_ids.
wait_slice_clamped, next to either outcomeYou asked for more than 55 seconds, and the server applied the cap.The wait still ran. Send 55 or less next time.
HTTP 524, 522, 523, or 525A transport failure, never a job outcome.Re-issue jobs_wait on the same ids, or read jobs_status once. Do not report the job blocked.
The whole call failsAn unknown or foreign-workspace id is in the list.Fix the id list, then wait again.

How do I read results for a whole batch?

jobs_result also takes job_ids, with the same 1–20 ceiling, so a wave you waited on in one call reads back in one call. The response is a job_result_batch: results[] in request order, one entry per id, each with ok plus either value or a typed error.

  • Partial success is normal. An id that is still running comes back as job_not_completed, while every finished id returns its result.
  • partial_failure.failed_job_ids names exactly the ids worth re-reading. Read ok per entry; a failure on one id says nothing about the others.
  • wait_for: "any" still reports every id, and the jobs it did not wait for keep running and billing.
  • A job whose own status is failed is a verdict on its input. The tool description currently points to jobs_get for error.public_reason and error.message: do not resubmit the identical create until the named input is fixed.

Does waiting cost anything?

Waiting is a read: hosted MCP lists jobs_wait with the read tools, not the paid ones. For rate limits, an MCP tool call spends the write budget once, for the run it creates, not for the JSON-RPC request that carried it, and a jobs_status poll over MCP spends no write budget at all. Reads get forty times the plan's write number, in their own bucket.

The job is what bills. A client-side timeout cancels nothing, and cancellation succeeds only before generation work starts; after that the API answers 409 job_generation_already_started. Over MCP, jobs_cancel is a write that needs an idempotency_key.

A script_run can call jobs_wait too, but the whole script is bounded by one request, so long renders are still waited on outside it. See programmatic tool calling with script_run.

Sources

Related posts

Written by Sume