Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
7715860
SEP-2663: Tasks Extension
LucaButBoring Apr 29, 2026
edb77c8
SEP-2663: Flatten CreateTaskResult
LucaButBoring Apr 29, 2026
5b125bd
SEP-2663: Put under Agents WG for now
LucaButBoring Apr 29, 2026
87a3f98
SEP-2663: Add requestState security guidance
LucaButBoring Apr 29, 2026
e224fc0
SEP-2663: Rephrase distinction between protocol-level errors and othe…
LucaButBoring Apr 29, 2026
23d2392
SEP-2663: Reformat document
LucaButBoring Apr 29, 2026
d3ad509
SEP-2663: Append units to duration fields
LucaButBoring Apr 29, 2026
4f85991
SEP-2663: Add requestState to GetTaskRequest
LucaButBoring Apr 29, 2026
ef21c6a
SEP-2663: Remove reference to initialization
LucaButBoring Apr 29, 2026
4526a80
SEP-2663: Reformat document
LucaButBoring Apr 29, 2026
ed4c83e
SEP-2663: Add task status notification requirements
LucaButBoring Apr 29, 2026
0c1771a
SEP-2663: Address task resumption and expiry
LucaButBoring Apr 30, 2026
c54e5ee
SEP-2663: State removal of old tasks and extension rationale
LucaButBoring Apr 30, 2026
3f3ed02
SEP-2663: Clarify requestState consistency limitations
LucaButBoring Apr 30, 2026
cbb156c
SEP-2663: Clarify protocol versioning in backwards-compatibility section
LucaButBoring Apr 30, 2026
451f5e1
SEP-2663: Allow IncompleteResult before task creation
LucaButBoring May 1, 2026
ee55336
SEP-2663: Fix units in task status notifications
LucaButBoring May 2, 2026
ffca36a
SEP-2663: Clarify MRTR+Task server behavior
LucaButBoring May 2, 2026
d963ad0
SEP-2663: Allow errors on update and cancel methods
LucaButBoring May 4, 2026
6d954fe
Merge branch 'main' into feat/ext-tasks
LucaButBoring May 5, 2026
2643deb
SEP-2663: Fix typos and formatting issues
LucaButBoring May 6, 2026
a1ed070
SEP-2663: Do not poll until cancelled
LucaButBoring May 6, 2026
c58c652
SEP-2663: Clarify state retention after task cancellation
LucaButBoring May 6, 2026
ebe238a
SEP-2663: Allow ttlSeconds to change during a task
LucaButBoring May 6, 2026
c4ff02d
SEP-2663: Send task status notifications on subscriptions/listen
LucaButBoring May 6, 2026
cfd09d3
SEP-2663: Do not require polling+streaming
LucaButBoring May 6, 2026
6275891
SEP-2663: Use Ms suffix consistently on durations
LucaButBoring May 7, 2026
a05d7f9
Merge branch 'main' into feat/ext-tasks
LucaButBoring May 7, 2026
82fb2c4
SEP-2663: Remove tasks from core spec; adjust MRTR
LucaButBoring May 7, 2026
3b383d1
SEP-2663: Rename incomplete to input_required
LucaButBoring May 7, 2026
f53121c
SEP-2663: Add mcpkit as reference implementation
LucaButBoring May 8, 2026
e768085
Merge branch 'main' of https://github.com/modelcontextprotocol/modelc…
LucaButBoring May 11, 2026
3e6eaf4
Update seps/2663-tasks-extension.md
LucaButBoring May 11, 2026
16d03e6
SEP-2663: Remove mentions of tasks from MRTR
LucaButBoring May 11, 2026
5324be3
SEP-2663: Format document
LucaButBoring May 11, 2026
3f33c7d
SEP-2663: Specify cancellation notifications don't cancel tasks
LucaButBoring May 11, 2026
3f1c3cf
SEP-2663: Remove requestState
LucaButBoring May 11, 2026
304aa7b
SEP-2663: Remove task schema categories
LucaButBoring May 11, 2026
f6112cf
SEP-2663: Add overview docs for Tasks Extension
LucaButBoring May 11, 2026
a9ea0a4
Merge branch 'main' into feat/ext-tasks
LucaButBoring May 12, 2026
6e4fd57
SEP-2663: Specify error for servers that require tasks
LucaButBoring May 12, 2026
46394d2
SEP-2663: Remove redundant 'On success' from cancellation ack
LucaButBoring May 13, 2026
7828857
SEP-2663: Trim partial-response sentence in tasks/update
LucaButBoring May 13, 2026
c248297
SEP-2663: Rename section to 'Task Update Requests'
LucaButBoring May 13, 2026
782d37a
SEP-2663: Link to MRTR spec for inputRequests
LucaButBoring May 13, 2026
527e5c5
SEP-2663: Add auth check requirement to security implications
LucaButBoring May 13, 2026
1d3813a
SEP-2663: Rename notifications/tasks/status to notifications/tasks
LucaButBoring May 13, 2026
25d1c9d
SEP-2663: Move detailed task types into task status section
LucaButBoring May 13, 2026
b15331e
SEP-2663: Add explicit polling response requirements
LucaButBoring May 13, 2026
2dba297
SEP-2663: Disallow progress/logging notifications on tasks
LucaButBoring May 13, 2026
1152e58
SEP-2663: Add spec language for client behavior on inputRequests
LucaButBoring May 13, 2026
7a66448
SEP-2663: Use relative MRTR link instead of absolute URL
LucaButBoring May 13, 2026
f2aca22
SEP-2663: Reformat document
LucaButBoring May 13, 2026
470072b
SEP-2663: Accepted
LucaButBoring May 13, 2026
5b2c24d
Update seps/2663-tasks-extension.md
LucaButBoring May 15, 2026
91d72e9
SEP-2663: Remove task examples and reformat
LucaButBoring May 15, 2026
38ece65
SEP-2663: Add changelog entry
LucaButBoring May 15, 2026
c47bd84
Merge branch 'main' into feat/ext-tasks
LucaButBoring May 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions docs/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,12 @@
"extensions/auth/oauth-client-credentials",
"extensions/auth/enterprise-managed-authorization"
]
},
{
"group": "MCP Tasks",
"pages": [
"extensions/tasks/overview"
]
}
]
},
Expand Down Expand Up @@ -324,7 +330,6 @@
"specification/draft/basic/utilities/cancellation",
"specification/draft/basic/utilities/progress",
"specification/draft/basic/utilities/subscriptions",
"specification/draft/basic/utilities/tasks",
"specification/draft/basic/utilities/mrtr"
]
}
Expand Down Expand Up @@ -424,7 +429,8 @@
"seps/2149-working-group-charter-template",
"seps/2243-http-standardization",
"seps/2260-Require-Server-requests-to-be-associated-with-Client-requests",
"seps/2567-sessionless-mcp"
"seps/2567-sessionless-mcp",
"seps/2663-tasks-extension"
]
},
{
Expand Down Expand Up @@ -666,6 +672,10 @@
"source": "/docs/extensions/apps",
"destination": "/extensions/apps/overview"
},
{
"source": "/docs/extensions/tasks",
"destination": "/extensions/tasks/overview"
},
{
"source": "/community/seps",
"destination": "/seps"
Expand Down
6 changes: 6 additions & 0 deletions docs/extensions/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ Official extensions live inside the [Model Context Protocol GitHub organization]

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).

### MCP Tasks

| Extension | Description |
| --------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| [MCP Tasks](/extensions/tasks/overview) | Asynchronous task execution for long-running operations, with polling, mid-flight input, and durable handles. |

## Experimental Extensions

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.
Expand Down
267 changes: 267 additions & 0 deletions docs/extensions/tasks/overview.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,267 @@
---
title: MCP Tasks
description: Asynchronous task execution for long-running MCP operations
---

The [experimental-ext-tasks repository](https://github.com/modelcontextprotocol/experimental-ext-tasks) contains the full specification and documentation for MCP Tasks.

@hvent90 hvent90 May 22, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would love for my mcp server to be able to attach p50/p90/p95 metrics to a task to help shape the polling frequency of the harness. where would be the appropriate place to submit this proposal?


<Card
title="modelcontextprotocol/experimental-ext-tasks"
icon="github"
href="https://github.com/modelcontextprotocol/experimental-ext-tasks"
>
Full specification and documentation for MCP Tasks.
</Card>

Not every tool call returns instantly. Some operations — CI pipelines, batch
processing, human approvals — take seconds, minutes, or longer. MCP Tasks let
servers return a durable handle instead of blocking, so clients can poll for
progress, provide input when needed, and retrieve the final result after
reconnecting.

## Why not just block?

You could hold the connection open until the work finishes. Tasks solve
problems that blocking cannot:

- **No long-lived connections.** Blocking ties up a connection for the duration
of the operation. Many clients and transport intermediaries impose timeouts
that make this impractical beyond a few seconds.
- **Crash resilience.** A task ID is a durable handle. If the client
disconnects or restarts, it can resume polling with the same ID.
- **Progress visibility.** Tasks carry status metadata (`working`,
`input_required`, `completed`, `failed`, `cancelled`) and optional status
messages, giving clients visibility into progress.
- **Mid-flight interaction.** When a task needs input (e.g., an elicitation for
user confirmation), it moves to `input_required` and surfaces the request.
The client responds via `tasks/update` — no second connection or unsolicited
server-to-client messages required.
- **Server-directed.** The server decides per-request whether to create a task.
Clients opt in once via the extension capability and handle whichever result
shape arrives. No per-tool warmup or per-request flag.

## How Tasks work

Tasks extend the standard request flow. When a server decides a request will be
long-running, it returns a task handle instead of the final result. The client
polls for completion.

1. **Capability negotiation.** The client includes
`io.modelcontextprotocol/tasks` in its per-request capabilities. The server
advertises the same extension in its own `server/discover` capabilities.

2. **Task creation.** In response to a supported request, the server returns a
`CreateTaskResult` (identified by `resultType: "task"`) containing a `taskId`,
initial status, TTL, and suggested polling interval. The task is durably
created before the response is sent.

3. **Polling.** The client calls `tasks/get` with the `taskId`. The response
carries the current status and, for terminal states, the final result or
error.

4. **Mid-flight input.** If the task moves to `input_required`, the `tasks/get`
response includes an `inputRequests` map with elicitations or other server
requests. The client fulfills these via `tasks/update`.

5. **Completion.** When the status reaches `completed`, the `result` field
contains what the original request would have returned synchronously. If the
status is `failed`, the `error` field contains the JSON-RPC error.

6. **Cancellation.** The client can send `tasks/cancel` at any time.
Cancellation is cooperative — the server acknowledges the intent but is not
obligated to stop the work.

```mermaid
sequenceDiagram
participant Client
participant Server

Client->>Server: tools/call (with tasks capability)
Server-->>Client: CreateTaskResult (taskId, status: working)

loop Poll until terminal
Client->>Server: tasks/get (taskId)
Server-->>Client: Task (status: working)
end

Note over Client,Server: Server needs user input
Client->>Server: tasks/get (taskId)
Server-->>Client: Task (status: input_required, inputRequests)
Client->>Server: tasks/update (taskId, inputResponses)
Server-->>Client: ack

loop Poll until terminal
Client->>Server: tasks/get (taskId)
Server-->>Client: Task (status: working)
end

Client->>Server: tasks/get (taskId)
Server-->>Client: Task (status: completed, result)
```

## When to use Tasks

Tasks are a good fit when your use case involves:

**Long-running operations.** CI pipelines, batch data processing, or model
training jobs that take minutes or hours.

**Human-in-the-loop workflows.** Approval gates, review steps, or any operation
that pauses for user confirmation. The task moves to `input_required` and the
client presents the request.

**External job systems.** If your server wraps an API that already uses job IDs
(cloud deployments, async APIs, queued work), return a task when you create the
job and resolve it when the job completes.

**Unreliable connections.** Mobile clients, intermittent networks, or
environments where connections drop. Task IDs survive disconnects.

**Batch processing.** Operations that process many items (bulk imports, mass
updates) where partial progress is meaningful. Status messages report progress.

## Task lifecycle

| Status | Meaning |
| ---------------- | -------------------------------------------------------------------------- |
| `working` | The operation is in progress. |
| `input_required` | The server needs client input before continuing. See `inputRequests`. |
| `completed` | The operation finished. The `result` field contains the final output. |
| `failed` | A JSON-RPC error occurred during execution. The `error` field has details. |
| `cancelled` | The operation was cancelled (not always honored). |

`completed`, `failed`, and `cancelled` are terminal — once reached, the task's
state does not change.

## Notifications

Servers can push status updates via `notifications/tasks/status`. Clients opt
into these through the `subscriptions/listen` mechanism. Each notification
carries the full task state, eliminating the need for an extra `tasks/get`
round-trip.

Polling is the default. If a server supports notifications, clients can rely on
them instead of polling.

## Implementation guide

### For MCP clients

To consume task-augmented responses, your client must:

<Steps>
<Step title="Declare support">

Include the extension in per-request capabilities:

```json
{
"params": {
"_meta": {
"io.modelcontextprotocol/clientCapabilities": {
"extensions": {
"io.modelcontextprotocol/tasks": {}
}
}
}
}
}
```

</Step>
<Step title="Handle polymorphic results">

When issuing a supported request (e.g., `tools/call`), be prepared to receive
either the standard result or a `CreateTaskResult` with `resultType: "task"`.

</Step>
<Step title="Poll for completion">

Call `tasks/get` with the returned `taskId`, respecting the `pollIntervalMs`
value. Continue polling until the task reaches a terminal status (`completed`,
`failed`, or `cancelled`).

</Step>
<Step title="Handle input requests">

If the task status is `input_required`, read the `inputRequests` map, present
the requests to the user or model, and submit responses via `tasks/update`.

</Step>
<Step title="Persist task IDs">

Store task IDs durably so polling can resume after a client crash or restart.

</Step>
</Steps>

### For MCP servers

To return tasks from your server:

<Steps>
<Step title="Advertise support">

Include the extension in your `server/discover` capabilities:

```json
{
"capabilities": {
"extensions": {
"io.modelcontextprotocol/tasks": {}
}
}
}
```

</Step>
<Step title="Check client capabilities">

Before returning a `CreateTaskResult`, verify that the client included the
extension in its per-request capabilities. Never return a task to a client that
did not declare support.

</Step>
<Step title="Return CreateTaskResult">

When a request will be long-running, respond with `resultType: "task"` and a
`Task` object containing a unique `taskId`, initial status, `ttlMs`, and
`pollIntervalMs`. The task must be durably created before sending the response.

</Step>
<Step title="Serve tasks/get">

Return the current task state on each poll. For terminal states, include the
`result` (on `completed`) or `error` (on `failed`) field.

</Step>
<Step title="Handle tasks/update">

Accept `inputResponses` keyed to outstanding `inputRequests`. Acknowledge with
an empty result. Ignore responses for unknown or already-satisfied keys.

</Step>
<Step title="Handle tasks/cancel">

Acknowledge cancellation requests with an empty result. Honor them when
possible, but cancellation is cooperative — the task may still reach a
non-`cancelled` terminal status.

</Step>
</Steps>

## Client support

<Note>

MCP Tasks is an extension to the [core MCP specification](/specification). Host
support varies by client.

</Note>

See the [client matrix](/extensions/client-matrix) for extension support across
clients. Task support requires explicit opt-in from both client and server.

## Specification

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.
Loading
Loading