skip to content

In MCP's tasks extension, what task statuses exist and which of them are terminal?

level: middleimportance: should knowfreq 47%

answer

  1. five statuses, two live
  2. one of them means paused, not broken
  3. three ways a task can end
  4. cancel asks, it does not kill
  5. working and input_required keep you polling

basics

~20 s

A task is working, input_required, completed, failed or cancelled. The first two are live states the client keeps polling; completed, failed and cancelled are terminal. Cancellation is cooperative — tasks/cancel requests it, the server decides when the task actually stops.

solid answer

~40 s

In MCP revision 2026-07-28 the `io.modelcontextprotocol/tasks` extension defines five statuses. `working` means the server is still executing. `input_required` means the task has paused because it needs something from the client, which the client supplies with `tasks/update`. `completed`, `failed` and `cancelled` are the three terminal states: `completed` carries the result the original call was asking for, `failed` reports that the work ended unsuccessfully, and `cancelled` follows a `tasks/cancel` request. Cancellation is cooperative — `tasks/cancel` asks the server to stop, it does not guarantee an instant halt, so a client should keep reading the status until it settles rather than assuming the task is dead the moment it asks. The client sees these statuses by polling `tasks/get`, or through optional `notifications/tasks` pushes.

go deeper

for a junior

Learn the list and the split: working and input_required mean keep waiting; completed, failed and cancelled mean the task is over.

for a middle

Be able to explain what moves a task between states — tasks/update out of input_required, tasks/cancel toward cancelled — and that the client observes the state by polling tasks/get.

for a senior

Demonstrate the cooperative-cancellation judgment: a cancel request is advisory, the terminal status may not be cancelled, and client code must poll to a terminal state rather than assuming one.

for a principal

Own the policy edges nobody asks about until production: how long finished task results are retained, what happens to abandoned tasks, and how that storage decision bounds the feature.

## The five statuses The Tasks extension in MCP revision 2026-07-28 (`io.modelcontextprotocol/tasks`) models a long-running unit of work as a small state machine with five statuses: | Status | Meaning | Terminal? | |---|---|---| | `working` | The server is executing the work. | No | | `input_required` | Execution is paused pending something from the client. | No | | `completed` | The work finished successfully; the result is available. | Yes | | `failed` | The work ended unsuccessfully. | Yes | | `cancelled` | The work stopped because cancellation was requested. | Yes | The distinction that matters operationally is live versus terminal. `working` and `input_required` are live: the client's job is not finished, and it must either keep polling `tasks/get` or act. `completed`, `failed` and `cancelled` are terminal: the state machine will not move again, and the client stops watching. ## Why input_required is a status and not an error A task can discover halfway through that it needs a decision, a credential, or a directory listing. Rather than failing, it parks in `input_required`. The client, seeing that status, supplies what is needed with `tasks/update`, and the task resumes — typically back to `working`. This is deliberately different from how the core protocol handles the same need. A plain `tools/call` that needs client input comes back as an interim result and the client resolves it by re-issuing the original request. A task is already running and already has a durable identity, so re-issuing anything would be wrong; the client feeds the running task through `tasks/update` instead. Candidates who have only read about the core pattern often try to describe a retry here, and that is a real discriminator. ## Cancellation is cooperative `tasks/cancel` is a **request** to stop, addressed to the server by `taskId`. It is not a kill switch. The server may need to unwind a transaction, finish an atomic step, or release a lock before it can stop, and some work simply cannot be interrupted at an arbitrary point. Two consequences follow: 1. A client should not assume the task is over the instant it calls `tasks/cancel`. It should keep reading the status until it becomes terminal. 2. The terminal status after a cancel request is not necessarily `cancelled`. A task that was already finishing may land on `completed`, and one that broke while unwinding may land on `failed`. Treating `cancelled` as the only possible outcome of a cancel is a common bug. Cooperative cancellation is the same philosophy MCP applies elsewhere: `notifications/cancelled` on an ordinary request is likewise advisory, and closing a Streamable HTTP response stream signals cancellation of that request without promising the server has stopped. ## How the client observes transitions Polling `tasks/get` with the `taskId` is the baseline and always available. It works identically over stdio and Streamable HTTP, and it survives reconnects, because the `taskId` is an explicit server-minted handle rather than connection state — the shape 2026-07-28 mandates now that protocol-level sessions are gone. Optionally, a server may push `notifications/tasks` over a `subscriptions/listen` stream, so the client learns of transitions without a tight poll loop. That is an optimisation. A robust client still polls on reconnect, because a notification delivered while its stream was down is simply gone — 2026-07-28 removed stream resumability entirely. ## Retention and the terminal state A terminal status does not mean the task record vanishes instantly; the client normally needs one more `tasks/get` to collect the result of a `completed` task. But nor can a server keep every finished task forever. How long a completed task's result remains fetchable is a server policy question, and a client that walks away without collecting the result of a task it started should expect that result to be reclaimed eventually. Designing that retention window — long enough for a client that slept and reconnected, short enough to bound storage — is a real operational decision when you run a task-capable MCP server. ## Interview framing Name the five statuses cleanly, split them into two live and three terminal, and volunteer two nuances: `input_required` is resolved with `tasks/update` rather than by retrying anything, and `tasks/cancel` is a cooperative request whose eventual terminal status might not be `cancelled`. That combination shows you have thought about the state machine rather than memorised a list.

  • After a client calls tasks/cancel, can the task still end as completed?
    Yes. Cancellation in MCP 2026-07-28 is cooperative: `tasks/cancel` asks the server to stop, and the server may already be at the last step, or may be unable to interrupt an atomic operation. The task can settle on `completed` or `failed` as well as `cancelled`, so the client should keep reading the status until it is terminal rather than assuming the outcome.
  • What moves a task out of input_required?
    The client calls `tasks/update`, naming the task and supplying what the server asked for; the task then resumes, normally returning to `working`. Note the contrast with the core protocol, where an interim result is resolved by retrying the original request — a running task is never re-issued, it is fed.
  • Should a client stop polling once it sees completed?
    It stops watching for transitions, but it still needs to collect the result of that `completed` task, and it should not assume the record lives forever — retention of finished tasks is server policy. A client that abandons a task it started should expect its result to be reclaimed.

saying these in an interview costs you the question

  • Thinks tasks/cancel immediately kills the running work
  • Assumes a cancelled request always ends in the cancelled status
  • Treats input_required as a failure or an error response
  • Tries to resolve input_required by re-issuing the original tools/call
  • Believes a completed task's result is retained indefinitely

context