MCP tasks/cancel vs Sume jobs_cancel: cancel works only before start
TypeScript SDK 2.3.0 adds tasks/get and tasks/cancel. Sume's jobs_cancel is narrower: it succeeds only before generation starts, then returns 409.

An MCP task cancel and a Sume job cancel are not the same promise. Sume's jobs_cancel works only while a job is still waiting; once generation has started the API answers 409 job_generation_already_started and the job runs to completion and bills.
The TypeScript SDK 2.3.0 release added tasks/get and tasks/cancel, so it is worth being clear about what a cancel button can honestly do for a paid render.
The task side
In the 2026-07-28 specification, the experimental tasks feature moved to the official extension io.modelcontextprotocol/tasks. The blocking tasks/result call was replaced by polling tasks/get plus tasks/update, tasks/list was removed, and servers may return task handles unsolicited.
| MCP task call | Closest Sume hosted tool | Notes |
|---|---|---|
| tasks/get | jobs_status | Read-only status for one job. |
| tasks/cancel | jobs_cancel | Needs a write session and an idempotency_key. |
| tasks/list (removed) | jobs_list | Lists jobs visible to the credential. |
What jobs_cancel guarantees
The Sume docs state the rule plainly. Cancellation succeeds only before generation work starts. After that the API returns 409 job_generation_already_started with details.cancelable: false, and the job completes or fails normally.
Two related cases matter for a retry loop. Cancelling a job that is already canceled is idempotent and returns the same canceled job. A job that is already completed is a different 409, job_not_cancelable.
queued: cancel is possible while the job waits for a concurrency slot.processing: cancel may already be too late; expect the 409.completed,failed: nothing to cancel.
Why queued time is the cancel window
Sume admits paid jobs queue-first. Concurrency is a dispatch limit, so a valid submit can be accepted as queued and wait for a slot. That wait is where cancel is useful: if a user changes their mind, or a batch is no longer needed, the queued jobs can be cancelled before they cost anything.
The admission docs recommend exactly this when you hit queue_full: poll existing jobs, cancel queued jobs that are no longer needed, and retry with the same idempotency key once capacity opens.
Design a cancel button honestly
If you wrap Sume generation in your own task-style interface, map the 409 to a clear state instead of pretending the cancel worked.
- Call
jobs_cancelwith its ownidempotency_keyand read the result. - On
job_generation_already_started, show the job as still running and keep waiting withjobs_waitslices. - Do not resubmit the original paid request just because the user pressed cancel and the cancel failed.
- Treat a client-side timeout as different from a cancel: stopping to watch a job does not stop it.
Sources
Related posts
More in Developers
- MCP spec timeline: 2025-11-25, RC on May 29, stable on July 28, 2026
The MCP 2026-07-28 spec went stable on July 28, 2026, 60 days after its May 29 RC, replacing 2025-11-25. Dates, and how to check what you run.
- MCP tasks extension and Sume job statuses: mapping for render tools
In MCP 2026-07-28 tasks are an extension polled with tasks/get. Map task handles, polling, update and list onto Sume job ids, status reads and jobs_cancel.
- Next.js 16.3.8 dev-server MCP disclosure and where the Sume key lives
Next.js 16.3.8 fixes a low-severity dev-server MCP disclosure and a high-severity image SSRF. How to keep a Sume API key server-side as you upgrade.
- Next.js 16.3.8 fixes ISR cache poisoning: keep job pages dynamic
Next.js v16.3.8 fixes cache poisoning in SSG and ISR and Draft Mode leaks. Why a Sume job status page should stay dynamic and uncached, whatever the version.
Written by Sume