Skip to content

Commit f6112cf

Browse files
committed
SEP-2663: Add overview docs for Tasks Extension
1 parent 304aa7b commit f6112cf

3 files changed

Lines changed: 283 additions & 1 deletion

File tree

docs/docs.json

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,12 @@
9999
"extensions/auth/oauth-client-credentials",
100100
"extensions/auth/enterprise-managed-authorization"
101101
]
102+
},
103+
{
104+
"group": "MCP Tasks",
105+
"pages": [
106+
"extensions/tasks/overview"
107+
]
102108
}
103109
]
104110
},
@@ -324,7 +330,6 @@
324330
"specification/draft/basic/utilities/cancellation",
325331
"specification/draft/basic/utilities/progress",
326332
"specification/draft/basic/utilities/subscriptions",
327-
"specification/draft/basic/utilities/tasks",
328333
"specification/draft/basic/utilities/mrtr"
329334
]
330335
}
@@ -675,6 +680,10 @@
675680
"source": "/docs/extensions/apps",
676681
"destination": "/extensions/apps/overview"
677682
},
683+
{
684+
"source": "/docs/extensions/tasks",
685+
"destination": "/extensions/tasks/overview"
686+
},
678687
{
679688
"source": "/community/seps",
680689
"destination": "/seps"

docs/extensions/overview.mdx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@ Official extensions live inside the [Model Context Protocol GitHub organization]
5151

5252
To get started building MCP Apps, see the [quickstart guide](/extensions/apps/build#getting-started) or read the full [MCP Apps documentation](https://apps.extensions.modelcontextprotocol.io/api/documents/Quickstart.html).
5353

54+
### MCP Tasks
55+
56+
| Extension | Description |
57+
| --------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
58+
| [MCP Tasks](/extensions/tasks/overview) | Asynchronous task execution for long-running operations, with polling, mid-flight input, and durable handles. |
59+
5460
## Experimental Extensions
5561

5662
Experimental extensions provide an incubation pathway for [Working Groups and Interest Groups](/community/working-interest-groups) to prototype ideas and collaborate on extension concepts before formal SEP submission.

docs/extensions/tasks/overview.mdx

Lines changed: 267 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,267 @@
1+
---
2+
title: MCP Tasks
3+
description: Asynchronous task execution for long-running MCP operations
4+
---
5+
6+
The [experimental-ext-tasks repository](https://github.com/modelcontextprotocol/experimental-ext-tasks) contains the full specification and documentation for MCP Tasks.
7+
8+
<Card
9+
title="modelcontextprotocol/experimental-ext-tasks"
10+
icon="github"
11+
href="https://github.com/modelcontextprotocol/experimental-ext-tasks"
12+
>
13+
Full specification and documentation for MCP Tasks.
14+
</Card>
15+
16+
Not every tool call returns instantly. Some operations — CI pipelines, batch
17+
processing, human approvals — take seconds, minutes, or longer. MCP Tasks let
18+
servers return a durable handle instead of blocking, so clients can poll for
19+
progress, provide input when needed, and retrieve the final result after
20+
reconnecting.
21+
22+
## Why not just block?
23+
24+
You could hold the connection open until the work finishes. Tasks solve
25+
problems that blocking cannot:
26+
27+
- **No long-lived connections.** Blocking ties up a connection for the duration
28+
of the operation. Many clients and transport intermediaries impose timeouts
29+
that make this impractical beyond a few seconds.
30+
- **Crash resilience.** A task ID is a durable handle. If the client
31+
disconnects or restarts, it can resume polling with the same ID.
32+
- **Progress visibility.** Tasks carry status metadata (`working`,
33+
`input_required`, `completed`, `failed`, `cancelled`) and optional status
34+
messages, giving clients visibility into progress.
35+
- **Mid-flight interaction.** When a task needs input (e.g., an elicitation for
36+
user confirmation), it moves to `input_required` and surfaces the request.
37+
The client responds via `tasks/update` — no second connection or unsolicited
38+
server-to-client messages required.
39+
- **Server-directed.** The server decides per-request whether to create a task.
40+
Clients opt in once via the extension capability and handle whichever result
41+
shape arrives. No per-tool warmup or per-request flag.
42+
43+
## How Tasks work
44+
45+
Tasks extend the standard request flow. When a server decides a request will be
46+
long-running, it returns a task handle instead of the final result. The client
47+
polls for completion.
48+
49+
1. **Capability negotiation.** The client includes
50+
`io.modelcontextprotocol/tasks` in its per-request capabilities. The server
51+
advertises the same extension in its own `server/discover` capabilities.
52+
53+
2. **Task creation.** In response to a supported request, the server returns a
54+
`CreateTaskResult` (identified by `resultType: "task"`) containing a `taskId`,
55+
initial status, TTL, and suggested polling interval. The task is durably
56+
created before the response is sent.
57+
58+
3. **Polling.** The client calls `tasks/get` with the `taskId`. The response
59+
carries the current status and, for terminal states, the final result or
60+
error.
61+
62+
4. **Mid-flight input.** If the task moves to `input_required`, the `tasks/get`
63+
response includes an `inputRequests` map with elicitations or other server
64+
requests. The client fulfills these via `tasks/update`.
65+
66+
5. **Completion.** When the status reaches `completed`, the `result` field
67+
contains what the original request would have returned synchronously. If the
68+
status is `failed`, the `error` field contains the JSON-RPC error.
69+
70+
6. **Cancellation.** The client can send `tasks/cancel` at any time.
71+
Cancellation is cooperative — the server acknowledges the intent but is not
72+
obligated to stop the work.
73+
74+
```mermaid
75+
sequenceDiagram
76+
participant Client
77+
participant Server
78+
79+
Client->>Server: tools/call (with tasks capability)
80+
Server-->>Client: CreateTaskResult (taskId, status: working)
81+
82+
loop Poll until terminal
83+
Client->>Server: tasks/get (taskId)
84+
Server-->>Client: Task (status: working)
85+
end
86+
87+
Note over Client,Server: Server needs user input
88+
Client->>Server: tasks/get (taskId)
89+
Server-->>Client: Task (status: input_required, inputRequests)
90+
Client->>Server: tasks/update (taskId, inputResponses)
91+
Server-->>Client: ack
92+
93+
loop Poll until terminal
94+
Client->>Server: tasks/get (taskId)
95+
Server-->>Client: Task (status: working)
96+
end
97+
98+
Client->>Server: tasks/get (taskId)
99+
Server-->>Client: Task (status: completed, result)
100+
```
101+
102+
## When to use Tasks
103+
104+
Tasks are a good fit when your use case involves:
105+
106+
**Long-running operations.** CI pipelines, batch data processing, or model
107+
training jobs that take minutes or hours.
108+
109+
**Human-in-the-loop workflows.** Approval gates, review steps, or any operation
110+
that pauses for user confirmation. The task moves to `input_required` and the
111+
client presents the request.
112+
113+
**External job systems.** If your server wraps an API that already uses job IDs
114+
(cloud deployments, async APIs, queued work), return a task when you create the
115+
job and resolve it when the job completes.
116+
117+
**Unreliable connections.** Mobile clients, intermittent networks, or
118+
environments where connections drop. Task IDs survive disconnects.
119+
120+
**Batch processing.** Operations that process many items (bulk imports, mass
121+
updates) where partial progress is meaningful. Status messages report progress.
122+
123+
## Task lifecycle
124+
125+
| Status | Meaning |
126+
| ---------------- | -------------------------------------------------------------------------- |
127+
| `working` | The operation is in progress. |
128+
| `input_required` | The server needs client input before continuing. See `inputRequests`. |
129+
| `completed` | The operation finished. The `result` field contains the final output. |
130+
| `failed` | A JSON-RPC error occurred during execution. The `error` field has details. |
131+
| `cancelled` | The operation was cancelled (not always honored). |
132+
133+
`completed`, `failed`, and `cancelled` are terminal — once reached, the task's
134+
state does not change.
135+
136+
## Notifications
137+
138+
Servers can push status updates via `notifications/tasks/status`. Clients opt
139+
into these through the `subscriptions/listen` mechanism. Each notification
140+
carries the full task state, eliminating the need for an extra `tasks/get`
141+
round-trip.
142+
143+
Polling is the default. If a server supports notifications, clients can rely on
144+
them instead of polling.
145+
146+
## Implementation guide
147+
148+
### For MCP clients
149+
150+
To consume task-augmented responses, your client must:
151+
152+
<Steps>
153+
<Step title="Declare support">
154+
155+
Include the extension in per-request capabilities:
156+
157+
```json
158+
{
159+
"params": {
160+
"_meta": {
161+
"io.modelcontextprotocol/clientCapabilities": {
162+
"extensions": {
163+
"io.modelcontextprotocol/tasks": {}
164+
}
165+
}
166+
}
167+
}
168+
}
169+
```
170+
171+
</Step>
172+
<Step title="Handle polymorphic results">
173+
174+
When issuing a supported request (e.g., `tools/call`), be prepared to receive
175+
either the standard result or a `CreateTaskResult` with `resultType: "task"`.
176+
177+
</Step>
178+
<Step title="Poll for completion">
179+
180+
Call `tasks/get` with the returned `taskId`, respecting the `pollIntervalMs`
181+
value. Continue polling until the task reaches a terminal status (`completed`,
182+
`failed`, or `cancelled`).
183+
184+
</Step>
185+
<Step title="Handle input requests">
186+
187+
If the task status is `input_required`, read the `inputRequests` map, present
188+
the requests to the user or model, and submit responses via `tasks/update`.
189+
190+
</Step>
191+
<Step title="Persist task IDs">
192+
193+
Store task IDs durably so polling can resume after a client crash or restart.
194+
195+
</Step>
196+
</Steps>
197+
198+
### For MCP servers
199+
200+
To return tasks from your server:
201+
202+
<Steps>
203+
<Step title="Advertise support">
204+
205+
Include the extension in your `server/discover` capabilities:
206+
207+
```json
208+
{
209+
"capabilities": {
210+
"extensions": {
211+
"io.modelcontextprotocol/tasks": {}
212+
}
213+
}
214+
}
215+
```
216+
217+
</Step>
218+
<Step title="Check client capabilities">
219+
220+
Before returning a `CreateTaskResult`, verify that the client included the
221+
extension in its per-request capabilities. Never return a task to a client that
222+
did not declare support.
223+
224+
</Step>
225+
<Step title="Return CreateTaskResult">
226+
227+
When a request will be long-running, respond with `resultType: "task"` and a
228+
`Task` object containing a unique `taskId`, initial status, `ttlMs`, and
229+
`pollIntervalMs`. The task must be durably created before sending the response.
230+
231+
</Step>
232+
<Step title="Serve tasks/get">
233+
234+
Return the current task state on each poll. For terminal states, include the
235+
`result` (on `completed`) or `error` (on `failed`) field.
236+
237+
</Step>
238+
<Step title="Handle tasks/update">
239+
240+
Accept `inputResponses` keyed to outstanding `inputRequests`. Acknowledge with
241+
an empty result. Ignore responses for unknown or already-satisfied keys.
242+
243+
</Step>
244+
<Step title="Handle tasks/cancel">
245+
246+
Acknowledge cancellation requests with an empty result. Honor them when
247+
possible, but cancellation is cooperative — the task may still reach a
248+
non-`cancelled` terminal status.
249+
250+
</Step>
251+
</Steps>
252+
253+
## Client support
254+
255+
<Note>
256+
257+
MCP Tasks is an extension to the [core MCP specification](/specification). Host
258+
support varies by client.
259+
260+
</Note>
261+
262+
See the [client matrix](/extensions/client-matrix) for extension support across
263+
clients. Task support requires explicit opt-in from both client and server.
264+
265+
## Specification
266+
267+
The Tasks extension is specified in the [experimental-ext-tasks repository](https://github.com/modelcontextprotocol/experimental-ext-tasks). It uses the standard MCP [extension negotiation](/extensions/overview#negotiation) mechanism: clients and servers declare support in the `extensions` field of their capabilities during initialization.

0 commit comments

Comments
 (0)