Protocol Revision: draft
Tasks were introduced in version 2025-11-25 of the MCP specification and are currently considered experimental.
The design and behavior of tasks may evolve in future protocol versions.
Definitions
Tasks represent parties as either “requestors” or “receivers,” defined as follows:- Requestor: The sender of a task-augmented request. This can be the client or the server — either can create tasks.
- Receiver: The receiver of a task-augmented request, and the entity executing the task. This can be the client or the server — either can receive and execute tasks.
User Interaction Model
Tasks are designed to be requestor-driven - requestors are responsible for augmenting requests with tasks and for polling for the results of those tasks; meanwhile, receivers tightly control which requests (if any) support task-based execution and manages the lifecycles of those tasks. This requestor-driven approach ensures deterministic response handling and enables sophisticated patterns such as dispatching concurrent requests, which only the requestor has sufficient context to orchestrate. Implementations are free to expose tasks through any interface pattern that suits their needs — the protocol itself does not mandate any specific user interaction model.Capabilities
Servers and clients that support task-augmented requests MUST declare atasks capability during initialization. The tasks capability is structured by request category, with boolean properties indicating which specific request types support task augmentation.
Server Capabilities
Servers declare if they support tasks, and if so, which server-side requests can be augmented with tasks.| Capability | Description |
|---|---|
tasks.list | Server supports the tasks/list operation |
tasks.cancel | Server supports the tasks/cancel operation |
tasks.requests.tools.call | Server supports task-augmented tools/call requests |
Client Capabilities
Clients declare if they support tasks, and if so, which client-side requests can be augmented with tasks.| Capability | Description |
|---|---|
tasks.list | Client supports the tasks/list operation |
tasks.cancel | Client supports the tasks/cancel operation |
tasks.requests.sampling.createMessage | Client supports task-augmented sampling/createMessage requests |
tasks.requests.elicitation.create | Client supports task-augmented elicitation/create requests |
Capability Negotiation
During the initialization phase, both parties exchange theirtasks capabilities to establish which operations support task-based execution. Requestors SHOULD only augment requests with a task if the corresponding capability has been declared by the receiver.
For example, if a server’s capabilities include tasks.requests.tools.call: {}, then clients may augment tools/call requests with a task. If a client’s capabilities include tasks.requests.sampling.createMessage: {}, then servers may augment sampling/createMessage requests with a task.
If capabilities.tasks is not defined, the peer SHOULD NOT attempt to create tasks during requests.
The set of capabilities in capabilities.tasks.requests is exhaustive. If a request type is not present, it does not support task-augmentation.
capabilities.tasks.list controls if the tasks/list operation is supported by the party.
capabilities.tasks.cancel controls if the tasks/cancel operation is supported by the party.
Tool-Level Negotiation
Tool calls are given special consideration for the purpose of task augmentation. In the result oftools/list, tools declare support for tasks via annotations.taskHint, which if present can have a value of "always", "optional", or "never".
This is to be interpreted as a fine-grained layer in addition to capabilities, following these rules:
- If a server’s capabilities include
tasks.requests.tools.call: false, then clients MUST NOT attempt to use task augmentation on that server’s tools, regardless of thetaskHintvalue. - If a server’s capabilities include
tasks.requests.tools.call: true, then clients consider the value oftaskHint, and handle it accordingly:- If
taskHintis not present or"never", clients MUST NOT attempt to invoke the tool as a task. Servers SHOULD return a-32601(Method not found) error if a client attempts to do so. This is the default behavior. - If
taskHintis"optional", clients MAY invoke the tool as a task or as a normal request. - If
taskHintis"always", clients SHOULD invoke the tool as a task. Servers MAY return a-32601(Method not found) error if a client does not attempt to do so.
- If
Protocol Messages
Creating Tasks
Task-augmented requests follow a two-phase response pattern that differs from normal requests:- Normal requests: The server processes the request and returns the actual operation result directly.
- Task-augmented requests: The server accepts the request and immediately returns a
CreateTaskResultcontaining task data. The actual operation result becomes available later throughtasks/resultafter the task completes.
task field included in the request params. Requestors MAY include a ttl value indicating the desired task lifetime duration (in milliseconds) since its creation.
Request:
CreateTaskResult containing task data. The response does not include the actual operation result. The actual result (e.g., tool result for tools/call) becomes available only through tasks/result after the task completes.
When a task is created in response to a
tools/call request, host applications may wish to return control to the model while the task is executing. This allows the model to continue processing other requests or perform additional work while waiting for the task to complete.To support this pattern, servers can provide an optional io.modelcontextprotocol/model-immediate-response key in the _meta field of the CreateTaskResult. The value of this key should be a string intended to be passed as an immediate tool result to the model.
If a server does not provide this field, the host application can fall back to its own predefined message.This guidance is non-binding and is provisional logic intended to account for the specific use case. This behavior may be formalized or modified as part of CreateTaskResult in future protocol versions.Getting Tasks
Requestors poll for task completion by sendingtasks/get requests.
Requestors SHOULD respect the pollInterval provided in responses when determining polling frequency.
Requestors SHOULD continue polling until the task reaches a terminal status (completed, failed, or cancelled), or until encountering the input_required status.
Request:
Retrieving Task Results
After a task completes the operation result is retrieved viatasks/result. This is distinct from the initial CreateTaskResult response, which contains only task data. The result structure matches the original request type (e.g., CallToolResult for tools/call).
To retrieve the result of a completed task, requestors can send a tasks/result request:
Request:
Task Status Notification
When a task status changes, receivers MAY send anotifications/tasks/status notification to inform the requestor of the change. This notification includes the full task state.
Notification:
Task object, including the updated status and statusMessage (if present). This allows requestors to access the complete task state without making an additional tasks/get request.
Requestors MUST NOT rely on receiving this notifications, as it is optional. Receivers are not required to send status notifications and may choose to only send them for certain status transitions. Requestors SHOULD continue to poll via tasks/get to ensure they receive status updates.
Listing Tasks
To retrieve a list of tasks, requestors can send atasks/list request. This operation supports pagination.
Request:
Cancelling Tasks
To explicitly cancel a task, requestors can send atasks/cancel request.
Request:
Behavior Requirements
These requirements apply to all parties that support receiving task-augmented requests.Task Support and Handling
- Receivers that do not declare the task capability for a request type MUST process requests of that type normally, ignoring any task-augmentation metadata if present.
- Receivers that declare the task capability for a request type MAY return an error for non-task-augmented requests, requiring requestors to use task augmentation.
Task ID Requirements
- Task IDs MUST be a string value.
- Task IDs MUST be generated by the receiver when creating a task.
- Task IDs MUST be unique among all tasks controlled by the receiver.
Task Status Lifecycle
- Tasks MUST begin in the
workingstatus when created. - Receivers MUST only transition tasks through the following valid paths:
- From
working: may move toinput_required,completed,failed, orcancelled - From
input_required: may move toworking,completed,failed, orcancelled - Tasks with a
completed,failed, orcancelledstatus are in a terminal state and MUST NOT transition to any other status
- From
Input Required Status
With the Streamable HTTP (SSE) transport, servers often close SSE streams after delivering a response message, which can lead to ambiguity regarding the stream used for subsequent task messages.Implementations have flexibility in how they manage SSE streams during task polling and result retrieval.
One possible approach is maintaining an SSE stream on
tasks/result (see notes on the input_required status).
Where possible, servers SHOULD NOT upgrade to an SSE stream in response to a tasks/get request, as the client has indicated it wishes to poll for a result.While this note is not prescriptive regarding the specific usage of SSE streams, all implementations MUST continue to comply with the existing Streamable HTTP transport specification.- When the task receiver has messages for the requestor that are necessary to complete the task, the receiver SHOULD move the task to the
input_requiredstatus. - The receiver MUST include the
io.modelcontextprotocol/related-taskmetadata in the request to associate it with the task. - When the requestor encounters the
input_requiredstatus, it SHOULD preemptively calltasks/result. - When the receiver receives all required input, the task SHOULD transition out of
input_requiredstatus (typically back toworking).
TTL and Resource Management
- Receivers MUST include a
createdAtISO 8601-formatted timestamp in all task responses to indicate when the task was created. - Receivers MAY override the requested
ttlduration. - Receivers MUST include the actual
ttlduration (ornullfor unlimited) intasks/getresponses. - After a task’s
ttllifetime has elapsed, receivers MAY delete the task and its results, regardless of the task status. - Receivers MAY include a
pollIntervalvalue (in milliseconds) intasks/getresponses to suggest polling intervals. Requestors SHOULD respect this value when provided.
Result Retrieval
- Receivers that accept a task-augmented request MUST return a
CreateTaskResultas the response. This result SHOULD be returned as soon as possible after accepting the task. - When a receiver receives a
tasks/resultrequest for a task in a terminal status (completed,failed, orcancelled), it MUST return the final result of the underlying request, whether that is a successful result or a JSON-RPC error. - When a receiver receives a
tasks/resultrequest for a task in any other non-terminal status (workingorinput_required), it MUST block the response until the task reaches a terminal status. - For tasks in a terminal status, receivers MUST return from
tasks/resultexactly what the underlying request would have returned, whether that is a successful result or a JSON-RPC error.
Associating Task-Related Messages
- All requests, notifications, and responses related to a task MUST include the
io.modelcontextprotocol/related-taskkey in their_metafield, with the value set to an object with ataskIdmatching the associated task ID.- For example, an elicitation that a task-augmented tool call depends on MUST share the same related task ID with that tool call’s task.
- For the
tasks/get,tasks/result, andtasks/canceloperations, thetaskIdparameter in the request MUST be used as the source of truth for identifying the target task. Requestors SHOULD NOT includeio.modelcontextprotocol/related-taskmetadata in these requests, and receivers MUST ignore such metadata if present in favor of the RPC method parameter. Similarly, for thetasks/get,tasks/list, andtasks/canceloperations, receivers SHOULD NOT includeio.modelcontextprotocol/related-taskmetadata in the result messages, as thetaskIdis already present in the response structure.
Task Notifications
- Receivers MAY send
notifications/tasks/statusnotifications when a task’s status changes. - Requestors MUST NOT rely on receiving the
notifications/tasks/statusnotification, as it is optional. - When sent, the
notifications/tasks/statusnotification SHOULD NOT include theio.modelcontextprotocol/related-taskmetadata, as the task ID is already present in the notification parameters.
Task Progress Notifications
Task-augmented requests support progress notifications as defined in the progress specification. TheprogressToken provided in the initial request remains valid throughout the task lifetime.
Task Listing
- Receivers SHOULD use cursor-based pagination to limit the number of tasks returned in a single response.
- Receivers MUST include a
nextCursorin the response if more tasks are available. - Requestors MUST treat cursors as opaque tokens and not attempt to parse or modify them.
- If a task is retrievable via
tasks/getfor a requestor, it MUST be retrievable viatasks/listfor that requestor.
Task Cancellation
- Receivers MUST reject cancellation requests for tasks already in a terminal status (
completed,failed, orcancelled) with error code-32602(Invalid params). - Upon receiving a valid cancellation request, receivers SHOULD attempt to stop the task execution and MUST transition the task to
cancelledstatus before sending the response. - Once a task is cancelled, it MUST remain in
cancelledstatus even if execution continues to completion or fails. - The
tasks/canceloperation does not define deletion behavior. However, receivers MAY delete cancelled tasks at their discretion at any time, including immediately after cancellation or after the taskttlexpires. - Requestors SHOULD NOT rely on cancelled tasks being retained for any specific duration and should retrieve any needed information before cancelling.
Message Flow
Basic Task Lifecycle
Task-Augmented Tool Call With Elicitation
Task-Augmented Sampling Request
Task Cancellation Flow
Data Types
Task
A task represents the execution state of a request. The task state includes:taskId: Unique identifier for the taskstatus: Current state of the task executionstatusMessage: Optional human-readable message describing the current state (can be present for any status, including error details for failed tasks)createdAt: ISO 8601 timestamp when the task was createdttl: Time in milliseconds from creation before task may be deletedpollInterval: Suggested time in milliseconds between status checks
Task Status
Tasks can be in one of the following states:working: The request is currently being processed.input_required: The receiver needs input from the requestor. The requestor should calltasks/resultto receive input requests, even though the task has not reached a terminal state.completed: The request completed successfully and results are available.failed: The associated request did not complete successfully. For tool calls specifically, this includes cases where the tool call result hasisErrorset to true.cancelled: The request was cancelled before completion.
Task Parameters
When augmenting a request with task execution, thetask field is included in the request parameters:
ttl(number, optional): Requested duration in milliseconds to retain task from creation
Related Task Metadata
All requests, responses, and notifications associated with a task MUST include theio.modelcontextprotocol/related-task key in _meta:
tasks/get, tasks/list, and tasks/cancel operations, requestors and receivers SHOULD NOT include this metadata in their messages, as the taskId is already present in the message structure.
The tasks/result operation MUST include this metadata in its response, as the result structure itself does not contain the task ID.
Error Handling
Tasks use two error reporting mechanisms:- Protocol Errors: Standard JSON-RPC errors for protocol-level issues
- Task Execution Errors: Errors in the underlying request execution, reported through task status
Protocol Errors
Receivers MUST return standard JSON-RPC errors for the following protocol error cases:- Invalid or nonexistent
taskIdintasks/get,tasks/result, ortasks/cancel:-32602(Invalid params) - Invalid or nonexistent cursor in
tasks/list:-32602(Invalid params) - Attempt to cancel a task already in a terminal status:
-32602(Invalid params) - Internal errors:
-32603(Internal error)
- Non-task-augmented request when receiver requires task augmentation for that request type:
-32600(Invalid request)
Receivers are not required to retain tasks indefinitely. It is compliant behavior for a receiver to return an error stating the task cannot be found if it has purged an expired task.
Task Execution Errors
When the underlying request does not complete successfully, the task moves to thefailed status. This includes JSON-RPC protocol errors during request execution, or for tool calls specifically, when the tool result has isError set to true. The tasks/get response SHOULD include a statusMessage field with diagnostic information about the failure.
Example: Task with execution error
isError set to true, the task should reach failed status.
The tasks/result endpoint returns exactly what the underlying request would have returned:
- If the underlying request resulted in a JSON-RPC error,
tasks/resultMUST return that same JSON-RPC error. - If the request completed with a JSON-RPC response,
tasks/resultMUST return a successful JSON-RPC response containing that result.
Security Considerations
Task Isolation and Access Control
Task IDs are the primary mechanism for accessing task state and results. Without proper access controls, any party that can guess or obtain a task ID could potentially access sensitive information or manipulate tasks they did not create. When an authorization context is provided, receivers MUST bind tasks to said context. Context-binding is not practical for all applications. Some MCP servers operate in environments without authorization, such as single-user tools, or use transports that don’t support authorization. In these scenarios, receivers SHOULD document this limitation clearly, as task results may be accessible to any requestor that can guess the task ID. If context-binding is unavailable, receivers MUST generate cryptographically secure task IDs with enough entropy to prevent guessing and should consider using shorter TTL durations to reduce the exposure window. If context-binding is available, receivers MUST rejecttasks/get, tasks/result, and tasks/cancel requests for tasks that do not belong to the same authorization context as the requestor. For tasks/list requests, receivers MUST ensure the returned task list includes only tasks associated with the requestor’s authorization context.
Additionally, receivers SHOULD implement rate limiting on task operations to prevent denial-of-service and enumeration attacks.
Resource Management
- Receivers SHOULD:
- Enforce limits on concurrent tasks per requestor
- Enforce maximum
ttldurations to prevent indefinite resource retention - Clean up expired tasks promptly to free resources
- Document maximum supported
ttlduration - Document maximum concurrent tasks per requestor
- Implement monitoring and alerting for resource usage
Audit and Logging
- Receivers SHOULD:
- Log task creation, completion, and retrieval events for audit purposes
- Include auth context in logs when available
- Monitor for suspicious patterns (e.g., many failed task lookups, excessive polling)
- Requestors SHOULD:
- Log task lifecycle events for debugging and audit purposes
- Track task IDs and their associated operations