|
| 1 | +--- |
| 2 | +title: Overview |
| 3 | +group: Getting Started |
| 4 | +description: MCP Tasks lets servers return durable poll handles instead of blocking on long-running tool calls. Clients poll for progress, provide mid-flight input, and retrieve results after reconnecting. |
| 5 | +--- |
| 6 | + |
| 7 | +# MCP Tasks Overview |
| 8 | + |
| 9 | +MCP Tasks is an extension to the Model Context Protocol. Servers return a durable task handle instead of blocking on a long-running operation; clients poll for progress and retrieve the result when ready. |
| 10 | + |
| 11 | +**Extension Identifier:** `io.modelcontextprotocol/tasks` |
| 12 | + |
| 13 | +## Why Tasks? |
| 14 | + |
| 15 | +Tool calls block until work finishes. Tasks solve the cases where blocking is impractical: |
| 16 | + |
| 17 | +- **CI pipelines and batch jobs** — minutes or hours of execution |
| 18 | +- **Human-in-the-loop workflows** — approval gates that block until a person responds |
| 19 | +- **External job systems** — cloud deployments, queued work, async APIs with their own job IDs |
| 20 | +- **Unreliable connections** — mobile clients, intermittent networks, transport intermediary timeouts |
| 21 | + |
| 22 | +A task ID is a durable handle that survives disconnects and carries status metadata, without requiring long-lived connections or unsolicited server-to-client messages. |
| 23 | + |
| 24 | +## Progressive Enhancement |
| 25 | + |
| 26 | +Servers only return task handles to clients that declared the extension in their per-request capabilities — otherwise, the server either blocks for a regular result as usual or returns a capability error. |
| 27 | + |
| 28 | +A server that requires task support from the client for a given request returns a `-32003` (Missing Required Client Capability) error, like so: |
| 29 | + |
| 30 | +```jsonc |
| 31 | +{ |
| 32 | + "jsonrpc": "2.0", |
| 33 | + "id": 1, |
| 34 | + "error": { |
| 35 | + // MISSING_REQUIRED_CLIENT_CAPABILITY |
| 36 | + "code": -32003, |
| 37 | + "message": "Missing required client capability", |
| 38 | + "data": { |
| 39 | + "requiredCapabilities": { |
| 40 | + "extensions": { |
| 41 | + "io.modelcontextprotocol/tasks": {} |
| 42 | + } |
| 43 | + } |
| 44 | + } |
| 45 | + } |
| 46 | +} |
| 47 | +``` |
| 48 | + |
| 49 | +## Architecture |
| 50 | + |
| 51 | +```mermaid |
| 52 | +flowchart LR |
| 53 | + subgraph Client ["MCP Client"] |
| 54 | + P[Poll Loop] |
| 55 | + I[Input Handler] |
| 56 | + end |
| 57 | +
|
| 58 | + subgraph Server ["MCP Server"] |
| 59 | + T[Task Store] |
| 60 | + W[Worker] |
| 61 | + end |
| 62 | +
|
| 63 | + Client -->|"tools/call"| Server |
| 64 | + Server -->|"CreateTaskResult"| Client |
| 65 | + P -->|"tasks/get"| T |
| 66 | + T -->|"DetailedTask"| P |
| 67 | + I -->|"tasks/update"| T |
| 68 | + W --> T |
| 69 | +``` |
| 70 | + |
| 71 | +- **Client** — Drives all interaction: issues tool calls, polls for completion, and fulfills input requests. |
| 72 | +- **Server** — Decides per-request whether to create a task and manages task state durably. |
| 73 | +- **Task Store** — Durable state reachable by `tasks/get` even if the worker or connection has died. A `CreateTaskResult` is not returned until the task is findable here. |
| 74 | +- **Worker** — The computation backing the task. Updates the task store as it progresses and writes the final result or error on completion. |
| 75 | + |
| 76 | +## Lifecycle |
| 77 | + |
| 78 | +```mermaid |
| 79 | +sequenceDiagram |
| 80 | + participant Client |
| 81 | + participant Server |
| 82 | +
|
| 83 | + Note over Client,Server: 1. Capability Negotiation |
| 84 | + Client->>Server: tools/call (with io.modelcontextprotocol/tasks capability) |
| 85 | +
|
| 86 | + Note over Client,Server: 2. Task Creation |
| 87 | + Server-->>Client: CreateTaskResult (taskId, status: working) |
| 88 | +
|
| 89 | + Note over Client,Server: 3. Polling |
| 90 | + loop Poll until terminal |
| 91 | + Client->>Server: tasks/get (taskId) |
| 92 | + Server-->>Client: Task (status: working) |
| 93 | + end |
| 94 | +
|
| 95 | + Note over Client,Server: 4. Mid-flight Input |
| 96 | + Client->>Server: tasks/get (taskId) |
| 97 | + Server-->>Client: Task (status: input_required, inputRequests) |
| 98 | + Client->>Server: tasks/update (taskId, inputResponses) |
| 99 | + Server-->>Client: ack |
| 100 | +
|
| 101 | + Note over Client,Server: 5. Completion |
| 102 | + loop Poll until terminal |
| 103 | + Client->>Server: tasks/get (taskId) |
| 104 | + Server-->>Client: Task (status: working) |
| 105 | + end |
| 106 | + Client->>Server: tasks/get (taskId) |
| 107 | + Server-->>Client: Task (status: completed, result) |
| 108 | +``` |
| 109 | + |
| 110 | +1. **Capability negotiation** — The client includes `io.modelcontextprotocol/tasks` in `_meta.io.modelcontextprotocol/clientCapabilities.extensions`. The server advertises the same in `server/discover`. No per-tool warmup or per-request flag. |
| 111 | + |
| 112 | +2. **Task creation** — The server returns a `CreateTaskResult` with `resultType: "task"`, containing a `taskId`, initial status, TTL, and polling interval. The task is durably created before the response is sent. |
| 113 | + |
| 114 | +3. **Polling** — The client calls `tasks/get` with the `taskId`, respecting `pollIntervalMs`, until the task reaches a terminal status (which includes the final result or error). |
| 115 | + |
| 116 | +4. **Mid-flight input** — If the task moves to `input_required`, `tasks/get` includes an `inputRequests` map that the client fulfills via `tasks/update`, after which the task transitions back to `working`. |
| 117 | + |
| 118 | +5. **Completion** — `completed`: `result` contains what the original request would have returned synchronously. `failed`: `error` contains the JSON-RPC error. |
| 119 | + |
| 120 | +## Task Status |
| 121 | + |
| 122 | +```mermaid |
| 123 | +stateDiagram-v2 |
| 124 | + [*] --> working |
| 125 | + working --> input_required |
| 126 | + working --> completed |
| 127 | + working --> failed |
| 128 | + working --> cancelled |
| 129 | + input_required --> working |
| 130 | + input_required --> completed |
| 131 | + input_required --> failed |
| 132 | + input_required --> cancelled |
| 133 | + completed --> [*] |
| 134 | + failed --> [*] |
| 135 | + cancelled --> [*] |
| 136 | +``` |
| 137 | + |
| 138 | +| Status | Meaning | |
| 139 | +| ---------------- | -------------------------------------------------------------------------- | |
| 140 | +| `working` | The operation is in progress. | |
| 141 | +| `input_required` | The server needs client input before continuing. See `inputRequests`. | |
| 142 | +| `completed` | The operation finished. `result` contains the final output. | |
| 143 | +| `failed` | A JSON-RPC error occurred during execution. `error` has details. | |
| 144 | +| `cancelled` | The operation was cancelled (not always honored). | |
| 145 | + |
| 146 | +`completed`, `failed`, and `cancelled` are terminal. |
| 147 | + |
| 148 | +Each task also carries: |
| 149 | + |
| 150 | +- **`statusMessage`** — Optional description of current state |
| 151 | +- **`createdAt` / `lastUpdatedAt`** — ISO 8601 timestamps |
| 152 | +- **`ttlMs`** — Time-to-live from creation in milliseconds; may change over lifetime; `null` for unlimited |
| 153 | +- **`pollIntervalMs`** — Suggested polling interval; may change over lifetime |
| 154 | + |
| 155 | +## Mid-flight Input |
| 156 | + |
| 157 | +When a task needs client input, it transitions to `input_required` and the `tasks/get` response includes an `inputRequests` map. The client fulfills these via `tasks/update`, which returns an empty ack: |
| 158 | + |
| 159 | +```json |
| 160 | +{ |
| 161 | + "status": "input_required", |
| 162 | + "inputRequests": { |
| 163 | + "approval": { |
| 164 | + "method": "elicitation/create", |
| 165 | + "params": { |
| 166 | + "mode": "form", |
| 167 | + "message": "Approve deployment to production?", |
| 168 | + "requestedSchema": { |
| 169 | + "type": "object", |
| 170 | + "properties": { "approved": { "type": "boolean" } }, |
| 171 | + "required": ["approved"] |
| 172 | + } |
| 173 | + } |
| 174 | + } |
| 175 | + } |
| 176 | +} |
| 177 | +``` |
| 178 | + |
| 179 | +Each key in `inputRequests` is unique over the lifetime of a task. The server may accept partial responses; the task remains `input_required` until all arrive. Reads (`tasks/get`) and writes (`tasks/update`) are separate to keep reads idempotent and cacheable. |
| 180 | + |
| 181 | +See the [specification](./specification/draft/tasks.mdx) for the full `tasks/update` request shape and consistency semantics. |
| 182 | + |
| 183 | +## Cancellation and Notifications |
| 184 | + |
| 185 | +Clients send `tasks/cancel` to signal cancellation intent. The server acks with an empty result — cancellation is cooperative, and the task may still reach a non-`cancelled` terminal status. |
| 186 | + |
| 187 | +Servers may also push status updates via `notifications/tasks`, which clients opt into through `subscriptions/listen`. Each notification carries the full task state, identical to a `tasks/get` response. |
| 188 | + |
| 189 | +See the [specification](./specification/draft/tasks.mdx) for details on both mechanisms. |
| 190 | + |
| 191 | +## Security |
| 192 | + |
| 193 | +- **Task ID unguessability.** Task IDs are generated with sufficient entropy to prevent enumeration, and may serve as bearer tokens for stored state. |
| 194 | +- **No task enumeration.** There is no `tasks/list`, so one caller's tasks are not visible to another. |
| 195 | +- **Input-request trust model.** `inputRequests` carry elicitation/sampling payloads from server to client. Hosts apply the same trust model as for standard elicitation/sampling requests. |
| 196 | + |
| 197 | +## Supported Methods |
| 198 | + |
| 199 | +Task-augmented execution is currently supported for: |
| 200 | + |
| 201 | +- `tools/call` |
| 202 | + |
| 203 | +## Learn More |
| 204 | + |
| 205 | +- [Specification](./specification/draft/tasks.mdx) — Full protocol specification |
| 206 | +- [SEP-2663](../seps/2663-tasks-extension.md) — The proposal defining this extension |
| 207 | +- [Schema](../schema/) — TypeScript types and generated JSON Schema |
0 commit comments