From 08116acb164e83a68713000462866312f2f722ba Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Wed, 29 Oct 2025 14:31:12 -0700 Subject: [PATCH 01/79] Write specification for SEP-1686: Tasks --- docs/docs.json | 3 +- .../draft/basic/utilities/tasks.mdx | 650 ++++++++++++++++++ 2 files changed, 652 insertions(+), 1 deletion(-) create mode 100644 docs/specification/draft/basic/utilities/tasks.mdx diff --git a/docs/docs.json b/docs/docs.json index 96dbbe76c..d30617189 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -231,7 +231,8 @@ "pages": [ "specification/draft/basic/utilities/cancellation", "specification/draft/basic/utilities/ping", - "specification/draft/basic/utilities/progress" + "specification/draft/basic/utilities/progress", + "specification/draft/basic/utilities/tasks" ] } ] diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx new file mode 100644 index 000000000..a65c41948 --- /dev/null +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -0,0 +1,650 @@ +--- +title: Tasks +--- + +
+ +**Protocol Revision**: draft + +The Model Context Protcol (MCP) allows requestors (which can be either clients or servers, depending on the direction of communication) to augment their requests with **tasks**. Tasks are durable state machines that carry information about the underlying execution state of the request they wrap, and are intended for requestor polling and deferred result retrieval. Each task is uniquely identifiable by a requestor-generated, idempotent **task ID**. + +## User Interaction Model + +Tasks are designed to be **application-driven**—receivers tightly-control which requests (if any) support task-based execution and manage the lifecycles of those tasks; meanwhile, requestors own the responsibility for augmenting requests with tasks, and for polling on the results of those tasks. + +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 + +Unlike other protocol features, tasks _do not_ require capabilities to be declared. + +## Protocol Messages + +### Creating Tasks + +To create a task, requestors send a request with the `modelcontextprotocol.io/task` key included in `_meta`, with a `taskId` value representing the task ID. Requestors **MAY** include a `keepAlive`, with a value representing how long after completion the requestor would like the task results to be kept for. + +**Request:** + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "method": "some_method", + "params": { + "_meta": { + "modelcontextprotocol.io/task": { + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", + "keepAlive": 60000 + } + } + } +} +``` + +### Getting Tasks + +To retrieve the state of a task, requestors send a `tasks/get` request: + +**Request:** + +```json +{ + "jsonrpc": "2.0", + "id": 3, + "method": "tasks/get", + "params": { + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", + "_meta": { + "modelcontextprotocol.io/related-task": { + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" + } + } + } +} +``` + +**Response:** + +```json +{ + "jsonrpc": "2.0", + "id": 3, + "result": { + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", + "keepAlive": 30000, + "pollFrequency": 5000, + "status": "submitted", + "_meta": { + "modelcontextprotocol.io/related-task": { + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" + } + } + } +} +``` + +### Retrieving Task Results + +To retrieve the result of a completed task, requestors send a `tasks/result` request: + +**Request:** + +```json +{ + "jsonrpc": "2.0", + "id": 4, + "method": "tasks/result", + "params": { + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", + "_meta": { + "modelcontextprotocol.io/related-task": { + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" + } + } + } +} +``` + +**Response:** + +```json +{ + "jsonrpc": "2.0", + "id": 4, + "result": { + "content": [ + { + "type": "text", + "text": "Current weather in New York:\nTemperature: 72°F\nConditions: Partly cloudy" + } + ], + "isError": false, + "_meta": { + "modelcontextprotocol.io/related-task": { + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" + } + } + } +} +``` + +### Task Creation Notification + +When a receiver creates a task, it **MUST** send a `notifications/tasks/created` notification to inform the requestor that the task has been created and polling can begin. + +**Notification:** + +```json +{ + "jsonrpc": "2.0", + "method": "notifications/tasks/created", + "params": { + "_meta": { + "modelcontextprotocol.io/related-task": { + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" + } + } + } +} +``` + +The task ID is conveyed through the `modelcontextprotocol.io/related-task` metadata key. The notification parameters are otherwise empty. + +This notification resolves the race condition where a requestor might attempt to poll for a task before the receiver has finished creating it. By sending this notification immediately after task creation, the receiver signals that the task is ready to be queried via `tasks/get`. + +Receivers that do not support tasks (and thus ignore task metadata in requests) will not send this notification, allowing requestors to fall back to waiting for the original request response. + +### Listing Tasks + +To retrieve a list of tasks, requestors send a `tasks/list` request. This operation supports pagination. + +**Request:** + +```json +{ + "jsonrpc": "2.0", + "id": 5, + "method": "tasks/list", + "params": { + "cursor": "optional-cursor-value" + } +} +``` + +**Response:** + +```json +{ + "jsonrpc": "2.0", + "id": 5, + "result": { + "tasks": [ + { + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", + "status": "working", + "keepAlive": 30000, + "pollFrequency": 5000 + }, + { + "taskId": "abc123-def456-ghi789", + "status": "completed", + "keepAlive": 60000 + } + ], + "nextCursor": "next-page-cursor" + } +} +``` + +## Behavior Requirements + +These requirements apply to all parties that support receiving task-augmented requests. + +### Task Support and Handling + +1. Receivers that do not support task augmentation on a request **MUST** process the request normally, ignoring any task metadata in `_meta`. +1. Receivers that support task augmentation **MAY** choose which request types support tasks. + +### Task ID Requirements + +1. Task IDs **MUST** be a string value. +1. Task IDs **MUST** be unique across all tasks controlled by the receiver. +1. The receiver of a request with a task ID in its `_meta` **MUST** validate that the provided task ID has not already been associated with a task controlled by that receiver. + +### Task Status Lifecycle + +1. Tasks **MUST** begin in the `submitted` status when created. +1. Receivers **MUST** only transition tasks through the following valid paths: + 1. From `submitted`: may move to `working`, `input_required`, `completed`, `failed`, `cancelled`, or `unknown` + 1. From `working`: may move to `input_required`, `completed`, `failed`, `cancelled`, or `unknown` + 1. From `input_required`: may move to `working`, `completed`, `failed`, `cancelled`, or `unknown` + 1. Tasks in `completed`, `failed`, `cancelled`, or `unknown` status **MUST NOT** transition to any other status (terminal states) +1. Receivers **MAY** move directly from `submitted` to `completed` if execution completes immediately. +1. The `unknown` status is a terminal fallback state for unexpected error conditions. Receivers **SHOULD** use `failed` with an error message instead when possible. + +**Task Status State Diagram:** + +```mermaid +stateDiagram-v2 + [*] --> submitted + + submitted --> working + submitted --> terminal + + working --> input_required + working --> terminal + + input_required --> working + input_required --> terminal + + terminal --> [*] + + note right of terminal + Terminal states: + • completed + • failed + • cancelled + • unknown + end note +``` + +### Input Required Status + +1. When a receiver sends a request associated with a task (e.g., elicitation, sampling), the receiver **MUST** move the task to the `input_required` status. +1. The receiver **MUST** include the `modelcontextprotocol.io/related-task` metadata in the request to associate it with the task. +1. When the receiver receives all required responses, the task **MAY** transition out of `input_required` status (typically back to `working`). +1. If multiple related requests are pending, the task **SHOULD** remain in `input_required` status until all are resolved. + +### Keep-Alive and Resource Management + +1. Receivers **MAY** override the requested `keepAlive` duration. +1. Receivers **MUST** include the actual `keepAlive` duration (or `null` for unlimited) in `tasks/get` responses. +1. After a task reaches a terminal status (`completed`, `failed`, or `cancelled`) and its `keepAlive` duration has elapsed, receivers **MAY** delete the task and its results. +1. Receivers **MAY** include a `pollFrequency` value (in milliseconds) in `tasks/get` responses to suggest polling intervals. Requestors **SHOULD** respect this value when provided. + +### Result Retrieval + +1. Receivers **MUST** only return results from `tasks/result` when the task status is `completed`. +1. Receivers **MUST** return an error if `tasks/result` is called for a task in any other status. +1. Requestors **MAY** call `tasks/result` multiple times for the same task while it remains available. + +### Associating Task-Related Messages + +1. All requests, notifications, and responses related to a task **MUST** include the `modelcontextprotocol.io/related-task` key in their `_meta`, with the value set to an object with a `taskId` matching the associated task ID. +1. 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. + +### Task Cancellation + +1. When a receiver receives a `notifications/cancelled` notification for the JSON-RPC request ID of a task-augmented request, the receiver **SHOULD** immediately move the task to the `cancelled` status and cease all processing associated with that task. +1. Due to the asynchronous nature of notifications, receivers **MAY** not cancel task processing instantaneously. Receivers **SHOULD** make a best-effort attempt to halt execution as quickly as possible. +1. If a `notifications/cancelled` notification arrives after a task has already reached a terminal status (`completed`, `failed`, `cancelled`, or `unknown`), receivers **SHOULD** ignore the notification. +1. After a task reaches `cancelled` status and its `keepAlive` duration has elapsed, receivers **MAY** delete the task and its metadata. +1. Requestors **MAY** send `notifications/cancelled` at any time during task execution, including when the task is in `input_required` status. If a task is cancelled while in `input_required` status, receivers **SHOULD** also disregard any pending responses to associated requests. +1. Because notifications do not provide confirmation of receipt, requestors **SHOULD** continue to poll with `tasks/get` after sending a cancellation notification to confirm the task has transitioned to `cancelled` status. If the task does not transition to `cancelled` within a reasonable timeframe, requestors **MAY** assume the cancellation was not processed. + +### Task Listing + +1. Receivers **SHOULD** use cursor-based pagination to limit the number of tasks returned in a single response. +1. Receivers **MUST** include a `nextCursor` in the response if more tasks are available. +1. Requestors **MUST** treat cursors as opaque tokens and not attempt to parse or modify them. + +## Message Flow + +### Basic Task Lifecycle + +```mermaid +sequenceDiagram + participant C as Client (Requestor) + participant S as Server (Receiver) + Note over C,S: 1. Task Creation + C->>S: Request with task metadata (taskId, keepAlive) + S--)C: notifications/tasks/created + Note over C,S: Original request will respond eventually,
but requestor uses task polling instead + Note over C,S: 2. Task Polling + C->>S: tasks/get (taskId) + S->>C: submitted + C->>S: tasks/get (taskId) + S->>C: working + Note over S: Task processing continues... + C->>S: tasks/get (taskId) + S->>C: working + Note over S: Task completes + C->>S: tasks/get (taskId) + S->>C: completed + Note over C,S: 3. Result Retrieval + C->>S: tasks/result (taskId) + S->>C: Result content + Note over C,S: 4. Cleanup + Note over S: After keepAlive period, task is cleaned up +``` + +### Task-Augmented Tool Call With Elicitation + +```mermaid +sequenceDiagram + participant U as User + participant LLM + participant C as Client (Requestor) + participant S as Server (Receiver) + + Note over LLM,C: LLM initiates request + LLM->>C: Request operation + + Note over C,S: Client augments with task metadata + C->>S: tools/call (task-123, keepAlive: 3600000) + S--)C: notifications/tasks/created + Note over C,S: Original request will respond eventually,
but client uses task polling instead + + Note over LLM,C: Client continues processing other requests
while task executes in background + LLM->>C: Request other operation + C->>LLM: Other operation result + + Note over C,S: Client polls for status + C->>S: tasks/get (task-123) + S->>C: working + + Note over S: Server requires additional information
Task moves to input_required + + Note over S,C: Server sends elicitation request + S->>C: elicitation/create (task-123) + + Note over C,S: Client polls and sees task waiting for input + C->>S: tasks/get (task-123) + S->>C: input_required + + C->>U: Prompt user for input + U->>C: Provide information + C->>S: elicitation response (task-123) + + Note over S: Task continues processing...
Task moves back to working + + Note over C,S: Client polls again + C->>S: tasks/get (task-123) + S->>C: working + + Note over S: Task completes + + Note over C,S: Client polls and discovers completion + C->>S: tasks/get (task-123) + S->>C: completed + + Note over C,S: Client retrieves final results + C->>S: tasks/result (task-123) + S->>C: Result content + C->>LLM: Process result + + Note over S: Results retained for keepAlive period +``` + +### Task-Augmented Sampling Request + +```mermaid +sequenceDiagram + participant U as User + participant LLM + participant C as Client (Receiver) + participant S as Server (Requestor) + + Note over S: Server decides to initiate request + + Note over S,C: Server requests client operation (task-augmented) + S->>C: sampling/createMessage (request-789, keepAlive: 3600000) + C--)S: notifications/tasks/created + Note over S,C: Original request will respond eventually,
but server uses task polling instead + + Note over S: Server continues processing
while waiting for result + + Note over S,C: Server polls for result + S->>C: tasks/get (request-789) + C->>S: working + + Note over C,U: Client may present request to user + C->>U: Review request + U->>C: Approve request + + Note over C,LLM: Client may involve LLM + C->>LLM: Request completion + LLM->>C: Return completion + + Note over C,U: Client may present result to user + C->>U: Review result + U->>C: Approve result + + Note over S,C: Server polls and discovers completion + S->>C: tasks/get (request-789) + C->>S: completed + + Note over S,C: Server retrieves result + S->>C: tasks/result (request-789) + C->>S: Result content + + Note over S: Server continues processing + + Note over C: Results retained for keepAlive period +``` + +### Task Cancellation Flow + +```mermaid +sequenceDiagram + participant C as Client (Requestor) + participant S as Server (Receiver) + + Note over C,S: 1. Task Creation + C->>S: tools/call (request ID: 42, task-123) + S--)C: notifications/tasks/created + + Note over C,S: 2. Task Processing + C->>S: tasks/get (task-123) + S->>C: working + + Note over C,S: 3. Client Cancellation + Note over C: User requests cancellation + C--)S: notifications/cancelled (requestId: 42) + + Note over S: Server processes cancellation + Note over S: Task moves to cancelled status + + Note over C,S: 4. Confirmation Polling + C->>S: tasks/get (task-123) + S->>C: cancelled + + Note over C: Client confirms cancellation succeeded + + Note over S: After keepAlive period, task cleaned up +``` + +## Data Types + +### Task + +A task represents the execution state of a request. The task metadata includes: + +- `taskId`: Unique identifier for the task +- `keepAlive`: Time in milliseconds that results will be kept available after completion +- `pollFrequency`: Suggested time in milliseconds between status checks +- `status`: Current state of the task execution + +### Task Status + +Tasks can be in one of the following states: + +- `submitted`: The request has been received and queued for execution +- `working`: The request is currently being processed +- `completed`: The request completed successfully and results are available +- `failed`: The request encountered an error during execution +- `cancelled`: The request was cancelled before completion +- `unknown`: A terminal fallback state for unexpected error conditions when the receiver cannot determine the actual task state + +### Task Metadata + +When augmenting a request with task execution, the `modelcontextprotocol.io/task` key is included in `_meta`: + +```json +{ + "modelcontextprotocol.io/task": { + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", + "keepAlive": 60000 + } +} +``` + +Fields: + +- `taskId` (string, required): Client-generated unique identifier for the task +- `keepAlive` (number, optional): Requested duration in milliseconds to retain results after completion + +### Related Task Metadata + +All requests, responses, and notifications associated with a task **MUST** include the `modelcontextprotocol.io/related-task` key in `_meta`: + +```json +{ + "modelcontextprotocol.io/related-task": { + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" + } +} +``` + +This associates messages with their originating task across the entire request lifecycle. + +## Error Handling + +Tasks use two error reporting mechanisms: + +1. **Protocol Errors**: Standard JSON-RPC errors for protocol-level issues +1. **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 `taskId` in `tasks/get`, `tasks/list`, or `tasks/result`: `-32602` (Invalid params) +- Invalid or nonexistent cursor in `tasks/list`: `-32602` (Invalid params) +- Request with a `taskId` that was already used for a different task: `-32602` (Invalid params) +- Attempting to retrieve result when task is not in `completed` status: `-32602` (Invalid params) +- Internal errors: `-32603` (Internal error) + +Receivers **SHOULD** provide informative error messages to describe the cause of errors. + +**Example: Task not found** + +```json +{ + "jsonrpc": "2.0", + "id": 70, + "error": { + "code": -32602, + "message": "Failed to retrieve task: Task not found" + } +} +``` + +**Example: Task expired** + +```json +{ + "jsonrpc": "2.0", + "id": 71, + "error": { + "code": -32602, + "message": "Failed to retrieve task: Task has expired" + } +} +``` + + + +Receivers are not obligated to retain task metadata indefinitely. It is compliant behavior for a receiver to return a "not-found" error if it has purged an expired task. + + + +**Example: Result requested for incomplete task** + +```json +{ + "jsonrpc": "2.0", + "id": 72, + "error": { + "code": -32602, + "message": "Cannot retrieve result: Task status is 'working', not 'completed'" + } +} +``` + +**Example: Duplicate task ID** + +```json +{ + "jsonrpc": "2.0", + "id": 73, + "error": { + "code": -32602, + "message": "Task ID already exists: 786512e2-9e0d-44bd-8f29-789f320fe840" + } +} +``` + +### Task Execution Errors + +When the underlying request fails during execution, the task moves to the `failed` status. The `tasks/get` response **SHOULD** include an `error` field with details about the failure. + +**Example: Task with execution error** + +```json +{ + "jsonrpc": "2.0", + "id": 4, + "result": { + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", + "status": "failed", + "keepAlive": 30000, + "error": "Tool execution failed: API rate limit exceeded" + } +} +``` + +For tasks that wrap requests with their own error semantics (like `tools/call` with `isError: true`), the task should still reach `completed` status, and the error information is conveyed through the result structure of the original request type. + +## Security Considerations + +### Task Isolation and Access Control + +1. Receivers **SHOULD** scope task IDs to prevent unauthorized access: + 1. Bind tasks to the session that created them (if sessions are supported) + 1. Bind tasks to the authentication context (if authentication is used) + 1. Reject `tasks/get`, `tasks/list`, or `tasks/result` requests for tasks from different sessions or auth contexts +1. Receivers that do not implement session or authentication binding **SHOULD** document this limitation clearly, as task results may be accessible to any requestor that can guess the task ID. +1. Receivers **SHOULD** implement rate limiting on: + 1. Task creation to prevent resource exhaustion + 1. Task status polling to prevent denial of service + 1. Task result retrieval attempts + 1. Task listing requests to prevent denial of service + +### Resource Management + + + +Task results may persist longer than the original request execution time. For sensitive operations, requestors should carefully consider the security implications of extended result retention and may want to retrieve results promptly and request shorter `keepAlive` durations. + + + +1. Receivers **SHOULD**: + 1. Enforce limits on concurrent tasks per requestor + 1. Enforce maximum `keepAlive` durations to prevent indefinite resource retention + 1. Clean up expired tasks promptly to free resources +1. Receivers **SHOULD**: + 1. Document maximum supported `keepAlive` duration + 1. Document maximum concurrent tasks per requestor + 1. Implement monitoring and alerting for resource usage + +### Audit and Logging + +1. Receivers **SHOULD**: + 1. Log task creation, completion, and retrieval events for audit purposes + 1. Include session/auth context in logs when available + 1. Monitor for suspicious patterns (e.g., many failed task lookups, excessive polling) +1. Requestors **SHOULD**: + 1. Log task lifecycle events for debugging and audit purposes + 1. Track task IDs and their associated operations From 74ba344cf0ceccbaebeff8b605c990c7d36366f3 Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Wed, 29 Oct 2025 15:15:18 -0700 Subject: [PATCH 02/79] Write schema for task-related types --- docs/specification/draft/schema.mdx | 60 ++++++ schema/draft/schema.json | 322 ++++++++++++++++++++++++++++ schema/draft/schema.ts | 214 +++++++++++++++++- 3 files changed, 590 insertions(+), 6 deletions(-) diff --git a/docs/specification/draft/schema.mdx b/docs/specification/draft/schema.mdx index e64a21a35..9aec78b36 100644 --- a/docs/specification/draft/schema.mdx +++ b/docs/specification/draft/schema.mdx @@ -334,6 +334,12 @@ Contains values matching the requested schema.

params?: { _meta?: { [key: string]: unknown }; [key: string]: unknown }
Type declaration
  • [key: string]: unknown
  • Optional_meta?: { [key: string]: unknown }

    See General fields: _meta for notes on _meta usage.

+## `notifications/tasks/created` + +### `TaskCreatedNotification` + +
interface TaskCreatedNotification {
  jsonrpc: "2.0";
  method: "notifications/tasks/created";
  params?: {
    _meta?: {
      "modelcontextprotocol.io/related-task"?: RelatedTaskMetadata;
      [key: string]: unknown;
    };
  };
}

A notification from the receiver to the requestor, informing them that a task has been created and is ready for polling.

params?: {
  _meta?: {
    "modelcontextprotocol.io/related-task"?: RelatedTaskMetadata;
    [key: string]: unknown;
  };
}
Type declaration
+ ## `notifications/tools/list_changed` ### `ToolListChangedNotification` @@ -440,6 +446,60 @@ or file that the server can operate on.

interface CreateMessageResult {
  _meta?: { [key: string]: unknown };
  content: TextContent | ImageContent | AudioContent;
  model: string;
  role: Role;
  stopReason?: string;
  [key: string]: unknown;
}

The client's response to a sampling/create_message request from the server. The client should inform the user before returning the sampled message, to allow them to inspect the response (human in the loop) and decide whether to allow the server to see it.

_meta?: { [key: string]: unknown }

See General fields: _meta for notes on _meta usage.

model: string

The name of the model that generated the message.

stopReason?: string

The reason why sampling stopped, if known.

+## `tasks` + +### `RelatedTaskMetadata` + +
interface RelatedTaskMetadata {
  taskId: string;
}

Metadata for associating messages with a task. +Include this in the _meta field under the key modelcontextprotocol.io/related-task.

taskId: string

The task identifier this message is associated with.

+ +### `TaskMetadata` + +
interface TaskMetadata {
  keepAlive?: number;
  taskId: string;
}

Metadata for augmenting a request with task execution. +Include this in the _meta field of a request under the key modelcontextprotocol.io/task.

keepAlive?: number

Requested duration in milliseconds to retain results after completion.

taskId: string

Client-generated unique identifier for the task.

+ +### `TaskStatus` + +
TaskStatus:
  | "submitted"
  | "working"
  | "input_required"
  | "completed"
  | "failed"
  | "cancelled"
  | "unknown"

The status of a task.

+ +## `tasks/get` + +### `GetTaskRequest` + +
interface GetTaskRequest {
  id: RequestId;
  jsonrpc: "2.0";
  method: "tasks/get";
  params: { taskId: string };
}

A request to retrieve the state of a task.

params: { taskId: string }
Type declaration
  • taskId: string

    The task identifier to query.

+ +### `GetTaskResult` + +
interface GetTaskResult {
  _meta?: { [key: string]: unknown };
  error?: string;
  keepAlive: null | number;
  pollFrequency?: number;
  status: TaskStatus;
  taskId: string;
  [key: string]: unknown;
}

The response to a tasks/get request.

_meta?: { [key: string]: unknown }

See General fields: _meta for notes on _meta usage.

error?: string

Error message if status is "failed".

keepAlive: null | number

Actual retention duration in milliseconds, null for unlimited.

pollFrequency?: number

Suggested polling interval in milliseconds.

status: TaskStatus

Current task state.

taskId: string

The task identifier.

+ +## `tasks/list` + +### `ListTasksRequest` + +
interface ListTasksRequest {
  id: RequestId;
  jsonrpc: "2.0";
  method: "tasks/list";
  params?: { cursor?: string };
}

A request to retrieve a list of tasks.

params?: { cursor?: string }
Type declaration
  • Optionalcursor?: string

    An opaque token representing the current pagination position. +If provided, the server should return results starting after this cursor.

+ +### `ListTasksResult` + +
interface ListTasksResult {
  _meta?: { [key: string]: unknown };
  nextCursor?: string;
  tasks: TaskInfo[];
  [key: string]: unknown;
}

The response to a tasks/list request.

_meta?: { [key: string]: unknown }

See General fields: _meta for notes on _meta usage.

nextCursor?: string

An opaque token representing the pagination position after the last returned result. +If present, there may be more results available.

+ +### `TaskInfo` + +
interface TaskInfo {
  error?: string;
  keepAlive: null | number;
  pollFrequency?: number;
  status: TaskStatus;
  taskId: string;
}

A summary of a task's state, as returned by tasks/list.

error?: string

Error message if status is "failed".

keepAlive: null | number

Retention duration in milliseconds, null for unlimited.

pollFrequency?: number

Suggested polling interval in milliseconds.

status: TaskStatus

Current task state.

taskId: string

The task identifier.

+ +## `tasks/result` + +### `GetTaskPayloadRequest` + +
interface GetTaskPayloadRequest {
  id: RequestId;
  jsonrpc: "2.0";
  method: "tasks/result";
  params: { taskId: string };
}

A request to retrieve the result of a completed task.

params: { taskId: string }
Type declaration
  • taskId: string

    The task identifier to retrieve results for.

+ +### `GetTaskPayloadResult` + +
interface GetTaskPayloadResult {
  _meta?: { [key: string]: unknown };
  [key: string]: unknown;
}

The response to a tasks/result request. +The structure matches the result type of the original request. +For example, a tools/call task would return CallToolResult structure.

_meta?: { [key: string]: unknown }

See General fields: _meta for notes on _meta usage.

+ ## `tools/call` ### `CallToolRequest` diff --git a/schema/draft/schema.json b/schema/draft/schema.json index 61a0ec9b4..22dca931b 100644 --- a/schema/draft/schema.json +++ b/schema/draft/schema.json @@ -274,6 +274,9 @@ { "$ref": "#/definitions/ProgressNotification" }, + { + "$ref": "#/definitions/TaskCreatedNotification" + }, { "$ref": "#/definitions/RootsListChangedNotification" } @@ -314,6 +317,15 @@ { "$ref": "#/definitions/CallToolRequest" }, + { + "$ref": "#/definitions/GetTaskRequest" + }, + { + "$ref": "#/definitions/GetTaskPayloadRequest" + }, + { + "$ref": "#/definitions/ListTasksRequest" + }, { "$ref": "#/definitions/SetLevelRequest" }, @@ -327,6 +339,15 @@ { "$ref": "#/definitions/Result" }, + { + "$ref": "#/definitions/GetTaskResult" + }, + { + "$ref": "#/definitions/GetTaskPayloadResult" + }, + { + "$ref": "#/definitions/ListTasksResult" + }, { "$ref": "#/definitions/CreateMessageResult" }, @@ -837,6 +858,124 @@ ], "type": "object" }, + "GetTaskPayloadRequest": { + "description": "A request to retrieve the result of a completed task.", + "properties": { + "id": { + "$ref": "#/definitions/RequestId" + }, + "jsonrpc": { + "const": "2.0", + "type": "string" + }, + "method": { + "const": "tasks/result", + "type": "string" + }, + "params": { + "properties": { + "taskId": { + "description": "The task identifier to retrieve results for.", + "type": "string" + } + }, + "required": [ + "taskId" + ], + "type": "object" + } + }, + "required": [ + "id", + "jsonrpc", + "method", + "params" + ], + "type": "object" + }, + "GetTaskPayloadResult": { + "additionalProperties": {}, + "description": "The response to a tasks/result request.\nThe structure matches the result type of the original request.\nFor example, a tools/call task would return CallToolResult structure.", + "properties": { + "_meta": { + "additionalProperties": {}, + "description": "See [General fields: `_meta`](/specification/draft/basic/index#meta) for notes on `_meta` usage.", + "type": "object" + } + }, + "type": "object" + }, + "GetTaskRequest": { + "description": "A request to retrieve the state of a task.", + "properties": { + "id": { + "$ref": "#/definitions/RequestId" + }, + "jsonrpc": { + "const": "2.0", + "type": "string" + }, + "method": { + "const": "tasks/get", + "type": "string" + }, + "params": { + "properties": { + "taskId": { + "description": "The task identifier to query.", + "type": "string" + } + }, + "required": [ + "taskId" + ], + "type": "object" + } + }, + "required": [ + "id", + "jsonrpc", + "method", + "params" + ], + "type": "object" + }, + "GetTaskResult": { + "description": "The response to a tasks/get request.", + "properties": { + "_meta": { + "additionalProperties": {}, + "description": "See [General fields: `_meta`](/specification/draft/basic/index#meta) for notes on `_meta` usage.", + "type": "object" + }, + "error": { + "description": "Error message if status is \"failed\".", + "type": "string" + }, + "keepAlive": { + "description": "Actual retention duration in milliseconds, null for unlimited.", + "type": "integer" + }, + "pollFrequency": { + "description": "Suggested polling interval in milliseconds.", + "type": "integer" + }, + "status": { + "$ref": "#/definitions/TaskStatus", + "description": "Current task state." + }, + "taskId": { + "description": "The task identifier.", + "type": "string" + } + }, + "required": [ + "keepAlive", + "status", + "taskId" + ], + "type": "object" + }, "Icon": { "description": "An optionally-sized icon that can be displayed in a user interface.", "properties": { @@ -1400,6 +1539,61 @@ ], "type": "object" }, + "ListTasksRequest": { + "description": "A request to retrieve a list of tasks.", + "properties": { + "id": { + "$ref": "#/definitions/RequestId" + }, + "jsonrpc": { + "const": "2.0", + "type": "string" + }, + "method": { + "const": "tasks/list", + "type": "string" + }, + "params": { + "properties": { + "cursor": { + "description": "An opaque token representing the current pagination position.\nIf provided, the server should return results starting after this cursor.", + "type": "string" + } + }, + "type": "object" + } + }, + "required": [ + "id", + "jsonrpc", + "method" + ], + "type": "object" + }, + "ListTasksResult": { + "description": "The response to a tasks/list request.", + "properties": { + "_meta": { + "additionalProperties": {}, + "description": "See [General fields: `_meta`](/specification/draft/basic/index#meta) for notes on `_meta` usage.", + "type": "object" + }, + "nextCursor": { + "description": "An opaque token representing the pagination position after the last returned result.\nIf present, there may be more results available.", + "type": "string" + }, + "tasks": { + "items": { + "$ref": "#/definitions/TaskInfo" + }, + "type": "array" + } + }, + "required": [ + "tasks" + ], + "type": "object" + }, "ListToolsRequest": { "description": "Sent from the client to request a list of tools the server has.", "properties": { @@ -1946,6 +2140,19 @@ ], "type": "object" }, + "RelatedTaskMetadata": { + "description": "Metadata for associating messages with a task.\nInclude this in the `_meta` field under the key `modelcontextprotocol.io/related-task`.", + "properties": { + "taskId": { + "description": "The task identifier this message is associated with.", + "type": "string" + } + }, + "required": [ + "taskId" + ], + "type": "object" + }, "Request": { "properties": { "method": { @@ -2416,6 +2623,9 @@ { "$ref": "#/definitions/ToolListChangedNotification" }, + { + "$ref": "#/definitions/TaskCreatedNotification" + }, { "$ref": "#/definitions/LoggingMessageNotification" } @@ -2426,6 +2636,15 @@ { "$ref": "#/definitions/PingRequest" }, + { + "$ref": "#/definitions/GetTaskRequest" + }, + { + "$ref": "#/definitions/GetTaskPayloadRequest" + }, + { + "$ref": "#/definitions/ListTasksRequest" + }, { "$ref": "#/definitions/CreateMessageRequest" }, @@ -2466,6 +2685,15 @@ { "$ref": "#/definitions/CallToolResult" }, + { + "$ref": "#/definitions/GetTaskResult" + }, + { + "$ref": "#/definitions/GetTaskPayloadResult" + }, + { + "$ref": "#/definitions/ListTasksResult" + }, { "$ref": "#/definitions/CompleteResult" } @@ -2578,6 +2806,100 @@ ], "type": "object" }, + "TaskCreatedNotification": { + "description": "A notification from the receiver to the requestor, informing them that a task has been created and is ready for polling.", + "properties": { + "jsonrpc": { + "const": "2.0", + "type": "string" + }, + "method": { + "const": "notifications/tasks/created", + "type": "string" + }, + "params": { + "properties": { + "_meta": { + "additionalProperties": {}, + "description": "The _meta field MUST include modelcontextprotocol.io/related-task with the taskId.", + "properties": { + "modelcontextprotocol.io/related-task": { + "$ref": "#/definitions/RelatedTaskMetadata" + } + }, + "type": "object" + } + }, + "type": "object" + } + }, + "required": [ + "jsonrpc", + "method" + ], + "type": "object" + }, + "TaskInfo": { + "description": "A summary of a task's state, as returned by tasks/list.", + "properties": { + "error": { + "description": "Error message if status is \"failed\".", + "type": "string" + }, + "keepAlive": { + "description": "Retention duration in milliseconds, null for unlimited.", + "type": "integer" + }, + "pollFrequency": { + "description": "Suggested polling interval in milliseconds.", + "type": "integer" + }, + "status": { + "$ref": "#/definitions/TaskStatus", + "description": "Current task state." + }, + "taskId": { + "description": "The task identifier.", + "type": "string" + } + }, + "required": [ + "keepAlive", + "status", + "taskId" + ], + "type": "object" + }, + "TaskMetadata": { + "description": "Metadata for augmenting a request with task execution.\nInclude this in the `_meta` field of a request under the key `modelcontextprotocol.io/task`.", + "properties": { + "keepAlive": { + "description": "Requested duration in milliseconds to retain results after completion.", + "type": "integer" + }, + "taskId": { + "description": "Client-generated unique identifier for the task.", + "type": "string" + } + }, + "required": [ + "taskId" + ], + "type": "object" + }, + "TaskStatus": { + "description": "The status of a task.", + "enum": [ + "cancelled", + "completed", + "failed", + "input_required", + "submitted", + "unknown", + "working" + ], + "type": "string" + }, "TextContent": { "description": "Text provided to or from an LLM.", "properties": { diff --git a/schema/draft/schema.ts b/schema/draft/schema.ts index ac992cfd7..6e5f39f48 100644 --- a/schema/draft/schema.ts +++ b/schema/draft/schema.ts @@ -994,6 +994,194 @@ export interface Tool extends BaseMetadata, Icons { _meta?: { [key: string]: unknown }; } +/* Tasks */ + +/** + * The status of a task. + * + * @category tasks + */ +export type TaskStatus = + | "submitted" // The request has been received and queued for execution + | "working" // The request is currently being processed + | "input_required" // The task is waiting for input (e.g., elicitation or sampling) + | "completed" // The request completed successfully and results are available + | "failed" // The request encountered an error during execution + | "cancelled" // The request was cancelled before completion + | "unknown"; // A terminal fallback state for unexpected error conditions + +/** + * Metadata for augmenting a request with task execution. + * Include this in the `_meta` field of a request under the key `modelcontextprotocol.io/task`. + * + * @category tasks + */ +export interface TaskMetadata { + /** + * Client-generated unique identifier for the task. + */ + taskId: string; + + /** + * Requested duration in milliseconds to retain results after completion. + */ + keepAlive?: number; +} + +/** + * Metadata for associating messages with a task. + * Include this in the `_meta` field under the key `modelcontextprotocol.io/related-task`. + * + * @category tasks + */ +export interface RelatedTaskMetadata { + /** + * The task identifier this message is associated with. + */ + taskId: string; +} + +/** + * A request to retrieve the state of a task. + * + * @category tasks/get + */ +export interface GetTaskRequest extends JSONRPCRequest { + method: "tasks/get"; + params: { + /** + * The task identifier to query. + */ + taskId: string; + }; +} + +/** + * The response to a tasks/get request. + * + * @category tasks/get + */ +export interface GetTaskResult extends Result { + /** + * The task identifier. + */ + taskId: string; + + /** + * Current task state. + */ + status: TaskStatus; + + /** + * Actual retention duration in milliseconds, null for unlimited. + */ + keepAlive: number | null; + + /** + * Suggested polling interval in milliseconds. + */ + pollFrequency?: number; + + /** + * Error message if status is "failed". + */ + error?: string; +} + +/** + * A request to retrieve the result of a completed task. + * + * @category tasks/result + */ +export interface GetTaskPayloadRequest extends JSONRPCRequest { + method: "tasks/result"; + params: { + /** + * The task identifier to retrieve results for. + */ + taskId: string; + }; +} + +/** + * The response to a tasks/result request. + * The structure matches the result type of the original request. + * For example, a tools/call task would return CallToolResult structure. + * + * @category tasks/result + */ +export interface GetTaskPayloadResult extends Result { + [key: string]: unknown; +} + +/** + * A request to retrieve a list of tasks. + * + * @category tasks/list + */ +export interface ListTasksRequest extends PaginatedRequest { + method: "tasks/list"; +} + +/** + * A summary of a task's state, as returned by tasks/list. + * + * @category tasks/list + */ +export interface TaskInfo { + /** + * The task identifier. + */ + taskId: string; + + /** + * Current task state. + */ + status: TaskStatus; + + /** + * Retention duration in milliseconds, null for unlimited. + */ + keepAlive: number | null; + + /** + * Suggested polling interval in milliseconds. + */ + pollFrequency?: number; + + /** + * Error message if status is "failed". + */ + error?: string; +} + +/** + * The response to a tasks/list request. + * + * @category tasks/list + */ +export interface ListTasksResult extends PaginatedResult { + tasks: TaskInfo[]; +} + +/** + * A notification from the receiver to the requestor, informing them that a task has been created and is ready for polling. + * + * @category notifications/tasks/created + */ +export interface TaskCreatedNotification extends JSONRPCNotification { + method: "notifications/tasks/created"; + params?: { + /** + * The _meta field MUST include modelcontextprotocol.io/related-task with the taskId. + */ + _meta?: { + "modelcontextprotocol.io/related-task"?: RelatedTaskMetadata; + [key: string]: unknown; + }; + }; +} + /* Logging */ /** * A request from the client to the server, to enable or adjust logging. @@ -1563,21 +1751,28 @@ export type ClientRequest = | SubscribeRequest | UnsubscribeRequest | CallToolRequest - | ListToolsRequest; + | ListToolsRequest + | GetTaskRequest + | GetTaskPayloadRequest + | ListTasksRequest; /** @internal */ export type ClientNotification = | CancelledNotification | ProgressNotification | InitializedNotification - | RootsListChangedNotification; + | RootsListChangedNotification + | TaskCreatedNotification; /** @internal */ export type ClientResult = | EmptyResult | CreateMessageResult | ListRootsResult - | ElicitResult; + | ElicitResult + | GetTaskResult + | GetTaskPayloadResult + | ListTasksResult; /* Server messages */ /** @internal */ @@ -1585,7 +1780,10 @@ export type ServerRequest = | PingRequest | CreateMessageRequest | ListRootsRequest - | ElicitRequest; + | ElicitRequest + | GetTaskRequest + | GetTaskPayloadRequest + | ListTasksRequest; /** @internal */ export type ServerNotification = @@ -1595,7 +1793,8 @@ export type ServerNotification = | ResourceUpdatedNotification | ResourceListChangedNotification | ToolListChangedNotification - | PromptListChangedNotification; + | PromptListChangedNotification + | TaskCreatedNotification; /** @internal */ export type ServerResult = @@ -1608,4 +1807,7 @@ export type ServerResult = | ListResourcesResult | ReadResourceResult | CallToolResult - | ListToolsResult; + | ListToolsResult + | GetTaskResult + | GetTaskPayloadResult + | ListTasksResult; From d52881b1be9a8a7d05058ae1f868a3095601d0da Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Wed, 29 Oct 2025 16:00:35 -0700 Subject: [PATCH 03/79] Add a mention of tasks to the Primitives docs --- docs/docs/learn/architecture.mdx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/docs/learn/architecture.mdx b/docs/docs/learn/architecture.mdx index c8b9b1582..76ede144a 100644 --- a/docs/docs/learn/architecture.mdx +++ b/docs/docs/learn/architecture.mdx @@ -132,6 +132,10 @@ MCP also defines primitives that _clients_ can expose. These primitives allow MC For more details about client primitives see [client concepts](./client-concepts). +MCP also defines cross-cutting utility primitives that augment how requests are executed: + +- **Tasks**: Asynchronous execution wrappers that enable deferred result retrieval and status tracking for any MCP request (e.g., long-running computations, workflow automation, batch processing, multi-step operations) + #### Notifications The protocol supports real-time notifications to enable dynamic updates between servers and clients. For example, when a server's available tools change—such as when new functionality becomes available or existing tools are modified—the server can send tool update notifications to inform connected clients about these changes. Notifications are sent as JSON-RPC 2.0 notification messages (without expecting a response) and enable MCP servers to provide real-time updates to connected clients. From 6444eb30d1b508a3adb636591e688499ee7162d9 Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Fri, 31 Oct 2025 11:20:18 -0700 Subject: [PATCH 04/79] Make task idempotency a MAY instead of a MUST --- docs/specification/draft/basic/utilities/tasks.mdx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index a65c41948..6d29ce8f3 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -6,7 +6,7 @@ title: Tasks **Protocol Revision**: draft -The Model Context Protcol (MCP) allows requestors (which can be either clients or servers, depending on the direction of communication) to augment their requests with **tasks**. Tasks are durable state machines that carry information about the underlying execution state of the request they wrap, and are intended for requestor polling and deferred result retrieval. Each task is uniquely identifiable by a requestor-generated, idempotent **task ID**. +The Model Context Protcol (MCP) allows requestors (which can be either clients or servers, depending on the direction of communication) to augment their requests with **tasks**. Tasks are durable state machines that carry information about the underlying execution state of the request they wrap, and are intended for requestor polling and deferred result retrieval. Each task is uniquely identifiable by a requestor-generated **task ID**. ## User Interaction Model @@ -209,8 +209,8 @@ These requirements apply to all parties that support receiving task-augmented re ### Task ID Requirements 1. Task IDs **MUST** be a string value. -1. Task IDs **MUST** be unique across all tasks controlled by the receiver. -1. The receiver of a request with a task ID in its `_meta` **MUST** validate that the provided task ID has not already been associated with a task controlled by that receiver. +1. Task IDs **SHOULD** be unique across all tasks controlled by the receiver. +1. The receiver of a request with a task ID in its `_meta` **MAY** validate that the provided task ID has not already been associated with a task controlled by that receiver. ### Task Status Lifecycle @@ -522,7 +522,7 @@ Receivers **MUST** return standard JSON-RPC errors for the following protocol er - Invalid or nonexistent `taskId` in `tasks/get`, `tasks/list`, or `tasks/result`: `-32602` (Invalid params) - Invalid or nonexistent cursor in `tasks/list`: `-32602` (Invalid params) -- Request with a `taskId` that was already used for a different task: `-32602` (Invalid params) +- Request with a `taskId` that was already used for a different task (if the receiver validates task ID uniqueness): `-32602` (Invalid params) - Attempting to retrieve result when task is not in `completed` status: `-32602` (Invalid params) - Internal errors: `-32603` (Internal error) @@ -573,7 +573,7 @@ Receivers are not obligated to retain task metadata indefinitely. It is complian } ``` -**Example: Duplicate task ID** +**Example: Duplicate task ID (if receiver validates uniqueness)** ```json { From 42a4e5b8ab57a6cfafdcb8677deacb7a60390f4c Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Fri, 31 Oct 2025 11:36:13 -0700 Subject: [PATCH 05/79] Add consistency requirement that tasks/list reflect tasks/get --- docs/specification/draft/basic/utilities/tasks.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index 6d29ce8f3..1be7e6f4b 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -288,6 +288,7 @@ stateDiagram-v2 1. Receivers **SHOULD** use cursor-based pagination to limit the number of tasks returned in a single response. 1. Receivers **MUST** include a `nextCursor` in the response if more tasks are available. 1. Requestors **MUST** treat cursors as opaque tokens and not attempt to parse or modify them. +1. If a task is retrievable via `tasks/get` for a requestor, it **MUST** be retrievable via `tasks/list` for that requestor. ## Message Flow From 1a4e2056eb4b55e8e6807f9b18e85dfe4112a64e Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Fri, 31 Oct 2025 12:14:02 -0700 Subject: [PATCH 06/79] Add capabilities and annotations for tasks --- docs/specification/draft/basic/lifecycle.mdx | 63 ++++++-- .../draft/basic/utilities/tasks.mdx | 71 ++++++++- docs/specification/draft/schema.mdx | 10 +- schema/draft/schema.json | 124 ++++++++++++++++ schema/draft/schema.ts | 135 ++++++++++++++++-- 5 files changed, 377 insertions(+), 26 deletions(-) diff --git a/docs/specification/draft/basic/lifecycle.mdx b/docs/specification/draft/basic/lifecycle.mdx index e6ee219c9..7f41f268a 100644 --- a/docs/specification/draft/basic/lifecycle.mdx +++ b/docs/specification/draft/basic/lifecycle.mdx @@ -64,7 +64,23 @@ The client **MUST** initiate this phase by sending an `initialize` request conta "listChanged": true }, "sampling": {}, - "elicitation": {} + "elicitation": {}, + "tasks": { + "sampling": { + "createMessage": true + }, + "elicitation": { + "create": true + }, + "roots": { + "list": true + }, + "tasks": { + "get": true, + "list": true, + "result": true + } + } }, "clientInfo": { "name": "ExampleClient", @@ -102,6 +118,25 @@ The server **MUST** respond with its own capabilities and information: }, "tools": { "listChanged": true + }, + "tasks": { + "tools": { + "call": true, + "list": true + }, + "resources": { + "read": true, + "list": true + }, + "prompts": { + "get": true, + "list": true + }, + "tasks": { + "get": true, + "list": true, + "result": true + } } }, "serverInfo": { @@ -166,18 +201,20 @@ available during the session. Key capabilities include: -| Category | Capability | Description | -| -------- | -------------- | ------------------------------------------------------------------------------------ | -| Client | `roots` | Ability to provide filesystem [roots](/specification/draft/client/roots) | -| Client | `sampling` | Support for LLM [sampling](/specification/draft/client/sampling) requests | -| Client | `elicitation` | Support for server [elicitation](/specification/draft/client/elicitation) requests | -| Client | `experimental` | Describes support for non-standard experimental features | -| Server | `prompts` | Offers [prompt templates](/specification/draft/server/prompts) | -| Server | `resources` | Provides readable [resources](/specification/draft/server/resources) | -| Server | `tools` | Exposes callable [tools](/specification/draft/server/tools) | -| Server | `logging` | Emits structured [log messages](/specification/draft/server/utilities/logging) | -| Server | `completions` | Supports argument [autocompletion](/specification/draft/server/utilities/completion) | -| Server | `experimental` | Describes support for non-standard experimental features | +| Category | Capability | Description | +| -------- | -------------- | ---------------------------------------------------------------------------------------- | +| Client | `roots` | Ability to provide filesystem [roots](/specification/draft/client/roots) | +| Client | `sampling` | Support for LLM [sampling](/specification/draft/client/sampling) requests | +| Client | `elicitation` | Support for server [elicitation](/specification/draft/client/elicitation) requests | +| Client | `tasks` | Support for [task-augmented](/specification/draft/basic/utilities/tasks) client requests | +| Client | `experimental` | Describes support for non-standard experimental features | +| Server | `prompts` | Offers [prompt templates](/specification/draft/server/prompts) | +| Server | `resources` | Provides readable [resources](/specification/draft/server/resources) | +| Server | `tools` | Exposes callable [tools](/specification/draft/server/tools) | +| Server | `logging` | Emits structured [log messages](/specification/draft/server/utilities/logging) | +| Server | `completions` | Supports argument [autocompletion](/specification/draft/server/utilities/completion) | +| Server | `tasks` | Support for [task-augmented](/specification/draft/basic/utilities/tasks) server requests | +| Server | `experimental` | Describes support for non-standard experimental features | Capability objects can describe sub-capabilities like: diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index 1be7e6f4b..a84a74ce0 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -16,7 +16,76 @@ Implementations are free to expose tasks through any interface pattern that suit ## Capabilities -Unlike other protocol features, tasks _do not_ require capabilities to be declared. +Servers and clients that support task-augmented requests **MUST** declare a `tasks` 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 which server-side requests can be augmented with tasks: + +```json +{ + "capabilities": { + "tasks": { + "tools": { + "call": true, + "list": true + }, + "resources": { + "read": true, + "list": true + }, + "prompts": { + "get": true, + "list": true + }, + "tasks": { + "get": true, + "list": true, + "result": true + } + } + } +} +``` + +Servers **MAY** support tasks for any subset of their available request types. If a request type is not listed in the `tasks` capability or is set to `false`, requestors **SHOULD NOT** augment those requests with task metadata. + +The `tasks.tasks` nested capability indicates whether the task management operations themselves (`tasks/get`, `tasks/list`, `tasks/result`) can be augmented with tasks, enabling recursive task tracking for task queries. + +### Client Capabilities + +Clients declare which client-side requests can be augmented with tasks: + +```json +{ + "capabilities": { + "tasks": { + "sampling": { + "createMessage": true + }, + "elicitation": { + "create": true + }, + "roots": { + "list": true + }, + "tasks": { + "get": true, + "list": true, + "result": true + } + } + } +} +``` + +The `tasks.tasks` capability applies when the client is acting as a receiver of task-augmented requests from the server (for example, when a server sends a task-augmented `sampling/createMessage` request to the client). + +### Capability Negotiation + +During the initialization phase, both parties exchange their `tasks` capabilities to establish which operations support task-based execution. Requestors **MUST** only augment requests with task metadata if the corresponding capability has been declared by the receiver. + +For example, if a server's capabilities include `tasks.tools.call: true`, then clients may augment `tools/call` requests with task metadata. However, if the server does not declare `tasks.resources.read`, clients should not send task-augmented `resources/read` requests. ## Protocol Messages diff --git a/docs/specification/draft/schema.mdx b/docs/specification/draft/schema.mdx index 9aec78b36..abcece284 100644 --- a/docs/specification/draft/schema.mdx +++ b/docs/specification/draft/schema.mdx @@ -27,7 +27,7 @@ the data is entirely optional.

interface ClientCapabilities {
  elicitation?: object;
  experimental?: { [key: string]: object };
  roots?: { listChanged?: boolean };
  sampling?: object;
}

Capabilities a client may support. Known capabilities are defined here, in this schema, but this is not a closed set: any client can define its own, additional capabilities.

elicitation?: object

Present if the client supports elicitation from the server.

experimental?: { [key: string]: object }

Experimental, non-standard capabilities that the client supports.

roots?: { listChanged?: boolean }

Present if the client supports listing roots.

Type declaration
  • OptionallistChanged?: boolean

    Whether the client supports notifications for changes to the roots list.

sampling?: object

Present if the client supports sampling from an LLM.

+
interface ClientCapabilities {
  elicitation?: object;
  experimental?: { [key: string]: object };
  roots?: { listChanged?: boolean };
  sampling?: object;
  tasks?: {
    elicitation?: { create?: boolean };
    roots?: { list?: boolean };
    sampling?: { createMessage?: boolean };
    tasks?: { get?: boolean; list?: boolean; result?: boolean };
  };
}

Capabilities a client may support. Known capabilities are defined here, in this schema, but this is not a closed set: any client can define its own, additional capabilities.

elicitation?: object

Present if the client supports elicitation from the server.

experimental?: { [key: string]: object }

Experimental, non-standard capabilities that the client supports.

roots?: { listChanged?: boolean }

Present if the client supports listing roots.

Type declaration
  • OptionallistChanged?: boolean

    Whether the client supports notifications for changes to the roots list.

sampling?: object

Present if the client supports sampling from an LLM.

tasks?: {
  elicitation?: { create?: boolean };
  roots?: { list?: boolean };
  sampling?: { createMessage?: boolean };
  tasks?: { get?: boolean; list?: boolean; result?: boolean };
}

Present if the client supports task-augmented requests. Nested properties indicate which specific request types can be augmented with tasks.

Type declaration
  • Optionalelicitation?: { create?: boolean }

    Task support for elicitation-related requests.

    • Optionalcreate?: boolean

      Whether the client supports task-augmented elicitation/create requests.

  • Optionalroots?: { list?: boolean }

    Task support for roots-related requests.

    • Optionallist?: boolean

      Whether the client supports task-augmented roots/list requests.

  • Optionalsampling?: { createMessage?: boolean }

    Task support for sampling-related requests.

    • OptionalcreateMessage?: boolean

      Whether the client supports task-augmented sampling/createMessage requests.

  • Optionaltasks?: { get?: boolean; list?: boolean; result?: boolean }

    Task support for task management requests. Enables recursive task tracking where task queries themselves can be augmented with tasks. This applies when the client acts as a receiver of task-augmented requests from the server.

    • Optionalget?: boolean

      Whether the client supports task-augmented tasks/get requests.

    • Optionallist?: boolean

      Whether the client supports task-augmented tasks/list requests.

    • Optionalresult?: boolean

      Whether the client supports task-augmented tasks/result requests.

### `ContentBlock` @@ -212,7 +212,7 @@ other URI schemes.

interface ServerCapabilities {
  completions?: object;
  experimental?: { [key: string]: object };
  logging?: object;
  prompts?: { listChanged?: boolean };
  resources?: { listChanged?: boolean; subscribe?: boolean };
  tools?: { listChanged?: boolean };
}

Capabilities that a server may support. Known capabilities are defined here, in this schema, but this is not a closed set: any server can define its own, additional capabilities.

completions?: object

Present if the server supports argument autocompletion suggestions.

experimental?: { [key: string]: object }

Experimental, non-standard capabilities that the server supports.

logging?: object

Present if the server supports sending log messages to the client.

prompts?: { listChanged?: boolean }

Present if the server offers any prompt templates.

Type declaration
  • OptionallistChanged?: boolean

    Whether this server supports notifications for changes to the prompt list.

resources?: { listChanged?: boolean; subscribe?: boolean }

Present if the server offers any resources to read.

Type declaration
  • OptionallistChanged?: boolean

    Whether this server supports notifications for changes to the resource list.

  • Optionalsubscribe?: boolean

    Whether this server supports subscribing to resource updates.

tools?: { listChanged?: boolean }

Present if the server offers any tools to call.

Type declaration
  • OptionallistChanged?: boolean

    Whether this server supports notifications for changes to the tool list.

+
interface ServerCapabilities {
  completions?: object;
  experimental?: { [key: string]: object };
  logging?: object;
  prompts?: { listChanged?: boolean };
  resources?: { listChanged?: boolean; subscribe?: boolean };
  tasks?: {
    prompts?: { get?: boolean; list?: boolean };
    resources?: { list?: boolean; read?: boolean };
    tasks?: { get?: boolean; list?: boolean; result?: boolean };
    tools?: { call?: boolean; list?: boolean };
  };
  tools?: { listChanged?: boolean };
}

Capabilities that a server may support. Known capabilities are defined here, in this schema, but this is not a closed set: any server can define its own, additional capabilities.

completions?: object

Present if the server supports argument autocompletion suggestions.

experimental?: { [key: string]: object }

Experimental, non-standard capabilities that the server supports.

logging?: object

Present if the server supports sending log messages to the client.

prompts?: { listChanged?: boolean }

Present if the server offers any prompt templates.

Type declaration
  • OptionallistChanged?: boolean

    Whether this server supports notifications for changes to the prompt list.

resources?: { listChanged?: boolean; subscribe?: boolean }

Present if the server offers any resources to read.

Type declaration
  • OptionallistChanged?: boolean

    Whether this server supports notifications for changes to the resource list.

  • Optionalsubscribe?: boolean

    Whether this server supports subscribing to resource updates.

tasks?: {
  prompts?: { get?: boolean; list?: boolean };
  resources?: { list?: boolean; read?: boolean };
  tasks?: { get?: boolean; list?: boolean; result?: boolean };
  tools?: { call?: boolean; list?: boolean };
}

Present if the server supports task-augmented requests. Nested properties indicate which specific request types can be augmented with tasks.

Type declaration
  • Optionalprompts?: { get?: boolean; list?: boolean }

    Task support for prompt-related requests.

    • Optionalget?: boolean

      Whether the server supports task-augmented prompts/get requests.

    • Optionallist?: boolean

      Whether the server supports task-augmented prompts/list requests.

  • Optionalresources?: { list?: boolean; read?: boolean }

    Task support for resource-related requests.

    • Optionallist?: boolean

      Whether the server supports task-augmented resources/list requests.

    • Optionalread?: boolean

      Whether the server supports task-augmented resources/read requests.

  • Optionaltasks?: { get?: boolean; list?: boolean; result?: boolean }

    Task support for task management requests. Enables recursive task tracking where task queries themselves can be augmented with tasks.

    • Optionalget?: boolean

      Whether the server supports task-augmented tasks/get requests.

    • Optionallist?: boolean

      Whether the server supports task-augmented tasks/list requests.

    • Optionalresult?: boolean

      Whether the server supports task-augmented tasks/result requests.

  • Optionaltools?: { call?: boolean; list?: boolean }

    Task support for tool-related requests.

    • Optionalcall?: boolean

      Whether the server supports task-augmented tools/call requests.

    • Optionallist?: boolean

      Whether the server supports task-augmented tools/list requests.

tools?: { listChanged?: boolean }

Present if the server offers any tools to call.

Type declaration
  • OptionallistChanged?: boolean

    Whether this server supports notifications for changes to the tool list.

### `StringSchema` @@ -236,7 +236,7 @@ if present).

readOnlyHint?: boolean

If true, the tool does not modify its environment.

Default: false

taskHint?: boolean

If true, this tool is expected to take a long time to execute and +is a good candidate for task-augmented execution. This allows clients +to handle long-running operations asynchronously through the task system.

Default: false

title?: string

A human-readable title for the tool.

## `completion/complete` diff --git a/schema/draft/schema.json b/schema/draft/schema.json index 22dca931b..a2ca8a969 100644 --- a/schema/draft/schema.json +++ b/schema/draft/schema.json @@ -259,6 +259,60 @@ "description": "Present if the client supports sampling from an LLM.", "properties": {}, "type": "object" + }, + "tasks": { + "description": "Present if the client supports task-augmented requests. Nested properties indicate which specific request types can be augmented with tasks.", + "properties": { + "elicitation": { + "description": "Task support for elicitation-related requests.", + "properties": { + "create": { + "description": "Whether the client supports task-augmented elicitation/create requests.", + "type": "boolean" + } + }, + "type": "object" + }, + "roots": { + "description": "Task support for roots-related requests.", + "properties": { + "list": { + "description": "Whether the client supports task-augmented roots/list requests.", + "type": "boolean" + } + }, + "type": "object" + }, + "sampling": { + "description": "Task support for sampling-related requests.", + "properties": { + "createMessage": { + "description": "Whether the client supports task-augmented sampling/createMessage requests.", + "type": "boolean" + } + }, + "type": "object" + }, + "tasks": { + "description": "Task support for task management requests. Enables recursive task tracking where task queries themselves can be augmented with tasks. This applies when the client acts as a receiver of task-augmented requests from the server.", + "properties": { + "get": { + "description": "Whether the client supports task-augmented tasks/get requests.", + "type": "boolean" + }, + "list": { + "description": "Whether the client supports task-augmented tasks/list requests.", + "type": "boolean" + }, + "result": { + "description": "Whether the client supports task-augmented tasks/result requests.", + "type": "boolean" + } + }, + "type": "object" + } + }, + "type": "object" } }, "type": "object" @@ -2590,6 +2644,72 @@ }, "type": "object" }, + "tasks": { + "description": "Present if the server supports task-augmented requests. Nested properties indicate which specific request types can be augmented with tasks.", + "properties": { + "prompts": { + "description": "Task support for prompt-related requests.", + "properties": { + "get": { + "description": "Whether the server supports task-augmented prompts/get requests.", + "type": "boolean" + }, + "list": { + "description": "Whether the server supports task-augmented prompts/list requests.", + "type": "boolean" + } + }, + "type": "object" + }, + "resources": { + "description": "Task support for resource-related requests.", + "properties": { + "list": { + "description": "Whether the server supports task-augmented resources/list requests.", + "type": "boolean" + }, + "read": { + "description": "Whether the server supports task-augmented resources/read requests.", + "type": "boolean" + } + }, + "type": "object" + }, + "tasks": { + "description": "Task support for task management requests. Enables recursive task tracking where task queries themselves can be augmented with tasks.", + "properties": { + "get": { + "description": "Whether the server supports task-augmented tasks/get requests.", + "type": "boolean" + }, + "list": { + "description": "Whether the server supports task-augmented tasks/list requests.", + "type": "boolean" + }, + "result": { + "description": "Whether the server supports task-augmented tasks/result requests.", + "type": "boolean" + } + }, + "type": "object" + }, + "tools": { + "description": "Task support for tool-related requests.", + "properties": { + "call": { + "description": "Whether the server supports task-augmented tools/call requests.", + "type": "boolean" + }, + "list": { + "description": "Whether the server supports task-augmented tools/list requests.", + "type": "boolean" + } + }, + "type": "object" + } + }, + "type": "object" + }, "tools": { "description": "Present if the server offers any tools to call.", "properties": { @@ -3065,6 +3185,10 @@ "description": "If true, the tool does not modify its environment.\n\nDefault: false", "type": "boolean" }, + "taskHint": { + "description": "If true, this tool is expected to take a long time to execute and\nis a good candidate for task-augmented execution. This allows clients\nto handle long-running operations asynchronously through the task system.\n\nDefault: false", + "type": "boolean" + }, "title": { "description": "A human-readable title for the tool.", "type": "string" diff --git a/schema/draft/schema.ts b/schema/draft/schema.ts index 6e5f39f48..50c949c96 100644 --- a/schema/draft/schema.ts +++ b/schema/draft/schema.ts @@ -77,7 +77,7 @@ export interface Error { * Additional information about the error. The value of this member is defined by the sender (e.g. detailed error information, nested errors etc.). */ data?: unknown; -}; +} /** * A uniquely identifying ID for a request in JSON-RPC. @@ -237,6 +237,55 @@ export interface ClientCapabilities { * Present if the client supports elicitation from the server. */ elicitation?: object; + /** + * Present if the client supports task-augmented requests. Nested properties indicate which specific request types can be augmented with tasks. + */ + tasks?: { + /** + * Task support for sampling-related requests. + */ + sampling?: { + /** + * Whether the client supports task-augmented sampling/createMessage requests. + */ + createMessage?: boolean; + }; + /** + * Task support for elicitation-related requests. + */ + elicitation?: { + /** + * Whether the client supports task-augmented elicitation/create requests. + */ + create?: boolean; + }; + /** + * Task support for roots-related requests. + */ + roots?: { + /** + * Whether the client supports task-augmented roots/list requests. + */ + list?: boolean; + }; + /** + * Task support for task management requests. Enables recursive task tracking where task queries themselves can be augmented with tasks. This applies when the client acts as a receiver of task-augmented requests from the server. + */ + tasks?: { + /** + * Whether the client supports task-augmented tasks/get requests. + */ + get?: boolean; + /** + * Whether the client supports task-augmented tasks/list requests. + */ + list?: boolean; + /** + * Whether the client supports task-augmented tasks/result requests. + */ + result?: boolean; + }; + }; } /** @@ -286,6 +335,67 @@ export interface ServerCapabilities { */ listChanged?: boolean; }; + /** + * Present if the server supports task-augmented requests. Nested properties indicate which specific request types can be augmented with tasks. + */ + tasks?: { + /** + * Task support for tool-related requests. + */ + tools?: { + /** + * Whether the server supports task-augmented tools/call requests. + */ + call?: boolean; + /** + * Whether the server supports task-augmented tools/list requests. + */ + list?: boolean; + }; + /** + * Task support for resource-related requests. + */ + resources?: { + /** + * Whether the server supports task-augmented resources/read requests. + */ + read?: boolean; + /** + * Whether the server supports task-augmented resources/list requests. + */ + list?: boolean; + }; + /** + * Task support for prompt-related requests. + */ + prompts?: { + /** + * Whether the server supports task-augmented prompts/get requests. + */ + get?: boolean; + /** + * Whether the server supports task-augmented prompts/list requests. + */ + list?: boolean; + }; + /** + * Task support for task management requests. Enables recursive task tracking where task queries themselves can be augmented with tasks. + */ + tasks?: { + /** + * Whether the server supports task-augmented tasks/get requests. + */ + get?: boolean; + /** + * Whether the server supports task-augmented tasks/list requests. + */ + list?: boolean; + /** + * Whether the server supports task-augmented tasks/result requests. + */ + result?: boolean; + }; + }; } /** @@ -327,7 +437,7 @@ export interface Icon { * * If not provided, the client should assume the icon can be used with any theme. */ - theme?: 'light' | 'dark'; + theme?: "light" | "dark"; } /** @@ -949,6 +1059,15 @@ export interface ToolAnnotations { * Default: true */ openWorldHint?: boolean; + + /** + * If true, this tool is expected to support task-augmented execution. + * This allows clients to handle long-running operations through polling + * the task system. + * + * Default: false + */ + taskHint?: boolean; } /** @@ -1002,13 +1121,13 @@ export interface Tool extends BaseMetadata, Icons { * @category tasks */ export type TaskStatus = - | "submitted" // The request has been received and queued for execution - | "working" // The request is currently being processed + | "submitted" // The request has been received and queued for execution + | "working" // The request is currently being processed | "input_required" // The task is waiting for input (e.g., elicitation or sampling) - | "completed" // The request completed successfully and results are available - | "failed" // The request encountered an error during execution - | "cancelled" // The request was cancelled before completion - | "unknown"; // A terminal fallback state for unexpected error conditions + | "completed" // The request completed successfully and results are available + | "failed" // The request encountered an error during execution + | "cancelled" // The request was cancelled before completion + | "unknown"; // A terminal fallback state for unexpected error conditions /** * Metadata for augmenting a request with task execution. From cd7c4cd0135efe261a4cd8e35dcaeab7f47eda41 Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Fri, 31 Oct 2025 13:15:40 -0700 Subject: [PATCH 07/79] Commit updated schema --- docs/specification/draft/schema.mdx | 6 +++--- schema/draft/schema.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/specification/draft/schema.mdx b/docs/specification/draft/schema.mdx index abcece284..117d9e0f1 100644 --- a/docs/specification/draft/schema.mdx +++ b/docs/specification/draft/schema.mdx @@ -244,9 +244,9 @@ If false, the tool performs only additive updates.

(This property is mean will have no additional effect on its environment.

(This property is meaningful only when readOnlyHint == false)

Default: false

openWorldHint?: boolean

If true, this tool may interact with an "open world" of external entities. If false, the tool's domain of interaction is closed. For example, the world of a web search tool is open, whereas that -of a memory tool is not.

Default: true

readOnlyHint?: boolean

If true, the tool does not modify its environment.

Default: false

taskHint?: boolean

If true, this tool is expected to take a long time to execute and -is a good candidate for task-augmented execution. This allows clients -to handle long-running operations asynchronously through the task system.

Default: false

title?: string

A human-readable title for the tool.

+of a memory tool is not.

Default: true

readOnlyHint?: boolean

If true, the tool does not modify its environment.

Default: false

taskHint?: boolean

If true, this tool is expected to support task-augmented execution. +This allows clients to handle long-running operations through polling +the task system.

Default: false

title?: string

A human-readable title for the tool.

## `completion/complete` diff --git a/schema/draft/schema.json b/schema/draft/schema.json index a2ca8a969..78ab1fac4 100644 --- a/schema/draft/schema.json +++ b/schema/draft/schema.json @@ -3186,7 +3186,7 @@ "type": "boolean" }, "taskHint": { - "description": "If true, this tool is expected to take a long time to execute and\nis a good candidate for task-augmented execution. This allows clients\nto handle long-running operations asynchronously through the task system.\n\nDefault: false", + "description": "If true, this tool is expected to support task-augmented execution.\nThis allows clients to handle long-running operations through polling\nthe task system.\n\nDefault: false", "type": "boolean" }, "title": { From 726a4db68aa4a37cbd94c322766f76b6c541adbb Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Fri, 31 Oct 2025 14:48:56 -0700 Subject: [PATCH 08/79] Add tasks/delete operation --- .../draft/basic/utilities/tasks.mdx | 96 ++++++++++++++++++- docs/specification/draft/schema.mdx | 14 ++- schema/draft/schema.json | 66 +++++++++++++ schema/draft/schema.ts | 42 +++++++- 4 files changed, 209 insertions(+), 9 deletions(-) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index a84a74ce0..42d721107 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -266,6 +266,44 @@ To retrieve a list of tasks, requestors send a `tasks/list` request. This operat } ``` +### Deleting Tasks + +To explicitly delete a task and its associated results, requestors send a `tasks/delete` request. + +**Request:** + +```json +{ + "jsonrpc": "2.0", + "id": 6, + "method": "tasks/delete", + "params": { + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", + "_meta": { + "modelcontextprotocol.io/related-task": { + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" + } + } + } +} +``` + +**Response:** + +```json +{ + "jsonrpc": "2.0", + "id": 6, + "result": { + "_meta": { + "modelcontextprotocol.io/related-task": { + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" + } + } + } +} +``` + ## Behavior Requirements These requirements apply to all parties that support receiving task-augmented requests. @@ -359,6 +397,13 @@ stateDiagram-v2 1. Requestors **MUST** treat cursors as opaque tokens and not attempt to parse or modify them. 1. If a task is retrievable via `tasks/get` for a requestor, it **MUST** be retrievable via `tasks/list` for that requestor. +### Task Deletion + +1. Receivers **MAY** accept or reject delete requests for any task at their discretion. +1. If a receiver accepts a delete request, it **SHOULD** delete the task and all associated results and metadata. +1. Receivers **MAY** choose not to support deletion at all, or only support deletion for tasks in certain statuses (e.g., only terminal statuses). +1. Requestors **SHOULD** delete tasks containing sensitive data promptly rather than relying solely on `keepAlive` expiration for cleanup. + ## Message Flow ### Basic Task Lifecycle @@ -525,6 +570,36 @@ sequenceDiagram Note over S: After keepAlive period, task cleaned up ``` +### Task Deletion Flow + +```mermaid +sequenceDiagram + participant C as Client (Requestor) + participant S as Server (Receiver) + + Note over C,S: 1. Task Creation and Completion + C->>S: tools/call (task-123) + S--)C: notifications/tasks/created + Note over S: Task processing... + C->>S: tasks/get (task-123) + S->>C: completed + + Note over C,S: 2. Result Retrieval + C->>S: tasks/result (task-123) + S->>C: Result content + + Note over C,S: 3. Explicit Deletion + Note over C: Client decides to clean up task + C->>S: tasks/delete (task-123) + S->>C: Success (empty result) + + Note over S: Task and results immediately deleted + + Note over C,S: 4. Verification (optional) + C->>S: tasks/get (task-123) + S->>C: Error: Task not found +``` + ## Data Types ### Task @@ -590,10 +665,11 @@ Tasks use two error reporting mechanisms: Receivers **MUST** return standard JSON-RPC errors for the following protocol error cases: -- Invalid or nonexistent `taskId` in `tasks/get`, `tasks/list`, or `tasks/result`: `-32602` (Invalid params) +- Invalid or nonexistent `taskId` in `tasks/get`, `tasks/list`, `tasks/result`, or `tasks/delete`: `-32602` (Invalid params) - Invalid or nonexistent cursor in `tasks/list`: `-32602` (Invalid params) - Request with a `taskId` that was already used for a different task (if the receiver validates task ID uniqueness): `-32602` (Invalid params) - Attempting to retrieve result when task is not in `completed` status: `-32602` (Invalid params) +- Receiver rejects a `tasks/delete` request: `-32600` (Invalid request) - Internal errors: `-32603` (Internal error) Receivers **SHOULD** provide informative error messages to describe the cause of errors. @@ -656,6 +732,19 @@ Receivers are not obligated to retain task metadata indefinitely. It is complian } ``` +**Example: Task deletion rejected by receiver** + +```json +{ + "jsonrpc": "2.0", + "id": 74, + "error": { + "code": -32600, + "message": "Task deletion not supported for tasks in 'working' status" + } +} +``` + ### Task Execution Errors When the underlying request fails during execution, the task moves to the `failed` status. The `tasks/get` response **SHOULD** include an `error` field with details about the failure. @@ -684,19 +773,20 @@ For tasks that wrap requests with their own error semantics (like `tools/call` w 1. Receivers **SHOULD** scope task IDs to prevent unauthorized access: 1. Bind tasks to the session that created them (if sessions are supported) 1. Bind tasks to the authentication context (if authentication is used) - 1. Reject `tasks/get`, `tasks/list`, or `tasks/result` requests for tasks from different sessions or auth contexts + 1. Reject `tasks/get`, `tasks/list`, `tasks/result`, or `tasks/delete` requests for tasks from different sessions or auth contexts 1. Receivers that do not implement session or authentication binding **SHOULD** document this limitation clearly, as task results may be accessible to any requestor that can guess the task ID. 1. Receivers **SHOULD** implement rate limiting on: 1. Task creation to prevent resource exhaustion 1. Task status polling to prevent denial of service 1. Task result retrieval attempts 1. Task listing requests to prevent denial of service + 1. Task deletion requests to prevent abuse ### Resource Management -Task results may persist longer than the original request execution time. For sensitive operations, requestors should carefully consider the security implications of extended result retention and may want to retrieve results promptly and request shorter `keepAlive` durations. +Task results may persist longer than the original request execution time. For sensitive operations, requestors should carefully consider the security implications of extended result retention and may want to retrieve results promptly and request shorter `keepAlive` durations. Requestors are encouraged to use `tasks/delete` to explicitly clean up tasks containing sensitive data rather than relying solely on `keepAlive` expiration. diff --git a/docs/specification/draft/schema.mdx b/docs/specification/draft/schema.mdx index 117d9e0f1..4b2a28f4e 100644 --- a/docs/specification/draft/schema.mdx +++ b/docs/specification/draft/schema.mdx @@ -27,7 +27,7 @@ the data is entirely optional.

interface ClientCapabilities {
  elicitation?: object;
  experimental?: { [key: string]: object };
  roots?: { listChanged?: boolean };
  sampling?: object;
  tasks?: {
    elicitation?: { create?: boolean };
    roots?: { list?: boolean };
    sampling?: { createMessage?: boolean };
    tasks?: { get?: boolean; list?: boolean; result?: boolean };
  };
}

Capabilities a client may support. Known capabilities are defined here, in this schema, but this is not a closed set: any client can define its own, additional capabilities.

elicitation?: object

Present if the client supports elicitation from the server.

experimental?: { [key: string]: object }

Experimental, non-standard capabilities that the client supports.

roots?: { listChanged?: boolean }

Present if the client supports listing roots.

Type declaration
  • OptionallistChanged?: boolean

    Whether the client supports notifications for changes to the roots list.

sampling?: object

Present if the client supports sampling from an LLM.

tasks?: {
  elicitation?: { create?: boolean };
  roots?: { list?: boolean };
  sampling?: { createMessage?: boolean };
  tasks?: { get?: boolean; list?: boolean; result?: boolean };
}

Present if the client supports task-augmented requests. Nested properties indicate which specific request types can be augmented with tasks.

Type declaration
  • Optionalelicitation?: { create?: boolean }

    Task support for elicitation-related requests.

    • Optionalcreate?: boolean

      Whether the client supports task-augmented elicitation/create requests.

  • Optionalroots?: { list?: boolean }

    Task support for roots-related requests.

    • Optionallist?: boolean

      Whether the client supports task-augmented roots/list requests.

  • Optionalsampling?: { createMessage?: boolean }

    Task support for sampling-related requests.

    • OptionalcreateMessage?: boolean

      Whether the client supports task-augmented sampling/createMessage requests.

  • Optionaltasks?: { get?: boolean; list?: boolean; result?: boolean }

    Task support for task management requests. Enables recursive task tracking where task queries themselves can be augmented with tasks. This applies when the client acts as a receiver of task-augmented requests from the server.

    • Optionalget?: boolean

      Whether the client supports task-augmented tasks/get requests.

    • Optionallist?: boolean

      Whether the client supports task-augmented tasks/list requests.

    • Optionalresult?: boolean

      Whether the client supports task-augmented tasks/result requests.

+
interface ClientCapabilities {
  elicitation?: object;
  experimental?: { [key: string]: object };
  roots?: { listChanged?: boolean };
  sampling?: object;
  tasks?: {
    elicitation?: { create?: boolean };
    roots?: { list?: boolean };
    sampling?: { createMessage?: boolean };
    tasks?: {
      delete?: boolean;
      get?: boolean;
      list?: boolean;
      result?: boolean;
    };
  };
}

Capabilities a client may support. Known capabilities are defined here, in this schema, but this is not a closed set: any client can define its own, additional capabilities.

elicitation?: object

Present if the client supports elicitation from the server.

experimental?: { [key: string]: object }

Experimental, non-standard capabilities that the client supports.

roots?: { listChanged?: boolean }

Present if the client supports listing roots.

Type declaration
  • OptionallistChanged?: boolean

    Whether the client supports notifications for changes to the roots list.

sampling?: object

Present if the client supports sampling from an LLM.

tasks?: {
  elicitation?: { create?: boolean };
  roots?: { list?: boolean };
  sampling?: { createMessage?: boolean };
  tasks?: {
    delete?: boolean;
    get?: boolean;
    list?: boolean;
    result?: boolean;
  };
}

Present if the client supports task-augmented requests. Nested properties indicate which specific request types can be augmented with tasks.

Type declaration
  • Optionalelicitation?: { create?: boolean }

    Task support for elicitation-related requests.

    • Optionalcreate?: boolean

      Whether the client supports task-augmented elicitation/create requests.

  • Optionalroots?: { list?: boolean }

    Task support for roots-related requests.

    • Optionallist?: boolean

      Whether the client supports task-augmented roots/list requests.

  • Optionalsampling?: { createMessage?: boolean }

    Task support for sampling-related requests.

    • OptionalcreateMessage?: boolean

      Whether the client supports task-augmented sampling/createMessage requests.

  • Optionaltasks?: { delete?: boolean; get?: boolean; list?: boolean; result?: boolean }

    Task support for task management requests. Enables recursive task tracking where task queries themselves can be augmented with tasks. This applies when the client acts as a receiver of task-augmented requests from the server.

    • Optionaldelete?: boolean

      Whether the client supports task-augmented tasks/delete requests.

    • Optionalget?: boolean

      Whether the client supports task-augmented tasks/get requests.

    • Optionallist?: boolean

      Whether the client supports task-augmented tasks/list requests.

    • Optionalresult?: boolean

      Whether the client supports task-augmented tasks/result requests.

### `ContentBlock` @@ -212,7 +212,7 @@ other URI schemes.

interface ServerCapabilities {
  completions?: object;
  experimental?: { [key: string]: object };
  logging?: object;
  prompts?: { listChanged?: boolean };
  resources?: { listChanged?: boolean; subscribe?: boolean };
  tasks?: {
    prompts?: { get?: boolean; list?: boolean };
    resources?: { list?: boolean; read?: boolean };
    tasks?: { get?: boolean; list?: boolean; result?: boolean };
    tools?: { call?: boolean; list?: boolean };
  };
  tools?: { listChanged?: boolean };
}

Capabilities that a server may support. Known capabilities are defined here, in this schema, but this is not a closed set: any server can define its own, additional capabilities.

completions?: object

Present if the server supports argument autocompletion suggestions.

experimental?: { [key: string]: object }

Experimental, non-standard capabilities that the server supports.

logging?: object

Present if the server supports sending log messages to the client.

prompts?: { listChanged?: boolean }

Present if the server offers any prompt templates.

Type declaration
  • OptionallistChanged?: boolean

    Whether this server supports notifications for changes to the prompt list.

resources?: { listChanged?: boolean; subscribe?: boolean }

Present if the server offers any resources to read.

Type declaration
  • OptionallistChanged?: boolean

    Whether this server supports notifications for changes to the resource list.

  • Optionalsubscribe?: boolean

    Whether this server supports subscribing to resource updates.

tasks?: {
  prompts?: { get?: boolean; list?: boolean };
  resources?: { list?: boolean; read?: boolean };
  tasks?: { get?: boolean; list?: boolean; result?: boolean };
  tools?: { call?: boolean; list?: boolean };
}

Present if the server supports task-augmented requests. Nested properties indicate which specific request types can be augmented with tasks.

Type declaration
  • Optionalprompts?: { get?: boolean; list?: boolean }

    Task support for prompt-related requests.

    • Optionalget?: boolean

      Whether the server supports task-augmented prompts/get requests.

    • Optionallist?: boolean

      Whether the server supports task-augmented prompts/list requests.

  • Optionalresources?: { list?: boolean; read?: boolean }

    Task support for resource-related requests.

    • Optionallist?: boolean

      Whether the server supports task-augmented resources/list requests.

    • Optionalread?: boolean

      Whether the server supports task-augmented resources/read requests.

  • Optionaltasks?: { get?: boolean; list?: boolean; result?: boolean }

    Task support for task management requests. Enables recursive task tracking where task queries themselves can be augmented with tasks.

    • Optionalget?: boolean

      Whether the server supports task-augmented tasks/get requests.

    • Optionallist?: boolean

      Whether the server supports task-augmented tasks/list requests.

    • Optionalresult?: boolean

      Whether the server supports task-augmented tasks/result requests.

  • Optionaltools?: { call?: boolean; list?: boolean }

    Task support for tool-related requests.

    • Optionalcall?: boolean

      Whether the server supports task-augmented tools/call requests.

    • Optionallist?: boolean

      Whether the server supports task-augmented tools/list requests.

tools?: { listChanged?: boolean }

Present if the server offers any tools to call.

Type declaration
  • OptionallistChanged?: boolean

    Whether this server supports notifications for changes to the tool list.

+
interface ServerCapabilities {
  completions?: object;
  experimental?: { [key: string]: object };
  logging?: object;
  prompts?: { listChanged?: boolean };
  resources?: { listChanged?: boolean; subscribe?: boolean };
  tasks?: {
    prompts?: { get?: boolean; list?: boolean };
    resources?: { list?: boolean; read?: boolean };
    tasks?: {
      delete?: boolean;
      get?: boolean;
      list?: boolean;
      result?: boolean;
    };
    tools?: { call?: boolean; list?: boolean };
  };
  tools?: { listChanged?: boolean };
}

Capabilities that a server may support. Known capabilities are defined here, in this schema, but this is not a closed set: any server can define its own, additional capabilities.

completions?: object

Present if the server supports argument autocompletion suggestions.

experimental?: { [key: string]: object }

Experimental, non-standard capabilities that the server supports.

logging?: object

Present if the server supports sending log messages to the client.

prompts?: { listChanged?: boolean }

Present if the server offers any prompt templates.

Type declaration
  • OptionallistChanged?: boolean

    Whether this server supports notifications for changes to the prompt list.

resources?: { listChanged?: boolean; subscribe?: boolean }

Present if the server offers any resources to read.

Type declaration
  • OptionallistChanged?: boolean

    Whether this server supports notifications for changes to the resource list.

  • Optionalsubscribe?: boolean

    Whether this server supports subscribing to resource updates.

tasks?: {
  prompts?: { get?: boolean; list?: boolean };
  resources?: { list?: boolean; read?: boolean };
  tasks?: {
    delete?: boolean;
    get?: boolean;
    list?: boolean;
    result?: boolean;
  };
  tools?: { call?: boolean; list?: boolean };
}

Present if the server supports task-augmented requests. Nested properties indicate which specific request types can be augmented with tasks.

Type declaration
  • Optionalprompts?: { get?: boolean; list?: boolean }

    Task support for prompt-related requests.

    • Optionalget?: boolean

      Whether the server supports task-augmented prompts/get requests.

    • Optionallist?: boolean

      Whether the server supports task-augmented prompts/list requests.

  • Optionalresources?: { list?: boolean; read?: boolean }

    Task support for resource-related requests.

    • Optionallist?: boolean

      Whether the server supports task-augmented resources/list requests.

    • Optionalread?: boolean

      Whether the server supports task-augmented resources/read requests.

  • Optionaltasks?: { delete?: boolean; get?: boolean; list?: boolean; result?: boolean }

    Task support for task management requests. Enables recursive task tracking where task queries themselves can be augmented with tasks.

    • Optionaldelete?: boolean

      Whether the server supports task-augmented tasks/delete requests.

    • Optionalget?: boolean

      Whether the server supports task-augmented tasks/get requests.

    • Optionallist?: boolean

      Whether the server supports task-augmented tasks/list requests.

    • Optionalresult?: boolean

      Whether the server supports task-augmented tasks/result requests.

  • Optionaltools?: { call?: boolean; list?: boolean }

    Task support for tool-related requests.

    • Optionalcall?: boolean

      Whether the server supports task-augmented tools/call requests.

    • Optionallist?: boolean

      Whether the server supports task-augmented tools/list requests.

tools?: { listChanged?: boolean }

Present if the server offers any tools to call.

Type declaration
  • OptionallistChanged?: boolean

    Whether this server supports notifications for changes to the tool list.

### `StringSchema` @@ -464,6 +464,16 @@ Include this in the _meta field of a request under the key TaskStatus:
  | "submitted"
  | "working"
  | "input_required"
  | "completed"
  | "failed"
  | "cancelled"
  | "unknown"

The status of a task.

+## `tasks/delete` + +### `DeleteTaskRequest` + +
interface DeleteTaskRequest {
  id: RequestId;
  jsonrpc: "2.0";
  method: "tasks/delete";
  params: { taskId: string };
}

A request to delete a task and its associated results.

params: { taskId: string }
Type declaration
  • taskId: string

    The task identifier to delete.

+ +### `DeleteTaskResult` + +
interface DeleteTaskResult {
  _meta?: { [key: string]: unknown };
  [key: string]: unknown;
}

The response to a tasks/delete request.

_meta?: { [key: string]: unknown }

See General fields: _meta for notes on _meta usage.

+ ## `tasks/get` ### `GetTaskRequest` diff --git a/schema/draft/schema.json b/schema/draft/schema.json index 78ab1fac4..65e874455 100644 --- a/schema/draft/schema.json +++ b/schema/draft/schema.json @@ -296,6 +296,10 @@ "tasks": { "description": "Task support for task management requests. Enables recursive task tracking where task queries themselves can be augmented with tasks. This applies when the client acts as a receiver of task-augmented requests from the server.", "properties": { + "delete": { + "description": "Whether the client supports task-augmented tasks/delete requests.", + "type": "boolean" + }, "get": { "description": "Whether the client supports task-augmented tasks/get requests.", "type": "boolean" @@ -377,6 +381,9 @@ { "$ref": "#/definitions/GetTaskPayloadRequest" }, + { + "$ref": "#/definitions/DeleteTaskRequest" + }, { "$ref": "#/definitions/ListTasksRequest" }, @@ -399,6 +406,9 @@ { "$ref": "#/definitions/GetTaskPayloadResult" }, + { + "$ref": "#/definitions/DeleteTaskResult" + }, { "$ref": "#/definitions/ListTasksResult" }, @@ -660,6 +670,52 @@ "description": "An opaque token used to represent a cursor for pagination.", "type": "string" }, + "DeleteTaskRequest": { + "description": "A request to delete a task and its associated results.", + "properties": { + "id": { + "$ref": "#/definitions/RequestId" + }, + "jsonrpc": { + "const": "2.0", + "type": "string" + }, + "method": { + "const": "tasks/delete", + "type": "string" + }, + "params": { + "properties": { + "taskId": { + "description": "The task identifier to delete.", + "type": "string" + } + }, + "required": [ + "taskId" + ], + "type": "object" + } + }, + "required": [ + "id", + "jsonrpc", + "method", + "params" + ], + "type": "object" + }, + "DeleteTaskResult": { + "description": "The response to a tasks/delete request.", + "properties": { + "_meta": { + "additionalProperties": {}, + "description": "See [General fields: `_meta`](/specification/draft/basic/index#meta) for notes on `_meta` usage.", + "type": "object" + } + }, + "type": "object" + }, "ElicitRequest": { "description": "A request from the server to elicit additional information from the user via the client.", "properties": { @@ -2678,6 +2734,10 @@ "tasks": { "description": "Task support for task management requests. Enables recursive task tracking where task queries themselves can be augmented with tasks.", "properties": { + "delete": { + "description": "Whether the server supports task-augmented tasks/delete requests.", + "type": "boolean" + }, "get": { "description": "Whether the server supports task-augmented tasks/get requests.", "type": "boolean" @@ -2762,6 +2822,9 @@ { "$ref": "#/definitions/GetTaskPayloadRequest" }, + { + "$ref": "#/definitions/DeleteTaskRequest" + }, { "$ref": "#/definitions/ListTasksRequest" }, @@ -2811,6 +2874,9 @@ { "$ref": "#/definitions/GetTaskPayloadResult" }, + { + "$ref": "#/definitions/DeleteTaskResult" + }, { "$ref": "#/definitions/ListTasksResult" }, diff --git a/schema/draft/schema.ts b/schema/draft/schema.ts index 50c949c96..7937332a3 100644 --- a/schema/draft/schema.ts +++ b/schema/draft/schema.ts @@ -284,6 +284,10 @@ export interface ClientCapabilities { * Whether the client supports task-augmented tasks/result requests. */ result?: boolean; + /** + * Whether the client supports task-augmented tasks/delete requests. + */ + delete?: boolean; }; }; } @@ -394,6 +398,10 @@ export interface ServerCapabilities { * Whether the server supports task-augmented tasks/result requests. */ result?: boolean; + /** + * Whether the server supports task-augmented tasks/delete requests. + */ + delete?: boolean; }; }; } @@ -1233,6 +1241,28 @@ export interface GetTaskPayloadResult extends Result { [key: string]: unknown; } +/** + * A request to delete a task and its associated results. + * + * @category tasks/delete + */ +export interface DeleteTaskRequest extends JSONRPCRequest { + method: "tasks/delete"; + params: { + /** + * The task identifier to delete. + */ + taskId: string; + }; +} + +/** + * The response to a tasks/delete request. + * + * @category tasks/delete + */ +export interface DeleteTaskResult extends Result {} + /** * A request to retrieve a list of tasks. * @@ -1873,7 +1903,8 @@ export type ClientRequest = | ListToolsRequest | GetTaskRequest | GetTaskPayloadRequest - | ListTasksRequest; + | ListTasksRequest + | DeleteTaskRequest; /** @internal */ export type ClientNotification = @@ -1891,7 +1922,8 @@ export type ClientResult = | ElicitResult | GetTaskResult | GetTaskPayloadResult - | ListTasksResult; + | ListTasksResult + | DeleteTaskResult; /* Server messages */ /** @internal */ @@ -1902,7 +1934,8 @@ export type ServerRequest = | ElicitRequest | GetTaskRequest | GetTaskPayloadRequest - | ListTasksRequest; + | ListTasksRequest + | DeleteTaskRequest; /** @internal */ export type ServerNotification = @@ -1929,4 +1962,5 @@ export type ServerResult = | ListToolsResult | GetTaskResult | GetTaskPayloadResult - | ListTasksResult; + | ListTasksResult + | DeleteTaskResult; From 7585a337d63e81e8b0e9b1251be3dcfea26c5e60 Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Fri, 31 Oct 2025 15:01:41 -0700 Subject: [PATCH 09/79] Move task-augmentation capabilities under tasks.requests for clarity --- .../draft/basic/utilities/tasks.mdx | 70 +++--- docs/specification/draft/schema.mdx | 4 +- schema/draft/schema.json | 216 +++++++++--------- schema/draft/schema.ts | 186 ++++++++------- 4 files changed, 251 insertions(+), 225 deletions(-) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index 42d721107..b99d3a400 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -26,31 +26,33 @@ Servers declare which server-side requests can be augmented with tasks: { "capabilities": { "tasks": { - "tools": { - "call": true, - "list": true - }, - "resources": { - "read": true, - "list": true - }, - "prompts": { - "get": true, - "list": true - }, - "tasks": { - "get": true, - "list": true, - "result": true + "requests": { + "tools": { + "call": true, + "list": true + }, + "resources": { + "read": true, + "list": true + }, + "prompts": { + "get": true, + "list": true + }, + "tasks": { + "get": true, + "list": true, + "result": true + } } } } } ``` -Servers **MAY** support tasks for any subset of their available request types. If a request type is not listed in the `tasks` capability or is set to `false`, requestors **SHOULD NOT** augment those requests with task metadata. +Servers **MAY** support tasks for any subset of their available request types. If a request type is not listed in the `tasks.requests` capability or is set to `false`, requestors **SHOULD NOT** augment those requests with task metadata. -The `tasks.tasks` nested capability indicates whether the task management operations themselves (`tasks/get`, `tasks/list`, `tasks/result`) can be augmented with tasks, enabling recursive task tracking for task queries. +The `tasks.requests.tasks` nested capability indicates whether the task management operations themselves (`tasks/get`, `tasks/list`, `tasks/result`) can be augmented with tasks, enabling recursive task tracking for task queries. ### Client Capabilities @@ -60,32 +62,34 @@ Clients declare which client-side requests can be augmented with tasks: { "capabilities": { "tasks": { - "sampling": { - "createMessage": true - }, - "elicitation": { - "create": true - }, - "roots": { - "list": true - }, - "tasks": { - "get": true, - "list": true, - "result": true + "requests": { + "sampling": { + "createMessage": true + }, + "elicitation": { + "create": true + }, + "roots": { + "list": true + }, + "tasks": { + "get": true, + "list": true, + "result": true + } } } } } ``` -The `tasks.tasks` capability applies when the client is acting as a receiver of task-augmented requests from the server (for example, when a server sends a task-augmented `sampling/createMessage` request to the client). +The `tasks.requests.tasks` capability applies when the client is acting as a receiver of task-augmented requests from the server (for example, when a server sends a task-augmented `sampling/createMessage` request to the client). ### Capability Negotiation During the initialization phase, both parties exchange their `tasks` capabilities to establish which operations support task-based execution. Requestors **MUST** only augment requests with task metadata if the corresponding capability has been declared by the receiver. -For example, if a server's capabilities include `tasks.tools.call: true`, then clients may augment `tools/call` requests with task metadata. However, if the server does not declare `tasks.resources.read`, clients should not send task-augmented `resources/read` requests. +For example, if a server's capabilities include `tasks.requests.tools.call: true`, then clients may augment `tools/call` requests with task metadata. However, if the server does not declare `tasks.requests.resources.read`, clients should not send task-augmented `resources/read` requests. ## Protocol Messages diff --git a/docs/specification/draft/schema.mdx b/docs/specification/draft/schema.mdx index 4b2a28f4e..18d540b74 100644 --- a/docs/specification/draft/schema.mdx +++ b/docs/specification/draft/schema.mdx @@ -27,7 +27,7 @@ the data is entirely optional.

interface ClientCapabilities {
  elicitation?: object;
  experimental?: { [key: string]: object };
  roots?: { listChanged?: boolean };
  sampling?: object;
  tasks?: {
    elicitation?: { create?: boolean };
    roots?: { list?: boolean };
    sampling?: { createMessage?: boolean };
    tasks?: {
      delete?: boolean;
      get?: boolean;
      list?: boolean;
      result?: boolean;
    };
  };
}

Capabilities a client may support. Known capabilities are defined here, in this schema, but this is not a closed set: any client can define its own, additional capabilities.

elicitation?: object

Present if the client supports elicitation from the server.

experimental?: { [key: string]: object }

Experimental, non-standard capabilities that the client supports.

roots?: { listChanged?: boolean }

Present if the client supports listing roots.

Type declaration
  • OptionallistChanged?: boolean

    Whether the client supports notifications for changes to the roots list.

sampling?: object

Present if the client supports sampling from an LLM.

tasks?: {
  elicitation?: { create?: boolean };
  roots?: { list?: boolean };
  sampling?: { createMessage?: boolean };
  tasks?: {
    delete?: boolean;
    get?: boolean;
    list?: boolean;
    result?: boolean;
  };
}

Present if the client supports task-augmented requests. Nested properties indicate which specific request types can be augmented with tasks.

Type declaration
  • Optionalelicitation?: { create?: boolean }

    Task support for elicitation-related requests.

    • Optionalcreate?: boolean

      Whether the client supports task-augmented elicitation/create requests.

  • Optionalroots?: { list?: boolean }

    Task support for roots-related requests.

    • Optionallist?: boolean

      Whether the client supports task-augmented roots/list requests.

  • Optionalsampling?: { createMessage?: boolean }

    Task support for sampling-related requests.

    • OptionalcreateMessage?: boolean

      Whether the client supports task-augmented sampling/createMessage requests.

  • Optionaltasks?: { delete?: boolean; get?: boolean; list?: boolean; result?: boolean }

    Task support for task management requests. Enables recursive task tracking where task queries themselves can be augmented with tasks. This applies when the client acts as a receiver of task-augmented requests from the server.

    • Optionaldelete?: boolean

      Whether the client supports task-augmented tasks/delete requests.

    • Optionalget?: boolean

      Whether the client supports task-augmented tasks/get requests.

    • Optionallist?: boolean

      Whether the client supports task-augmented tasks/list requests.

    • Optionalresult?: boolean

      Whether the client supports task-augmented tasks/result requests.

+
interface ClientCapabilities {
  elicitation?: object;
  experimental?: { [key: string]: object };
  roots?: { listChanged?: boolean };
  sampling?: object;
  tasks?: {
    requests?: {
      elicitation?: { create?: boolean };
      roots?: { list?: boolean };
      sampling?: { createMessage?: boolean };
      tasks?: {
        delete?: boolean;
        get?: boolean;
        list?: boolean;
        result?: boolean;
      };
    };
  };
}

Capabilities a client may support. Known capabilities are defined here, in this schema, but this is not a closed set: any client can define its own, additional capabilities.

elicitation?: object

Present if the client supports elicitation from the server.

experimental?: { [key: string]: object }

Experimental, non-standard capabilities that the client supports.

roots?: { listChanged?: boolean }

Present if the client supports listing roots.

Type declaration
  • OptionallistChanged?: boolean

    Whether the client supports notifications for changes to the roots list.

sampling?: object

Present if the client supports sampling from an LLM.

tasks?: {
  requests?: {
    elicitation?: { create?: boolean };
    roots?: { list?: boolean };
    sampling?: { createMessage?: boolean };
    tasks?: {
      delete?: boolean;
      get?: boolean;
      list?: boolean;
      result?: boolean;
    };
  };
}

Present if the client supports task-augmented requests.

Type declaration
  • Optionalrequests?: {
      elicitation?: { create?: boolean };
      roots?: { list?: boolean };
      sampling?: { createMessage?: boolean };
      tasks?: {
        delete?: boolean;
        get?: boolean;
        list?: boolean;
        result?: boolean;
      };
    }

    Specifies which request types can be augmented with tasks.

    • Optionalelicitation?: { create?: boolean }

      Task support for elicitation-related requests.

      • Optionalcreate?: boolean

        Whether the client supports task-augmented elicitation/create requests.

    • Optionalroots?: { list?: boolean }

      Task support for roots-related requests.

      • Optionallist?: boolean

        Whether the client supports task-augmented roots/list requests.

    • Optionalsampling?: { createMessage?: boolean }

      Task support for sampling-related requests.

      • OptionalcreateMessage?: boolean

        Whether the client supports task-augmented sampling/createMessage requests.

    • Optionaltasks?: { delete?: boolean; get?: boolean; list?: boolean; result?: boolean }

      Task support for task management requests. Enables recursive task tracking where task queries themselves can be augmented with tasks. This applies when the client acts as a receiver of task-augmented requests from the server.

      • Optionaldelete?: boolean

        Whether the client supports task-augmented tasks/delete requests.

      • Optionalget?: boolean

        Whether the client supports task-augmented tasks/get requests.

      • Optionallist?: boolean

        Whether the client supports task-augmented tasks/list requests.

      • Optionalresult?: boolean

        Whether the client supports task-augmented tasks/result requests.

### `ContentBlock` @@ -212,7 +212,7 @@ other URI schemes.

interface ServerCapabilities {
  completions?: object;
  experimental?: { [key: string]: object };
  logging?: object;
  prompts?: { listChanged?: boolean };
  resources?: { listChanged?: boolean; subscribe?: boolean };
  tasks?: {
    prompts?: { get?: boolean; list?: boolean };
    resources?: { list?: boolean; read?: boolean };
    tasks?: {
      delete?: boolean;
      get?: boolean;
      list?: boolean;
      result?: boolean;
    };
    tools?: { call?: boolean; list?: boolean };
  };
  tools?: { listChanged?: boolean };
}

Capabilities that a server may support. Known capabilities are defined here, in this schema, but this is not a closed set: any server can define its own, additional capabilities.

completions?: object

Present if the server supports argument autocompletion suggestions.

experimental?: { [key: string]: object }

Experimental, non-standard capabilities that the server supports.

logging?: object

Present if the server supports sending log messages to the client.

prompts?: { listChanged?: boolean }

Present if the server offers any prompt templates.

Type declaration
  • OptionallistChanged?: boolean

    Whether this server supports notifications for changes to the prompt list.

resources?: { listChanged?: boolean; subscribe?: boolean }

Present if the server offers any resources to read.

Type declaration
  • OptionallistChanged?: boolean

    Whether this server supports notifications for changes to the resource list.

  • Optionalsubscribe?: boolean

    Whether this server supports subscribing to resource updates.

tasks?: {
  prompts?: { get?: boolean; list?: boolean };
  resources?: { list?: boolean; read?: boolean };
  tasks?: {
    delete?: boolean;
    get?: boolean;
    list?: boolean;
    result?: boolean;
  };
  tools?: { call?: boolean; list?: boolean };
}

Present if the server supports task-augmented requests. Nested properties indicate which specific request types can be augmented with tasks.

Type declaration
  • Optionalprompts?: { get?: boolean; list?: boolean }

    Task support for prompt-related requests.

    • Optionalget?: boolean

      Whether the server supports task-augmented prompts/get requests.

    • Optionallist?: boolean

      Whether the server supports task-augmented prompts/list requests.

  • Optionalresources?: { list?: boolean; read?: boolean }

    Task support for resource-related requests.

    • Optionallist?: boolean

      Whether the server supports task-augmented resources/list requests.

    • Optionalread?: boolean

      Whether the server supports task-augmented resources/read requests.

  • Optionaltasks?: { delete?: boolean; get?: boolean; list?: boolean; result?: boolean }

    Task support for task management requests. Enables recursive task tracking where task queries themselves can be augmented with tasks.

    • Optionaldelete?: boolean

      Whether the server supports task-augmented tasks/delete requests.

    • Optionalget?: boolean

      Whether the server supports task-augmented tasks/get requests.

    • Optionallist?: boolean

      Whether the server supports task-augmented tasks/list requests.

    • Optionalresult?: boolean

      Whether the server supports task-augmented tasks/result requests.

  • Optionaltools?: { call?: boolean; list?: boolean }

    Task support for tool-related requests.

    • Optionalcall?: boolean

      Whether the server supports task-augmented tools/call requests.

    • Optionallist?: boolean

      Whether the server supports task-augmented tools/list requests.

tools?: { listChanged?: boolean }

Present if the server offers any tools to call.

Type declaration
  • OptionallistChanged?: boolean

    Whether this server supports notifications for changes to the tool list.

+
interface ServerCapabilities {
  completions?: object;
  experimental?: { [key: string]: object };
  logging?: object;
  prompts?: { listChanged?: boolean };
  resources?: { listChanged?: boolean; subscribe?: boolean };
  tasks?: {
    requests?: {
      prompts?: { get?: boolean; list?: boolean };
      resources?: { list?: boolean; read?: boolean };
      tasks?: {
        delete?: boolean;
        get?: boolean;
        list?: boolean;
        result?: boolean;
      };
      tools?: { call?: boolean; list?: boolean };
    };
  };
  tools?: { listChanged?: boolean };
}

Capabilities that a server may support. Known capabilities are defined here, in this schema, but this is not a closed set: any server can define its own, additional capabilities.

completions?: object

Present if the server supports argument autocompletion suggestions.

experimental?: { [key: string]: object }

Experimental, non-standard capabilities that the server supports.

logging?: object

Present if the server supports sending log messages to the client.

prompts?: { listChanged?: boolean }

Present if the server offers any prompt templates.

Type declaration
  • OptionallistChanged?: boolean

    Whether this server supports notifications for changes to the prompt list.

resources?: { listChanged?: boolean; subscribe?: boolean }

Present if the server offers any resources to read.

Type declaration
  • OptionallistChanged?: boolean

    Whether this server supports notifications for changes to the resource list.

  • Optionalsubscribe?: boolean

    Whether this server supports subscribing to resource updates.

tasks?: {
  requests?: {
    prompts?: { get?: boolean; list?: boolean };
    resources?: { list?: boolean; read?: boolean };
    tasks?: {
      delete?: boolean;
      get?: boolean;
      list?: boolean;
      result?: boolean;
    };
    tools?: { call?: boolean; list?: boolean };
  };
}

Present if the server supports task-augmented requests.

Type declaration
  • Optionalrequests?: {
      prompts?: { get?: boolean; list?: boolean };
      resources?: { list?: boolean; read?: boolean };
      tasks?: {
        delete?: boolean;
        get?: boolean;
        list?: boolean;
        result?: boolean;
      };
      tools?: { call?: boolean; list?: boolean };
    }

    Specifies which request types can be augmented with tasks.

    • Optionalprompts?: { get?: boolean; list?: boolean }

      Task support for prompt-related requests.

      • Optionalget?: boolean

        Whether the server supports task-augmented prompts/get requests.

      • Optionallist?: boolean

        Whether the server supports task-augmented prompts/list requests.

    • Optionalresources?: { list?: boolean; read?: boolean }

      Task support for resource-related requests.

      • Optionallist?: boolean

        Whether the server supports task-augmented resources/list requests.

      • Optionalread?: boolean

        Whether the server supports task-augmented resources/read requests.

    • Optionaltasks?: { delete?: boolean; get?: boolean; list?: boolean; result?: boolean }

      Task support for task management requests. Enables recursive task tracking where task queries themselves can be augmented with tasks.

      • Optionaldelete?: boolean

        Whether the server supports task-augmented tasks/delete requests.

      • Optionalget?: boolean

        Whether the server supports task-augmented tasks/get requests.

      • Optionallist?: boolean

        Whether the server supports task-augmented tasks/list requests.

      • Optionalresult?: boolean

        Whether the server supports task-augmented tasks/result requests.

    • Optionaltools?: { call?: boolean; list?: boolean }

      Task support for tool-related requests.

      • Optionalcall?: boolean

        Whether the server supports task-augmented tools/call requests.

      • Optionallist?: boolean

        Whether the server supports task-augmented tools/list requests.

tools?: { listChanged?: boolean }

Present if the server offers any tools to call.

Type declaration
  • OptionallistChanged?: boolean

    Whether this server supports notifications for changes to the tool list.

### `StringSchema` diff --git a/schema/draft/schema.json b/schema/draft/schema.json index 65e874455..3c02b0d88 100644 --- a/schema/draft/schema.json +++ b/schema/draft/schema.json @@ -261,56 +261,62 @@ "type": "object" }, "tasks": { - "description": "Present if the client supports task-augmented requests. Nested properties indicate which specific request types can be augmented with tasks.", + "description": "Present if the client supports task-augmented requests.", "properties": { - "elicitation": { - "description": "Task support for elicitation-related requests.", + "requests": { + "description": "Specifies which request types can be augmented with tasks.", "properties": { - "create": { - "description": "Whether the client supports task-augmented elicitation/create requests.", - "type": "boolean" - } - }, - "type": "object" - }, - "roots": { - "description": "Task support for roots-related requests.", - "properties": { - "list": { - "description": "Whether the client supports task-augmented roots/list requests.", - "type": "boolean" - } - }, - "type": "object" - }, - "sampling": { - "description": "Task support for sampling-related requests.", - "properties": { - "createMessage": { - "description": "Whether the client supports task-augmented sampling/createMessage requests.", - "type": "boolean" - } - }, - "type": "object" - }, - "tasks": { - "description": "Task support for task management requests. Enables recursive task tracking where task queries themselves can be augmented with tasks. This applies when the client acts as a receiver of task-augmented requests from the server.", - "properties": { - "delete": { - "description": "Whether the client supports task-augmented tasks/delete requests.", - "type": "boolean" + "elicitation": { + "description": "Task support for elicitation-related requests.", + "properties": { + "create": { + "description": "Whether the client supports task-augmented elicitation/create requests.", + "type": "boolean" + } + }, + "type": "object" }, - "get": { - "description": "Whether the client supports task-augmented tasks/get requests.", - "type": "boolean" + "roots": { + "description": "Task support for roots-related requests.", + "properties": { + "list": { + "description": "Whether the client supports task-augmented roots/list requests.", + "type": "boolean" + } + }, + "type": "object" }, - "list": { - "description": "Whether the client supports task-augmented tasks/list requests.", - "type": "boolean" + "sampling": { + "description": "Task support for sampling-related requests.", + "properties": { + "createMessage": { + "description": "Whether the client supports task-augmented sampling/createMessage requests.", + "type": "boolean" + } + }, + "type": "object" }, - "result": { - "description": "Whether the client supports task-augmented tasks/result requests.", - "type": "boolean" + "tasks": { + "description": "Task support for task management requests. Enables recursive task tracking where task queries themselves can be augmented with tasks. This applies when the client acts as a receiver of task-augmented requests from the server.", + "properties": { + "delete": { + "description": "Whether the client supports task-augmented tasks/delete requests.", + "type": "boolean" + }, + "get": { + "description": "Whether the client supports task-augmented tasks/get requests.", + "type": "boolean" + }, + "list": { + "description": "Whether the client supports task-augmented tasks/list requests.", + "type": "boolean" + }, + "result": { + "description": "Whether the client supports task-augmented tasks/result requests.", + "type": "boolean" + } + }, + "type": "object" } }, "type": "object" @@ -2701,68 +2707,74 @@ "type": "object" }, "tasks": { - "description": "Present if the server supports task-augmented requests. Nested properties indicate which specific request types can be augmented with tasks.", + "description": "Present if the server supports task-augmented requests.", "properties": { - "prompts": { - "description": "Task support for prompt-related requests.", + "requests": { + "description": "Specifies which request types can be augmented with tasks.", "properties": { - "get": { - "description": "Whether the server supports task-augmented prompts/get requests.", - "type": "boolean" - }, - "list": { - "description": "Whether the server supports task-augmented prompts/list requests.", - "type": "boolean" - } - }, - "type": "object" - }, - "resources": { - "description": "Task support for resource-related requests.", - "properties": { - "list": { - "description": "Whether the server supports task-augmented resources/list requests.", - "type": "boolean" - }, - "read": { - "description": "Whether the server supports task-augmented resources/read requests.", - "type": "boolean" - } - }, - "type": "object" - }, - "tasks": { - "description": "Task support for task management requests. Enables recursive task tracking where task queries themselves can be augmented with tasks.", - "properties": { - "delete": { - "description": "Whether the server supports task-augmented tasks/delete requests.", - "type": "boolean" - }, - "get": { - "description": "Whether the server supports task-augmented tasks/get requests.", - "type": "boolean" + "prompts": { + "description": "Task support for prompt-related requests.", + "properties": { + "get": { + "description": "Whether the server supports task-augmented prompts/get requests.", + "type": "boolean" + }, + "list": { + "description": "Whether the server supports task-augmented prompts/list requests.", + "type": "boolean" + } + }, + "type": "object" }, - "list": { - "description": "Whether the server supports task-augmented tasks/list requests.", - "type": "boolean" + "resources": { + "description": "Task support for resource-related requests.", + "properties": { + "list": { + "description": "Whether the server supports task-augmented resources/list requests.", + "type": "boolean" + }, + "read": { + "description": "Whether the server supports task-augmented resources/read requests.", + "type": "boolean" + } + }, + "type": "object" }, - "result": { - "description": "Whether the server supports task-augmented tasks/result requests.", - "type": "boolean" - } - }, - "type": "object" - }, - "tools": { - "description": "Task support for tool-related requests.", - "properties": { - "call": { - "description": "Whether the server supports task-augmented tools/call requests.", - "type": "boolean" + "tasks": { + "description": "Task support for task management requests. Enables recursive task tracking where task queries themselves can be augmented with tasks.", + "properties": { + "delete": { + "description": "Whether the server supports task-augmented tasks/delete requests.", + "type": "boolean" + }, + "get": { + "description": "Whether the server supports task-augmented tasks/get requests.", + "type": "boolean" + }, + "list": { + "description": "Whether the server supports task-augmented tasks/list requests.", + "type": "boolean" + }, + "result": { + "description": "Whether the server supports task-augmented tasks/result requests.", + "type": "boolean" + } + }, + "type": "object" }, - "list": { - "description": "Whether the server supports task-augmented tools/list requests.", - "type": "boolean" + "tools": { + "description": "Task support for tool-related requests.", + "properties": { + "call": { + "description": "Whether the server supports task-augmented tools/call requests.", + "type": "boolean" + }, + "list": { + "description": "Whether the server supports task-augmented tools/list requests.", + "type": "boolean" + } + }, + "type": "object" } }, "type": "object" diff --git a/schema/draft/schema.ts b/schema/draft/schema.ts index 7937332a3..74a400801 100644 --- a/schema/draft/schema.ts +++ b/schema/draft/schema.ts @@ -238,56 +238,61 @@ export interface ClientCapabilities { */ elicitation?: object; /** - * Present if the client supports task-augmented requests. Nested properties indicate which specific request types can be augmented with tasks. + * Present if the client supports task-augmented requests. */ tasks?: { /** - * Task support for sampling-related requests. + * Specifies which request types can be augmented with tasks. */ - sampling?: { + requests?: { /** - * Whether the client supports task-augmented sampling/createMessage requests. + * Task support for sampling-related requests. */ - createMessage?: boolean; - }; - /** - * Task support for elicitation-related requests. - */ - elicitation?: { - /** - * Whether the client supports task-augmented elicitation/create requests. - */ - create?: boolean; - }; - /** - * Task support for roots-related requests. - */ - roots?: { - /** - * Whether the client supports task-augmented roots/list requests. - */ - list?: boolean; - }; - /** - * Task support for task management requests. Enables recursive task tracking where task queries themselves can be augmented with tasks. This applies when the client acts as a receiver of task-augmented requests from the server. - */ - tasks?: { - /** - * Whether the client supports task-augmented tasks/get requests. - */ - get?: boolean; + sampling?: { + /** + * Whether the client supports task-augmented sampling/createMessage requests. + */ + createMessage?: boolean; + }; /** - * Whether the client supports task-augmented tasks/list requests. + * Task support for elicitation-related requests. */ - list?: boolean; + elicitation?: { + /** + * Whether the client supports task-augmented elicitation/create requests. + */ + create?: boolean; + }; /** - * Whether the client supports task-augmented tasks/result requests. + * Task support for roots-related requests. */ - result?: boolean; + roots?: { + /** + * Whether the client supports task-augmented roots/list requests. + */ + list?: boolean; + }; /** - * Whether the client supports task-augmented tasks/delete requests. + * Task support for task management requests. Enables recursive task tracking where task queries themselves can be augmented with tasks. This applies when the client acts as a receiver of task-augmented requests from the server. */ - delete?: boolean; + tasks?: { + /** + * Whether the client supports task-augmented tasks/get requests. + */ + get?: boolean; + /** + * Whether the client supports task-augmented tasks/list requests. + */ + list?: boolean; + /** + * Whether the client supports task-augmented tasks/result requests. + */ + result?: boolean; + /** + * Whether the client supports task-augmented tasks/delete requests. + */ + delete?: boolean; + }; }; }; } @@ -340,68 +345,73 @@ export interface ServerCapabilities { listChanged?: boolean; }; /** - * Present if the server supports task-augmented requests. Nested properties indicate which specific request types can be augmented with tasks. + * Present if the server supports task-augmented requests. */ tasks?: { /** - * Task support for tool-related requests. - */ - tools?: { - /** - * Whether the server supports task-augmented tools/call requests. - */ - call?: boolean; - /** - * Whether the server supports task-augmented tools/list requests. - */ - list?: boolean; - }; - /** - * Task support for resource-related requests. - */ - resources?: { - /** - * Whether the server supports task-augmented resources/read requests. - */ - read?: boolean; - /** - * Whether the server supports task-augmented resources/list requests. - */ - list?: boolean; - }; - /** - * Task support for prompt-related requests. + * Specifies which request types can be augmented with tasks. */ - prompts?: { + requests?: { /** - * Whether the server supports task-augmented prompts/get requests. + * Task support for tool-related requests. */ - get?: boolean; - /** - * Whether the server supports task-augmented prompts/list requests. - */ - list?: boolean; - }; - /** - * Task support for task management requests. Enables recursive task tracking where task queries themselves can be augmented with tasks. - */ - tasks?: { - /** - * Whether the server supports task-augmented tasks/get requests. - */ - get?: boolean; + tools?: { + /** + * Whether the server supports task-augmented tools/call requests. + */ + call?: boolean; + /** + * Whether the server supports task-augmented tools/list requests. + */ + list?: boolean; + }; /** - * Whether the server supports task-augmented tasks/list requests. + * Task support for resource-related requests. */ - list?: boolean; + resources?: { + /** + * Whether the server supports task-augmented resources/read requests. + */ + read?: boolean; + /** + * Whether the server supports task-augmented resources/list requests. + */ + list?: boolean; + }; /** - * Whether the server supports task-augmented tasks/result requests. + * Task support for prompt-related requests. */ - result?: boolean; + prompts?: { + /** + * Whether the server supports task-augmented prompts/get requests. + */ + get?: boolean; + /** + * Whether the server supports task-augmented prompts/list requests. + */ + list?: boolean; + }; /** - * Whether the server supports task-augmented tasks/delete requests. + * Task support for task management requests. Enables recursive task tracking where task queries themselves can be augmented with tasks. */ - delete?: boolean; + tasks?: { + /** + * Whether the server supports task-augmented tasks/get requests. + */ + get?: boolean; + /** + * Whether the server supports task-augmented tasks/list requests. + */ + list?: boolean; + /** + * Whether the server supports task-augmented tasks/result requests. + */ + result?: boolean; + /** + * Whether the server supports task-augmented tasks/delete requests. + */ + delete?: boolean; + }; }; }; } From a0b93c85e9cf8b61c5b1e03cd66ff2a50b13d2f5 Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Fri, 31 Oct 2025 15:04:36 -0700 Subject: [PATCH 10/79] Clarify that failed status refers to lifecycle --- docs/specification/draft/basic/utilities/tasks.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index b99d3a400..e9aaf40c6 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -622,7 +622,7 @@ Tasks can be in one of the following states: - `submitted`: The request has been received and queued for execution - `working`: The request is currently being processed - `completed`: The request completed successfully and results are available -- `failed`: The request encountered an error during execution +- `failed`: The task lifecycle itself encountered an error - `cancelled`: The request was cancelled before completion - `unknown`: A terminal fallback state for unexpected error conditions when the receiver cannot determine the actual task state From 81fd957079532cd8eae40861069f0bbd7b4a952f Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Fri, 31 Oct 2025 15:13:52 -0700 Subject: [PATCH 11/79] Specify that task methods themselves should not have related-task metadata --- .../draft/basic/utilities/tasks.mdx | 22 ++++--------------- 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index e9aaf40c6..3bbeb4ca8 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -127,12 +127,7 @@ To retrieve the state of a task, requestors send a `tasks/get` request: "id": 3, "method": "tasks/get", "params": { - "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", - "_meta": { - "modelcontextprotocol.io/related-task": { - "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" - } - } + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" } } ``` @@ -169,12 +164,7 @@ To retrieve the result of a completed task, requestors send a `tasks/result` req "id": 4, "method": "tasks/result", "params": { - "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", - "_meta": { - "modelcontextprotocol.io/related-task": { - "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" - } - } + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" } } ``` @@ -282,12 +272,7 @@ To explicitly delete a task and its associated results, requestors send a `tasks "id": 6, "method": "tasks/delete", "params": { - "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", - "_meta": { - "modelcontextprotocol.io/related-task": { - "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" - } - } + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" } } ``` @@ -384,6 +369,7 @@ stateDiagram-v2 1. All requests, notifications, and responses related to a task **MUST** include the `modelcontextprotocol.io/related-task` key in their `_meta`, with the value set to an object with a `taskId` matching the associated task ID. 1. 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. +1. For the `tasks/get`, `tasks/list`, `tasks/result`, and `tasks/delete` operations, the `taskId` parameter in the request **MUST** be used as the source of truth for identifying the target task. Requestors **SHOULD NOT** include `modelcontextprotocol.io/related-task` metadata in these requests, and receivers **MUST** ignore such metadata if present in favor of the RPC method parameter. ### Task Cancellation From c0260cc74e5b9cf854a0f154a55b9eae0ef16bab Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Fri, 31 Oct 2025 15:22:12 -0700 Subject: [PATCH 12/79] Rename pollFrequency to pollInterval --- docs/specification/draft/basic/utilities/tasks.mdx | 8 ++++---- docs/specification/draft/schema.mdx | 4 ++-- schema/draft/schema.json | 4 ++-- schema/draft/schema.ts | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index 3bbeb4ca8..2dedff64f 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -141,7 +141,7 @@ To retrieve the state of a task, requestors send a `tasks/get` request: "result": { "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", "keepAlive": 30000, - "pollFrequency": 5000, + "pollInterval": 5000, "status": "submitted", "_meta": { "modelcontextprotocol.io/related-task": { @@ -247,7 +247,7 @@ To retrieve a list of tasks, requestors send a `tasks/list` request. This operat "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", "status": "working", "keepAlive": 30000, - "pollFrequency": 5000 + "pollInterval": 5000 }, { "taskId": "abc123-def456-ghi789", @@ -357,7 +357,7 @@ stateDiagram-v2 1. Receivers **MAY** override the requested `keepAlive` duration. 1. Receivers **MUST** include the actual `keepAlive` duration (or `null` for unlimited) in `tasks/get` responses. 1. After a task reaches a terminal status (`completed`, `failed`, or `cancelled`) and its `keepAlive` duration has elapsed, receivers **MAY** delete the task and its results. -1. Receivers **MAY** include a `pollFrequency` value (in milliseconds) in `tasks/get` responses to suggest polling intervals. Requestors **SHOULD** respect this value when provided. +1. Receivers **MAY** include a `pollInterval` value (in milliseconds) in `tasks/get` responses to suggest polling intervals. Requestors **SHOULD** respect this value when provided. ### Result Retrieval @@ -598,7 +598,7 @@ A task represents the execution state of a request. The task metadata includes: - `taskId`: Unique identifier for the task - `keepAlive`: Time in milliseconds that results will be kept available after completion -- `pollFrequency`: Suggested time in milliseconds between status checks +- `pollInterval`: Suggested time in milliseconds between status checks - `status`: Current state of the task execution ### Task Status diff --git a/docs/specification/draft/schema.mdx b/docs/specification/draft/schema.mdx index 18d540b74..64190c99f 100644 --- a/docs/specification/draft/schema.mdx +++ b/docs/specification/draft/schema.mdx @@ -482,7 +482,7 @@ Include this in the _meta field of a request under the key interface GetTaskResult {
  _meta?: { [key: string]: unknown };
  error?: string;
  keepAlive: null | number;
  pollFrequency?: number;
  status: TaskStatus;
  taskId: string;
  [key: string]: unknown;
}

The response to a tasks/get request.

_meta?: { [key: string]: unknown }

See General fields: _meta for notes on _meta usage.

error?: string

Error message if status is "failed".

keepAlive: null | number

Actual retention duration in milliseconds, null for unlimited.

pollFrequency?: number

Suggested polling interval in milliseconds.

status: TaskStatus

Current task state.

taskId: string

The task identifier.

+
interface GetTaskResult {
  _meta?: { [key: string]: unknown };
  error?: string;
  keepAlive: null | number;
  pollInterval?: number;
  status: TaskStatus;
  taskId: string;
  [key: string]: unknown;
}

The response to a tasks/get request.

_meta?: { [key: string]: unknown }

See General fields: _meta for notes on _meta usage.

error?: string

Error message if status is "failed".

keepAlive: null | number

Actual retention duration in milliseconds, null for unlimited.

pollInterval?: number

Suggested polling interval in milliseconds.

status: TaskStatus

Current task state.

taskId: string

The task identifier.

## `tasks/list` @@ -498,7 +498,7 @@ If present, there may be more results available.

interface TaskInfo {
  error?: string;
  keepAlive: null | number;
  pollFrequency?: number;
  status: TaskStatus;
  taskId: string;
}

A summary of a task's state, as returned by tasks/list.

error?: string

Error message if status is "failed".

keepAlive: null | number

Retention duration in milliseconds, null for unlimited.

pollFrequency?: number

Suggested polling interval in milliseconds.

status: TaskStatus

Current task state.

taskId: string

The task identifier.

+
interface TaskInfo {
  error?: string;
  keepAlive: null | number;
  pollInterval?: number;
  status: TaskStatus;
  taskId: string;
}

A summary of a task's state, as returned by tasks/list.

error?: string

Error message if status is "failed".

keepAlive: null | number

Retention duration in milliseconds, null for unlimited.

pollInterval?: number

Suggested polling interval in milliseconds.

status: TaskStatus

Current task state.

taskId: string

The task identifier.

## `tasks/result` diff --git a/schema/draft/schema.json b/schema/draft/schema.json index 3c02b0d88..3239f09bf 100644 --- a/schema/draft/schema.json +++ b/schema/draft/schema.json @@ -1072,7 +1072,7 @@ "description": "Actual retention duration in milliseconds, null for unlimited.", "type": "integer" }, - "pollFrequency": { + "pollInterval": { "description": "Suggested polling interval in milliseconds.", "type": "integer" }, @@ -3048,7 +3048,7 @@ "description": "Retention duration in milliseconds, null for unlimited.", "type": "integer" }, - "pollFrequency": { + "pollInterval": { "description": "Suggested polling interval in milliseconds.", "type": "integer" }, diff --git a/schema/draft/schema.ts b/schema/draft/schema.ts index 74a400801..bd6e9cf01 100644 --- a/schema/draft/schema.ts +++ b/schema/draft/schema.ts @@ -1217,7 +1217,7 @@ export interface GetTaskResult extends Result { /** * Suggested polling interval in milliseconds. */ - pollFrequency?: number; + pollInterval?: number; /** * Error message if status is "failed". @@ -1306,7 +1306,7 @@ export interface TaskInfo { /** * Suggested polling interval in milliseconds. */ - pollFrequency?: number; + pollInterval?: number; /** * Error message if status is "failed". From 5e53553cd097207d75ada0712c0ef861d536b113 Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Tue, 4 Nov 2025 14:23:09 -0800 Subject: [PATCH 13/79] Document input_required status in data types --- docs/specification/draft/basic/utilities/tasks.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index 2dedff64f..ff9f1fb32 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -607,6 +607,7 @@ Tasks can be in one of the following states: - `submitted`: The request has been received and queued for execution - `working`: The request is currently being processed +- `input_required`: The task lifecycle itself encountered an error, unrelated to the associated request logic - `completed`: The request completed successfully and results are available - `failed`: The task lifecycle itself encountered an error - `cancelled`: The request was cancelled before completion From e4e2a08bc3eb6a64e25cb70070a910938e76006f Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Wed, 5 Nov 2025 16:28:53 -0800 Subject: [PATCH 14/79] Add capability for augmenting tasks/delete itself with a task --- docs/specification/draft/basic/utilities/tasks.mdx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index ff9f1fb32..0c95200b4 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -42,7 +42,8 @@ Servers declare which server-side requests can be augmented with tasks: "tasks": { "get": true, "list": true, - "result": true + "result": true, + "delete": true } } } @@ -52,7 +53,7 @@ Servers declare which server-side requests can be augmented with tasks: Servers **MAY** support tasks for any subset of their available request types. If a request type is not listed in the `tasks.requests` capability or is set to `false`, requestors **SHOULD NOT** augment those requests with task metadata. -The `tasks.requests.tasks` nested capability indicates whether the task management operations themselves (`tasks/get`, `tasks/list`, `tasks/result`) can be augmented with tasks, enabling recursive task tracking for task queries. +The `tasks.requests.tasks` nested capability indicates whether the task management operations themselves (`tasks/get`, `tasks/list`, `tasks/result`, `tasks/delete`) can be augmented with tasks, enabling recursive task tracking for task queries. ### Client Capabilities @@ -75,7 +76,8 @@ Clients declare which client-side requests can be augmented with tasks: "tasks": { "get": true, "list": true, - "result": true + "result": true, + "delete": true } } } From 2a9c374ae5bef31ef5b47bed395dafed844e92d4 Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Wed, 5 Nov 2025 16:39:25 -0800 Subject: [PATCH 15/79] Receiver SHOULD move tasks to input_required --- docs/specification/draft/basic/utilities/tasks.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index 0c95200b4..d582fefd6 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -349,7 +349,7 @@ stateDiagram-v2 ### Input Required Status -1. When a receiver sends a request associated with a task (e.g., elicitation, sampling), the receiver **MUST** move the task to the `input_required` status. +1. When a receiver sends a request associated with a task (e.g., elicitation, sampling), the receiver **SHOULD** move the task to the `input_required` status. 1. The receiver **MUST** include the `modelcontextprotocol.io/related-task` metadata in the request to associate it with the task. 1. When the receiver receives all required responses, the task **MAY** transition out of `input_required` status (typically back to `working`). 1. If multiple related requests are pending, the task **SHOULD** remain in `input_required` status until all are resolved. From e57ea318be701f8d205140e7611a2e84e09508a0 Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Thu, 6 Nov 2025 11:09:56 -0800 Subject: [PATCH 16/79] Fix input_required and failed status descriptions --- docs/specification/draft/basic/utilities/tasks.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index d582fefd6..898d88df5 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -609,9 +609,9 @@ Tasks can be in one of the following states: - `submitted`: The request has been received and queued for execution - `working`: The request is currently being processed -- `input_required`: The task lifecycle itself encountered an error, unrelated to the associated request logic +- `input_required`: The request is waiting on additional input from the requestor - `completed`: The request completed successfully and results are available -- `failed`: The task lifecycle itself encountered an error +- `failed`: The task lifecycle itself encountered an error, unrelated to the associated request logic - `cancelled`: The request was cancelled before completion - `unknown`: A terminal fallback state for unexpected error conditions when the receiver cannot determine the actual task state From 97fcd60138545298d7178f233c01393b8c2435a1 Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Thu, 6 Nov 2025 15:16:55 -0800 Subject: [PATCH 17/79] Add optional status notifications for tasks --- .../draft/basic/utilities/tasks.mdx | 29 ++++++++++ docs/specification/draft/schema.mdx | 10 ++++ schema/draft/schema.json | 55 +++++++++++++++++++ schema/draft/schema.ts | 44 +++++++++++++-- 4 files changed, 134 insertions(+), 4 deletions(-) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index 898d88df5..d54acddb5 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -220,6 +220,35 @@ This notification resolves the race condition where a requestor might attempt to Receivers that do not support tasks (and thus ignore task metadata in requests) will not send this notification, allowing requestors to fall back to waiting for the original request response. +### Task Status Notification + +When a task's status changes, receivers **MAY** send a `notifications/tasks/status` notification to inform the requestor of the change. + +**Notification:** + +```json +{ + "jsonrpc": "2.0", + "method": "notifications/tasks/status", + "params": { + "status": "completed", + "_meta": { + "modelcontextprotocol.io/related-task": { + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" + } + } + } +} +``` + +The notification includes: +- `status`: The new task status +- `error` (optional): Error message if the status is `failed` + +The task ID is conveyed through the `modelcontextprotocol.io/related-task` metadata key. + +Requestors **MUST NOT** rely on receiving these notifications, as they are 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 send a `tasks/list` request. This operation supports pagination. diff --git a/docs/specification/draft/schema.mdx b/docs/specification/draft/schema.mdx index 54fe67e07..7a1a11e72 100644 --- a/docs/specification/draft/schema.mdx +++ b/docs/specification/draft/schema.mdx @@ -383,6 +383,16 @@ The server should then request an updated list of roots using the ListRootsReque
interface TaskCreatedNotification {
  jsonrpc: "2.0";
  method: "notifications/tasks/created";
  params?: {
    _meta?: {
      "modelcontextprotocol.io/related-task"?: RelatedTaskMetadata;
      [key: string]: unknown;
    };
  };
}

A notification from the receiver to the requestor, informing them that a task has been created and is ready for polling.

params?: {
  _meta?: {
    "modelcontextprotocol.io/related-task"?: RelatedTaskMetadata;
    [key: string]: unknown;
  };
}
Type declaration
+## `notifications/tasks/status` + +### `TaskStatusNotification` + +
interface TaskStatusNotification {
  jsonrpc: "2.0";
  method: "notifications/tasks/status";
  params: TaskStatusNotificationParams;
}

An optional notification from the receiver to the requestor, informing them that a task's status has changed. Receivers are not required to send these notifications.

+ +### `TaskStatusNotificationParams` + +
interface TaskStatusNotificationParams {
  _meta?: {
    "modelcontextprotocol.io/related-task"?: RelatedTaskMetadata;
    [key: string]: unknown;
  };
  error?: string;
  status: TaskStatus;
}

Parameters for a notifications/tasks/status notification.

_meta?: {
  "modelcontextprotocol.io/related-task"?: RelatedTaskMetadata;
  [key: string]: unknown;
}

The _meta field MUST include modelcontextprotocol.io/related-task with the taskId.

error?: string

Error message if status is "failed".

status: TaskStatus

The new task status.

+ ## `notifications/tools/list_changed` ### `ToolListChangedNotification` diff --git a/schema/draft/schema.json b/schema/draft/schema.json index 6ed97d024..81bd71b5e 100644 --- a/schema/draft/schema.json +++ b/schema/draft/schema.json @@ -369,6 +369,9 @@ { "$ref": "#/definitions/TaskCreatedNotification" }, + { + "$ref": "#/definitions/TaskStatusNotification" + }, { "$ref": "#/definitions/RootsListChangedNotification" } @@ -2900,6 +2903,9 @@ { "$ref": "#/definitions/TaskCreatedNotification" }, + { + "$ref": "#/definitions/TaskStatusNotification" + }, { "$ref": "#/definitions/LoggingMessageNotification" } @@ -3210,6 +3216,55 @@ ], "type": "string" }, + "TaskStatusNotification": { + "description": "An optional notification from the receiver to the requestor, informing them that a task's status has changed. Receivers are not required to send these notifications.", + "properties": { + "jsonrpc": { + "const": "2.0", + "type": "string" + }, + "method": { + "const": "notifications/tasks/status", + "type": "string" + }, + "params": { + "$ref": "#/definitions/TaskStatusNotificationParams" + } + }, + "required": [ + "jsonrpc", + "method", + "params" + ], + "type": "object" + }, + "TaskStatusNotificationParams": { + "description": "Parameters for a `notifications/tasks/status` notification.", + "properties": { + "_meta": { + "additionalProperties": {}, + "description": "The _meta field MUST include modelcontextprotocol.io/related-task with the taskId.", + "properties": { + "modelcontextprotocol.io/related-task": { + "$ref": "#/definitions/RelatedTaskMetadata" + } + }, + "type": "object" + }, + "error": { + "description": "Error message if status is \"failed\".", + "type": "string" + }, + "status": { + "$ref": "#/definitions/TaskStatus", + "description": "The new task status." + } + }, + "required": [ + "status" + ], + "type": "object" + }, "TextContent": { "description": "Text provided to or from an LLM.", "properties": { diff --git a/schema/draft/schema.ts b/schema/draft/schema.ts index 7afb76832..09630656e 100644 --- a/schema/draft/schema.ts +++ b/schema/draft/schema.ts @@ -57,7 +57,6 @@ export interface NotificationParams { _meta?: { [key: string]: unknown }; } - /** @internal */ export interface Notification { method: string; @@ -546,7 +545,7 @@ export interface Implementation extends BaseMetadata, Icons { */ export interface PingRequest extends JSONRPCRequest { method: "ping"; - params?: RequestParams + params?: RequestParams; } /* Progress notifications */ @@ -1423,6 +1422,41 @@ export interface TaskCreatedNotification extends JSONRPCNotification { }; } +/** + * Parameters for a `notifications/tasks/status` notification. + * + * @category notifications/tasks/status + */ +export interface TaskStatusNotificationParams extends NotificationParams { + /** + * The new task status. + */ + status: TaskStatus; + + /** + * Error message if status is "failed". + */ + error?: string; + + /** + * The _meta field MUST include modelcontextprotocol.io/related-task with the taskId. + */ + _meta?: { + "modelcontextprotocol.io/related-task"?: RelatedTaskMetadata; + [key: string]: unknown; + }; +} + +/** + * An optional notification from the receiver to the requestor, informing them that a task's status has changed. Receivers are not required to send these notifications. + * + * @category notifications/tasks/status + */ +export interface TaskStatusNotification extends JSONRPCNotification { + method: "notifications/tasks/status"; + params: TaskStatusNotificationParams; +} + /* Logging */ /** @@ -2042,7 +2076,8 @@ export type ClientNotification = | ProgressNotification | InitializedNotification | RootsListChangedNotification - | TaskCreatedNotification; + | TaskCreatedNotification + | TaskStatusNotification; /** @internal */ export type ClientResult = @@ -2076,7 +2111,8 @@ export type ServerNotification = | ResourceListChangedNotification | ToolListChangedNotification | PromptListChangedNotification - | TaskCreatedNotification; + | TaskCreatedNotification + | TaskStatusNotification; /** @internal */ export type ServerResult = From 2b9c6daa212caad22d10044ad577856faa52e671 Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Thu, 6 Nov 2025 15:19:43 -0800 Subject: [PATCH 18/79] Format docs --- docs/specification/draft/basic/utilities/tasks.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index d54acddb5..a4bf050e9 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -242,6 +242,7 @@ When a task's status changes, receivers **MAY** send a `notifications/tasks/stat ``` The notification includes: + - `status`: The new task status - `error` (optional): Error message if the status is `failed` From 9b717e2740bcc78550b938cf5b2010b52317711a Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Fri, 7 Nov 2025 12:32:45 -0800 Subject: [PATCH 19/79] Make "failed" reflect the request error --- docs/specification/draft/basic/utilities/tasks.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index a4bf050e9..9fb0cf06f 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -641,7 +641,7 @@ Tasks can be in one of the following states: - `working`: The request is currently being processed - `input_required`: The request is waiting on additional input from the requestor - `completed`: The request completed successfully and results are available -- `failed`: The task lifecycle itself encountered an error, unrelated to the associated request logic +- `failed`: The associated request did not complete successfully. For tool calls specifically, this includes cases where the tool call result has `isError` set to true. - `cancelled`: The request was cancelled before completion - `unknown`: A terminal fallback state for unexpected error conditions when the receiver cannot determine the actual task state @@ -770,7 +770,7 @@ Receivers are not obligated to retain task metadata indefinitely. It is complian ### Task Execution Errors -When the underlying request fails during execution, the task moves to the `failed` status. The `tasks/get` response **SHOULD** include an `error` field with details about the failure. +When the underlying request does not complete successfully, the task moves to the `failed` 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 an `error` field with details about the failure. **Example: Task with execution error** @@ -787,7 +787,7 @@ When the underlying request fails during execution, the task moves to the `faile } ``` -For tasks that wrap requests with their own error semantics (like `tools/call` with `isError: true`), the task should still reach `completed` status, and the error information is conveyed through the result structure of the original request type. +For tasks that wrap tool call requests, when the tool result has `isError` set to true, the task should reach `failed` status. The error information is conveyed both through the task's `failed` status and through the result structure when retrieved via `tasks/result`. ## Security Considerations From 96b8d49e3c21665facf576d545e7a3e34f589a8a Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Fri, 7 Nov 2025 12:39:47 -0800 Subject: [PATCH 20/79] Fix empty result type --- docs/specification/draft/schema.mdx | 2 +- schema/draft/schema.json | 16 +--------------- schema/draft/schema.ts | 2 +- 3 files changed, 3 insertions(+), 17 deletions(-) diff --git a/docs/specification/draft/schema.mdx b/docs/specification/draft/schema.mdx index 3c3f0b865..bca399c07 100644 --- a/docs/specification/draft/schema.mdx +++ b/docs/specification/draft/schema.mdx @@ -540,7 +540,7 @@ Include this in the _meta field of a request under the key interface DeleteTaskResult {
  _meta?: { [key: string]: unknown };
  [key: string]: unknown;
}

The response to a tasks/delete request.

_meta?: { [key: string]: unknown }

See General fields: _meta for notes on _meta usage.

+
DeleteTaskResult: Result

The response to a tasks/delete request.

## `tasks/get` diff --git a/schema/draft/schema.json b/schema/draft/schema.json index 62caaebee..e02f1a389 100644 --- a/schema/draft/schema.json +++ b/schema/draft/schema.json @@ -441,9 +441,6 @@ { "$ref": "#/definitions/GetTaskPayloadResult" }, - { - "$ref": "#/definitions/DeleteTaskResult" - }, { "$ref": "#/definitions/ListTasksResult" }, @@ -771,15 +768,7 @@ "type": "object" }, "DeleteTaskResult": { - "description": "The response to a tasks/delete request.", - "properties": { - "_meta": { - "additionalProperties": {}, - "description": "See [General fields: `_meta`](/specification/draft/basic/index#meta) for notes on `_meta` usage.", - "type": "object" - } - }, - "type": "object" + "$ref": "#/definitions/Result" }, "ElicitRequest": { "description": "A request from the server to elicit additional information from the user via the client.", @@ -2972,9 +2961,6 @@ { "$ref": "#/definitions/GetTaskPayloadResult" }, - { - "$ref": "#/definitions/DeleteTaskResult" - }, { "$ref": "#/definitions/ListTasksResult" }, diff --git a/schema/draft/schema.ts b/schema/draft/schema.ts index 8431c879a..717ceb7df 100644 --- a/schema/draft/schema.ts +++ b/schema/draft/schema.ts @@ -1357,7 +1357,7 @@ export interface DeleteTaskRequest extends JSONRPCRequest { * * @category tasks/delete */ -export interface DeleteTaskResult extends Result {} +export type DeleteTaskResult = Result; /** * A request to retrieve a list of tasks. From 0394a5d665f46b0ecda0a43972342b3787e6100a Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Fri, 7 Nov 2025 13:39:27 -0800 Subject: [PATCH 21/79] Restrict tasks to tools/call, elicitation/create, and sampling/createMessage --- .../draft/basic/utilities/tasks.mdx | 40 +++------ docs/specification/draft/schema.mdx | 4 +- schema/draft/schema.json | 86 ------------------- schema/draft/schema.ts | 81 ----------------- 4 files changed, 12 insertions(+), 199 deletions(-) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index 9fb0cf06f..972970712 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -28,22 +28,7 @@ Servers declare which server-side requests can be augmented with tasks: "tasks": { "requests": { "tools": { - "call": true, - "list": true - }, - "resources": { - "read": true, - "list": true - }, - "prompts": { - "get": true, - "list": true - }, - "tasks": { - "get": true, - "list": true, - "result": true, - "delete": true + "call": true } } } @@ -51,9 +36,7 @@ Servers declare which server-side requests can be augmented with tasks: } ``` -Servers **MAY** support tasks for any subset of their available request types. If a request type is not listed in the `tasks.requests` capability or is set to `false`, requestors **SHOULD NOT** augment those requests with task metadata. - -The `tasks.requests.tasks` nested capability indicates whether the task management operations themselves (`tasks/get`, `tasks/list`, `tasks/result`, `tasks/delete`) can be augmented with tasks, enabling recursive task tracking for task queries. +This set of capabilities is exhaustive. If a request type is not present, it does not support task-augmentation. ### Client Capabilities @@ -69,15 +52,6 @@ Clients declare which client-side requests can be augmented with tasks: }, "elicitation": { "create": true - }, - "roots": { - "list": true - }, - "tasks": { - "get": true, - "list": true, - "result": true, - "delete": true } } } @@ -85,13 +59,19 @@ Clients declare which client-side requests can be augmented with tasks: } ``` -The `tasks.requests.tasks` capability applies when the client is acting as a receiver of task-augmented requests from the server (for example, when a server sends a task-augmented `sampling/createMessage` request to the client). +This set of capabilities is exhaustive. If a request type is not present, it does not support task-augmentation. ### Capability Negotiation During the initialization phase, both parties exchange their `tasks` capabilities to establish which operations support task-based execution. Requestors **MUST** only augment requests with task metadata if the corresponding capability has been declared by the receiver. -For example, if a server's capabilities include `tasks.requests.tools.call: true`, then clients may augment `tools/call` requests with task metadata. However, if the server does not declare `tasks.requests.resources.read`, clients should not send task-augmented `resources/read` requests. +For example, if a server's capabilities include `tasks.requests.tools.call: true`, then clients may augment `tools/call` requests with task metadata. If a client's capabilities include `tasks.requests.sampling.createMessage: true`, then servers may augment `sampling/createMessage` requests with task metadata. + +### Tool-Level Negotiation + +Tool calls are given special consideration for the purpose of task augmentation. In the result of `tools/list`, tools declare support for tasks via `annotations.taskHint`. + +This is to be interpreted as a fine-grained layer in addition to capabilities. 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, even if they declare tool-level support via `annotations.taskHint`. ## Protocol Messages diff --git a/docs/specification/draft/schema.mdx b/docs/specification/draft/schema.mdx index bca399c07..3e9521697 100644 --- a/docs/specification/draft/schema.mdx +++ b/docs/specification/draft/schema.mdx @@ -27,7 +27,7 @@ the data is entirely optional.

interface ClientCapabilities {
  elicitation?: object;
  experimental?: { [key: string]: object };
  roots?: { listChanged?: boolean };
  sampling?: object;
  tasks?: {
    requests?: {
      elicitation?: { create?: boolean };
      roots?: { list?: boolean };
      sampling?: { createMessage?: boolean };
      tasks?: {
        delete?: boolean;
        get?: boolean;
        list?: boolean;
        result?: boolean;
      };
    };
  };
}

Capabilities a client may support. Known capabilities are defined here, in this schema, but this is not a closed set: any client can define its own, additional capabilities.

elicitation?: object

Present if the client supports elicitation from the server.

experimental?: { [key: string]: object }

Experimental, non-standard capabilities that the client supports.

roots?: { listChanged?: boolean }

Present if the client supports listing roots.

Type declaration
  • OptionallistChanged?: boolean

    Whether the client supports notifications for changes to the roots list.

sampling?: object

Present if the client supports sampling from an LLM.

tasks?: {
  requests?: {
    elicitation?: { create?: boolean };
    roots?: { list?: boolean };
    sampling?: { createMessage?: boolean };
    tasks?: {
      delete?: boolean;
      get?: boolean;
      list?: boolean;
      result?: boolean;
    };
  };
}

Present if the client supports task-augmented requests.

Type declaration
  • Optionalrequests?: {
      elicitation?: { create?: boolean };
      roots?: { list?: boolean };
      sampling?: { createMessage?: boolean };
      tasks?: {
        delete?: boolean;
        get?: boolean;
        list?: boolean;
        result?: boolean;
      };
    }

    Specifies which request types can be augmented with tasks.

    • Optionalelicitation?: { create?: boolean }

      Task support for elicitation-related requests.

      • Optionalcreate?: boolean

        Whether the client supports task-augmented elicitation/create requests.

    • Optionalroots?: { list?: boolean }

      Task support for roots-related requests.

      • Optionallist?: boolean

        Whether the client supports task-augmented roots/list requests.

    • Optionalsampling?: { createMessage?: boolean }

      Task support for sampling-related requests.

      • OptionalcreateMessage?: boolean

        Whether the client supports task-augmented sampling/createMessage requests.

    • Optionaltasks?: { delete?: boolean; get?: boolean; list?: boolean; result?: boolean }

      Task support for task management requests. Enables recursive task tracking where task queries themselves can be augmented with tasks. This applies when the client acts as a receiver of task-augmented requests from the server.

      • Optionaldelete?: boolean

        Whether the client supports task-augmented tasks/delete requests.

      • Optionalget?: boolean

        Whether the client supports task-augmented tasks/get requests.

      • Optionallist?: boolean

        Whether the client supports task-augmented tasks/list requests.

      • Optionalresult?: boolean

        Whether the client supports task-augmented tasks/result requests.

+
interface ClientCapabilities {
  elicitation?: object;
  experimental?: { [key: string]: object };
  roots?: { listChanged?: boolean };
  sampling?: object;
  tasks?: {
    requests?: {
      elicitation?: { create?: boolean };
      sampling?: { createMessage?: boolean };
    };
  };
}

Capabilities a client may support. Known capabilities are defined here, in this schema, but this is not a closed set: any client can define its own, additional capabilities.

elicitation?: object

Present if the client supports elicitation from the server.

experimental?: { [key: string]: object }

Experimental, non-standard capabilities that the client supports.

roots?: { listChanged?: boolean }

Present if the client supports listing roots.

Type declaration
  • OptionallistChanged?: boolean

    Whether the client supports notifications for changes to the roots list.

sampling?: object

Present if the client supports sampling from an LLM.

tasks?: {
  requests?: {
    elicitation?: { create?: boolean };
    sampling?: { createMessage?: boolean };
  };
}

Present if the client supports task-augmented requests.

Type declaration
  • Optionalrequests?: { elicitation?: { create?: boolean }; sampling?: { createMessage?: boolean } }

    Specifies which request types can be augmented with tasks.

    • Optionalelicitation?: { create?: boolean }

      Task support for elicitation-related requests.

      • Optionalcreate?: boolean

        Whether the client supports task-augmented elicitation/create requests.

    • Optionalsampling?: { createMessage?: boolean }

      Task support for sampling-related requests.

      • OptionalcreateMessage?: boolean

        Whether the client supports task-augmented sampling/createMessage requests.

### `ContentBlock` @@ -221,7 +221,7 @@ other URI schemes.

interface ServerCapabilities {
  completions?: object;
  experimental?: { [key: string]: object };
  logging?: object;
  prompts?: { listChanged?: boolean };
  resources?: { listChanged?: boolean; subscribe?: boolean };
  tasks?: {
    requests?: {
      prompts?: { get?: boolean; list?: boolean };
      resources?: { list?: boolean; read?: boolean };
      tasks?: {
        delete?: boolean;
        get?: boolean;
        list?: boolean;
        result?: boolean;
      };
      tools?: { call?: boolean; list?: boolean };
    };
  };
  tools?: { listChanged?: boolean };
}

Capabilities that a server may support. Known capabilities are defined here, in this schema, but this is not a closed set: any server can define its own, additional capabilities.

completions?: object

Present if the server supports argument autocompletion suggestions.

experimental?: { [key: string]: object }

Experimental, non-standard capabilities that the server supports.

logging?: object

Present if the server supports sending log messages to the client.

prompts?: { listChanged?: boolean }

Present if the server offers any prompt templates.

Type declaration
  • OptionallistChanged?: boolean

    Whether this server supports notifications for changes to the prompt list.

resources?: { listChanged?: boolean; subscribe?: boolean }

Present if the server offers any resources to read.

Type declaration
  • OptionallistChanged?: boolean

    Whether this server supports notifications for changes to the resource list.

  • Optionalsubscribe?: boolean

    Whether this server supports subscribing to resource updates.

tasks?: {
  requests?: {
    prompts?: { get?: boolean; list?: boolean };
    resources?: { list?: boolean; read?: boolean };
    tasks?: {
      delete?: boolean;
      get?: boolean;
      list?: boolean;
      result?: boolean;
    };
    tools?: { call?: boolean; list?: boolean };
  };
}

Present if the server supports task-augmented requests.

Type declaration
  • Optionalrequests?: {
      prompts?: { get?: boolean; list?: boolean };
      resources?: { list?: boolean; read?: boolean };
      tasks?: {
        delete?: boolean;
        get?: boolean;
        list?: boolean;
        result?: boolean;
      };
      tools?: { call?: boolean; list?: boolean };
    }

    Specifies which request types can be augmented with tasks.

    • Optionalprompts?: { get?: boolean; list?: boolean }

      Task support for prompt-related requests.

      • Optionalget?: boolean

        Whether the server supports task-augmented prompts/get requests.

      • Optionallist?: boolean

        Whether the server supports task-augmented prompts/list requests.

    • Optionalresources?: { list?: boolean; read?: boolean }

      Task support for resource-related requests.

      • Optionallist?: boolean

        Whether the server supports task-augmented resources/list requests.

      • Optionalread?: boolean

        Whether the server supports task-augmented resources/read requests.

    • Optionaltasks?: { delete?: boolean; get?: boolean; list?: boolean; result?: boolean }

      Task support for task management requests. Enables recursive task tracking where task queries themselves can be augmented with tasks.

      • Optionaldelete?: boolean

        Whether the server supports task-augmented tasks/delete requests.

      • Optionalget?: boolean

        Whether the server supports task-augmented tasks/get requests.

      • Optionallist?: boolean

        Whether the server supports task-augmented tasks/list requests.

      • Optionalresult?: boolean

        Whether the server supports task-augmented tasks/result requests.

    • Optionaltools?: { call?: boolean; list?: boolean }

      Task support for tool-related requests.

      • Optionalcall?: boolean

        Whether the server supports task-augmented tools/call requests.

      • Optionallist?: boolean

        Whether the server supports task-augmented tools/list requests.

tools?: { listChanged?: boolean }

Present if the server offers any tools to call.

Type declaration
  • OptionallistChanged?: boolean

    Whether this server supports notifications for changes to the tool list.

+
interface ServerCapabilities {
  completions?: object;
  experimental?: { [key: string]: object };
  logging?: object;
  prompts?: { listChanged?: boolean };
  resources?: { listChanged?: boolean; subscribe?: boolean };
  tasks?: { requests?: { tools?: { call?: boolean } } };
  tools?: { listChanged?: boolean };
}

Capabilities that a server may support. Known capabilities are defined here, in this schema, but this is not a closed set: any server can define its own, additional capabilities.

completions?: object

Present if the server supports argument autocompletion suggestions.

experimental?: { [key: string]: object }

Experimental, non-standard capabilities that the server supports.

logging?: object

Present if the server supports sending log messages to the client.

prompts?: { listChanged?: boolean }

Present if the server offers any prompt templates.

Type declaration
  • OptionallistChanged?: boolean

    Whether this server supports notifications for changes to the prompt list.

resources?: { listChanged?: boolean; subscribe?: boolean }

Present if the server offers any resources to read.

Type declaration
  • OptionallistChanged?: boolean

    Whether this server supports notifications for changes to the resource list.

  • Optionalsubscribe?: boolean

    Whether this server supports subscribing to resource updates.

tasks?: { requests?: { tools?: { call?: boolean } } }

Present if the server supports task-augmented requests.

Type declaration
  • Optionalrequests?: { tools?: { call?: boolean } }

    Specifies which request types can be augmented with tasks.

    • Optionaltools?: { call?: boolean }

      Task support for tool-related requests.

      • Optionalcall?: boolean

        Whether the server supports task-augmented tools/call requests.

tools?: { listChanged?: boolean }

Present if the server offers any tools to call.

Type declaration
  • OptionallistChanged?: boolean

    Whether this server supports notifications for changes to the tool list.

### `StringSchema` diff --git a/schema/draft/schema.json b/schema/draft/schema.json index e02f1a389..bdcea5082 100644 --- a/schema/draft/schema.json +++ b/schema/draft/schema.json @@ -302,16 +302,6 @@ }, "type": "object" }, - "roots": { - "description": "Task support for roots-related requests.", - "properties": { - "list": { - "description": "Whether the client supports task-augmented roots/list requests.", - "type": "boolean" - } - }, - "type": "object" - }, "sampling": { "description": "Task support for sampling-related requests.", "properties": { @@ -321,28 +311,6 @@ } }, "type": "object" - }, - "tasks": { - "description": "Task support for task management requests. Enables recursive task tracking where task queries themselves can be augmented with tasks. This applies when the client acts as a receiver of task-augmented requests from the server.", - "properties": { - "delete": { - "description": "Whether the client supports task-augmented tasks/delete requests.", - "type": "boolean" - }, - "get": { - "description": "Whether the client supports task-augmented tasks/get requests.", - "type": "boolean" - }, - "list": { - "description": "Whether the client supports task-augmented tasks/list requests.", - "type": "boolean" - }, - "result": { - "description": "Whether the client supports task-augmented tasks/result requests.", - "type": "boolean" - } - }, - "type": "object" } }, "type": "object" @@ -2784,66 +2752,12 @@ "requests": { "description": "Specifies which request types can be augmented with tasks.", "properties": { - "prompts": { - "description": "Task support for prompt-related requests.", - "properties": { - "get": { - "description": "Whether the server supports task-augmented prompts/get requests.", - "type": "boolean" - }, - "list": { - "description": "Whether the server supports task-augmented prompts/list requests.", - "type": "boolean" - } - }, - "type": "object" - }, - "resources": { - "description": "Task support for resource-related requests.", - "properties": { - "list": { - "description": "Whether the server supports task-augmented resources/list requests.", - "type": "boolean" - }, - "read": { - "description": "Whether the server supports task-augmented resources/read requests.", - "type": "boolean" - } - }, - "type": "object" - }, - "tasks": { - "description": "Task support for task management requests. Enables recursive task tracking where task queries themselves can be augmented with tasks.", - "properties": { - "delete": { - "description": "Whether the server supports task-augmented tasks/delete requests.", - "type": "boolean" - }, - "get": { - "description": "Whether the server supports task-augmented tasks/get requests.", - "type": "boolean" - }, - "list": { - "description": "Whether the server supports task-augmented tasks/list requests.", - "type": "boolean" - }, - "result": { - "description": "Whether the server supports task-augmented tasks/result requests.", - "type": "boolean" - } - }, - "type": "object" - }, "tools": { "description": "Task support for tool-related requests.", "properties": { "call": { "description": "Whether the server supports task-augmented tools/call requests.", "type": "boolean" - }, - "list": { - "description": "Whether the server supports task-augmented tools/list requests.", - "type": "boolean" } }, "type": "object" diff --git a/schema/draft/schema.ts b/schema/draft/schema.ts index 717ceb7df..c52ec7a73 100644 --- a/schema/draft/schema.ts +++ b/schema/draft/schema.ts @@ -288,36 +288,6 @@ export interface ClientCapabilities { */ create?: boolean; }; - /** - * Task support for roots-related requests. - */ - roots?: { - /** - * Whether the client supports task-augmented roots/list requests. - */ - list?: boolean; - }; - /** - * Task support for task management requests. Enables recursive task tracking where task queries themselves can be augmented with tasks. This applies when the client acts as a receiver of task-augmented requests from the server. - */ - tasks?: { - /** - * Whether the client supports task-augmented tasks/get requests. - */ - get?: boolean; - /** - * Whether the client supports task-augmented tasks/list requests. - */ - list?: boolean; - /** - * Whether the client supports task-augmented tasks/result requests. - */ - result?: boolean; - /** - * Whether the client supports task-augmented tasks/delete requests. - */ - delete?: boolean; - }; }; }; } @@ -385,57 +355,6 @@ export interface ServerCapabilities { * Whether the server supports task-augmented tools/call requests. */ call?: boolean; - /** - * Whether the server supports task-augmented tools/list requests. - */ - list?: boolean; - }; - /** - * Task support for resource-related requests. - */ - resources?: { - /** - * Whether the server supports task-augmented resources/read requests. - */ - read?: boolean; - /** - * Whether the server supports task-augmented resources/list requests. - */ - list?: boolean; - }; - /** - * Task support for prompt-related requests. - */ - prompts?: { - /** - * Whether the server supports task-augmented prompts/get requests. - */ - get?: boolean; - /** - * Whether the server supports task-augmented prompts/list requests. - */ - list?: boolean; - }; - /** - * Task support for task management requests. Enables recursive task tracking where task queries themselves can be augmented with tasks. - */ - tasks?: { - /** - * Whether the server supports task-augmented tasks/get requests. - */ - get?: boolean; - /** - * Whether the server supports task-augmented tasks/list requests. - */ - list?: boolean; - /** - * Whether the server supports task-augmented tasks/result requests. - */ - result?: boolean; - /** - * Whether the server supports task-augmented tasks/delete requests. - */ - delete?: boolean; }; }; }; From f7229a565174f059059717028e977761a0ff6ec8 Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Fri, 7 Nov 2025 13:54:24 -0800 Subject: [PATCH 22/79] Add capabilities for tasks/list and tasks/delete --- .../draft/basic/utilities/tasks.mdx | 26 +++++++++----- docs/specification/draft/schema.mdx | 4 +-- schema/draft/schema.json | 36 +++++++++++++++++-- schema/draft/schema.ts | 22 ++++++++++-- 4 files changed, 71 insertions(+), 17 deletions(-) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index 972970712..e3948411a 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -20,15 +20,17 @@ Servers and clients that support task-augmented requests **MUST** declare a `tas ### Server Capabilities -Servers declare which server-side requests can be augmented with tasks: +Servers declare if they support tasks, and if so, which server-side requests can be augmented with tasks: ```json { "capabilities": { "tasks": { + "list": {}, + "delete": {}, "requests": { "tools": { - "call": true + "call": {} } } } @@ -36,22 +38,22 @@ Servers declare which server-side requests can be augmented with tasks: } ``` -This set of capabilities is exhaustive. If a request type is not present, it does not support task-augmentation. - ### Client Capabilities -Clients declare which client-side requests can be augmented with tasks: +Clients declare if they support tasks, and if so, which client-side requests can be augmented with tasks: ```json { "capabilities": { "tasks": { + "list": {}, + "delete": {}, "requests": { "sampling": { - "createMessage": true + "createMessage": {} }, "elicitation": { - "create": true + "create": {} } } } @@ -59,14 +61,20 @@ Clients declare which client-side requests can be augmented with tasks: } ``` -This set of capabilities is exhaustive. If a request type is not present, it does not support task-augmentation. - ### Capability Negotiation During the initialization phase, both parties exchange their `tasks` capabilities to establish which operations support task-based execution. Requestors **MUST** only augment requests with task metadata if the corresponding capability has been declared by the receiver. For example, if a server's capabilities include `tasks.requests.tools.call: true`, then clients may augment `tools/call` requests with task metadata. If a client's capabilities include `tasks.requests.sampling.createMessage: true`, then servers may augment `sampling/createMessage` requests with task metadata. +If `capabilities.tasks` is not defined, the peer **MUST 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.delete` controls if the `tasks/delete` operation is supported by the party. + ### Tool-Level Negotiation Tool calls are given special consideration for the purpose of task augmentation. In the result of `tools/list`, tools declare support for tasks via `annotations.taskHint`. diff --git a/docs/specification/draft/schema.mdx b/docs/specification/draft/schema.mdx index 3e9521697..194195d88 100644 --- a/docs/specification/draft/schema.mdx +++ b/docs/specification/draft/schema.mdx @@ -27,7 +27,7 @@ the data is entirely optional.

interface ClientCapabilities {
  elicitation?: object;
  experimental?: { [key: string]: object };
  roots?: { listChanged?: boolean };
  sampling?: object;
  tasks?: {
    requests?: {
      elicitation?: { create?: boolean };
      sampling?: { createMessage?: boolean };
    };
  };
}

Capabilities a client may support. Known capabilities are defined here, in this schema, but this is not a closed set: any client can define its own, additional capabilities.

elicitation?: object

Present if the client supports elicitation from the server.

experimental?: { [key: string]: object }

Experimental, non-standard capabilities that the client supports.

roots?: { listChanged?: boolean }

Present if the client supports listing roots.

Type declaration
  • OptionallistChanged?: boolean

    Whether the client supports notifications for changes to the roots list.

sampling?: object

Present if the client supports sampling from an LLM.

tasks?: {
  requests?: {
    elicitation?: { create?: boolean };
    sampling?: { createMessage?: boolean };
  };
}

Present if the client supports task-augmented requests.

Type declaration
  • Optionalrequests?: { elicitation?: { create?: boolean }; sampling?: { createMessage?: boolean } }

    Specifies which request types can be augmented with tasks.

    • Optionalelicitation?: { create?: boolean }

      Task support for elicitation-related requests.

      • Optionalcreate?: boolean

        Whether the client supports task-augmented elicitation/create requests.

    • Optionalsampling?: { createMessage?: boolean }

      Task support for sampling-related requests.

      • OptionalcreateMessage?: boolean

        Whether the client supports task-augmented sampling/createMessage requests.

+
interface ClientCapabilities {
  elicitation?: object;
  experimental?: { [key: string]: object };
  roots?: { listChanged?: boolean };
  sampling?: object;
  tasks?: {
    delete?: object;
    list?: object;
    requests?: {
      elicitation?: { create?: object };
      sampling?: { createMessage?: object };
    };
  };
}

Capabilities a client may support. Known capabilities are defined here, in this schema, but this is not a closed set: any client can define its own, additional capabilities.

elicitation?: object

Present if the client supports elicitation from the server.

experimental?: { [key: string]: object }

Experimental, non-standard capabilities that the client supports.

roots?: { listChanged?: boolean }

Present if the client supports listing roots.

Type declaration
  • OptionallistChanged?: boolean

    Whether the client supports notifications for changes to the roots list.

sampling?: object

Present if the client supports sampling from an LLM.

tasks?: {
  delete?: object;
  list?: object;
  requests?: {
    elicitation?: { create?: object };
    sampling?: { createMessage?: object };
  };
}

Present if the client supports task-augmented requests.

Type declaration
  • Optionaldelete?: object

    Whether this client supports tasks/delete.

  • Optionallist?: object

    Whether this client supports tasks/list.

  • Optionalrequests?: { elicitation?: { create?: object }; sampling?: { createMessage?: object } }

    Specifies which request types can be augmented with tasks.

    • Optionalelicitation?: { create?: object }

      Task support for elicitation-related requests.

      • Optionalcreate?: object

        Whether the client supports task-augmented elicitation/create requests.

    • Optionalsampling?: { createMessage?: object }

      Task support for sampling-related requests.

      • OptionalcreateMessage?: object

        Whether the client supports task-augmented sampling/createMessage requests.

### `ContentBlock` @@ -221,7 +221,7 @@ other URI schemes.

interface ServerCapabilities {
  completions?: object;
  experimental?: { [key: string]: object };
  logging?: object;
  prompts?: { listChanged?: boolean };
  resources?: { listChanged?: boolean; subscribe?: boolean };
  tasks?: { requests?: { tools?: { call?: boolean } } };
  tools?: { listChanged?: boolean };
}

Capabilities that a server may support. Known capabilities are defined here, in this schema, but this is not a closed set: any server can define its own, additional capabilities.

completions?: object

Present if the server supports argument autocompletion suggestions.

experimental?: { [key: string]: object }

Experimental, non-standard capabilities that the server supports.

logging?: object

Present if the server supports sending log messages to the client.

prompts?: { listChanged?: boolean }

Present if the server offers any prompt templates.

Type declaration
  • OptionallistChanged?: boolean

    Whether this server supports notifications for changes to the prompt list.

resources?: { listChanged?: boolean; subscribe?: boolean }

Present if the server offers any resources to read.

Type declaration
  • OptionallistChanged?: boolean

    Whether this server supports notifications for changes to the resource list.

  • Optionalsubscribe?: boolean

    Whether this server supports subscribing to resource updates.

tasks?: { requests?: { tools?: { call?: boolean } } }

Present if the server supports task-augmented requests.

Type declaration
  • Optionalrequests?: { tools?: { call?: boolean } }

    Specifies which request types can be augmented with tasks.

    • Optionaltools?: { call?: boolean }

      Task support for tool-related requests.

      • Optionalcall?: boolean

        Whether the server supports task-augmented tools/call requests.

tools?: { listChanged?: boolean }

Present if the server offers any tools to call.

Type declaration
  • OptionallistChanged?: boolean

    Whether this server supports notifications for changes to the tool list.

+
interface ServerCapabilities {
  completions?: object;
  experimental?: { [key: string]: object };
  logging?: object;
  prompts?: { listChanged?: boolean };
  resources?: { listChanged?: boolean; subscribe?: boolean };
  tasks?: {
    delete?: object;
    list?: object;
    requests?: { tools?: { call?: object } };
  };
  tools?: { listChanged?: boolean };
}

Capabilities that a server may support. Known capabilities are defined here, in this schema, but this is not a closed set: any server can define its own, additional capabilities.

completions?: object

Present if the server supports argument autocompletion suggestions.

experimental?: { [key: string]: object }

Experimental, non-standard capabilities that the server supports.

logging?: object

Present if the server supports sending log messages to the client.

prompts?: { listChanged?: boolean }

Present if the server offers any prompt templates.

Type declaration
  • OptionallistChanged?: boolean

    Whether this server supports notifications for changes to the prompt list.

resources?: { listChanged?: boolean; subscribe?: boolean }

Present if the server offers any resources to read.

Type declaration
  • OptionallistChanged?: boolean

    Whether this server supports notifications for changes to the resource list.

  • Optionalsubscribe?: boolean

    Whether this server supports subscribing to resource updates.

tasks?: {
  delete?: object;
  list?: object;
  requests?: { tools?: { call?: object } };
}

Present if the server supports task-augmented requests.

Type declaration
  • Optionaldelete?: object

    Whether this server supports tasks/delete.

  • Optionallist?: object

    Whether this server supports tasks/list.

  • Optionalrequests?: { tools?: { call?: object } }

    Specifies which request types can be augmented with tasks.

    • Optionaltools?: { call?: object }

      Task support for tool-related requests.

      • Optionalcall?: object

        Whether the server supports task-augmented tools/call requests.

tools?: { listChanged?: boolean }

Present if the server offers any tools to call.

Type declaration
  • OptionallistChanged?: boolean

    Whether this server supports notifications for changes to the tool list.

### `StringSchema` diff --git a/schema/draft/schema.json b/schema/draft/schema.json index bdcea5082..5a230fd95 100644 --- a/schema/draft/schema.json +++ b/schema/draft/schema.json @@ -289,6 +289,18 @@ "tasks": { "description": "Present if the client supports task-augmented requests.", "properties": { + "delete": { + "additionalProperties": true, + "description": "Whether this client supports tasks/delete.", + "properties": {}, + "type": "object" + }, + "list": { + "additionalProperties": true, + "description": "Whether this client supports tasks/list.", + "properties": {}, + "type": "object" + }, "requests": { "description": "Specifies which request types can be augmented with tasks.", "properties": { @@ -296,8 +308,10 @@ "description": "Task support for elicitation-related requests.", "properties": { "create": { + "additionalProperties": true, "description": "Whether the client supports task-augmented elicitation/create requests.", - "type": "boolean" + "properties": {}, + "type": "object" } }, "type": "object" @@ -306,8 +320,10 @@ "description": "Task support for sampling-related requests.", "properties": { "createMessage": { + "additionalProperties": true, "description": "Whether the client supports task-augmented sampling/createMessage requests.", - "type": "boolean" + "properties": {}, + "type": "object" } }, "type": "object" @@ -2749,6 +2765,18 @@ "tasks": { "description": "Present if the server supports task-augmented requests.", "properties": { + "delete": { + "additionalProperties": true, + "description": "Whether this server supports tasks/delete.", + "properties": {}, + "type": "object" + }, + "list": { + "additionalProperties": true, + "description": "Whether this server supports tasks/list.", + "properties": {}, + "type": "object" + }, "requests": { "description": "Specifies which request types can be augmented with tasks.", "properties": { @@ -2756,8 +2784,10 @@ "description": "Task support for tool-related requests.", "properties": { "call": { + "additionalProperties": true, "description": "Whether the server supports task-augmented tools/call requests.", - "type": "boolean" + "properties": {}, + "type": "object" } }, "type": "object" diff --git a/schema/draft/schema.ts b/schema/draft/schema.ts index c52ec7a73..8f11fcd35 100644 --- a/schema/draft/schema.ts +++ b/schema/draft/schema.ts @@ -266,6 +266,14 @@ export interface ClientCapabilities { * Present if the client supports task-augmented requests. */ tasks?: { + /** + * Whether this client supports tasks/list. + */ + list?: object; + /** + * Whether this client supports tasks/delete. + */ + delete?: object; /** * Specifies which request types can be augmented with tasks. */ @@ -277,7 +285,7 @@ export interface ClientCapabilities { /** * Whether the client supports task-augmented sampling/createMessage requests. */ - createMessage?: boolean; + createMessage?: object; }; /** * Task support for elicitation-related requests. @@ -286,7 +294,7 @@ export interface ClientCapabilities { /** * Whether the client supports task-augmented elicitation/create requests. */ - create?: boolean; + create?: object; }; }; }; @@ -343,6 +351,14 @@ export interface ServerCapabilities { * Present if the server supports task-augmented requests. */ tasks?: { + /** + * Whether this server supports tasks/list. + */ + list?: object; + /** + * Whether this server supports tasks/delete. + */ + delete?: object; /** * Specifies which request types can be augmented with tasks. */ @@ -354,7 +370,7 @@ export interface ServerCapabilities { /** * Whether the server supports task-augmented tools/call requests. */ - call?: boolean; + call?: object; }; }; }; From 0ab678519cee9d46b6db1fccb15f5bbe08f82ce0 Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Fri, 7 Nov 2025 14:33:19 -0800 Subject: [PATCH 23/79] Use response instead of notification for task acceptance --- .../draft/basic/utilities/tasks.mdx | 45 ++++++++-- docs/specification/draft/schema.mdx | 10 ++- schema/draft/schema.json | 85 ++++++++++++------- schema/draft/schema.ts | 52 +++++++----- 4 files changed, 134 insertions(+), 58 deletions(-) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index e3948411a..9d159406b 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -85,6 +85,11 @@ This is to be interpreted as a fine-grained layer in addition to capabilities. I ### 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 `CreateTaskResult` containing task metadata. The actual operation result becomes available later through `tasks/result` after the task completes. + To create a task, requestors send a request with the `modelcontextprotocol.io/task` key included in `_meta`, with a `taskId` value representing the task ID. Requestors **MAY** include a `keepAlive`, with a value representing how long after completion the requestor would like the task results to be kept for. **Request:** @@ -93,8 +98,12 @@ To create a task, requestors send a request with the `modelcontextprotocol.io/ta { "jsonrpc": "2.0", "id": 1, - "method": "some_method", + "method": "tools/call", "params": { + "name": "get_weather", + "arguments": { + "city": "New York" + }, "_meta": { "modelcontextprotocol.io/task": { "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", @@ -105,6 +114,28 @@ To create a task, requestors send a request with the `modelcontextprotocol.io/ta } ``` +**Response:** + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", + "status": "submitted", + "keepAlive": 60000, + "pollInterval": 5000, + "_meta": { + "modelcontextprotocol.io/related-task": { + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" + } + } + } +} +``` + +When a receiver accepts a task-augmented request, it returns a `CreateTaskResult` containing task metadata. This 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. + ### Getting Tasks To retrieve the state of a task, requestors send a `tasks/get` request: @@ -144,6 +175,8 @@ To retrieve the state of a task, requestors send a `tasks/get` request: ### Retrieving Task Results +After a task completes, the actual operation result is retrieved via `tasks/result`. This is distinct from the initial `CreateTaskResult` response, which contains only task metadata. The result structure matches the original request type (e.g., `CallToolResult` for `tools/call`). + To retrieve the result of a completed task, requestors send a `tasks/result` request: **Request:** @@ -381,7 +414,8 @@ stateDiagram-v2 ### Result Retrieval -1. Receivers **MUST** only return results from `tasks/result` when the task status is `completed`. +1. Receivers that accept a task-augmented request **MUST** return a `CreateTaskResult` as the response. This result **SHOULD** be returned as soon as possible after accepting the task. +1. Receivers **MUST** only return the actual operation results via `tasks/result` when the task status is `completed`. 1. Receivers **MUST** return an error if `tasks/result` is called for a task in any other status. 1. Requestors **MAY** call `tasks/result` multiple times for the same task while it remains available. @@ -424,8 +458,8 @@ sequenceDiagram participant S as Server (Receiver) Note over C,S: 1. Task Creation C->>S: Request with task metadata (taskId, keepAlive) + S->>C: CreateTaskResult (taskId, status: submitted, keepAlive, pollInterval) S--)C: notifications/tasks/created - Note over C,S: Original request will respond eventually,
but requestor uses task polling instead Note over C,S: 2. Task Polling C->>S: tasks/get (taskId) S->>C: submitted @@ -458,8 +492,8 @@ sequenceDiagram Note over C,S: Client augments with task metadata C->>S: tools/call (task-123, keepAlive: 3600000) + S->>C: CreateTaskResult (task-123, status: submitted) S--)C: notifications/tasks/created - Note over C,S: Original request will respond eventually,
but client uses task polling instead Note over LLM,C: Client continues processing other requests
while task executes in background LLM->>C: Request other operation @@ -515,8 +549,8 @@ sequenceDiagram Note over S,C: Server requests client operation (task-augmented) S->>C: sampling/createMessage (request-789, keepAlive: 3600000) + C->>S: CreateTaskResult (request-789, status: submitted) C--)S: notifications/tasks/created - Note over S,C: Original request will respond eventually,
but server uses task polling instead Note over S: Server continues processing
while waiting for result @@ -589,6 +623,7 @@ sequenceDiagram Note over C,S: 1. Task Creation and Completion C->>S: tools/call (task-123) + S->>C: CreateTaskResult (task-123, status: submitted) S--)C: notifications/tasks/created Note over S: Task processing... C->>S: tasks/get (task-123) diff --git a/docs/specification/draft/schema.mdx b/docs/specification/draft/schema.mdx index 194195d88..381d9e206 100644 --- a/docs/specification/draft/schema.mdx +++ b/docs/specification/draft/schema.mdx @@ -518,11 +518,19 @@ or file that the server can operate on.

CreateTaskResult: Result & Task

A response to a task-augmented request.

+ ### `RelatedTaskMetadata`
interface RelatedTaskMetadata {
  taskId: string;
}

Metadata for associating messages with a task. Include this in the _meta field under the key modelcontextprotocol.io/related-task.

taskId: string

The task identifier this message is associated with.

+### `Task` + +
interface Task {
  error?: string;
  keepAlive: null | number;
  pollInterval?: number;
  status: TaskStatus;
  taskId: string;
}

Data associated with a task.

error?: string

Error message if status is "failed".

keepAlive: null | number

Actual retention duration in milliseconds, null for unlimited.

pollInterval?: number

Suggested polling interval in milliseconds.

status: TaskStatus

Current task state.

taskId: string

The task identifier.

+ ### `TaskMetadata`
interface TaskMetadata {
  keepAlive?: number;
  taskId: string;
}

Metadata for augmenting a request with task execution. @@ -550,7 +558,7 @@ Include this in the _meta field of a request under the key interface GetTaskResult {
  _meta?: { [key: string]: unknown };
  error?: string;
  keepAlive: null | number;
  pollInterval?: number;
  status: TaskStatus;
  taskId: string;
  [key: string]: unknown;
}

The response to a tasks/get request.

_meta?: { [key: string]: unknown }

See General fields: _meta for notes on _meta usage.

error?: string

Error message if status is "failed".

keepAlive: null | number

Actual retention duration in milliseconds, null for unlimited.

pollInterval?: number

Suggested polling interval in milliseconds.

status: TaskStatus

Current task state.

taskId: string

The task identifier.

+
GetTaskResult: Result & Task

The response to a tasks/get request.

## `tasks/list` diff --git a/schema/draft/schema.json b/schema/draft/schema.json index 5a230fd95..27c712603 100644 --- a/schema/draft/schema.json +++ b/schema/draft/schema.json @@ -420,7 +420,8 @@ "$ref": "#/definitions/Result" }, { - "$ref": "#/definitions/GetTaskResult" + "$ref": "#/definitions/GetTaskResult", + "description": "The response to a tasks/get request." }, { "$ref": "#/definitions/GetTaskPayloadResult" @@ -712,6 +713,17 @@ ], "type": "object" }, + "CreateTaskResult": { + "allOf": [ + { + "$ref": "#/definitions/Result" + }, + { + "$ref": "#/definitions/Task" + } + ], + "description": "A response to a task-augmented request." + }, "Cursor": { "description": "An opaque token used to represent a cursor for pagination.", "type": "string" @@ -1119,40 +1131,15 @@ "type": "object" }, "GetTaskResult": { - "description": "The response to a tasks/get request.", - "properties": { - "_meta": { - "additionalProperties": {}, - "description": "See [General fields: `_meta`](/specification/draft/basic/index#meta) for notes on `_meta` usage.", - "type": "object" - }, - "error": { - "description": "Error message if status is \"failed\".", - "type": "string" - }, - "keepAlive": { - "description": "Actual retention duration in milliseconds, null for unlimited.", - "type": "integer" - }, - "pollInterval": { - "description": "Suggested polling interval in milliseconds.", - "type": "integer" - }, - "status": { - "$ref": "#/definitions/TaskStatus", - "description": "Current task state." + "allOf": [ + { + "$ref": "#/definitions/Result" }, - "taskId": { - "description": "The task identifier.", - "type": "string" + { + "$ref": "#/definitions/Task" } - }, - "required": [ - "keepAlive", - "status", - "taskId" ], - "type": "object" + "description": "The response to a tasks/get request." }, "Icon": { "description": "An optionally-sized icon that can be displayed in a user interface.", @@ -2900,7 +2887,8 @@ "$ref": "#/definitions/CallToolResult" }, { - "$ref": "#/definitions/GetTaskResult" + "$ref": "#/definitions/GetTaskResult", + "description": "The response to a tasks/get request." }, { "$ref": "#/definitions/GetTaskPayloadResult" @@ -3050,6 +3038,37 @@ ], "type": "object" }, + "Task": { + "description": "Data associated with a task.", + "properties": { + "error": { + "description": "Error message if status is \"failed\".", + "type": "string" + }, + "keepAlive": { + "description": "Actual retention duration in milliseconds, null for unlimited.", + "type": "integer" + }, + "pollInterval": { + "description": "Suggested polling interval in milliseconds.", + "type": "integer" + }, + "status": { + "$ref": "#/definitions/TaskStatus", + "description": "Current task state." + }, + "taskId": { + "description": "The task identifier.", + "type": "string" + } + }, + "required": [ + "keepAlive", + "status", + "taskId" + ], + "type": "object" + }, "TaskCreatedNotification": { "description": "A notification from the receiver to the requestor, informing them that a task has been created and is ready for polling.", "properties": { diff --git a/schema/draft/schema.ts b/schema/draft/schema.ts index 8f11fcd35..68d20ee62 100644 --- a/schema/draft/schema.ts +++ b/schema/draft/schema.ts @@ -1164,7 +1164,7 @@ export type TaskStatus = | "working" // The request is currently being processed | "input_required" // The task is waiting for input (e.g., elicitation or sampling) | "completed" // The request completed successfully and results are available - | "failed" // The request encountered an error during execution + | "failed" // The associated request did not complete successfully. For tool calls specifically, this includes cases where the tool call result has `isError` set to true. | "cancelled" // The request was cancelled before completion | "unknown"; // A terminal fallback state for unexpected error conditions @@ -1200,26 +1200,11 @@ export interface RelatedTaskMetadata { } /** - * A request to retrieve the state of a task. - * - * @category tasks/get - */ -export interface GetTaskRequest extends JSONRPCRequest { - method: "tasks/get"; - params: { - /** - * The task identifier to query. - */ - taskId: string; - }; -} - -/** - * The response to a tasks/get request. + * Data associated with a task. * - * @category tasks/get + * @category tasks */ -export interface GetTaskResult extends Result { +export interface Task { /** * The task identifier. */ @@ -1246,6 +1231,35 @@ export interface GetTaskResult extends Result { error?: string; } +/** + * A response to a task-augmented request. + * + * @category tasks + */ +export type CreateTaskResult = Result & Task; + +/** + * A request to retrieve the state of a task. + * + * @category tasks/get + */ +export interface GetTaskRequest extends JSONRPCRequest { + method: "tasks/get"; + params: { + /** + * The task identifier to query. + */ + taskId: string; + }; +} + +/** + * The response to a tasks/get request. + * + * @category tasks/get + */ +export type GetTaskResult = Result & Task; + /** * A request to retrieve the result of a completed task. * From 2fdea385163343acefdae3730da0dd03692d1f68 Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Fri, 7 Nov 2025 14:49:46 -0800 Subject: [PATCH 24/79] Make task IDs exclusively server-generated --- .../draft/basic/utilities/tasks.mdx | 25 +++---------------- docs/specification/draft/schema.mdx | 4 +-- schema/draft/schema.json | 7 ------ schema/draft/schema.ts | 5 ---- 4 files changed, 6 insertions(+), 35 deletions(-) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index 9d159406b..415fc1133 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -6,7 +6,7 @@ title: Tasks **Protocol Revision**: draft -The Model Context Protcol (MCP) allows requestors (which can be either clients or servers, depending on the direction of communication) to augment their requests with **tasks**. Tasks are durable state machines that carry information about the underlying execution state of the request they wrap, and are intended for requestor polling and deferred result retrieval. Each task is uniquely identifiable by a requestor-generated **task ID**. +The Model Context Protcol (MCP) allows requestors (which can be either clients or servers, depending on the direction of communication) to augment their requests with **tasks**. Tasks are durable state machines that carry information about the underlying execution state of the request they wrap, and are intended for requestor polling and deferred result retrieval. Each task is uniquely identifiable by a receiver-generated **task ID**. ## User Interaction Model @@ -90,7 +90,7 @@ Task-augmented requests follow a two-phase response pattern that differs from no - **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 `CreateTaskResult` containing task metadata. The actual operation result becomes available later through `tasks/result` after the task completes. -To create a task, requestors send a request with the `modelcontextprotocol.io/task` key included in `_meta`, with a `taskId` value representing the task ID. Requestors **MAY** include a `keepAlive`, with a value representing how long after completion the requestor would like the task results to be kept for. +To create a task, requestors send a request with the `modelcontextprotocol.io/task` key included in `_meta`. Requestors **MAY** include a `keepAlive` value representing how long after completion the requestor would like the task results to be kept for. **Request:** @@ -106,7 +106,6 @@ To create a task, requestors send a request with the `modelcontextprotocol.io/ta }, "_meta": { "modelcontextprotocol.io/task": { - "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", "keepAlive": 60000 } } @@ -358,8 +357,8 @@ These requirements apply to all parties that support receiving task-augmented re ### Task ID Requirements 1. Task IDs **MUST** be a string value. -1. Task IDs **SHOULD** be unique across all tasks controlled by the receiver. -1. The receiver of a request with a task ID in its `_meta` **MAY** validate that the provided task ID has not already been associated with a task controlled by that receiver. +1. Task IDs **MUST** be generated by the receiver when creating a task. +1. Task IDs **MUST** be unique across all tasks controlled by the receiver. ### Task Status Lifecycle @@ -675,7 +674,6 @@ When augmenting a request with task execution, the `modelcontextprotocol.io/task ```json { "modelcontextprotocol.io/task": { - "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", "keepAlive": 60000 } } @@ -683,7 +681,6 @@ When augmenting a request with task execution, the `modelcontextprotocol.io/task Fields: -- `taskId` (string, required): Client-generated unique identifier for the task - `keepAlive` (number, optional): Requested duration in milliseconds to retain results after completion ### Related Task Metadata @@ -713,7 +710,6 @@ Receivers **MUST** return standard JSON-RPC errors for the following protocol er - Invalid or nonexistent `taskId` in `tasks/get`, `tasks/list`, `tasks/result`, or `tasks/delete`: `-32602` (Invalid params) - Invalid or nonexistent cursor in `tasks/list`: `-32602` (Invalid params) -- Request with a `taskId` that was already used for a different task (if the receiver validates task ID uniqueness): `-32602` (Invalid params) - Attempting to retrieve result when task is not in `completed` status: `-32602` (Invalid params) - Receiver rejects a `tasks/delete` request: `-32600` (Invalid request) - Internal errors: `-32603` (Internal error) @@ -765,19 +761,6 @@ Receivers are not obligated to retain task metadata indefinitely. It is complian } ``` -**Example: Duplicate task ID (if receiver validates uniqueness)** - -```json -{ - "jsonrpc": "2.0", - "id": 73, - "error": { - "code": -32602, - "message": "Task ID already exists: 786512e2-9e0d-44bd-8f29-789f320fe840" - } -} -``` - **Example: Task deletion rejected by receiver** ```json diff --git a/docs/specification/draft/schema.mdx b/docs/specification/draft/schema.mdx index 381d9e206..6573c0755 100644 --- a/docs/specification/draft/schema.mdx +++ b/docs/specification/draft/schema.mdx @@ -533,8 +533,8 @@ Include this in the _meta field under the key modelconte ### `TaskMetadata` -
interface TaskMetadata {
  keepAlive?: number;
  taskId: string;
}

Metadata for augmenting a request with task execution. -Include this in the _meta field of a request under the key modelcontextprotocol.io/task.

keepAlive?: number

Requested duration in milliseconds to retain results after completion.

taskId: string

Client-generated unique identifier for the task.

+
interface TaskMetadata {
  keepAlive?: number;
}

Metadata for augmenting a request with task execution. +Include this in the _meta field of a request under the key modelcontextprotocol.io/task.

keepAlive?: number

Requested duration in milliseconds to retain results after completion.

### `TaskStatus` diff --git a/schema/draft/schema.json b/schema/draft/schema.json index 27c712603..05138cf0b 100644 --- a/schema/draft/schema.json +++ b/schema/draft/schema.json @@ -3139,15 +3139,8 @@ "keepAlive": { "description": "Requested duration in milliseconds to retain results after completion.", "type": "integer" - }, - "taskId": { - "description": "Client-generated unique identifier for the task.", - "type": "string" } }, - "required": [ - "taskId" - ], "type": "object" }, "TaskStatus": { diff --git a/schema/draft/schema.ts b/schema/draft/schema.ts index 68d20ee62..eec8fdfc9 100644 --- a/schema/draft/schema.ts +++ b/schema/draft/schema.ts @@ -1175,11 +1175,6 @@ export type TaskStatus = * @category tasks */ export interface TaskMetadata { - /** - * Client-generated unique identifier for the task. - */ - taskId: string; - /** * Requested duration in milliseconds to retain results after completion. */ From e96ce21126d85b36b33f14688dc59efd1a4db1a9 Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Fri, 7 Nov 2025 15:00:54 -0800 Subject: [PATCH 25/79] Add stipulation that receivers are allowed to require tasks --- .../draft/basic/utilities/tasks.mdx | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index 415fc1133..9952251b6 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -351,8 +351,8 @@ These requirements apply to all parties that support receiving task-augmented re ### Task Support and Handling -1. Receivers that do not support task augmentation on a request **MUST** process the request normally, ignoring any task metadata in `_meta`. -1. Receivers that support task augmentation **MAY** choose which request types support tasks. +1. 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. +1. Receivers that do declare the task capability for a request type **MAY** return an error for non-task-augmented requests of that type, requiring requestors to use task augmentation. ### Task ID Requirements @@ -714,8 +714,25 @@ Receivers **MUST** return standard JSON-RPC errors for the following protocol er - Receiver rejects a `tasks/delete` request: `-32600` (Invalid request) - Internal errors: `-32603` (Internal error) +Additionally, receivers **MAY** return the following errors: + +- Non-task-augmented request when receiver requires task augmentation for that request type: `-32600` (Invalid request) + Receivers **SHOULD** provide informative error messages to describe the cause of errors. +**Example: Task augmentation required** + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "error": { + "code": -32600, + "message": "Task augmentation required for tools/call requests" + } +} +``` + **Example: Task not found** ```json From 642c3c78d3dcf317340ffa270f9656670e8a8e52 Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Fri, 7 Nov 2025 15:17:34 -0800 Subject: [PATCH 26/79] Update tasks/result to block until completion --- .../draft/basic/utilities/tasks.mdx | 22 ++++--------------- 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index 9952251b6..75bdc7cae 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -414,9 +414,9 @@ stateDiagram-v2 ### Result Retrieval 1. Receivers that accept a task-augmented request **MUST** return a `CreateTaskResult` as the response. This result **SHOULD** be returned as soon as possible after accepting the task. -1. Receivers **MUST** only return the actual operation results via `tasks/result` when the task status is `completed`. -1. Receivers **MUST** return an error if `tasks/result` is called for a task in any other status. -1. Requestors **MAY** call `tasks/result` multiple times for the same task while it remains available. +1. When a receiver receives a `tasks/result` request, it **MUST** block the response until the task reaches a terminal status (`completed`, `failed`, `cancelled`, or `unknown`). +1. For tasks in `completed` status, receivers **MUST** return the actual operation results as specified by the original request type. +1. For tasks in `failed`, `cancelled`, or `unknown` status, receivers **MUST** return a successful JSON-RPC response containing error or status details in the result structure. ### Associating Task-Related Messages @@ -710,7 +710,6 @@ Receivers **MUST** return standard JSON-RPC errors for the following protocol er - Invalid or nonexistent `taskId` in `tasks/get`, `tasks/list`, `tasks/result`, or `tasks/delete`: `-32602` (Invalid params) - Invalid or nonexistent cursor in `tasks/list`: `-32602` (Invalid params) -- Attempting to retrieve result when task is not in `completed` status: `-32602` (Invalid params) - Receiver rejects a `tasks/delete` request: `-32600` (Invalid request) - Internal errors: `-32603` (Internal error) @@ -765,19 +764,6 @@ Receivers are not obligated to retain task metadata indefinitely. It is complian -**Example: Result requested for incomplete task** - -```json -{ - "jsonrpc": "2.0", - "id": 72, - "error": { - "code": -32602, - "message": "Cannot retrieve result: Task status is 'working', not 'completed'" - } -} -``` - **Example: Task deletion rejected by receiver** ```json @@ -810,7 +796,7 @@ When the underlying request does not complete successfully, the task moves to th } ``` -For tasks that wrap tool call requests, when the tool result has `isError` set to true, the task should reach `failed` status. The error information is conveyed both through the task's `failed` status and through the result structure when retrieved via `tasks/result`. +For tasks that wrap tool call requests, when the tool result has `isError` set to true, the task should reach `failed` status. ## Security Considerations From 7d008e0f4e34e0d311f7cd87441a19ee38775a3f Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Fri, 7 Nov 2025 15:23:52 -0800 Subject: [PATCH 27/79] Add explicit note that tasks/result can return an error --- docs/specification/draft/basic/utilities/tasks.mdx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index 75bdc7cae..6153ee333 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -415,8 +415,7 @@ stateDiagram-v2 1. Receivers that accept a task-augmented request **MUST** return a `CreateTaskResult` as the response. This result **SHOULD** be returned as soon as possible after accepting the task. 1. When a receiver receives a `tasks/result` request, it **MUST** block the response until the task reaches a terminal status (`completed`, `failed`, `cancelled`, or `unknown`). -1. For tasks in `completed` status, receivers **MUST** return the actual operation results as specified by the original request type. -1. For tasks in `failed`, `cancelled`, or `unknown` status, receivers **MUST** return a successful JSON-RPC response containing error or status details in the result structure. +1. Receivers **MUST** return from `tasks/result` exactly what the underlying request would have returned, whether that is a successful result or a JSON-RPC error. ### Associating Task-Related Messages @@ -798,6 +797,11 @@ When the underlying request does not complete successfully, the task moves to th For tasks that wrap tool call requests, when the tool result has `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/result` **MUST** return that same JSON-RPC error. +- If the request completed with a JSON-RPC response, `tasks/result` **MUST** return a successful JSON-RPC response containing that result. + ## Security Considerations ### Task Isolation and Access Control From d05cfbbc9de90a25083f446cafb07731f0986f16 Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Fri, 7 Nov 2025 16:03:29 -0800 Subject: [PATCH 28/79] Alter input_required to note tasks/result relation --- .../draft/basic/utilities/tasks.mdx | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index 6153ee333..9eb81bee5 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -399,10 +399,10 @@ stateDiagram-v2 ### Input Required Status -1. When a receiver sends a request associated with a task (e.g., elicitation, sampling), the receiver **SHOULD** move the task to the `input_required` status. +1. 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_required` status. 1. The receiver **MUST** include the `modelcontextprotocol.io/related-task` metadata in the request to associate it with the task. -1. When the receiver receives all required responses, the task **MAY** transition out of `input_required` status (typically back to `working`). -1. If multiple related requests are pending, the task **SHOULD** remain in `input_required` status until all are resolved. +1. When the requestor encounters the `input_required` status, it **SHOULD** call `tasks/result` prematurely. +1. When the receiver receives all required input, the task **SHOULD** transition out of `input_required` status (typically back to `working`). ### Keep-Alive and Resource Management @@ -414,8 +414,9 @@ stateDiagram-v2 ### Result Retrieval 1. Receivers that accept a task-augmented request **MUST** return a `CreateTaskResult` as the response. This result **SHOULD** be returned as soon as possible after accepting the task. -1. When a receiver receives a `tasks/result` request, it **MUST** block the response until the task reaches a terminal status (`completed`, `failed`, `cancelled`, or `unknown`). -1. Receivers **MUST** return from `tasks/result` exactly what the underlying request would have returned, whether that is a successful result or a JSON-RPC error. +1. When a receiver receives a `tasks/result` request for a task in a terminal status (`completed`, `failed`, `cancelled`, or `unknown`), it **MUST** return the final result of the underlying request, whether that is a successful result or a JSON-RPC error. +1. When a receiver receives a `tasks/result` request for a task in any other non-terminal status (`submitted`, `working`, `input_required`), it **MUST** block the response until the task reaches a terminal status. +1. For tasks in a terminal status, receivers **MUST** return from `tasks/result` exactly what the underlying request would have returned, whether that is a successful result or a JSON-RPC error. ### Associating Task-Related Messages @@ -425,11 +426,11 @@ stateDiagram-v2 ### Task Cancellation +1. Requestors **MAY** send `notifications/cancelled` at any time during task execution. 1. When a receiver receives a `notifications/cancelled` notification for the JSON-RPC request ID of a task-augmented request, the receiver **SHOULD** immediately move the task to the `cancelled` status and cease all processing associated with that task. 1. Due to the asynchronous nature of notifications, receivers **MAY** not cancel task processing instantaneously. Receivers **SHOULD** make a best-effort attempt to halt execution as quickly as possible. 1. If a `notifications/cancelled` notification arrives after a task has already reached a terminal status (`completed`, `failed`, `cancelled`, or `unknown`), receivers **SHOULD** ignore the notification. 1. After a task reaches `cancelled` status and its `keepAlive` duration has elapsed, receivers **MAY** delete the task and its metadata. -1. Requestors **MAY** send `notifications/cancelled` at any time during task execution, including when the task is in `input_required` status. If a task is cancelled while in `input_required` status, receivers **SHOULD** also disregard any pending responses to associated requests. 1. Because notifications do not provide confirmation of receipt, requestors **SHOULD** continue to poll with `tasks/get` after sending a cancellation notification to confirm the task has transitioned to `cancelled` status. If the task does not transition to `cancelled` within a reasonable timeframe, requestors **MAY** assume the cancellation was not processed. ### Task Listing @@ -501,15 +502,15 @@ sequenceDiagram C->>S: tasks/get (task-123) S->>C: working - Note over S: Server requires additional information
Task moves to input_required + Note over S: Server needs information from client
Task moves to input_required - Note over S,C: Server sends elicitation request - S->>C: elicitation/create (task-123) - - Note over C,S: Client polls and sees task waiting for input + Note over C,S: Client polls and discovers input_required C->>S: tasks/get (task-123) S->>C: input_required + Note over C,S: Client receives input requests + C->>S: tasks/result (task-123) + S->>C: elicitation/create (task-123) C->>U: Prompt user for input U->>C: Provide information C->>S: elicitation response (task-123) @@ -660,7 +661,7 @@ Tasks can be in one of the following states: - `submitted`: The request has been received and queued for execution - `working`: The request is currently being processed -- `input_required`: The request is waiting on additional input from the requestor +- `input_required`: The receiver needs input from the requestor. The requestor should call `tasks/result` to 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 has `isError` set to true. - `cancelled`: The request was cancelled before completion From dbc2b0a3bd15f7a4aad0d2ccab9a8493ab8b73a5 Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Fri, 7 Nov 2025 16:13:04 -0800 Subject: [PATCH 29/79] Remove submitted and unknown statuses --- .../draft/basic/utilities/tasks.mdx | 37 +++++++------------ docs/specification/draft/schema.mdx | 2 +- schema/draft/schema.json | 2 - schema/draft/schema.ts | 4 +- 4 files changed, 15 insertions(+), 30 deletions(-) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index 9eb81bee5..cc72ea274 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -121,7 +121,7 @@ To create a task, requestors send a request with the `modelcontextprotocol.io/ta "id": 1, "result": { "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", - "status": "submitted", + "status": "working", "keepAlive": 60000, "pollInterval": 5000, "_meta": { @@ -162,7 +162,7 @@ To retrieve the state of a task, requestors send a `tasks/get` request: "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", "keepAlive": 30000, "pollInterval": 5000, - "status": "submitted", + "status": "working", "_meta": { "modelcontextprotocol.io/related-task": { "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" @@ -362,23 +362,17 @@ These requirements apply to all parties that support receiving task-augmented re ### Task Status Lifecycle -1. Tasks **MUST** begin in the `submitted` status when created. +1. Tasks **MUST** begin in the `working` status when created. 1. Receivers **MUST** only transition tasks through the following valid paths: - 1. From `submitted`: may move to `working`, `input_required`, `completed`, `failed`, `cancelled`, or `unknown` - 1. From `working`: may move to `input_required`, `completed`, `failed`, `cancelled`, or `unknown` - 1. From `input_required`: may move to `working`, `completed`, `failed`, `cancelled`, or `unknown` - 1. Tasks in `completed`, `failed`, `cancelled`, or `unknown` status **MUST NOT** transition to any other status (terminal states) -1. Receivers **MAY** move directly from `submitted` to `completed` if execution completes immediately. -1. The `unknown` status is a terminal fallback state for unexpected error conditions. Receivers **SHOULD** use `failed` with an error message instead when possible. + 1. From `working`: may move to `input_required`, `completed`, `failed`, or `cancelled` + 1. From `input_required`: may move to `working`, `completed`, `failed`, or `cancelled` + 1. Tasks in `completed`, `failed`, or `cancelled` status **MUST NOT** transition to any other status (terminal states) **Task Status State Diagram:** ```mermaid stateDiagram-v2 - [*] --> submitted - - submitted --> working - submitted --> terminal + [*] --> working working --> input_required working --> terminal @@ -393,7 +387,6 @@ stateDiagram-v2 • completed • failed • cancelled - • unknown end note ``` @@ -414,8 +407,8 @@ stateDiagram-v2 ### Result Retrieval 1. Receivers that accept a task-augmented request **MUST** return a `CreateTaskResult` as the response. This result **SHOULD** be returned as soon as possible after accepting the task. -1. When a receiver receives a `tasks/result` request for a task in a terminal status (`completed`, `failed`, `cancelled`, or `unknown`), it **MUST** return the final result of the underlying request, whether that is a successful result or a JSON-RPC error. -1. When a receiver receives a `tasks/result` request for a task in any other non-terminal status (`submitted`, `working`, `input_required`), it **MUST** block the response until the task reaches a terminal status. +1. When a receiver receives a `tasks/result` request for a task in a terminal status (`completed`, `failed`, or `cancelled`), it **MUST** return the final result of the underlying request, whether that is a successful result or a JSON-RPC error. +1. When a receiver receives a `tasks/result` request for a task in any other non-terminal status (`working` or `input_required`), it **MUST** block the response until the task reaches a terminal status. 1. For tasks in a terminal status, receivers **MUST** return from `tasks/result` exactly what the underlying request would have returned, whether that is a successful result or a JSON-RPC error. ### Associating Task-Related Messages @@ -429,7 +422,7 @@ stateDiagram-v2 1. Requestors **MAY** send `notifications/cancelled` at any time during task execution. 1. When a receiver receives a `notifications/cancelled` notification for the JSON-RPC request ID of a task-augmented request, the receiver **SHOULD** immediately move the task to the `cancelled` status and cease all processing associated with that task. 1. Due to the asynchronous nature of notifications, receivers **MAY** not cancel task processing instantaneously. Receivers **SHOULD** make a best-effort attempt to halt execution as quickly as possible. -1. If a `notifications/cancelled` notification arrives after a task has already reached a terminal status (`completed`, `failed`, `cancelled`, or `unknown`), receivers **SHOULD** ignore the notification. +1. If a `notifications/cancelled` notification arrives after a task has already reached a terminal status (`completed`, `failed`, or `cancelled`), receivers **SHOULD** ignore the notification. 1. After a task reaches `cancelled` status and its `keepAlive` duration has elapsed, receivers **MAY** delete the task and its metadata. 1. Because notifications do not provide confirmation of receipt, requestors **SHOULD** continue to poll with `tasks/get` after sending a cancellation notification to confirm the task has transitioned to `cancelled` status. If the task does not transition to `cancelled` within a reasonable timeframe, requestors **MAY** assume the cancellation was not processed. @@ -457,12 +450,10 @@ sequenceDiagram participant S as Server (Receiver) Note over C,S: 1. Task Creation C->>S: Request with task metadata (taskId, keepAlive) - S->>C: CreateTaskResult (taskId, status: submitted, keepAlive, pollInterval) + S->>C: CreateTaskResult (taskId, status: working, keepAlive, pollInterval) S--)C: notifications/tasks/created Note over C,S: 2. Task Polling C->>S: tasks/get (taskId) - S->>C: submitted - C->>S: tasks/get (taskId) S->>C: working Note over S: Task processing continues... C->>S: tasks/get (taskId) @@ -491,7 +482,7 @@ sequenceDiagram Note over C,S: Client augments with task metadata C->>S: tools/call (task-123, keepAlive: 3600000) - S->>C: CreateTaskResult (task-123, status: submitted) + S->>C: CreateTaskResult (task-123, status: working) S--)C: notifications/tasks/created Note over LLM,C: Client continues processing other requests
while task executes in background @@ -548,7 +539,7 @@ sequenceDiagram Note over S,C: Server requests client operation (task-augmented) S->>C: sampling/createMessage (request-789, keepAlive: 3600000) - C->>S: CreateTaskResult (request-789, status: submitted) + C->>S: CreateTaskResult (request-789, status: working) C--)S: notifications/tasks/created Note over S: Server continues processing
while waiting for result @@ -659,13 +650,11 @@ A task represents the execution state of a request. The task metadata includes: Tasks can be in one of the following states: -- `submitted`: The request has been received and queued for execution - `working`: The request is currently being processed - `input_required`: The receiver needs input from the requestor. The requestor should call `tasks/result` to 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 has `isError` set to true. - `cancelled`: The request was cancelled before completion -- `unknown`: A terminal fallback state for unexpected error conditions when the receiver cannot determine the actual task state ### Task Metadata diff --git a/docs/specification/draft/schema.mdx b/docs/specification/draft/schema.mdx index 6573c0755..4e2cf040a 100644 --- a/docs/specification/draft/schema.mdx +++ b/docs/specification/draft/schema.mdx @@ -538,7 +538,7 @@ Include this in the _meta field of a request under the key TaskStatus:
  | "submitted"
  | "working"
  | "input_required"
  | "completed"
  | "failed"
  | "cancelled"
  | "unknown"

The status of a task.

+
TaskStatus: "working" | "input_required" | "completed" | "failed" | "cancelled"

The status of a task.

## `tasks/delete` diff --git a/schema/draft/schema.json b/schema/draft/schema.json index 05138cf0b..a72fb5bff 100644 --- a/schema/draft/schema.json +++ b/schema/draft/schema.json @@ -3150,8 +3150,6 @@ "completed", "failed", "input_required", - "submitted", - "unknown", "working" ], "type": "string" diff --git a/schema/draft/schema.ts b/schema/draft/schema.ts index eec8fdfc9..18e40e6b8 100644 --- a/schema/draft/schema.ts +++ b/schema/draft/schema.ts @@ -1160,13 +1160,11 @@ export interface Tool extends BaseMetadata, Icons { * @category tasks */ export type TaskStatus = - | "submitted" // The request has been received and queued for execution | "working" // The request is currently being processed | "input_required" // The task is waiting for input (e.g., elicitation or sampling) | "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 has `isError` set to true. - | "cancelled" // The request was cancelled before completion - | "unknown"; // A terminal fallback state for unexpected error conditions + | "cancelled"; // The request was cancelled before completion /** * Metadata for augmenting a request with task execution. From 8169347c5e4d44555b70a2b36ae72e8ac43f53c8 Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Fri, 7 Nov 2025 16:32:23 -0800 Subject: [PATCH 30/79] Update cancellation to reflect CreateTaskResult semantics --- .../draft/basic/utilities/cancellation.mdx | 48 +++++++++++++++---- .../draft/basic/utilities/tasks.mdx | 7 ++- docs/specification/draft/schema.mdx | 10 +++- schema/draft/schema.json | 13 ++--- schema/draft/schema.ts | 23 +++++++-- 5 files changed, 79 insertions(+), 22 deletions(-) diff --git a/docs/specification/draft/basic/utilities/cancellation.mdx b/docs/specification/draft/basic/utilities/cancellation.mdx index 1669b418c..1509b0b6f 100644 --- a/docs/specification/draft/basic/utilities/cancellation.mdx +++ b/docs/specification/draft/basic/utilities/cancellation.mdx @@ -15,9 +15,12 @@ indicate that a previously-issued request should be terminated. When a party wants to cancel an in-progress request, it sends a `notifications/cancelled` notification containing: -- The ID of the request to cancel +- For non-task requests: The ID of the request to cancel +- For task cancellation: The ID of the task to cancel - An optional reason string that can be logged or displayed +### Cancelling Non-Task Requests + ```json { "jsonrpc": "2.0", @@ -29,23 +32,49 @@ notification containing: } ``` +### Cancelling Tasks + +For task-augmented requests, once the `CreateTaskResult` is returned, the original request is complete and `requestId` becomes ambiguous. Therefore, task cancellation **MUST** use `taskId`: + +```json +{ + "jsonrpc": "2.0", + "method": "notifications/cancelled", + "params": { + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", + "reason": "User requested cancellation" + } +} +``` + ## Behavior Requirements -1. Cancellation notifications **MUST** only reference requests that: +### General Requirements + +1. Cancellation notifications **MUST** only reference requests or tasks that: - Were previously issued in the same direction - Are believed to still be in-progress 2. The `initialize` request **MUST NOT** be cancelled by clients 3. Receivers of cancellation notifications **SHOULD**: - - Stop processing the cancelled request + - Stop processing the cancelled request or task - Free associated resources - - Not send a response for the cancelled request + - For non-task requests: Not send a response for the cancelled request + - For tasks: Move the task to `cancelled` status 4. Receivers **MAY** ignore cancellation notifications if: - - The referenced request is unknown - - Processing has already completed - - The request cannot be cancelled + - The referenced request or task is unknown + - Processing has already completed (for non-task requests) or reached a terminal status (for tasks) + - The request or task cannot be cancelled 5. The sender of the cancellation notification **SHOULD** ignore any response to the request that arrives afterward +### Task-Specific Requirements + +1. For task cancellation, `taskId` **MUST** be provided (not `requestId`) +2. `requestId` **MUST NOT** be used for task cancellation once `CreateTaskResult` has been returned +3. When a receiver receives a `notifications/cancelled` notification with a `taskId`, it **SHOULD** immediately move the task to `cancelled` status +4. If a cancellation notification arrives after a task has already reached a terminal status (`completed`, `failed`, or `cancelled`), receivers **SHOULD** ignore the notification +5. Requestors **SHOULD** poll with `tasks/get` after sending a cancellation notification to confirm the task has transitioned to `cancelled` status + ## Timing Considerations Due to network latency, cancellation notifications may arrive after request processing @@ -77,9 +106,10 @@ sequenceDiagram Invalid cancellation notifications **SHOULD** be ignored: -- Unknown request IDs -- Already completed requests +- Unknown request IDs or task IDs +- Already completed requests or tasks in terminal status - Malformed notifications +- Using `requestId` for task cancellation (should use `taskId` instead) This maintains the "fire and forget" nature of notifications while allowing for race conditions in asynchronous communication. diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index cc72ea274..b7e99c621 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -420,7 +420,10 @@ stateDiagram-v2 ### Task Cancellation 1. Requestors **MAY** send `notifications/cancelled` at any time during task execution. -1. When a receiver receives a `notifications/cancelled` notification for the JSON-RPC request ID of a task-augmented request, the receiver **SHOULD** immediately move the task to the `cancelled` status and cease all processing associated with that task. +1. For task cancellation, the `notifications/cancelled` notification **MUST** include a `taskId` field: + 1. The `taskId` **MUST** correspond to a task previously created in the same direction. + 1. Once a task-augmented request returns `CreateTaskResult`, the original request is complete and `requestId` becomes ambiguous. Therefore, `requestId` **MUST NOT** be used for task cancellation. +1. When a receiver receives a `notifications/cancelled` notification with a `taskId`, the receiver **SHOULD** immediately move the task to the `cancelled` status and cease all processing associated with that task. 1. Due to the asynchronous nature of notifications, receivers **MAY** not cancel task processing instantaneously. Receivers **SHOULD** make a best-effort attempt to halt execution as quickly as possible. 1. If a `notifications/cancelled` notification arrives after a task has already reached a terminal status (`completed`, `failed`, or `cancelled`), receivers **SHOULD** ignore the notification. 1. After a task reaches `cancelled` status and its `keepAlive` duration has elapsed, receivers **MAY** delete the task and its metadata. @@ -590,7 +593,7 @@ sequenceDiagram Note over C,S: 3. Client Cancellation Note over C: User requests cancellation - C--)S: notifications/cancelled (requestId: 42) + C--)S: notifications/cancelled (taskId: task-123) Note over S: Server processes cancellation Note over S: Task moves to cancelled status diff --git a/docs/specification/draft/schema.mdx b/docs/specification/draft/schema.mdx index 4e2cf040a..453c1bcae 100644 --- a/docs/specification/draft/schema.mdx +++ b/docs/specification/draft/schema.mdx @@ -315,11 +315,17 @@ Contains values matching the requested schema.

interface CancelledNotification {
  jsonrpc: "2.0";
  method: "notifications/cancelled";
  params: CancelledNotificationParams;
}

This notification can be sent by either side to indicate that it is cancelling a previously-issued request.

The request SHOULD still be in-flight, but due to communication latency, it is always possible that this notification MAY arrive after the request has already finished.

This notification indicates that the result will be unused, so any associated processing SHOULD cease.

A client MUST NOT attempt to cancel its initialize request.

+
interface CancelledNotification {
  jsonrpc: "2.0";
  method: "notifications/cancelled";
  params: CancelledNotificationParams;
}

This notification can be sent by either side to indicate that it is cancelling a previously-issued request or task.

The request or task SHOULD still be in-flight, but due to communication latency, it is always possible that this notification MAY arrive after the request has already finished.

This notification indicates that the result will be unused, so any associated processing SHOULD cease.

A client MUST NOT attempt to cancel its initialize request.

For non-task requests, use requestId to cancel the request. +For task cancellation, use taskId to cancel the task. Once a task-augmented request returns CreateTaskResult, +the original request is complete and requestId becomes ambiguous - only taskId should be used for cancellation.

### `CancelledNotificationParams` -
interface CancelledNotificationParams {
  _meta?: { [key: string]: unknown };
  reason?: string;
  requestId: RequestId;
}

Parameters for a notifications/cancelled notification.

_meta?: { [key: string]: unknown }

See General fields: _meta for notes on _meta usage.

reason?: string

An optional string describing the reason for the cancellation. This MAY be logged or presented to the user.

requestId: RequestId

The ID of the request to cancel.

This MUST correspond to the ID of a request previously issued in the same direction.

+
interface CancelledNotificationParams {
  _meta?: { [key: string]: unknown };
  reason?: string;
  requestId?: RequestId;
  taskId?: string;
}

Parameters for a notifications/cancelled notification.

For non-task requests: requestId MUST be provided. +For task cancellation: taskId MUST be provided (using requestId is not supported once the task has been created).

_meta?: { [key: string]: unknown }

See General fields: _meta for notes on _meta usage.

reason?: string

An optional string describing the reason for the cancellation. This MAY be logged or presented to the user.

requestId?: RequestId

The ID of the request to cancel.

This MUST correspond to the ID of a request previously issued in the same direction. +This MUST be provided for cancelling non-task requests. +This MUST NOT be used for cancelling tasks (use taskId instead).

taskId?: string

The ID of the task to cancel.

This MUST correspond to the ID of a task previously created in the same direction. +This MUST be provided for cancelling tasks.

## `notifications/initialized` diff --git a/schema/draft/schema.json b/schema/draft/schema.json index a72fb5bff..2c85f38d5 100644 --- a/schema/draft/schema.json +++ b/schema/draft/schema.json @@ -209,7 +209,7 @@ "type": "object" }, "CancelledNotification": { - "description": "This notification can be sent by either side to indicate that it is cancelling a previously-issued request.\n\nThe request SHOULD still be in-flight, but due to communication latency, it is always possible that this notification MAY arrive after the request has already finished.\n\nThis notification indicates that the result will be unused, so any associated processing SHOULD cease.\n\nA client MUST NOT attempt to cancel its `initialize` request.", + "description": "This notification can be sent by either side to indicate that it is cancelling a previously-issued request or task.\n\nThe request or task SHOULD still be in-flight, but due to communication latency, it is always possible that this notification MAY arrive after the request has already finished.\n\nThis notification indicates that the result will be unused, so any associated processing SHOULD cease.\n\nA client MUST NOT attempt to cancel its `initialize` request.\n\nFor non-task requests, use `requestId` to cancel the request.\nFor task cancellation, use `taskId` to cancel the task. Once a task-augmented request returns `CreateTaskResult`,\nthe original request is complete and `requestId` becomes ambiguous - only `taskId` should be used for cancellation.", "properties": { "jsonrpc": { "const": "2.0", @@ -231,7 +231,7 @@ "type": "object" }, "CancelledNotificationParams": { - "description": "Parameters for a `notifications/cancelled` notification.", + "description": "Parameters for a `notifications/cancelled` notification.\n\nFor non-task requests: `requestId` MUST be provided.\nFor task cancellation: `taskId` MUST be provided (using `requestId` is not supported once the task has been created).", "properties": { "_meta": { "additionalProperties": {}, @@ -244,12 +244,13 @@ }, "requestId": { "$ref": "#/definitions/RequestId", - "description": "The ID of the request to cancel.\n\nThis MUST correspond to the ID of a request previously issued in the same direction." + "description": "The ID of the request to cancel.\n\nThis MUST correspond to the ID of a request previously issued in the same direction.\nThis MUST be provided for cancelling non-task requests.\nThis MUST NOT be used for cancelling tasks (use `taskId` instead)." + }, + "taskId": { + "description": "The ID of the task to cancel.\n\nThis MUST correspond to the ID of a task previously created in the same direction.\nThis MUST be provided for cancelling tasks.", + "type": "string" } }, - "required": [ - "requestId" - ], "type": "object" }, "ClientCapabilities": { diff --git a/schema/draft/schema.ts b/schema/draft/schema.ts index 18e40e6b8..1084ef2ec 100644 --- a/schema/draft/schema.ts +++ b/schema/draft/schema.ts @@ -149,6 +149,9 @@ export type EmptyResult = Result; /** * Parameters for a `notifications/cancelled` notification. * + * For non-task requests: `requestId` MUST be provided. + * For task cancellation: `taskId` MUST be provided (using `requestId` is not supported once the task has been created). + * * @category notifications/cancelled */ export interface CancelledNotificationParams extends NotificationParams { @@ -156,8 +159,18 @@ export interface CancelledNotificationParams extends NotificationParams { * The ID of the request to cancel. * * This MUST correspond to the ID of a request previously issued in the same direction. + * This MUST be provided for cancelling non-task requests. + * This MUST NOT be used for cancelling tasks (use `taskId` instead). + */ + requestId?: RequestId; + + /** + * The ID of the task to cancel. + * + * This MUST correspond to the ID of a task previously created in the same direction. + * This MUST be provided for cancelling tasks. */ - requestId: RequestId; + taskId?: string; /** * An optional string describing the reason for the cancellation. This MAY be logged or presented to the user. @@ -166,14 +179,18 @@ export interface CancelledNotificationParams extends NotificationParams { } /** - * This notification can be sent by either side to indicate that it is cancelling a previously-issued request. + * This notification can be sent by either side to indicate that it is cancelling a previously-issued request or task. * - * The request SHOULD still be in-flight, but due to communication latency, it is always possible that this notification MAY arrive after the request has already finished. + * The request or task SHOULD still be in-flight, but due to communication latency, it is always possible that this notification MAY arrive after the request has already finished. * * This notification indicates that the result will be unused, so any associated processing SHOULD cease. * * A client MUST NOT attempt to cancel its `initialize` request. * + * For non-task requests, use `requestId` to cancel the request. + * For task cancellation, use `taskId` to cancel the task. Once a task-augmented request returns `CreateTaskResult`, + * the original request is complete and `requestId` becomes ambiguous - only `taskId` should be used for cancellation. + * * @category notifications/cancelled */ export interface CancelledNotification extends JSONRPCNotification { From 8a675ea6fcc7500302f45e8349e3541645baf9da Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Fri, 7 Nov 2025 16:50:04 -0800 Subject: [PATCH 31/79] Update progress spec to reflect task semantics --- docs/specification/draft/basic/utilities/progress.mdx | 4 ++++ docs/specification/draft/basic/utilities/tasks.mdx | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/docs/specification/draft/basic/utilities/progress.mdx b/docs/specification/draft/basic/utilities/progress.mdx index df51ef958..95a4c561d 100644 --- a/docs/specification/draft/basic/utilities/progress.mdx +++ b/docs/specification/draft/basic/utilities/progress.mdx @@ -68,6 +68,10 @@ The receiver **MAY** then send progress notifications containing: - Send notifications at whatever frequency they deem appropriate - Omit the total value if unknown +3. For task-augmented requests, the `progressToken` provided in the original request **MUST** continue to be used for progress notifications throughout the task's lifetime, even after the `CreateTaskResult` has been returned. The progress token remains valid and associated with the task until the task reaches a terminal status. + - Progress notifications for tasks **MUST** use the same `progressToken` that was provided in the initial task-augmented request + - Progress notifications for tasks **MUST** stop after the task reaches a terminal status (`completed`, `failed`, or `cancelled`) + ```mermaid sequenceDiagram participant Sender diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index b7e99c621..8b7894f07 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -417,6 +417,10 @@ stateDiagram-v2 1. 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. 1. For the `tasks/get`, `tasks/list`, `tasks/result`, and `tasks/delete` operations, the `taskId` parameter in the request **MUST** be used as the source of truth for identifying the target task. Requestors **SHOULD NOT** include `modelcontextprotocol.io/related-task` metadata in these requests, and receivers **MUST** ignore such metadata if present in favor of the RPC method parameter. +### Task Progress Notifications + +Task-augmented requests support progress notifications as defined in the progress notification specification. The `progressToken` provided in the initial request remains valid throughout the task's lifetime. + ### Task Cancellation 1. Requestors **MAY** send `notifications/cancelled` at any time during task execution. From 13c683538dec3e157ca8c771061d32f29a443926 Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Mon, 10 Nov 2025 10:58:28 -0800 Subject: [PATCH 32/79] Add optional statusMessage field --- docs/specification/draft/basic/utilities/tasks.mdx | 2 ++ docs/specification/draft/schema.mdx | 2 +- schema/draft/schema.json | 4 ++++ schema/draft/schema.ts | 5 +++++ 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index 8b7894f07..4b41cf7a0 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -122,6 +122,7 @@ To create a task, requestors send a request with the `modelcontextprotocol.io/ta "result": { "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", "status": "working", + "statusMessage": "The operation is now in progress.", "keepAlive": 60000, "pollInterval": 5000, "_meta": { @@ -163,6 +164,7 @@ To retrieve the state of a task, requestors send a `tasks/get` request: "keepAlive": 30000, "pollInterval": 5000, "status": "working", + "statusMessage": "The operation is now in progress.", "_meta": { "modelcontextprotocol.io/related-task": { "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" diff --git a/docs/specification/draft/schema.mdx b/docs/specification/draft/schema.mdx index 453c1bcae..4b2a831fa 100644 --- a/docs/specification/draft/schema.mdx +++ b/docs/specification/draft/schema.mdx @@ -535,7 +535,7 @@ Include this in the _meta field under the key modelconte ### `Task` -
interface Task {
  error?: string;
  keepAlive: null | number;
  pollInterval?: number;
  status: TaskStatus;
  taskId: string;
}

Data associated with a task.

error?: string

Error message if status is "failed".

keepAlive: null | number

Actual retention duration in milliseconds, null for unlimited.

pollInterval?: number

Suggested polling interval in milliseconds.

status: TaskStatus

Current task state.

taskId: string

The task identifier.

+
interface Task {
  error?: string;
  keepAlive: null | number;
  pollInterval?: number;
  status: TaskStatus;
  statusMessage?: string;
  taskId: string;
}

Data associated with a task.

error?: string

Error message if status is "failed".

keepAlive: null | number

Actual retention duration in milliseconds, null for unlimited.

pollInterval?: number

Suggested polling interval in milliseconds.

status: TaskStatus

Current task state.

statusMessage?: string

Current task state message, optional.

taskId: string

The task identifier.

### `TaskMetadata` diff --git a/schema/draft/schema.json b/schema/draft/schema.json index 2c85f38d5..01e15aaf3 100644 --- a/schema/draft/schema.json +++ b/schema/draft/schema.json @@ -3058,6 +3058,10 @@ "$ref": "#/definitions/TaskStatus", "description": "Current task state." }, + "statusMessage": { + "description": "Current task state message, optional.", + "type": "string" + }, "taskId": { "description": "The task identifier.", "type": "string" diff --git a/schema/draft/schema.ts b/schema/draft/schema.ts index 1084ef2ec..491117e0e 100644 --- a/schema/draft/schema.ts +++ b/schema/draft/schema.ts @@ -1225,6 +1225,11 @@ export interface Task { */ status: TaskStatus; + /** + * Current task state message, optional. + */ + statusMessage?: string; + /** * Actual retention duration in milliseconds, null for unlimited. */ From b9a9ac4be42d0c0793ba1dac3ce51d3454f875ea Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Mon, 10 Nov 2025 12:08:17 -0800 Subject: [PATCH 33/79] Remove cancellation changes and convert deletion into cancel RPC method --- .../draft/basic/utilities/cancellation.mdx | 48 ++----- .../draft/basic/utilities/tasks.mdx | 114 +++++++++------ docs/specification/draft/schema.mdx | 27 ++-- schema/draft/schema.json | 130 +++++++++++------- schema/draft/schema.ts | 70 ++++++---- 5 files changed, 215 insertions(+), 174 deletions(-) diff --git a/docs/specification/draft/basic/utilities/cancellation.mdx b/docs/specification/draft/basic/utilities/cancellation.mdx index 1509b0b6f..1669b418c 100644 --- a/docs/specification/draft/basic/utilities/cancellation.mdx +++ b/docs/specification/draft/basic/utilities/cancellation.mdx @@ -15,12 +15,9 @@ indicate that a previously-issued request should be terminated. When a party wants to cancel an in-progress request, it sends a `notifications/cancelled` notification containing: -- For non-task requests: The ID of the request to cancel -- For task cancellation: The ID of the task to cancel +- The ID of the request to cancel - An optional reason string that can be logged or displayed -### Cancelling Non-Task Requests - ```json { "jsonrpc": "2.0", @@ -32,49 +29,23 @@ notification containing: } ``` -### Cancelling Tasks - -For task-augmented requests, once the `CreateTaskResult` is returned, the original request is complete and `requestId` becomes ambiguous. Therefore, task cancellation **MUST** use `taskId`: - -```json -{ - "jsonrpc": "2.0", - "method": "notifications/cancelled", - "params": { - "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", - "reason": "User requested cancellation" - } -} -``` - ## Behavior Requirements -### General Requirements - -1. Cancellation notifications **MUST** only reference requests or tasks that: +1. Cancellation notifications **MUST** only reference requests that: - Were previously issued in the same direction - Are believed to still be in-progress 2. The `initialize` request **MUST NOT** be cancelled by clients 3. Receivers of cancellation notifications **SHOULD**: - - Stop processing the cancelled request or task + - Stop processing the cancelled request - Free associated resources - - For non-task requests: Not send a response for the cancelled request - - For tasks: Move the task to `cancelled` status + - Not send a response for the cancelled request 4. Receivers **MAY** ignore cancellation notifications if: - - The referenced request or task is unknown - - Processing has already completed (for non-task requests) or reached a terminal status (for tasks) - - The request or task cannot be cancelled + - The referenced request is unknown + - Processing has already completed + - The request cannot be cancelled 5. The sender of the cancellation notification **SHOULD** ignore any response to the request that arrives afterward -### Task-Specific Requirements - -1. For task cancellation, `taskId` **MUST** be provided (not `requestId`) -2. `requestId` **MUST NOT** be used for task cancellation once `CreateTaskResult` has been returned -3. When a receiver receives a `notifications/cancelled` notification with a `taskId`, it **SHOULD** immediately move the task to `cancelled` status -4. If a cancellation notification arrives after a task has already reached a terminal status (`completed`, `failed`, or `cancelled`), receivers **SHOULD** ignore the notification -5. Requestors **SHOULD** poll with `tasks/get` after sending a cancellation notification to confirm the task has transitioned to `cancelled` status - ## Timing Considerations Due to network latency, cancellation notifications may arrive after request processing @@ -106,10 +77,9 @@ sequenceDiagram Invalid cancellation notifications **SHOULD** be ignored: -- Unknown request IDs or task IDs -- Already completed requests or tasks in terminal status +- Unknown request IDs +- Already completed requests - Malformed notifications -- Using `requestId` for task cancellation (should use `taskId` instead) This maintains the "fire and forget" nature of notifications while allowing for race conditions in asynchronous communication. diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index 4b41cf7a0..698265095 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -27,7 +27,7 @@ Servers declare if they support tasks, and if so, which server-side requests can "capabilities": { "tasks": { "list": {}, - "delete": {}, + "cancel": {}, "requests": { "tools": { "call": {} @@ -47,7 +47,7 @@ Clients declare if they support tasks, and if so, which client-side requests can "capabilities": { "tasks": { "list": {}, - "delete": {}, + "cancel": {}, "requests": { "sampling": { "createMessage": {} @@ -73,7 +73,7 @@ The set of capabilities in `capabilities.tasks.requests` is exhaustive. If a req `capabilities.tasks.list` controls if the `tasks/list` operation is supported by the party. -`capabilities.tasks.delete` controls if the `tasks/delete` operation is supported by the party. +`capabilities.tasks.cancel` controls if the `tasks/cancel` operation is supported by the party. ### Tool-Level Negotiation @@ -314,17 +314,17 @@ To retrieve a list of tasks, requestors send a `tasks/list` request. This operat } ``` -### Deleting Tasks +### Cancelling Tasks -To explicitly delete a task and its associated results, requestors send a `tasks/delete` request. +To explicitly cancel a task, requestors send a `tasks/cancel` request. The request can optionally include a `delete` parameter to immediately delete the task and its results after cancellation. -**Request:** +**Request (basic cancellation):** ```json { "jsonrpc": "2.0", "id": 6, - "method": "tasks/delete", + "method": "tasks/cancel", "params": { "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" } @@ -338,6 +338,41 @@ To explicitly delete a task and its associated results, requestors send a `tasks "jsonrpc": "2.0", "id": 6, "result": { + "status": "cancelled", + "executionStopped": true, + "_meta": { + "modelcontextprotocol.io/related-task": { + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" + } + } + } +} +``` + +**Request (cancellation with deletion):** + +```json +{ + "jsonrpc": "2.0", + "id": 7, + "method": "tasks/cancel", + "params": { + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", + "delete": true + } +} +``` + +**Response:** + +```json +{ + "jsonrpc": "2.0", + "id": 7, + "result": { + "status": "cancelled", + "executionStopped": true, + "deleted": true, "_meta": { "modelcontextprotocol.io/related-task": { "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" @@ -417,24 +452,12 @@ stateDiagram-v2 1. All requests, notifications, and responses related to a task **MUST** include the `modelcontextprotocol.io/related-task` key in their `_meta`, with the value set to an object with a `taskId` matching the associated task ID. 1. 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. -1. For the `tasks/get`, `tasks/list`, `tasks/result`, and `tasks/delete` operations, the `taskId` parameter in the request **MUST** be used as the source of truth for identifying the target task. Requestors **SHOULD NOT** include `modelcontextprotocol.io/related-task` metadata in these requests, and receivers **MUST** ignore such metadata if present in favor of the RPC method parameter. +1. For the `tasks/get`, `tasks/list`, `tasks/result`, and `tasks/cancel` operations, the `taskId` parameter in the request **MUST** be used as the source of truth for identifying the target task. Requestors **SHOULD NOT** include `modelcontextprotocol.io/related-task` metadata in these requests, and receivers **MUST** ignore such metadata if present in favor of the RPC method parameter. ### Task Progress Notifications Task-augmented requests support progress notifications as defined in the progress notification specification. The `progressToken` provided in the initial request remains valid throughout the task's lifetime. -### Task Cancellation - -1. Requestors **MAY** send `notifications/cancelled` at any time during task execution. -1. For task cancellation, the `notifications/cancelled` notification **MUST** include a `taskId` field: - 1. The `taskId` **MUST** correspond to a task previously created in the same direction. - 1. Once a task-augmented request returns `CreateTaskResult`, the original request is complete and `requestId` becomes ambiguous. Therefore, `requestId` **MUST NOT** be used for task cancellation. -1. When a receiver receives a `notifications/cancelled` notification with a `taskId`, the receiver **SHOULD** immediately move the task to the `cancelled` status and cease all processing associated with that task. -1. Due to the asynchronous nature of notifications, receivers **MAY** not cancel task processing instantaneously. Receivers **SHOULD** make a best-effort attempt to halt execution as quickly as possible. -1. If a `notifications/cancelled` notification arrives after a task has already reached a terminal status (`completed`, `failed`, or `cancelled`), receivers **SHOULD** ignore the notification. -1. After a task reaches `cancelled` status and its `keepAlive` duration has elapsed, receivers **MAY** delete the task and its metadata. -1. Because notifications do not provide confirmation of receipt, requestors **SHOULD** continue to poll with `tasks/get` after sending a cancellation notification to confirm the task has transitioned to `cancelled` status. If the task does not transition to `cancelled` within a reasonable timeframe, requestors **MAY** assume the cancellation was not processed. - ### Task Listing 1. Receivers **SHOULD** use cursor-based pagination to limit the number of tasks returned in a single response. @@ -442,12 +465,14 @@ Task-augmented requests support progress notifications as defined in the progres 1. Requestors **MUST** treat cursors as opaque tokens and not attempt to parse or modify them. 1. If a task is retrievable via `tasks/get` for a requestor, it **MUST** be retrievable via `tasks/list` for that requestor. -### Task Deletion +### Task Cancellation -1. Receivers **MAY** accept or reject delete requests for any task at their discretion. -1. If a receiver accepts a delete request, it **SHOULD** delete the task and all associated results and metadata. -1. Receivers **MAY** choose not to support deletion at all, or only support deletion for tasks in certain statuses (e.g., only terminal statuses). -1. Requestors **SHOULD** delete tasks containing sensitive data promptly rather than relying solely on `keepAlive` expiration for cleanup. +1. Receivers **MUST** reject cancellation requests for tasks already in a terminal status (`completed`, `failed`, or `cancelled`) with error code `-32602` (Invalid params). +1. Upon receiving a valid cancellation request, receivers **SHOULD** attempt to stop the task's execution (best effort) and **MUST** transition the task to `cancelled` status before sending the response. +1. Once a task is cancelled, it **MUST** remain in `cancelled` status even if execution continues to completion or fails. +1. If the `delete` parameter is `true`, receivers **SHOULD** delete the task and all associated results and metadata after transitioning to `cancelled` status. Receivers **MAY** choose not to support deletion and ignore this parameter. +1. If the `delete` parameter is `false` or omitted, receivers **MUST** retain the task in `cancelled` status subject to the `keepAlive` duration. +1. Requestors **SHOULD** use the `delete` parameter to clean up tasks containing sensitive data promptly rather than relying solely on `keepAlive` expiration. ## Message Flow @@ -591,6 +616,7 @@ sequenceDiagram Note over C,S: 1. Task Creation C->>S: tools/call (request ID: 42, task-123) + S->>C: CreateTaskResult (task-123, status: working) S--)C: notifications/tasks/created Note over C,S: 2. Task Processing @@ -599,21 +625,19 @@ sequenceDiagram Note over C,S: 3. Client Cancellation Note over C: User requests cancellation - C--)S: notifications/cancelled (taskId: task-123) + C->>S: tasks/cancel (taskId: task-123) - Note over S: Server processes cancellation + Note over S: Server stops execution (best effort) Note over S: Task moves to cancelled status - Note over C,S: 4. Confirmation Polling - C->>S: tasks/get (task-123) - S->>C: cancelled + S->>C: Result (status: cancelled, executionStopped: true) - Note over C: Client confirms cancellation succeeded + Note over C: Client receives confirmation Note over S: After keepAlive period, task cleaned up ``` -### Task Deletion Flow +### Task Cancellation with Deletion Flow ```mermaid sequenceDiagram @@ -622,7 +646,7 @@ sequenceDiagram Note over C,S: 1. Task Creation and Completion C->>S: tools/call (task-123) - S->>C: CreateTaskResult (task-123, status: submitted) + S->>C: CreateTaskResult (task-123, status: working) S--)C: notifications/tasks/created Note over S: Task processing... C->>S: tasks/get (task-123) @@ -632,13 +656,15 @@ sequenceDiagram C->>S: tasks/result (task-123) S->>C: Result content - Note over C,S: 3. Explicit Deletion + Note over C,S: 3. Cancellation with Deletion Note over C: Client decides to clean up task - C->>S: tasks/delete (task-123) - S->>C: Success (empty result) + C->>S: tasks/cancel (task-123, delete: true) + Note over S: Task moves to cancelled status Note over S: Task and results immediately deleted + S->>C: Result (status: cancelled, deleted: true) + Note over C,S: 4. Verification (optional) C->>S: tasks/get (task-123) S->>C: Error: Task not found @@ -706,9 +732,9 @@ Tasks use two error reporting mechanisms: Receivers **MUST** return standard JSON-RPC errors for the following protocol error cases: -- Invalid or nonexistent `taskId` in `tasks/get`, `tasks/list`, `tasks/result`, or `tasks/delete`: `-32602` (Invalid params) +- Invalid or nonexistent `taskId` in `tasks/get`, `tasks/list`, `tasks/result`, or `tasks/cancel`: `-32602` (Invalid params) - Invalid or nonexistent cursor in `tasks/list`: `-32602` (Invalid params) -- Receiver rejects a `tasks/delete` request: `-32600` (Invalid request) +- Attempt to cancel a task already in a terminal status: `-32602` (Invalid params) - Internal errors: `-32603` (Internal error) Additionally, receivers **MAY** return the following errors: @@ -762,15 +788,15 @@ Receivers are not obligated to retain task metadata indefinitely. It is complian -**Example: Task deletion rejected by receiver** +**Example: Task cancellation rejected (already terminal)** ```json { "jsonrpc": "2.0", "id": 74, "error": { - "code": -32600, - "message": "Task deletion not supported for tasks in 'working' status" + "code": -32602, + "message": "Cannot cancel task: already in terminal status 'completed'" } } ``` @@ -808,20 +834,20 @@ The `tasks/result` endpoint returns exactly what the underlying request would ha 1. Receivers **SHOULD** scope task IDs to prevent unauthorized access: 1. Bind tasks to the session that created them (if sessions are supported) 1. Bind tasks to the authentication context (if authentication is used) - 1. Reject `tasks/get`, `tasks/list`, `tasks/result`, or `tasks/delete` requests for tasks from different sessions or auth contexts + 1. Reject `tasks/get`, `tasks/list`, `tasks/result`, or `tasks/cancel` requests for tasks from different sessions or auth contexts 1. Receivers that do not implement session or authentication binding **SHOULD** document this limitation clearly, as task results may be accessible to any requestor that can guess the task ID. 1. Receivers **SHOULD** implement rate limiting on: 1. Task creation to prevent resource exhaustion 1. Task status polling to prevent denial of service 1. Task result retrieval attempts 1. Task listing requests to prevent denial of service - 1. Task deletion requests to prevent abuse + 1. Task cancellation requests to prevent abuse ### Resource Management -Task results may persist longer than the original request execution time. For sensitive operations, requestors should carefully consider the security implications of extended result retention and may want to retrieve results promptly and request shorter `keepAlive` durations. Requestors are encouraged to use `tasks/delete` to explicitly clean up tasks containing sensitive data rather than relying solely on `keepAlive` expiration. +Task results may persist longer than the original request execution time. For sensitive operations, requestors should carefully consider the security implications of extended result retention and may want to retrieve results promptly and request shorter `keepAlive` durations. Requestors are encouraged to use `tasks/cancel` with the `delete` parameter set to `true` to explicitly clean up tasks containing sensitive data rather than relying solely on `keepAlive` expiration. diff --git a/docs/specification/draft/schema.mdx b/docs/specification/draft/schema.mdx index 4b2a831fa..a6099b9ca 100644 --- a/docs/specification/draft/schema.mdx +++ b/docs/specification/draft/schema.mdx @@ -27,7 +27,7 @@ the data is entirely optional.

interface ClientCapabilities {
  elicitation?: object;
  experimental?: { [key: string]: object };
  roots?: { listChanged?: boolean };
  sampling?: object;
  tasks?: {
    delete?: object;
    list?: object;
    requests?: {
      elicitation?: { create?: object };
      sampling?: { createMessage?: object };
    };
  };
}

Capabilities a client may support. Known capabilities are defined here, in this schema, but this is not a closed set: any client can define its own, additional capabilities.

elicitation?: object

Present if the client supports elicitation from the server.

experimental?: { [key: string]: object }

Experimental, non-standard capabilities that the client supports.

roots?: { listChanged?: boolean }

Present if the client supports listing roots.

Type declaration
  • OptionallistChanged?: boolean

    Whether the client supports notifications for changes to the roots list.

sampling?: object

Present if the client supports sampling from an LLM.

tasks?: {
  delete?: object;
  list?: object;
  requests?: {
    elicitation?: { create?: object };
    sampling?: { createMessage?: object };
  };
}

Present if the client supports task-augmented requests.

Type declaration
  • Optionaldelete?: object

    Whether this client supports tasks/delete.

  • Optionallist?: object

    Whether this client supports tasks/list.

  • Optionalrequests?: { elicitation?: { create?: object }; sampling?: { createMessage?: object } }

    Specifies which request types can be augmented with tasks.

    • Optionalelicitation?: { create?: object }

      Task support for elicitation-related requests.

      • Optionalcreate?: object

        Whether the client supports task-augmented elicitation/create requests.

    • Optionalsampling?: { createMessage?: object }

      Task support for sampling-related requests.

      • OptionalcreateMessage?: object

        Whether the client supports task-augmented sampling/createMessage requests.

+
interface ClientCapabilities {
  elicitation?: object;
  experimental?: { [key: string]: object };
  roots?: { listChanged?: boolean };
  sampling?: object;
  tasks?: {
    cancel?: object;
    list?: object;
    requests?: {
      elicitation?: { create?: object };
      sampling?: { createMessage?: object };
    };
  };
}

Capabilities a client may support. Known capabilities are defined here, in this schema, but this is not a closed set: any client can define its own, additional capabilities.

elicitation?: object

Present if the client supports elicitation from the server.

experimental?: { [key: string]: object }

Experimental, non-standard capabilities that the client supports.

roots?: { listChanged?: boolean }

Present if the client supports listing roots.

Type declaration
  • OptionallistChanged?: boolean

    Whether the client supports notifications for changes to the roots list.

sampling?: object

Present if the client supports sampling from an LLM.

tasks?: {
  cancel?: object;
  list?: object;
  requests?: {
    elicitation?: { create?: object };
    sampling?: { createMessage?: object };
  };
}

Present if the client supports task-augmented requests.

Type declaration
  • Optionalcancel?: object

    Whether this client supports tasks/cancel.

  • Optionallist?: object

    Whether this client supports tasks/list.

  • Optionalrequests?: { elicitation?: { create?: object }; sampling?: { createMessage?: object } }

    Specifies which request types can be augmented with tasks.

    • Optionalelicitation?: { create?: object }

      Task support for elicitation-related requests.

      • Optionalcreate?: object

        Whether the client supports task-augmented elicitation/create requests.

    • Optionalsampling?: { createMessage?: object }

      Task support for sampling-related requests.

      • OptionalcreateMessage?: object

        Whether the client supports task-augmented sampling/createMessage requests.

### `ContentBlock` @@ -221,7 +221,7 @@ other URI schemes.

interface ServerCapabilities {
  completions?: object;
  experimental?: { [key: string]: object };
  logging?: object;
  prompts?: { listChanged?: boolean };
  resources?: { listChanged?: boolean; subscribe?: boolean };
  tasks?: {
    delete?: object;
    list?: object;
    requests?: { tools?: { call?: object } };
  };
  tools?: { listChanged?: boolean };
}

Capabilities that a server may support. Known capabilities are defined here, in this schema, but this is not a closed set: any server can define its own, additional capabilities.

completions?: object

Present if the server supports argument autocompletion suggestions.

experimental?: { [key: string]: object }

Experimental, non-standard capabilities that the server supports.

logging?: object

Present if the server supports sending log messages to the client.

prompts?: { listChanged?: boolean }

Present if the server offers any prompt templates.

Type declaration
  • OptionallistChanged?: boolean

    Whether this server supports notifications for changes to the prompt list.

resources?: { listChanged?: boolean; subscribe?: boolean }

Present if the server offers any resources to read.

Type declaration
  • OptionallistChanged?: boolean

    Whether this server supports notifications for changes to the resource list.

  • Optionalsubscribe?: boolean

    Whether this server supports subscribing to resource updates.

tasks?: {
  delete?: object;
  list?: object;
  requests?: { tools?: { call?: object } };
}

Present if the server supports task-augmented requests.

Type declaration
  • Optionaldelete?: object

    Whether this server supports tasks/delete.

  • Optionallist?: object

    Whether this server supports tasks/list.

  • Optionalrequests?: { tools?: { call?: object } }

    Specifies which request types can be augmented with tasks.

    • Optionaltools?: { call?: object }

      Task support for tool-related requests.

      • Optionalcall?: object

        Whether the server supports task-augmented tools/call requests.

tools?: { listChanged?: boolean }

Present if the server offers any tools to call.

Type declaration
  • OptionallistChanged?: boolean

    Whether this server supports notifications for changes to the tool list.

+
interface ServerCapabilities {
  completions?: object;
  experimental?: { [key: string]: object };
  logging?: object;
  prompts?: { listChanged?: boolean };
  resources?: { listChanged?: boolean; subscribe?: boolean };
  tasks?: {
    cancel?: object;
    list?: object;
    requests?: { tools?: { call?: object } };
  };
  tools?: { listChanged?: boolean };
}

Capabilities that a server may support. Known capabilities are defined here, in this schema, but this is not a closed set: any server can define its own, additional capabilities.

completions?: object

Present if the server supports argument autocompletion suggestions.

experimental?: { [key: string]: object }

Experimental, non-standard capabilities that the server supports.

logging?: object

Present if the server supports sending log messages to the client.

prompts?: { listChanged?: boolean }

Present if the server offers any prompt templates.

Type declaration
  • OptionallistChanged?: boolean

    Whether this server supports notifications for changes to the prompt list.

resources?: { listChanged?: boolean; subscribe?: boolean }

Present if the server offers any resources to read.

Type declaration
  • OptionallistChanged?: boolean

    Whether this server supports notifications for changes to the resource list.

  • Optionalsubscribe?: boolean

    Whether this server supports subscribing to resource updates.

tasks?: {
  cancel?: object;
  list?: object;
  requests?: { tools?: { call?: object } };
}

Present if the server supports task-augmented requests.

Type declaration
  • Optionalcancel?: object

    Whether this server supports tasks/cancel.

  • Optionallist?: object

    Whether this server supports tasks/list.

  • Optionalrequests?: { tools?: { call?: object } }

    Specifies which request types can be augmented with tasks.

    • Optionaltools?: { call?: object }

      Task support for tool-related requests.

      • Optionalcall?: object

        Whether the server supports task-augmented tools/call requests.

tools?: { listChanged?: boolean }

Present if the server offers any tools to call.

Type declaration
  • OptionallistChanged?: boolean

    Whether this server supports notifications for changes to the tool list.

### `StringSchema` @@ -315,17 +315,13 @@ Contains values matching the requested schema.

interface CancelledNotification {
  jsonrpc: "2.0";
  method: "notifications/cancelled";
  params: CancelledNotificationParams;
}

This notification can be sent by either side to indicate that it is cancelling a previously-issued request or task.

The request or task SHOULD still be in-flight, but due to communication latency, it is always possible that this notification MAY arrive after the request has already finished.

This notification indicates that the result will be unused, so any associated processing SHOULD cease.

A client MUST NOT attempt to cancel its initialize request.

For non-task requests, use requestId to cancel the request. -For task cancellation, use taskId to cancel the task. Once a task-augmented request returns CreateTaskResult, -the original request is complete and requestId becomes ambiguous - only taskId should be used for cancellation.

+
interface CancelledNotification {
  jsonrpc: "2.0";
  method: "notifications/cancelled";
  params: CancelledNotificationParams;
}

This notification can be sent by either side to indicate that it is cancelling a previously-issued request.

The request SHOULD still be in-flight, but due to communication latency, it is always possible that this notification MAY arrive after the request has already finished.

This notification indicates that the result will be unused, so any associated processing SHOULD cease.

A client MUST NOT attempt to cancel its initialize request.

For task cancellation, use the tasks/cancel request instead of this notification.

### `CancelledNotificationParams` -
interface CancelledNotificationParams {
  _meta?: { [key: string]: unknown };
  reason?: string;
  requestId?: RequestId;
  taskId?: string;
}

Parameters for a notifications/cancelled notification.

For non-task requests: requestId MUST be provided. -For task cancellation: taskId MUST be provided (using requestId is not supported once the task has been created).

_meta?: { [key: string]: unknown }

See General fields: _meta for notes on _meta usage.

reason?: string

An optional string describing the reason for the cancellation. This MAY be logged or presented to the user.

requestId?: RequestId

The ID of the request to cancel.

This MUST correspond to the ID of a request previously issued in the same direction. +

interface CancelledNotificationParams {
  _meta?: { [key: string]: unknown };
  reason?: string;
  requestId?: RequestId;
  taskId?: string;
}

Parameters for a notifications/cancelled notification.

_meta?: { [key: string]: unknown }

See General fields: _meta for notes on _meta usage.

reason?: string

An optional string describing the reason for the cancellation. This MAY be logged or presented to the user.

requestId?: RequestId

The ID of the request to cancel.

This MUST correspond to the ID of a request previously issued in the same direction. This MUST be provided for cancelling non-task requests. -This MUST NOT be used for cancelling tasks (use taskId instead).

taskId?: string

The ID of the task to cancel.

This MUST correspond to the ID of a task previously created in the same direction. -This MUST be provided for cancelling tasks.

+This MUST NOT be used for cancelling tasks (use the tasks/cancel request instead).

taskId?: string

Deprecated: Use the tasks/cancel request instead of this notification for task cancellation.

## `notifications/initialized` @@ -546,15 +542,18 @@ Include this in the _meta field of a request under the key TaskStatus: "working" | "input_required" | "completed" | "failed" | "cancelled"

The status of a task.

-## `tasks/delete` +## `tasks/cancel` -### `DeleteTaskRequest` +### `CancelTaskRequest` -
interface DeleteTaskRequest {
  id: RequestId;
  jsonrpc: "2.0";
  method: "tasks/delete";
  params: { taskId: string };
}

A request to delete a task and its associated results.

params: { taskId: string }
Type declaration
  • taskId: string

    The task identifier to delete.

+
interface CancelTaskRequest {
  id: RequestId;
  jsonrpc: "2.0";
  method: "tasks/cancel";
  params: { delete?: boolean; taskId: string };
}

A request to cancel a task and optionally delete its associated results.

params: { delete?: boolean; taskId: string }
Type declaration
  • Optionaldelete?: boolean

    Whether to delete the task and its results after cancellation. +If true, the task and all associated results and metadata will be deleted. +If false or omitted, the task will be retained according to its keepAlive duration.

  • taskId: string

    The task identifier to cancel.

-### `DeleteTaskResult` +### `CancelTaskResult` -
DeleteTaskResult: Result

The response to a tasks/delete request.

+
interface CancelTaskResult {
  _meta?: { [key: string]: unknown };
  deleted?: boolean;
  executionStopped?: boolean;
  status: "cancelled";
  [key: string]: unknown;
}

The response to a tasks/cancel request.

_meta?: { [key: string]: unknown }

See General fields: _meta for notes on _meta usage.

deleted?: boolean

Whether the task and its results were deleted.

executionStopped?: boolean

Whether execution was successfully stopped. +If not provided, it is unknown whether execution was stopped.

status: "cancelled"

The status of the task after cancellation (always "cancelled").

## `tasks/get` diff --git a/schema/draft/schema.json b/schema/draft/schema.json index 01e15aaf3..f77360564 100644 --- a/schema/draft/schema.json +++ b/schema/draft/schema.json @@ -208,8 +208,74 @@ ], "type": "object" }, + "CancelTaskRequest": { + "description": "A request to cancel a task and optionally delete its associated results.", + "properties": { + "id": { + "$ref": "#/definitions/RequestId" + }, + "jsonrpc": { + "const": "2.0", + "type": "string" + }, + "method": { + "const": "tasks/cancel", + "type": "string" + }, + "params": { + "properties": { + "delete": { + "description": "Whether to delete the task and its results after cancellation.\nIf true, the task and all associated results and metadata will be deleted.\nIf false or omitted, the task will be retained according to its keepAlive duration.", + "type": "boolean" + }, + "taskId": { + "description": "The task identifier to cancel.", + "type": "string" + } + }, + "required": [ + "taskId" + ], + "type": "object" + } + }, + "required": [ + "id", + "jsonrpc", + "method", + "params" + ], + "type": "object" + }, + "CancelTaskResult": { + "description": "The response to a tasks/cancel request.", + "properties": { + "_meta": { + "additionalProperties": {}, + "description": "See [General fields: `_meta`](/specification/draft/basic/index#meta) for notes on `_meta` usage.", + "type": "object" + }, + "deleted": { + "description": "Whether the task and its results were deleted.", + "type": "boolean" + }, + "executionStopped": { + "description": "Whether execution was successfully stopped.\nIf not provided, it is unknown whether execution was stopped.", + "type": "boolean" + }, + "status": { + "const": "cancelled", + "description": "The status of the task after cancellation (always \"cancelled\").", + "type": "string" + } + }, + "required": [ + "status" + ], + "type": "object" + }, "CancelledNotification": { - "description": "This notification can be sent by either side to indicate that it is cancelling a previously-issued request or task.\n\nThe request or task SHOULD still be in-flight, but due to communication latency, it is always possible that this notification MAY arrive after the request has already finished.\n\nThis notification indicates that the result will be unused, so any associated processing SHOULD cease.\n\nA client MUST NOT attempt to cancel its `initialize` request.\n\nFor non-task requests, use `requestId` to cancel the request.\nFor task cancellation, use `taskId` to cancel the task. Once a task-augmented request returns `CreateTaskResult`,\nthe original request is complete and `requestId` becomes ambiguous - only `taskId` should be used for cancellation.", + "description": "This notification can be sent by either side to indicate that it is cancelling a previously-issued request.\n\nThe request SHOULD still be in-flight, but due to communication latency, it is always possible that this notification MAY arrive after the request has already finished.\n\nThis notification indicates that the result will be unused, so any associated processing SHOULD cease.\n\nA client MUST NOT attempt to cancel its `initialize` request.\n\nFor task cancellation, use the `tasks/cancel` request instead of this notification.", "properties": { "jsonrpc": { "const": "2.0", @@ -231,7 +297,7 @@ "type": "object" }, "CancelledNotificationParams": { - "description": "Parameters for a `notifications/cancelled` notification.\n\nFor non-task requests: `requestId` MUST be provided.\nFor task cancellation: `taskId` MUST be provided (using `requestId` is not supported once the task has been created).", + "description": "Parameters for a `notifications/cancelled` notification.", "properties": { "_meta": { "additionalProperties": {}, @@ -244,10 +310,10 @@ }, "requestId": { "$ref": "#/definitions/RequestId", - "description": "The ID of the request to cancel.\n\nThis MUST correspond to the ID of a request previously issued in the same direction.\nThis MUST be provided for cancelling non-task requests.\nThis MUST NOT be used for cancelling tasks (use `taskId` instead)." + "description": "The ID of the request to cancel.\n\nThis MUST correspond to the ID of a request previously issued in the same direction.\nThis MUST be provided for cancelling non-task requests.\nThis MUST NOT be used for cancelling tasks (use the `tasks/cancel` request instead)." }, "taskId": { - "description": "The ID of the task to cancel.\n\nThis MUST correspond to the ID of a task previously created in the same direction.\nThis MUST be provided for cancelling tasks.", + "description": "Deprecated: Use the `tasks/cancel` request instead of this notification for task cancellation.", "type": "string" } }, @@ -290,9 +356,9 @@ "tasks": { "description": "Present if the client supports task-augmented requests.", "properties": { - "delete": { + "cancel": { "additionalProperties": true, - "description": "Whether this client supports tasks/delete.", + "description": "Whether this client supports tasks/cancel.", "properties": {}, "type": "object" }, @@ -402,7 +468,7 @@ "$ref": "#/definitions/GetTaskPayloadRequest" }, { - "$ref": "#/definitions/DeleteTaskRequest" + "$ref": "#/definitions/CancelTaskRequest" }, { "$ref": "#/definitions/ListTasksRequest" @@ -427,6 +493,9 @@ { "$ref": "#/definitions/GetTaskPayloadResult" }, + { + "$ref": "#/definitions/CancelTaskResult" + }, { "$ref": "#/definitions/ListTasksResult" }, @@ -729,44 +798,6 @@ "description": "An opaque token used to represent a cursor for pagination.", "type": "string" }, - "DeleteTaskRequest": { - "description": "A request to delete a task and its associated results.", - "properties": { - "id": { - "$ref": "#/definitions/RequestId" - }, - "jsonrpc": { - "const": "2.0", - "type": "string" - }, - "method": { - "const": "tasks/delete", - "type": "string" - }, - "params": { - "properties": { - "taskId": { - "description": "The task identifier to delete.", - "type": "string" - } - }, - "required": [ - "taskId" - ], - "type": "object" - } - }, - "required": [ - "id", - "jsonrpc", - "method", - "params" - ], - "type": "object" - }, - "DeleteTaskResult": { - "$ref": "#/definitions/Result" - }, "ElicitRequest": { "description": "A request from the server to elicit additional information from the user via the client.", "properties": { @@ -2753,9 +2784,9 @@ "tasks": { "description": "Present if the server supports task-augmented requests.", "properties": { - "delete": { + "cancel": { "additionalProperties": true, - "description": "Whether this server supports tasks/delete.", + "description": "Whether this server supports tasks/cancel.", "properties": {}, "type": "object" }, @@ -2842,7 +2873,7 @@ "$ref": "#/definitions/GetTaskPayloadRequest" }, { - "$ref": "#/definitions/DeleteTaskRequest" + "$ref": "#/definitions/CancelTaskRequest" }, { "$ref": "#/definitions/ListTasksRequest" @@ -2894,6 +2925,9 @@ { "$ref": "#/definitions/GetTaskPayloadResult" }, + { + "$ref": "#/definitions/CancelTaskResult" + }, { "$ref": "#/definitions/ListTasksResult" }, diff --git a/schema/draft/schema.ts b/schema/draft/schema.ts index 491117e0e..8ac2b4a0d 100644 --- a/schema/draft/schema.ts +++ b/schema/draft/schema.ts @@ -149,9 +149,6 @@ export type EmptyResult = Result; /** * Parameters for a `notifications/cancelled` notification. * - * For non-task requests: `requestId` MUST be provided. - * For task cancellation: `taskId` MUST be provided (using `requestId` is not supported once the task has been created). - * * @category notifications/cancelled */ export interface CancelledNotificationParams extends NotificationParams { @@ -160,15 +157,12 @@ export interface CancelledNotificationParams extends NotificationParams { * * This MUST correspond to the ID of a request previously issued in the same direction. * This MUST be provided for cancelling non-task requests. - * This MUST NOT be used for cancelling tasks (use `taskId` instead). + * This MUST NOT be used for cancelling tasks (use the `tasks/cancel` request instead). */ requestId?: RequestId; /** - * The ID of the task to cancel. - * - * This MUST correspond to the ID of a task previously created in the same direction. - * This MUST be provided for cancelling tasks. + * Deprecated: Use the `tasks/cancel` request instead of this notification for task cancellation. */ taskId?: string; @@ -179,17 +173,15 @@ export interface CancelledNotificationParams extends NotificationParams { } /** - * This notification can be sent by either side to indicate that it is cancelling a previously-issued request or task. + * This notification can be sent by either side to indicate that it is cancelling a previously-issued request. * - * The request or task SHOULD still be in-flight, but due to communication latency, it is always possible that this notification MAY arrive after the request has already finished. + * The request SHOULD still be in-flight, but due to communication latency, it is always possible that this notification MAY arrive after the request has already finished. * * This notification indicates that the result will be unused, so any associated processing SHOULD cease. * * A client MUST NOT attempt to cancel its `initialize` request. * - * For non-task requests, use `requestId` to cancel the request. - * For task cancellation, use `taskId` to cancel the task. Once a task-augmented request returns `CreateTaskResult`, - * the original request is complete and `requestId` becomes ambiguous - only `taskId` should be used for cancellation. + * For task cancellation, use the `tasks/cancel` request instead of this notification. * * @category notifications/cancelled */ @@ -288,9 +280,9 @@ export interface ClientCapabilities { */ list?: object; /** - * Whether this client supports tasks/delete. + * Whether this client supports tasks/cancel. */ - delete?: object; + cancel?: object; /** * Specifies which request types can be augmented with tasks. */ @@ -373,9 +365,9 @@ export interface ServerCapabilities { */ list?: object; /** - * Whether this server supports tasks/delete. + * Whether this server supports tasks/cancel. */ - delete?: object; + cancel?: object; /** * Specifies which request types can be augmented with tasks. */ @@ -1302,26 +1294,46 @@ export interface GetTaskPayloadResult extends Result { } /** - * A request to delete a task and its associated results. + * A request to cancel a task and optionally delete its associated results. * - * @category tasks/delete + * @category tasks/cancel */ -export interface DeleteTaskRequest extends JSONRPCRequest { - method: "tasks/delete"; +export interface CancelTaskRequest extends JSONRPCRequest { + method: "tasks/cancel"; params: { /** - * The task identifier to delete. + * The task identifier to cancel. */ taskId: string; + /** + * Whether to delete the task and its results after cancellation. + * If true, the task and all associated results and metadata will be deleted. + * If false or omitted, the task will be retained according to its keepAlive duration. + */ + delete?: boolean; }; } /** - * The response to a tasks/delete request. + * The response to a tasks/cancel request. * - * @category tasks/delete + * @category tasks/cancel */ -export type DeleteTaskResult = Result; +export interface CancelTaskResult extends Result { + /** + * The status of the task after cancellation (always "cancelled"). + */ + status: "cancelled"; + /** + * Whether execution was successfully stopped. + * If not provided, it is unknown whether execution was stopped. + */ + executionStopped?: boolean; + /** + * Whether the task and its results were deleted. + */ + deleted?: boolean; +} /** * A request to retrieve a list of tasks. @@ -2037,7 +2049,7 @@ export type ClientRequest = | GetTaskRequest | GetTaskPayloadRequest | ListTasksRequest - | DeleteTaskRequest; + | CancelTaskRequest; /** @internal */ export type ClientNotification = @@ -2057,7 +2069,7 @@ export type ClientResult = | GetTaskResult | GetTaskPayloadResult | ListTasksResult - | DeleteTaskResult; + | CancelTaskResult; /* Server messages */ /** @internal */ @@ -2069,7 +2081,7 @@ export type ServerRequest = | GetTaskRequest | GetTaskPayloadRequest | ListTasksRequest - | DeleteTaskRequest; + | CancelTaskRequest; /** @internal */ export type ServerNotification = @@ -2098,4 +2110,4 @@ export type ServerResult = | GetTaskResult | GetTaskPayloadResult | ListTasksResult - | DeleteTaskResult; + | CancelTaskResult; From aa0629af0faa0d8d1ad7add47c9b8ff1b2dce60f Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Tue, 11 Nov 2025 13:24:39 -0800 Subject: [PATCH 34/79] Replace keepalive with TTL; add createdAt --- .../draft/basic/utilities/tasks.mdx | 67 ++++++++++--------- docs/specification/draft/schema.mdx | 10 +-- schema/draft/schema.json | 40 ++++++----- schema/draft/schema.ts | 24 +++++-- 4 files changed, 84 insertions(+), 57 deletions(-) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index 698265095..61bcb3093 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -90,7 +90,7 @@ Task-augmented requests follow a two-phase response pattern that differs from no - **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 `CreateTaskResult` containing task metadata. The actual operation result becomes available later through `tasks/result` after the task completes. -To create a task, requestors send a request with the `modelcontextprotocol.io/task` key included in `_meta`. Requestors **MAY** include a `keepAlive` value representing how long after completion the requestor would like the task results to be kept for. +To create a task, requestors send a request with the `modelcontextprotocol.io/task` key included in `_meta`. Requestors **MAY** include a `ttl` value representing how long from task creation the requestor would like the task to be retained for. **Request:** @@ -106,7 +106,7 @@ To create a task, requestors send a request with the `modelcontextprotocol.io/ta }, "_meta": { "modelcontextprotocol.io/task": { - "keepAlive": 60000 + "ttl": 60000 } } } @@ -123,7 +123,8 @@ To create a task, requestors send a request with the `modelcontextprotocol.io/ta "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", "status": "working", "statusMessage": "The operation is now in progress.", - "keepAlive": 60000, + "createdAt": "2025-11-25T10:30:00Z", + "ttl": 60000, "pollInterval": 5000, "_meta": { "modelcontextprotocol.io/related-task": { @@ -161,10 +162,11 @@ To retrieve the state of a task, requestors send a `tasks/get` request: "id": 3, "result": { "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", - "keepAlive": 30000, - "pollInterval": 5000, "status": "working", "statusMessage": "The operation is now in progress.", + "createdAt": "2025-11-25T10:30:00Z", + "ttl": 30000, + "pollInterval": 5000, "_meta": { "modelcontextprotocol.io/related-task": { "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" @@ -300,13 +302,15 @@ To retrieve a list of tasks, requestors send a `tasks/list` request. This operat { "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", "status": "working", - "keepAlive": 30000, + "createdAt": "2025-11-25T10:30:00Z", + "ttl": 30000, "pollInterval": 5000 }, { "taskId": "abc123-def456-ghi789", "status": "completed", - "keepAlive": 60000 + "createdAt": "2025-11-25T09:15:00Z", + "ttl": 60000 } ], "nextCursor": "next-page-cursor" @@ -434,11 +438,12 @@ stateDiagram-v2 1. When the requestor encounters the `input_required` status, it **SHOULD** call `tasks/result` prematurely. 1. When the receiver receives all required input, the task **SHOULD** transition out of `input_required` status (typically back to `working`). -### Keep-Alive and Resource Management +### TTL and Resource Management -1. Receivers **MAY** override the requested `keepAlive` duration. -1. Receivers **MUST** include the actual `keepAlive` duration (or `null` for unlimited) in `tasks/get` responses. -1. After a task reaches a terminal status (`completed`, `failed`, or `cancelled`) and its `keepAlive` duration has elapsed, receivers **MAY** delete the task and its results. +1. Receivers **MUST** include a `createdAt` timestamp (ISO 8601 format) in all task responses to indicate when the task was created. +1. Receivers **MAY** override the requested `ttl` duration. +1. Receivers **MUST** include the actual `ttl` duration (or `null` for unlimited) in `tasks/get` responses. +1. After a task's `ttl` duration has elapsed from creation, receivers **MAY** delete the task and its results, regardless of the task's status. 1. Receivers **MAY** include a `pollInterval` value (in milliseconds) in `tasks/get` responses to suggest polling intervals. Requestors **SHOULD** respect this value when provided. ### Result Retrieval @@ -471,8 +476,8 @@ Task-augmented requests support progress notifications as defined in the progres 1. Upon receiving a valid cancellation request, receivers **SHOULD** attempt to stop the task's execution (best effort) and **MUST** transition the task to `cancelled` status before sending the response. 1. Once a task is cancelled, it **MUST** remain in `cancelled` status even if execution continues to completion or fails. 1. If the `delete` parameter is `true`, receivers **SHOULD** delete the task and all associated results and metadata after transitioning to `cancelled` status. Receivers **MAY** choose not to support deletion and ignore this parameter. -1. If the `delete` parameter is `false` or omitted, receivers **MUST** retain the task in `cancelled` status subject to the `keepAlive` duration. -1. Requestors **SHOULD** use the `delete` parameter to clean up tasks containing sensitive data promptly rather than relying solely on `keepAlive` expiration. +1. If the `delete` parameter is `false` or omitted, receivers **MUST** retain the task in `cancelled` status subject to the `ttl` duration. +1. Requestors **SHOULD** use the `delete` parameter to clean up tasks containing sensitive data promptly rather than relying solely on `ttl` expiration. ## Message Flow @@ -483,8 +488,8 @@ sequenceDiagram participant C as Client (Requestor) participant S as Server (Receiver) Note over C,S: 1. Task Creation - C->>S: Request with task metadata (taskId, keepAlive) - S->>C: CreateTaskResult (taskId, status: working, keepAlive, pollInterval) + C->>S: Request with task metadata (taskId, ttl) + S->>C: CreateTaskResult (taskId, status: working, ttl, pollInterval) S--)C: notifications/tasks/created Note over C,S: 2. Task Polling C->>S: tasks/get (taskId) @@ -499,7 +504,7 @@ sequenceDiagram C->>S: tasks/result (taskId) S->>C: Result content Note over C,S: 4. Cleanup - Note over S: After keepAlive period, task is cleaned up + Note over S: After ttl period from creation, task is cleaned up ``` ### Task-Augmented Tool Call With Elicitation @@ -515,7 +520,7 @@ sequenceDiagram LLM->>C: Request operation Note over C,S: Client augments with task metadata - C->>S: tools/call (task-123, keepAlive: 3600000) + C->>S: tools/call (task-123, ttl: 3600000) S->>C: CreateTaskResult (task-123, status: working) S--)C: notifications/tasks/created @@ -557,7 +562,7 @@ sequenceDiagram S->>C: Result content C->>LLM: Process result - Note over S: Results retained for keepAlive period + Note over S: Results retained for ttl period from creation ``` ### Task-Augmented Sampling Request @@ -572,7 +577,7 @@ sequenceDiagram Note over S: Server decides to initiate request Note over S,C: Server requests client operation (task-augmented) - S->>C: sampling/createMessage (request-789, keepAlive: 3600000) + S->>C: sampling/createMessage (request-789, ttl: 3600000) C->>S: CreateTaskResult (request-789, status: working) C--)S: notifications/tasks/created @@ -604,7 +609,7 @@ sequenceDiagram Note over S: Server continues processing - Note over C: Results retained for keepAlive period + Note over C: Results retained for ttl period from creation ``` ### Task Cancellation Flow @@ -634,7 +639,7 @@ sequenceDiagram Note over C: Client receives confirmation - Note over S: After keepAlive period, task cleaned up + Note over S: After ttl period from creation, task cleaned up ``` ### Task Cancellation with Deletion Flow @@ -677,9 +682,10 @@ sequenceDiagram A task represents the execution state of a request. The task metadata includes: - `taskId`: Unique identifier for the task -- `keepAlive`: Time in milliseconds that results will be kept available after completion -- `pollInterval`: Suggested time in milliseconds between status checks - `status`: Current state of the task execution +- `createdAt`: ISO 8601 timestamp when the task was created +- `ttl`: Time in milliseconds from creation before task may be deleted +- `pollInterval`: Suggested time in milliseconds between status checks ### Task Status @@ -698,14 +704,14 @@ When augmenting a request with task execution, the `modelcontextprotocol.io/task ```json { "modelcontextprotocol.io/task": { - "keepAlive": 60000 + "ttl": 60000 } } ``` Fields: -- `keepAlive` (number, optional): Requested duration in milliseconds to retain results after completion +- `ttl` (number, optional): Requested duration in milliseconds to retain task from creation ### Related Task Metadata @@ -812,9 +818,10 @@ When the underlying request does not complete successfully, the task moves to th "jsonrpc": "2.0", "id": 4, "result": { - "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", + "taskId": "786512e2-9e0d-44bd-8f29-789f820fe840", "status": "failed", - "keepAlive": 30000, + "createdAt": "2025-11-25T10:30:00Z", + "ttl": 30000, "error": "Tool execution failed: API rate limit exceeded" } } @@ -847,16 +854,16 @@ The `tasks/result` endpoint returns exactly what the underlying request would ha -Task results may persist longer than the original request execution time. For sensitive operations, requestors should carefully consider the security implications of extended result retention and may want to retrieve results promptly and request shorter `keepAlive` durations. Requestors are encouraged to use `tasks/cancel` with the `delete` parameter set to `true` to explicitly clean up tasks containing sensitive data rather than relying solely on `keepAlive` expiration. +Task results may persist for the duration specified by the TTL. For sensitive operations, requestors should carefully consider the security implications of extended task retention and may want to retrieve results promptly and request shorter `ttl` durations. Requestors are encouraged to use `tasks/cancel` with the `delete` parameter set to `true` to explicitly clean up tasks containing sensitive data rather than relying solely on `ttl` expiration. 1. Receivers **SHOULD**: 1. Enforce limits on concurrent tasks per requestor - 1. Enforce maximum `keepAlive` durations to prevent indefinite resource retention + 1. Enforce maximum `ttl` durations to prevent indefinite resource retention 1. Clean up expired tasks promptly to free resources 1. Receivers **SHOULD**: - 1. Document maximum supported `keepAlive` duration + 1. Document maximum supported `ttl` duration 1. Document maximum concurrent tasks per requestor 1. Implement monitoring and alerting for resource usage diff --git a/docs/specification/draft/schema.mdx b/docs/specification/draft/schema.mdx index a6099b9ca..232f1e3ce 100644 --- a/docs/specification/draft/schema.mdx +++ b/docs/specification/draft/schema.mdx @@ -531,12 +531,12 @@ Include this in the _meta field under the key modelconte ### `Task` -
interface Task {
  error?: string;
  keepAlive: null | number;
  pollInterval?: number;
  status: TaskStatus;
  statusMessage?: string;
  taskId: string;
}

Data associated with a task.

error?: string

Error message if status is "failed".

keepAlive: null | number

Actual retention duration in milliseconds, null for unlimited.

pollInterval?: number

Suggested polling interval in milliseconds.

status: TaskStatus

Current task state.

statusMessage?: string

Current task state message, optional.

taskId: string

The task identifier.

+
interface Task {
  createdAt: string;
  error?: string;
  pollInterval?: number;
  status: TaskStatus;
  statusMessage?: string;
  taskId: string;
  ttl: null | number;
}

Data associated with a task.

createdAt: string

ISO 8601 timestamp when the task was created.

error?: string

Error message if status is "failed".

pollInterval?: number

Suggested polling interval in milliseconds.

status: TaskStatus

Current task state.

statusMessage?: string

Current task state message, optional.

taskId: string

The task identifier.

ttl: null | number

Actual retention duration from creation in milliseconds, null for unlimited.

### `TaskMetadata` -
interface TaskMetadata {
  keepAlive?: number;
}

Metadata for augmenting a request with task execution. -Include this in the _meta field of a request under the key modelcontextprotocol.io/task.

keepAlive?: number

Requested duration in milliseconds to retain results after completion.

+
interface TaskMetadata {
  ttl?: number;
}

Metadata for augmenting a request with task execution. +Include this in the _meta field of a request under the key modelcontextprotocol.io/task.

ttl?: number

Requested duration in milliseconds to retain task from creation.

### `TaskStatus` @@ -548,7 +548,7 @@ Include this in the _meta field of a request under the key interface CancelTaskRequest {
  id: RequestId;
  jsonrpc: "2.0";
  method: "tasks/cancel";
  params: { delete?: boolean; taskId: string };
}

A request to cancel a task and optionally delete its associated results.

params: { delete?: boolean; taskId: string }
Type declaration
  • Optionaldelete?: boolean

    Whether to delete the task and its results after cancellation. If true, the task and all associated results and metadata will be deleted. -If false or omitted, the task will be retained according to its keepAlive duration.

  • taskId: string

    The task identifier to cancel.

+If false or omitted, the task will be retained according to its ttl duration.

  • taskId: string

    The task identifier to cancel.

  • ### `CancelTaskResult` @@ -578,7 +578,7 @@ If present, there may be more results available.

    interface TaskInfo {
      error?: string;
      keepAlive: null | number;
      pollInterval?: number;
      status: TaskStatus;
      taskId: string;
    }

    A summary of a task's state, as returned by tasks/list.

    error?: string

    Error message if status is "failed".

    keepAlive: null | number

    Retention duration in milliseconds, null for unlimited.

    pollInterval?: number

    Suggested polling interval in milliseconds.

    status: TaskStatus

    Current task state.

    taskId: string

    The task identifier.

    +
    interface TaskInfo {
      createdAt: string;
      error?: string;
      pollInterval?: number;
      status: TaskStatus;
      taskId: string;
      ttl: null | number;
    }

    A summary of a task's state, as returned by tasks/list.

    createdAt: string

    ISO 8601 timestamp when the task was created.

    error?: string

    Error message if status is "failed".

    pollInterval?: number

    Suggested polling interval in milliseconds.

    status: TaskStatus

    Current task state.

    taskId: string

    The task identifier.

    ttl: null | number

    Retention duration from creation in milliseconds, null for unlimited.

    ## `tasks/result` diff --git a/schema/draft/schema.json b/schema/draft/schema.json index f77360564..b98dc090a 100644 --- a/schema/draft/schema.json +++ b/schema/draft/schema.json @@ -225,7 +225,7 @@ "params": { "properties": { "delete": { - "description": "Whether to delete the task and its results after cancellation.\nIf true, the task and all associated results and metadata will be deleted.\nIf false or omitted, the task will be retained according to its keepAlive duration.", + "description": "Whether to delete the task and its results after cancellation.\nIf true, the task and all associated results and metadata will be deleted.\nIf false or omitted, the task will be retained according to its ttl duration.", "type": "boolean" }, "taskId": { @@ -3076,14 +3076,14 @@ "Task": { "description": "Data associated with a task.", "properties": { + "createdAt": { + "description": "ISO 8601 timestamp when the task was created.", + "type": "string" + }, "error": { "description": "Error message if status is \"failed\".", "type": "string" }, - "keepAlive": { - "description": "Actual retention duration in milliseconds, null for unlimited.", - "type": "integer" - }, "pollInterval": { "description": "Suggested polling interval in milliseconds.", "type": "integer" @@ -3099,12 +3099,17 @@ "taskId": { "description": "The task identifier.", "type": "string" + }, + "ttl": { + "description": "Actual retention duration from creation in milliseconds, null for unlimited.", + "type": "integer" } }, "required": [ - "keepAlive", + "createdAt", "status", - "taskId" + "taskId", + "ttl" ], "type": "object" }, @@ -3144,14 +3149,14 @@ "TaskInfo": { "description": "A summary of a task's state, as returned by tasks/list.", "properties": { + "createdAt": { + "description": "ISO 8601 timestamp when the task was created.", + "type": "string" + }, "error": { "description": "Error message if status is \"failed\".", "type": "string" }, - "keepAlive": { - "description": "Retention duration in milliseconds, null for unlimited.", - "type": "integer" - }, "pollInterval": { "description": "Suggested polling interval in milliseconds.", "type": "integer" @@ -3163,20 +3168,25 @@ "taskId": { "description": "The task identifier.", "type": "string" + }, + "ttl": { + "description": "Retention duration from creation in milliseconds, null for unlimited.", + "type": "integer" } }, "required": [ - "keepAlive", + "createdAt", "status", - "taskId" + "taskId", + "ttl" ], "type": "object" }, "TaskMetadata": { "description": "Metadata for augmenting a request with task execution.\nInclude this in the `_meta` field of a request under the key `modelcontextprotocol.io/task`.", "properties": { - "keepAlive": { - "description": "Requested duration in milliseconds to retain results after completion.", + "ttl": { + "description": "Requested duration in milliseconds to retain task from creation.", "type": "integer" } }, diff --git a/schema/draft/schema.ts b/schema/draft/schema.ts index 8ac2b4a0d..40fe217b6 100644 --- a/schema/draft/schema.ts +++ b/schema/draft/schema.ts @@ -1183,9 +1183,9 @@ export type TaskStatus = */ export interface TaskMetadata { /** - * Requested duration in milliseconds to retain results after completion. + * Requested duration in milliseconds to retain task from creation. */ - keepAlive?: number; + ttl?: number; } /** @@ -1223,9 +1223,14 @@ export interface Task { statusMessage?: string; /** - * Actual retention duration in milliseconds, null for unlimited. + * ISO 8601 timestamp when the task was created. */ - keepAlive: number | null; + createdAt: string; + + /** + * Actual retention duration from creation in milliseconds, null for unlimited. + */ + ttl: number | null; /** * Suggested polling interval in milliseconds. @@ -1308,7 +1313,7 @@ export interface CancelTaskRequest extends JSONRPCRequest { /** * Whether to delete the task and its results after cancellation. * If true, the task and all associated results and metadata will be deleted. - * If false or omitted, the task will be retained according to its keepAlive duration. + * If false or omitted, the task will be retained according to its ttl duration. */ delete?: boolean; }; @@ -1361,9 +1366,14 @@ export interface TaskInfo { status: TaskStatus; /** - * Retention duration in milliseconds, null for unlimited. + * ISO 8601 timestamp when the task was created. + */ + createdAt: string; + + /** + * Retention duration from creation in milliseconds, null for unlimited. */ - keepAlive: number | null; + ttl: number | null; /** * Suggested polling interval in milliseconds. From b9e04adf519f8a38b3ebfdf4b088cdd703260259 Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Tue, 11 Nov 2025 13:39:16 -0800 Subject: [PATCH 35/79] Make CancelTaskResult include full task; loosen deletion reqs --- .../draft/basic/utilities/tasks.mdx | 89 +++---------------- docs/specification/draft/schema.mdx | 7 +- schema/draft/schema.json | 40 +++------ schema/draft/schema.ts | 24 +---- 4 files changed, 25 insertions(+), 135 deletions(-) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index 61bcb3093..053ff3268 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -320,9 +320,9 @@ To retrieve a list of tasks, requestors send a `tasks/list` request. This operat ### Cancelling Tasks -To explicitly cancel a task, requestors send a `tasks/cancel` request. The request can optionally include a `delete` parameter to immediately delete the task and its results after cancellation. +To explicitly cancel a task, requestors send a `tasks/cancel` request. -**Request (basic cancellation):** +**Request:** ```json { @@ -342,41 +342,12 @@ To explicitly cancel a task, requestors send a `tasks/cancel` request. The reque "jsonrpc": "2.0", "id": 6, "result": { - "status": "cancelled", - "executionStopped": true, - "_meta": { - "modelcontextprotocol.io/related-task": { - "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" - } - } - } -} -``` - -**Request (cancellation with deletion):** - -```json -{ - "jsonrpc": "2.0", - "id": 7, - "method": "tasks/cancel", - "params": { "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", - "delete": true - } -} -``` - -**Response:** - -```json -{ - "jsonrpc": "2.0", - "id": 7, - "result": { "status": "cancelled", - "executionStopped": true, - "deleted": true, + "statusMessage": "The task was cancelled by request.", + "createdAt": "2025-11-25T10:30:00Z", + "ttl": 30000, + "pollInterval": 5000, "_meta": { "modelcontextprotocol.io/related-task": { "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" @@ -475,9 +446,8 @@ Task-augmented requests support progress notifications as defined in the progres 1. Receivers **MUST** reject cancellation requests for tasks already in a terminal status (`completed`, `failed`, or `cancelled`) with error code `-32602` (Invalid params). 1. Upon receiving a valid cancellation request, receivers **SHOULD** attempt to stop the task's execution (best effort) and **MUST** transition the task to `cancelled` status before sending the response. 1. Once a task is cancelled, it **MUST** remain in `cancelled` status even if execution continues to completion or fails. -1. If the `delete` parameter is `true`, receivers **SHOULD** delete the task and all associated results and metadata after transitioning to `cancelled` status. Receivers **MAY** choose not to support deletion and ignore this parameter. -1. If the `delete` parameter is `false` or omitted, receivers **MUST** retain the task in `cancelled` status subject to the `ttl` duration. -1. Requestors **SHOULD** use the `delete` parameter to clean up tasks containing sensitive data promptly rather than relying solely on `ttl` expiration. +1. The `tasks/cancel` operation does not define deletion behavior. However, receivers **MAY** delete cancelled tasks at their discretion at any time, including immediately after cancellation or after the task's `ttl` expires. +1. Requestors **SHOULD NOT** rely on cancelled tasks being retained for any specific duration and should retrieve any needed information before cancelling. ## Message Flow @@ -635,44 +605,11 @@ sequenceDiagram Note over S: Server stops execution (best effort) Note over S: Task moves to cancelled status - S->>C: Result (status: cancelled, executionStopped: true) + S->>C: Task (status: cancelled) Note over C: Client receives confirmation - Note over S: After ttl period from creation, task cleaned up -``` - -### Task Cancellation with Deletion Flow - -```mermaid -sequenceDiagram - participant C as Client (Requestor) - participant S as Server (Receiver) - - Note over C,S: 1. Task Creation and Completion - C->>S: tools/call (task-123) - S->>C: CreateTaskResult (task-123, status: working) - S--)C: notifications/tasks/created - Note over S: Task processing... - C->>S: tasks/get (task-123) - S->>C: completed - - Note over C,S: 2. Result Retrieval - C->>S: tasks/result (task-123) - S->>C: Result content - - Note over C,S: 3. Cancellation with Deletion - Note over C: Client decides to clean up task - C->>S: tasks/cancel (task-123, delete: true) - - Note over S: Task moves to cancelled status - Note over S: Task and results immediately deleted - - S->>C: Result (status: cancelled, deleted: true) - - Note over C,S: 4. Verification (optional) - C->>S: tasks/get (task-123) - S->>C: Error: Task not found + Note over S: Server may delete task at its discretion ``` ## Data Types @@ -852,12 +789,6 @@ The `tasks/result` endpoint returns exactly what the underlying request would ha ### Resource Management - - -Task results may persist for the duration specified by the TTL. For sensitive operations, requestors should carefully consider the security implications of extended task retention and may want to retrieve results promptly and request shorter `ttl` durations. Requestors are encouraged to use `tasks/cancel` with the `delete` parameter set to `true` to explicitly clean up tasks containing sensitive data rather than relying solely on `ttl` expiration. - - - 1. Receivers **SHOULD**: 1. Enforce limits on concurrent tasks per requestor 1. Enforce maximum `ttl` durations to prevent indefinite resource retention diff --git a/docs/specification/draft/schema.mdx b/docs/specification/draft/schema.mdx index 4e7e91f59..62af1be34 100644 --- a/docs/specification/draft/schema.mdx +++ b/docs/specification/draft/schema.mdx @@ -576,14 +576,11 @@ Include this in the _meta field of a request under the key interface CancelTaskRequest {
      id: RequestId;
      jsonrpc: "2.0";
      method: "tasks/cancel";
      params: { delete?: boolean; taskId: string };
    }

    A request to cancel a task and optionally delete its associated results.

    params: { delete?: boolean; taskId: string }
    Type declaration
    • Optionaldelete?: boolean

      Whether to delete the task and its results after cancellation. -If true, the task and all associated results and metadata will be deleted. -If false or omitted, the task will be retained according to its ttl duration.

    • taskId: string

      The task identifier to cancel.

    +
    interface CancelTaskRequest {
      id: RequestId;
      jsonrpc: "2.0";
      method: "tasks/cancel";
      params: { taskId: string };
    }

    A request to cancel a task.

    params: { taskId: string }
    Type declaration
    • taskId: string

      The task identifier to cancel.

    ### `CancelTaskResult` -
    interface CancelTaskResult {
      _meta?: { [key: string]: unknown };
      deleted?: boolean;
      executionStopped?: boolean;
      status: "cancelled";
      [key: string]: unknown;
    }

    The response to a tasks/cancel request.

    _meta?: { [key: string]: unknown }

    See General fields: _meta for notes on _meta usage.

    deleted?: boolean

    Whether the task and its results were deleted.

    executionStopped?: boolean

    Whether execution was successfully stopped. -If not provided, it is unknown whether execution was stopped.

    status: "cancelled"

    The status of the task after cancellation (always "cancelled").

    +
    CancelTaskResult: Result & Task

    The response to a tasks/cancel request.

    ## `tasks/get` diff --git a/schema/draft/schema.json b/schema/draft/schema.json index eb44378f8..541e55f4d 100644 --- a/schema/draft/schema.json +++ b/schema/draft/schema.json @@ -209,7 +209,7 @@ "type": "object" }, "CancelTaskRequest": { - "description": "A request to cancel a task and optionally delete its associated results.", + "description": "A request to cancel a task.", "properties": { "id": { "$ref": "#/definitions/RequestId" @@ -224,10 +224,6 @@ }, "params": { "properties": { - "delete": { - "description": "Whether to delete the task and its results after cancellation.\nIf true, the task and all associated results and metadata will be deleted.\nIf false or omitted, the task will be retained according to its ttl duration.", - "type": "boolean" - }, "taskId": { "description": "The task identifier to cancel.", "type": "string" @@ -248,31 +244,15 @@ "type": "object" }, "CancelTaskResult": { - "description": "The response to a tasks/cancel request.", - "properties": { - "_meta": { - "additionalProperties": {}, - "description": "See [General fields: `_meta`](/specification/draft/basic/index#meta) for notes on `_meta` usage.", - "type": "object" - }, - "deleted": { - "description": "Whether the task and its results were deleted.", - "type": "boolean" - }, - "executionStopped": { - "description": "Whether execution was successfully stopped.\nIf not provided, it is unknown whether execution was stopped.", - "type": "boolean" + "allOf": [ + { + "$ref": "#/definitions/Result" }, - "status": { - "const": "cancelled", - "description": "The status of the task after cancellation (always \"cancelled\").", - "type": "string" + { + "$ref": "#/definitions/Task" } - }, - "required": [ - "status" ], - "type": "object" + "description": "The response to a tasks/cancel request." }, "CancelledNotification": { "description": "This notification can be sent by either side to indicate that it is cancelling a previously-issued request.\n\nThe request SHOULD still be in-flight, but due to communication latency, it is always possible that this notification MAY arrive after the request has already finished.\n\nThis notification indicates that the result will be unused, so any associated processing SHOULD cease.\n\nA client MUST NOT attempt to cancel its `initialize` request.\n\nFor task cancellation, use the `tasks/cancel` request instead of this notification.", @@ -494,7 +474,8 @@ "$ref": "#/definitions/GetTaskPayloadResult" }, { - "$ref": "#/definitions/CancelTaskResult" + "$ref": "#/definitions/CancelTaskResult", + "description": "The response to a tasks/cancel request." }, { "$ref": "#/definitions/ListTasksResult" @@ -2979,7 +2960,8 @@ "$ref": "#/definitions/GetTaskPayloadResult" }, { - "$ref": "#/definitions/CancelTaskResult" + "$ref": "#/definitions/CancelTaskResult", + "description": "The response to a tasks/cancel request." }, { "$ref": "#/definitions/ListTasksResult" diff --git a/schema/draft/schema.ts b/schema/draft/schema.ts index c442bb9f7..e2125b321 100644 --- a/schema/draft/schema.ts +++ b/schema/draft/schema.ts @@ -1299,7 +1299,7 @@ export interface GetTaskPayloadResult extends Result { } /** - * A request to cancel a task and optionally delete its associated results. + * A request to cancel a task. * * @category tasks/cancel */ @@ -1310,12 +1310,6 @@ export interface CancelTaskRequest extends JSONRPCRequest { * The task identifier to cancel. */ taskId: string; - /** - * Whether to delete the task and its results after cancellation. - * If true, the task and all associated results and metadata will be deleted. - * If false or omitted, the task will be retained according to its ttl duration. - */ - delete?: boolean; }; } @@ -1324,21 +1318,7 @@ export interface CancelTaskRequest extends JSONRPCRequest { * * @category tasks/cancel */ -export interface CancelTaskResult extends Result { - /** - * The status of the task after cancellation (always "cancelled"). - */ - status: "cancelled"; - /** - * Whether execution was successfully stopped. - * If not provided, it is unknown whether execution was stopped. - */ - executionStopped?: boolean; - /** - * Whether the task and its results were deleted. - */ - deleted?: boolean; -} +export type CancelTaskResult = Result & Task; /** * A request to retrieve a list of tasks. From 6bcfab5512e316e3b0474cb79ef264c89c5f16f2 Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Tue, 11 Nov 2025 14:03:52 -0800 Subject: [PATCH 36/79] Rewrite access control section to explain session-binding --- .../draft/basic/utilities/tasks.mdx | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index 053ff3268..da2874753 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -775,17 +775,15 @@ The `tasks/result` endpoint returns exactly what the underlying request would ha ### Task Isolation and Access Control -1. Receivers **SHOULD** scope task IDs to prevent unauthorized access: - 1. Bind tasks to the session that created them (if sessions are supported) - 1. Bind tasks to the authentication context (if authentication is used) - 1. Reject `tasks/get`, `tasks/list`, `tasks/result`, or `tasks/cancel` requests for tasks from different sessions or auth contexts -1. Receivers that do not implement session or authentication binding **SHOULD** document this limitation clearly, as task results may be accessible to any requestor that can guess the task ID. -1. Receivers **SHOULD** implement rate limiting on: - 1. Task creation to prevent resource exhaustion - 1. Task status polling to prevent denial of service - 1. Task result retrieval attempts - 1. Task listing requests to prevent denial of service - 1. Task cancellation requests to prevent abuse +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. To prevent unauthorized access, receivers **SHOULD** bind tasks to the session or authentication context that created them. + +However, context-binding is not practical for all applications. Some MCP servers operate in environments without session management (such as single-user tools), or use transports that don't support sessions or authentication. +In these cases, receivers **SHOULD** document this limitation clearly, as task results may be accessible to any requestor that can guess the task ID. +When context-binding is not available, receivers **SHOULD** use cryptographically random task IDs with sufficient entropy to make guessing infeasible, and consider implementing shorter TTL durations to limit exposure windows. + +If context-binding is supported, for `tasks/get`, `tasks/result`, and `tasks/cancel` requests, receivers **MUST** reject requests for tasks from different sessions or authentication contexts. For `tasks/list` requests, receivers **MUST** filter the returned task list to only include tasks belonging to the requestor's session or authentication context. + +Additionally, receivers **SHOULD** implement rate limiting on task operations to prevent denial-of-service and enumeration attacks. ### Resource Management From 29fffbc87d18ba976bc89742acc9f42af56d0c66 Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Tue, 11 Nov 2025 14:26:37 -0800 Subject: [PATCH 37/79] Make notifications include full task info --- .../draft/basic/utilities/tasks.mdx | 50 ++++++++++------- docs/specification/draft/schema.mdx | 10 +++- schema/draft/schema.json | 56 +++++++------------ schema/draft/schema.ts | 37 +++--------- 4 files changed, 66 insertions(+), 87 deletions(-) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index da2874753..5b0eea34e 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -220,7 +220,7 @@ To retrieve the result of a completed task, requestors send a `tasks/result` req ### Task Creation Notification -When a receiver creates a task, it **MUST** send a `notifications/tasks/created` notification to inform the requestor that the task has been created and polling can begin. +When a receiver creates a task, it **MAY** send a `notifications/tasks/created` notification to inform the requestor that the task has been created and polling can begin. This notification includes the full task state. **Notification:** @@ -229,6 +229,12 @@ When a receiver creates a task, it **MUST** send a `notifications/tasks/created` "jsonrpc": "2.0", "method": "notifications/tasks/created", "params": { + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", + "status": "working", + "statusMessage": "The operation is now in progress.", + "createdAt": "2025-11-25T10:30:00Z", + "ttl": 60000, + "pollInterval": 5000, "_meta": { "modelcontextprotocol.io/related-task": { "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" @@ -238,15 +244,13 @@ When a receiver creates a task, it **MUST** send a `notifications/tasks/created` } ``` -The task ID is conveyed through the `modelcontextprotocol.io/related-task` metadata key. The notification parameters are otherwise empty. +The notification includes the full `Task` object with all task metadata fields, allowing requestors to immediately access the task state without making an additional `tasks/get` request. -This notification resolves the race condition where a requestor might attempt to poll for a task before the receiver has finished creating it. By sending this notification immediately after task creation, the receiver signals that the task is ready to be queried via `tasks/get`. - -Receivers that do not support tasks (and thus ignore task metadata in requests) will not send this notification, allowing requestors to fall back to waiting for the original request response. +Requestors **MUST NOT** rely on receiving this notification. Requestors **SHOULD** be prepared to begin polling via `tasks/get` immediately after receiving the `CreateTaskResult` response, regardless of whether this notification is received. ### Task Status Notification -When a task's status changes, receivers **MAY** send a `notifications/tasks/status` notification to inform the requestor of the change. +When a task's status changes, receivers **MAY** send a `notifications/tasks/status` notification to inform the requestor of the change. This notification includes the full task state. **Notification:** @@ -255,7 +259,11 @@ When a task's status changes, receivers **MAY** send a `notifications/tasks/stat "jsonrpc": "2.0", "method": "notifications/tasks/status", "params": { + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", "status": "completed", + "createdAt": "2025-11-25T10:30:00Z", + "ttl": 60000, + "pollInterval": 5000, "_meta": { "modelcontextprotocol.io/related-task": { "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" @@ -265,12 +273,7 @@ When a task's status changes, receivers **MAY** send a `notifications/tasks/stat } ``` -The notification includes: - -- `status`: The new task status -- `error` (optional): Error message if the status is `failed` - -The task ID is conveyed through the `modelcontextprotocol.io/related-task` metadata key. +The notification includes the full `Task` object with all task metadata fields, including the updated `status`, `statusMessage` (if present), and `error` (if the status is `failed`). This allows requestors to access the complete task state without making an additional `tasks/get` request. Requestors **MUST NOT** rely on receiving these notifications, as they are 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. @@ -430,6 +433,13 @@ stateDiagram-v2 1. 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. 1. For the `tasks/get`, `tasks/list`, `tasks/result`, and `tasks/cancel` operations, the `taskId` parameter in the request **MUST** be used as the source of truth for identifying the target task. Requestors **SHOULD NOT** include `modelcontextprotocol.io/related-task` metadata in these requests, and receivers **MUST** ignore such metadata if present in favor of the RPC method parameter. +### Task Notifications + +1. Receivers **MAY** send a `notifications/tasks/created` notification after creating a task to inform the requestor that the task is ready for polling. +1. Receivers **MAY** send `notifications/tasks/status` notifications when a task's status changes. +1. Requestors **MUST NOT** rely on receiving either notification type, as they are both optional. +1. When sent, these notifications **MUST** include the `modelcontextprotocol.io/related-task` metadata as described in "Associating Task-Related Messages". + ### Task Progress Notifications Task-augmented requests support progress notifications as defined in the progress notification specification. The `progressToken` provided in the initial request remains valid throughout the task's lifetime. @@ -458,9 +468,9 @@ sequenceDiagram participant C as Client (Requestor) participant S as Server (Receiver) Note over C,S: 1. Task Creation - C->>S: Request with task metadata (taskId, ttl) + C->>S: Request with task metadata (ttl) S->>C: CreateTaskResult (taskId, status: working, ttl, pollInterval) - S--)C: notifications/tasks/created + S--)C: notifications/tasks/created (full Task) Note over C,S: 2. Task Polling C->>S: tasks/get (taskId) S->>C: working @@ -490,9 +500,9 @@ sequenceDiagram LLM->>C: Request operation Note over C,S: Client augments with task metadata - C->>S: tools/call (task-123, ttl: 3600000) + C->>S: tools/call (ttl: 3600000) S->>C: CreateTaskResult (task-123, status: working) - S--)C: notifications/tasks/created + S--)C: notifications/tasks/created (task-123, full Task) Note over LLM,C: Client continues processing other requests
    while task executes in background LLM->>C: Request other operation @@ -547,9 +557,9 @@ sequenceDiagram Note over S: Server decides to initiate request Note over S,C: Server requests client operation (task-augmented) - S->>C: sampling/createMessage (request-789, ttl: 3600000) + S->>C: sampling/createMessage (ttl: 3600000) C->>S: CreateTaskResult (request-789, status: working) - C--)S: notifications/tasks/created + C--)S: notifications/tasks/created (request-789, full Task) Note over S: Server continues processing
    while waiting for result @@ -590,9 +600,9 @@ sequenceDiagram participant S as Server (Receiver) Note over C,S: 1. Task Creation - C->>S: tools/call (request ID: 42, task-123) + C->>S: tools/call (request ID: 42, ttl: 60000) S->>C: CreateTaskResult (task-123, status: working) - S--)C: notifications/tasks/created + S--)C: notifications/tasks/created (task-123, full Task) Note over C,S: 2. Task Processing C->>S: tasks/get (task-123) diff --git a/docs/specification/draft/schema.mdx b/docs/specification/draft/schema.mdx index 62af1be34..169bf7235 100644 --- a/docs/specification/draft/schema.mdx +++ b/docs/specification/draft/schema.mdx @@ -413,17 +413,21 @@ The server should then request an updated list of roots using the ListRootsReque ### `TaskCreatedNotification` -
    interface TaskCreatedNotification {
      jsonrpc: "2.0";
      method: "notifications/tasks/created";
      params?: {
        _meta?: {
          "modelcontextprotocol.io/related-task"?: RelatedTaskMetadata;
          [key: string]: unknown;
        };
      };
    }

    A notification from the receiver to the requestor, informing them that a task has been created and is ready for polling.

    params?: {
      _meta?: {
        "modelcontextprotocol.io/related-task"?: RelatedTaskMetadata;
        [key: string]: unknown;
      };
    }
    Type declaration
    +
    interface TaskCreatedNotification {
      jsonrpc: "2.0";
      method: "notifications/tasks/created";
      params: TaskCreatedNotificationParams;
    }

    A notification from the receiver to the requestor, informing them that a task has been created and is ready for polling.

    + +### `TaskCreatedNotificationParams` + +
    TaskCreatedNotificationParams: NotificationParams & Task

    Parameters for a notifications/tasks/created notification.

    ## `notifications/tasks/status` ### `TaskStatusNotification` -
    interface TaskStatusNotification {
      jsonrpc: "2.0";
      method: "notifications/tasks/status";
      params: TaskStatusNotificationParams;
    }

    An optional notification from the receiver to the requestor, informing them that a task's status has changed. Receivers are not required to send these notifications.

    +
    interface TaskStatusNotification {
      jsonrpc: "2.0";
      method: "notifications/tasks/status";
      params: TaskStatusNotificationParams;
    }

    An optional notification from the receiver to the requestor, informing them that a task's status has changed. Receivers are not required to send these notifications.

    ### `TaskStatusNotificationParams` -
    interface TaskStatusNotificationParams {
      _meta?: {
        "modelcontextprotocol.io/related-task"?: RelatedTaskMetadata;
        [key: string]: unknown;
      };
      error?: string;
      status: TaskStatus;
    }

    Parameters for a notifications/tasks/status notification.

    _meta?: {
      "modelcontextprotocol.io/related-task"?: RelatedTaskMetadata;
      [key: string]: unknown;
    }

    The _meta field MUST include modelcontextprotocol.io/related-task with the taskId.

    error?: string

    Error message if status is "failed".

    status: TaskStatus

    The new task status.

    +
    TaskStatusNotificationParams: NotificationParams & Task

    Parameters for a notifications/tasks/status notification.

    ## `notifications/tools/list_changed` diff --git a/schema/draft/schema.json b/schema/draft/schema.json index 541e55f4d..6945db0c9 100644 --- a/schema/draft/schema.json +++ b/schema/draft/schema.json @@ -3170,27 +3170,27 @@ "type": "string" }, "params": { - "properties": { - "_meta": { - "additionalProperties": {}, - "description": "The _meta field MUST include modelcontextprotocol.io/related-task with the taskId.", - "properties": { - "modelcontextprotocol.io/related-task": { - "$ref": "#/definitions/RelatedTaskMetadata" - } - }, - "type": "object" - } - }, - "type": "object" + "$ref": "#/definitions/TaskCreatedNotificationParams" } }, "required": [ "jsonrpc", - "method" + "method", + "params" ], "type": "object" }, + "TaskCreatedNotificationParams": { + "allOf": [ + { + "$ref": "#/definitions/NotificationParams" + }, + { + "$ref": "#/definitions/Task" + } + ], + "description": "Parameters for a `notifications/tasks/created` notification." + }, "TaskInfo": { "description": "A summary of a task's state, as returned by tasks/list.", "properties": { @@ -3271,31 +3271,15 @@ "type": "object" }, "TaskStatusNotificationParams": { - "description": "Parameters for a `notifications/tasks/status` notification.", - "properties": { - "_meta": { - "additionalProperties": {}, - "description": "The _meta field MUST include modelcontextprotocol.io/related-task with the taskId.", - "properties": { - "modelcontextprotocol.io/related-task": { - "$ref": "#/definitions/RelatedTaskMetadata" - } - }, - "type": "object" - }, - "error": { - "description": "Error message if status is \"failed\".", - "type": "string" + "allOf": [ + { + "$ref": "#/definitions/NotificationParams" }, - "status": { - "$ref": "#/definitions/TaskStatus", - "description": "The new task status." + { + "$ref": "#/definitions/Task" } - }, - "required": [ - "status" ], - "type": "object" + "description": "Parameters for a `notifications/tasks/status` notification." }, "TextContent": { "description": "Text provided to or from an LLM.", diff --git a/schema/draft/schema.ts b/schema/draft/schema.ts index e2125b321..ee6db98dc 100644 --- a/schema/draft/schema.ts +++ b/schema/draft/schema.ts @@ -1375,6 +1375,13 @@ export interface ListTasksResult extends PaginatedResult { tasks: TaskInfo[]; } +/** + * Parameters for a `notifications/tasks/created` notification. + * + * @category notifications/tasks/created + */ +export type TaskCreatedNotificationParams = NotificationParams & Task; + /** * A notification from the receiver to the requestor, informing them that a task has been created and is ready for polling. * @@ -1382,15 +1389,7 @@ export interface ListTasksResult extends PaginatedResult { */ export interface TaskCreatedNotification extends JSONRPCNotification { method: "notifications/tasks/created"; - params?: { - /** - * The _meta field MUST include modelcontextprotocol.io/related-task with the taskId. - */ - _meta?: { - "modelcontextprotocol.io/related-task"?: RelatedTaskMetadata; - [key: string]: unknown; - }; - }; + params: TaskCreatedNotificationParams; } /** @@ -1398,25 +1397,7 @@ export interface TaskCreatedNotification extends JSONRPCNotification { * * @category notifications/tasks/status */ -export interface TaskStatusNotificationParams extends NotificationParams { - /** - * The new task status. - */ - status: TaskStatus; - - /** - * Error message if status is "failed". - */ - error?: string; - - /** - * The _meta field MUST include modelcontextprotocol.io/related-task with the taskId. - */ - _meta?: { - "modelcontextprotocol.io/related-task"?: RelatedTaskMetadata; - [key: string]: unknown; - }; -} +export type TaskStatusNotificationParams = NotificationParams & Task; /** * An optional notification from the receiver to the requestor, informing them that a task's status has changed. Receivers are not required to send these notifications. From bc12768640025e380ca81a827508620a7fb20db6 Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Tue, 11 Nov 2025 14:59:05 -0800 Subject: [PATCH 38/79] Add experimental notice --- docs/specification/draft/basic/utilities/tasks.mdx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index 5b0eea34e..6b41096f9 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -6,6 +6,13 @@ title: Tasks **Protocol Revision**: draft + + +Tasks are newly-introduced in this version of the MCP specification and are currently considered **experimental**. +The design of tasks may evolve in future protocol versions. + + + The Model Context Protcol (MCP) allows requestors (which can be either clients or servers, depending on the direction of communication) to augment their requests with **tasks**. Tasks are durable state machines that carry information about the underlying execution state of the request they wrap, and are intended for requestor polling and deferred result retrieval. Each task is uniquely identifiable by a receiver-generated **task ID**. ## User Interaction Model From b25069f900def0992c743902336225ac5bf0961a Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Tue, 11 Nov 2025 15:02:33 -0800 Subject: [PATCH 39/79] Link to task spec from progress --- docs/specification/draft/basic/utilities/progress.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/specification/draft/basic/utilities/progress.mdx b/docs/specification/draft/basic/utilities/progress.mdx index 95a4c561d..5e46558f7 100644 --- a/docs/specification/draft/basic/utilities/progress.mdx +++ b/docs/specification/draft/basic/utilities/progress.mdx @@ -68,7 +68,7 @@ The receiver **MAY** then send progress notifications containing: - Send notifications at whatever frequency they deem appropriate - Omit the total value if unknown -3. For task-augmented requests, the `progressToken` provided in the original request **MUST** continue to be used for progress notifications throughout the task's lifetime, even after the `CreateTaskResult` has been returned. The progress token remains valid and associated with the task until the task reaches a terminal status. +3. For [task-augmented requests](./tasks), the `progressToken` provided in the original request **MUST** continue to be used for progress notifications throughout the task's lifetime, even after the `CreateTaskResult` has been returned. The progress token remains valid and associated with the task until the task reaches a terminal status. - Progress notifications for tasks **MUST** use the same `progressToken` that was provided in the initial task-augmented request - Progress notifications for tasks **MUST** stop after the task reaches a terminal status (`completed`, `failed`, or `cancelled`) From ca166f36b13a7feb0ae220595358ccc2d06e1a51 Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Tue, 11 Nov 2025 15:04:52 -0800 Subject: [PATCH 40/79] Update task capabilities in lifecycle spec example --- docs/specification/draft/basic/lifecycle.mdx | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/docs/specification/draft/basic/lifecycle.mdx b/docs/specification/draft/basic/lifecycle.mdx index 7f41f268a..d6f7dbde2 100644 --- a/docs/specification/draft/basic/lifecycle.mdx +++ b/docs/specification/draft/basic/lifecycle.mdx @@ -76,9 +76,11 @@ The client **MUST** initiate this phase by sending an `initialize` request conta "list": true }, "tasks": { - "get": true, - "list": true, - "result": true + "requests": { + "elicitation": { + "create": {} + } + } } } }, @@ -133,9 +135,13 @@ The server **MUST** respond with its own capabilities and information: "list": true }, "tasks": { - "get": true, - "list": true, - "result": true + "list": {}, + "cancel": {}, + "requests": { + "tools": { + "call": {} + } + } } } }, From fb7d06328ffcb22c3d2e6fcdbd01a8a6c17bfbe2 Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Tue, 11 Nov 2025 15:18:37 -0800 Subject: [PATCH 41/79] Update changelog to include tasks --- docs/specification/draft/changelog.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/specification/draft/changelog.mdx b/docs/specification/draft/changelog.mdx index 827d98446..f22e40e56 100644 --- a/docs/specification/draft/changelog.mdx +++ b/docs/specification/draft/changelog.mdx @@ -14,6 +14,7 @@ the previous revision, [2025-06-18](/specification/2025-06-18). 3. Enhance authorization flows with incremental scope consent via `WWW-Authenticate` ([SEP-835](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/835)) 4. Provide guidance on tool names ([SEP-986](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/1603)) 5. Update `ElicitResult` and `EnumSchema` to use a more standards-based approach and support titled, untitled, single-select, and multi-select enums ([SEP-1330](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1330)). +6. Add experimental support for [tasks](/specification/draft/basic/utilities/tasks) to enable tracking durable requests with polling and deferred result retrieval ([SEP-1686](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1686)). ## Minor changes From 5cafa6dca2e0da186ff24624c4b3fca48f1555c3 Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Tue, 11 Nov 2025 15:25:05 -0800 Subject: [PATCH 42/79] Link to Progress spec from Tasks spec --- docs/specification/draft/basic/utilities/tasks.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index 6b41096f9..ca59f8cb1 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -449,7 +449,7 @@ stateDiagram-v2 ### Task Progress Notifications -Task-augmented requests support progress notifications as defined in the progress notification specification. The `progressToken` provided in the initial request remains valid throughout the task's lifetime. +Task-augmented requests support progress notifications as defined in the [progress](./progress) specification. The `progressToken` provided in the initial request remains valid throughout the task's lifetime. ### Task Listing From 4dbb5c7c7df01b72828e0e468ce0d41eb2ed9574 Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Tue, 11 Nov 2025 15:40:22 -0800 Subject: [PATCH 43/79] Add note about SSE stream management --- docs/specification/draft/basic/utilities/tasks.mdx | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index ca59f8cb1..c418d9dc4 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -414,6 +414,17 @@ stateDiagram-v2 ### Input Required Status + + +In the Streamable HTTP (SSE) transport, it is common for servers to close SSE streams upon sending a response message, rendering the stream that task messages will be sent on ambiguous. + +Implementations have flexibility in how they manage SSE streams during task polling and result retrieval. +Possible approaches include using short-lived streams for each `tasks/get` request or maintaining a longer-lived stream on `tasks/result` (see notes on the `input_required` status), among others. + +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](../transports#sending-messages-to-the-server). + + + 1. 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_required` status. 1. The receiver **MUST** include the `modelcontextprotocol.io/related-task` metadata in the request to associate it with the task. 1. When the requestor encounters the `input_required` status, it **SHOULD** call `tasks/result` prematurely. From 7da2b7f2984606e4b3e00363e8f27147108491d7 Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Tue, 11 Nov 2025 16:11:10 -0800 Subject: [PATCH 44/79] Add note on metadata for immediate model responses --- docs/specification/draft/basic/utilities/tasks.mdx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index c418d9dc4..745d8c34a 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -144,6 +144,16 @@ To create a task, requestors send a request with the `modelcontextprotocol.io/ta When a receiver accepts a task-augmented request, it returns a `CreateTaskResult` containing task metadata. This 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, receivers can provide an optional `modelcontextprotocol.io/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. + +This is a provisional field intended to account for this use case, which may be formalized as part of `CreateTaskResult` in future protocol versions. + + + ### Getting Tasks To retrieve the state of a task, requestors send a `tasks/get` request: From 66b98720aede8e59ef36e925b385076575bb9df4 Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Tue, 11 Nov 2025 16:16:46 -0800 Subject: [PATCH 45/79] Switch to reverse-DNS metadata prefixes --- .../draft/basic/utilities/tasks.mdx | 34 +++++++++---------- docs/specification/draft/schema.mdx | 4 +-- schema/draft/schema.json | 4 +-- schema/draft/schema.ts | 4 +-- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index 745d8c34a..ce6a3f8fe 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -97,7 +97,7 @@ Task-augmented requests follow a two-phase response pattern that differs from no - **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 `CreateTaskResult` containing task metadata. The actual operation result becomes available later through `tasks/result` after the task completes. -To create a task, requestors send a request with the `modelcontextprotocol.io/task` key included in `_meta`. Requestors **MAY** include a `ttl` value representing how long from task creation the requestor would like the task to be retained for. +To create a task, requestors send a request with the `io.modelcontextprotocol/task` key included in `_meta`. Requestors **MAY** include a `ttl` value representing how long from task creation the requestor would like the task to be retained for. **Request:** @@ -112,7 +112,7 @@ To create a task, requestors send a request with the `modelcontextprotocol.io/ta "city": "New York" }, "_meta": { - "modelcontextprotocol.io/task": { + "io.modelcontextprotocol/task": { "ttl": 60000 } } @@ -134,7 +134,7 @@ To create a task, requestors send a request with the `modelcontextprotocol.io/ta "ttl": 60000, "pollInterval": 5000, "_meta": { - "modelcontextprotocol.io/related-task": { + "io.modelcontextprotocol/related-task": { "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" } } @@ -148,7 +148,7 @@ When a receiver accepts a task-augmented request, it returns a `CreateTaskResult 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, receivers can provide an optional `modelcontextprotocol.io/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. +To support this pattern, receivers 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. This is a provisional field intended to account for this use case, which may be formalized as part of `CreateTaskResult` in future protocol versions. @@ -185,7 +185,7 @@ To retrieve the state of a task, requestors send a `tasks/get` request: "ttl": 30000, "pollInterval": 5000, "_meta": { - "modelcontextprotocol.io/related-task": { + "io.modelcontextprotocol/related-task": { "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" } } @@ -227,7 +227,7 @@ To retrieve the result of a completed task, requestors send a `tasks/result` req ], "isError": false, "_meta": { - "modelcontextprotocol.io/related-task": { + "io.modelcontextprotocol/related-task": { "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" } } @@ -253,7 +253,7 @@ When a receiver creates a task, it **MAY** send a `notifications/tasks/created` "ttl": 60000, "pollInterval": 5000, "_meta": { - "modelcontextprotocol.io/related-task": { + "io.modelcontextprotocol/related-task": { "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" } } @@ -282,7 +282,7 @@ When a task's status changes, receivers **MAY** send a `notifications/tasks/stat "ttl": 60000, "pollInterval": 5000, "_meta": { - "modelcontextprotocol.io/related-task": { + "io.modelcontextprotocol/related-task": { "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" } } @@ -369,7 +369,7 @@ To explicitly cancel a task, requestors send a `tasks/cancel` request. "ttl": 30000, "pollInterval": 5000, "_meta": { - "modelcontextprotocol.io/related-task": { + "io.modelcontextprotocol/related-task": { "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" } } @@ -436,7 +436,7 @@ While this note is not prescriptive regarding the specific usage of SSE streams, 1. 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_required` status. -1. The receiver **MUST** include the `modelcontextprotocol.io/related-task` metadata in the request to associate it with the task. +1. The receiver **MUST** include the `io.modelcontextprotocol/related-task` metadata in the request to associate it with the task. 1. When the requestor encounters the `input_required` status, it **SHOULD** call `tasks/result` prematurely. 1. When the receiver receives all required input, the task **SHOULD** transition out of `input_required` status (typically back to `working`). @@ -457,16 +457,16 @@ While this note is not prescriptive regarding the specific usage of SSE streams, ### Associating Task-Related Messages -1. All requests, notifications, and responses related to a task **MUST** include the `modelcontextprotocol.io/related-task` key in their `_meta`, with the value set to an object with a `taskId` matching the associated task ID. +1. All requests, notifications, and responses related to a task **MUST** include the `io.modelcontextprotocol/related-task` key in their `_meta`, with the value set to an object with a `taskId` matching the associated task ID. 1. 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. -1. For the `tasks/get`, `tasks/list`, `tasks/result`, and `tasks/cancel` operations, the `taskId` parameter in the request **MUST** be used as the source of truth for identifying the target task. Requestors **SHOULD NOT** include `modelcontextprotocol.io/related-task` metadata in these requests, and receivers **MUST** ignore such metadata if present in favor of the RPC method parameter. +1. For the `tasks/get`, `tasks/list`, `tasks/result`, and `tasks/cancel` operations, the `taskId` parameter in the request **MUST** be used as the source of truth for identifying the target task. Requestors **SHOULD NOT** include `io.modelcontextprotocol/related-task` metadata in these requests, and receivers **MUST** ignore such metadata if present in favor of the RPC method parameter. ### Task Notifications 1. Receivers **MAY** send a `notifications/tasks/created` notification after creating a task to inform the requestor that the task is ready for polling. 1. Receivers **MAY** send `notifications/tasks/status` notifications when a task's status changes. 1. Requestors **MUST NOT** rely on receiving either notification type, as they are both optional. -1. When sent, these notifications **MUST** include the `modelcontextprotocol.io/related-task` metadata as described in "Associating Task-Related Messages". +1. When sent, these notifications **MUST** include the `io.modelcontextprotocol/related-task` metadata as described in "Associating Task-Related Messages". ### Task Progress Notifications @@ -674,11 +674,11 @@ Tasks can be in one of the following states: ### Task Metadata -When augmenting a request with task execution, the `modelcontextprotocol.io/task` key is included in `_meta`: +When augmenting a request with task execution, the `io.modelcontextprotocol/task` key is included in `_meta`: ```json { - "modelcontextprotocol.io/task": { + "io.modelcontextprotocol/task": { "ttl": 60000 } } @@ -690,11 +690,11 @@ Fields: ### Related Task Metadata -All requests, responses, and notifications associated with a task **MUST** include the `modelcontextprotocol.io/related-task` key in `_meta`: +All requests, responses, and notifications associated with a task **MUST** include the `io.modelcontextprotocol/related-task` key in `_meta`: ```json { - "modelcontextprotocol.io/related-task": { + "io.modelcontextprotocol/related-task": { "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" } } diff --git a/docs/specification/draft/schema.mdx b/docs/specification/draft/schema.mdx index 169bf7235..07c694245 100644 --- a/docs/specification/draft/schema.mdx +++ b/docs/specification/draft/schema.mdx @@ -561,7 +561,7 @@ or file that the server can operate on.

    interface RelatedTaskMetadata {
      taskId: string;
    }

    Metadata for associating messages with a task. -Include this in the _meta field under the key modelcontextprotocol.io/related-task.

    taskId: string

    The task identifier this message is associated with.

    +Include this in the _meta field under the key io.modelcontextprotocol/related-task.

    taskId: string

    The task identifier this message is associated with.

    ### `Task` @@ -570,7 +570,7 @@ Include this in the _meta field under the key modelconte ### `TaskMetadata`
    interface TaskMetadata {
      ttl?: number;
    }

    Metadata for augmenting a request with task execution. -Include this in the _meta field of a request under the key modelcontextprotocol.io/task.

    ttl?: number

    Requested duration in milliseconds to retain task from creation.

    +Include this in the _meta field of a request under the key io.modelcontextprotocol/task.

    ttl?: number

    Requested duration in milliseconds to retain task from creation.

    ### `TaskStatus` diff --git a/schema/draft/schema.json b/schema/draft/schema.json index 6945db0c9..a013f267d 100644 --- a/schema/draft/schema.json +++ b/schema/draft/schema.json @@ -2344,7 +2344,7 @@ "type": "object" }, "RelatedTaskMetadata": { - "description": "Metadata for associating messages with a task.\nInclude this in the `_meta` field under the key `modelcontextprotocol.io/related-task`.", + "description": "Metadata for associating messages with a task.\nInclude this in the `_meta` field under the key `io.modelcontextprotocol/related-task`.", "properties": { "taskId": { "description": "The task identifier this message is associated with.", @@ -3228,7 +3228,7 @@ "type": "object" }, "TaskMetadata": { - "description": "Metadata for augmenting a request with task execution.\nInclude this in the `_meta` field of a request under the key `modelcontextprotocol.io/task`.", + "description": "Metadata for augmenting a request with task execution.\nInclude this in the `_meta` field of a request under the key `io.modelcontextprotocol/task`.", "properties": { "ttl": { "description": "Requested duration in milliseconds to retain task from creation.", diff --git a/schema/draft/schema.ts b/schema/draft/schema.ts index ee6db98dc..6c40a5ea1 100644 --- a/schema/draft/schema.ts +++ b/schema/draft/schema.ts @@ -1177,7 +1177,7 @@ export type TaskStatus = /** * Metadata for augmenting a request with task execution. - * Include this in the `_meta` field of a request under the key `modelcontextprotocol.io/task`. + * Include this in the `_meta` field of a request under the key `io.modelcontextprotocol/task`. * * @category tasks */ @@ -1190,7 +1190,7 @@ export interface TaskMetadata { /** * Metadata for associating messages with a task. - * Include this in the `_meta` field under the key `modelcontextprotocol.io/related-task`. + * Include this in the `_meta` field under the key `io.modelcontextprotocol/related-task`. * * @category tasks */ From a4f8c070efae84f205280aecf4c52466f8b97275 Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Tue, 11 Nov 2025 16:19:52 -0800 Subject: [PATCH 46/79] Revise immediate result note to clarify non-binding nature --- docs/specification/draft/basic/utilities/tasks.mdx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index ce6a3f8fe..963b383a0 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -148,9 +148,10 @@ When a receiver accepts a task-augmented request, it returns a `CreateTaskResult 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, receivers 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. +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 is a provisional field intended to account for this use case, which may be formalized as part of `CreateTaskResult` in future protocol versions. +This guidance is non-binding, and is provisional logic intended to account for this use case. This may be formalized as part of `CreateTaskResult` in future protocol versions. From 60620cdebd7566ffac3ba834eca50a9141a18a26 Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Tue, 11 Nov 2025 16:32:12 -0800 Subject: [PATCH 47/79] Fix minor issues - Consolidated TaskInfo and Task types for tasks/list - Fixed a type --- .../draft/basic/utilities/tasks.mdx | 2 +- docs/specification/draft/schema.mdx | 6 +-- schema/draft/schema.json | 38 +----------------- schema/draft/schema.ts | 39 +------------------ 4 files changed, 4 insertions(+), 81 deletions(-) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index 963b383a0..e23f3615b 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -13,7 +13,7 @@ The design of tasks may evolve in future protocol versions. -The Model Context Protcol (MCP) allows requestors (which can be either clients or servers, depending on the direction of communication) to augment their requests with **tasks**. Tasks are durable state machines that carry information about the underlying execution state of the request they wrap, and are intended for requestor polling and deferred result retrieval. Each task is uniquely identifiable by a receiver-generated **task ID**. +The Model Context Protocol (MCP) allows requestors (which can be either clients or servers, depending on the direction of communication) to augment their requests with **tasks**. Tasks are durable state machines that carry information about the underlying execution state of the request they wrap, and are intended for requestor polling and deferred result retrieval. Each task is uniquely identifiable by a receiver-generated **task ID**. ## User Interaction Model diff --git a/docs/specification/draft/schema.mdx b/docs/specification/draft/schema.mdx index 07c694245..9bc0b0b8d 100644 --- a/docs/specification/draft/schema.mdx +++ b/docs/specification/draft/schema.mdx @@ -604,13 +604,9 @@ Include this in the _meta field of a request under the key interface ListTasksResult {
      _meta?: { [key: string]: unknown };
      nextCursor?: string;
      tasks: TaskInfo[];
      [key: string]: unknown;
    }

    The response to a tasks/list request.

    _meta?: { [key: string]: unknown }

    See General fields: _meta for notes on _meta usage.

    nextCursor?: string

    An opaque token representing the pagination position after the last returned result. +

    interface ListTasksResult {
      _meta?: { [key: string]: unknown };
      nextCursor?: string;
      tasks: Task[];
      [key: string]: unknown;
    }

    The response to a tasks/list request.

    _meta?: { [key: string]: unknown }

    See General fields: _meta for notes on _meta usage.

    nextCursor?: string

    An opaque token representing the pagination position after the last returned result. If present, there may be more results available.

    -### `TaskInfo` - -
    interface TaskInfo {
      createdAt: string;
      error?: string;
      pollInterval?: number;
      status: TaskStatus;
      taskId: string;
      ttl: null | number;
    }

    A summary of a task's state, as returned by tasks/list.

    createdAt: string

    ISO 8601 timestamp when the task was created.

    error?: string

    Error message if status is "failed".

    pollInterval?: number

    Suggested polling interval in milliseconds.

    status: TaskStatus

    Current task state.

    taskId: string

    The task identifier.

    ttl: null | number

    Retention duration from creation in milliseconds, null for unlimited.

    - ## `tasks/result` ### `GetTaskPayloadRequest` diff --git a/schema/draft/schema.json b/schema/draft/schema.json index a013f267d..0a27ec8d4 100644 --- a/schema/draft/schema.json +++ b/schema/draft/schema.json @@ -1742,7 +1742,7 @@ }, "tasks": { "items": { - "$ref": "#/definitions/TaskInfo" + "$ref": "#/definitions/Task" }, "type": "array" } @@ -3191,42 +3191,6 @@ ], "description": "Parameters for a `notifications/tasks/created` notification." }, - "TaskInfo": { - "description": "A summary of a task's state, as returned by tasks/list.", - "properties": { - "createdAt": { - "description": "ISO 8601 timestamp when the task was created.", - "type": "string" - }, - "error": { - "description": "Error message if status is \"failed\".", - "type": "string" - }, - "pollInterval": { - "description": "Suggested polling interval in milliseconds.", - "type": "integer" - }, - "status": { - "$ref": "#/definitions/TaskStatus", - "description": "Current task state." - }, - "taskId": { - "description": "The task identifier.", - "type": "string" - }, - "ttl": { - "description": "Retention duration from creation in milliseconds, null for unlimited.", - "type": "integer" - } - }, - "required": [ - "createdAt", - "status", - "taskId", - "ttl" - ], - "type": "object" - }, "TaskMetadata": { "description": "Metadata for augmenting a request with task execution.\nInclude this in the `_meta` field of a request under the key `io.modelcontextprotocol/task`.", "properties": { diff --git a/schema/draft/schema.ts b/schema/draft/schema.ts index 6c40a5ea1..b8af33e7b 100644 --- a/schema/draft/schema.ts +++ b/schema/draft/schema.ts @@ -1329,50 +1329,13 @@ export interface ListTasksRequest extends PaginatedRequest { method: "tasks/list"; } -/** - * A summary of a task's state, as returned by tasks/list. - * - * @category tasks/list - */ -export interface TaskInfo { - /** - * The task identifier. - */ - taskId: string; - - /** - * Current task state. - */ - status: TaskStatus; - - /** - * ISO 8601 timestamp when the task was created. - */ - createdAt: string; - - /** - * Retention duration from creation in milliseconds, null for unlimited. - */ - ttl: number | null; - - /** - * Suggested polling interval in milliseconds. - */ - pollInterval?: number; - - /** - * Error message if status is "failed". - */ - error?: string; -} - /** * The response to a tasks/list request. * * @category tasks/list */ export interface ListTasksResult extends PaginatedResult { - tasks: TaskInfo[]; + tasks: Task[]; } /** From e3dce0d144e63cfbabac328a59c86dd5bddeb9fc Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Tue, 11 Nov 2025 16:41:48 -0800 Subject: [PATCH 48/79] Clarify distinction between statusMessage and error fields --- docs/specification/draft/basic/utilities/tasks.mdx | 7 +++++++ docs/specification/draft/schema.mdx | 6 +++++- schema/draft/schema.json | 4 ++-- schema/draft/schema.ts | 8 ++++++-- 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index e23f3615b..cfecc1590 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -659,9 +659,11 @@ A task represents the execution state of a request. The task metadata includes: - `taskId`: Unique identifier for the task - `status`: Current state of the task execution +- `statusMessage`: Optional human-readable message describing the current state (can be present for any status) - `createdAt`: ISO 8601 timestamp when the task was created - `ttl`: Time in milliseconds from creation before task may be deleted - `pollInterval`: Suggested time in milliseconds between status checks +- `error`: Error details when status is `failed` (should only be present for failed tasks) ### Task Status @@ -787,6 +789,11 @@ Receivers are not obligated to retain task metadata indefinitely. It is complian When the underlying request does not complete successfully, the task moves to the `failed` 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 an `error` field with details about the failure. +The `error` field is distinct from `statusMessage`: + +- `error`: Provides diagnostic information about what went wrong (only present when `status` is `failed`) +- `statusMessage`: Provides optional human-readable context for any task status (e.g., cancellation reasons, completion summaries) + **Example: Task with execution error** ```json diff --git a/docs/specification/draft/schema.mdx b/docs/specification/draft/schema.mdx index 9bc0b0b8d..991f3b3a7 100644 --- a/docs/specification/draft/schema.mdx +++ b/docs/specification/draft/schema.mdx @@ -565,7 +565,11 @@ Include this in the _meta field under the key io.modelco ### `Task` -
    interface Task {
      createdAt: string;
      error?: string;
      pollInterval?: number;
      status: TaskStatus;
      statusMessage?: string;
      taskId: string;
      ttl: null | number;
    }

    Data associated with a task.

    createdAt: string

    ISO 8601 timestamp when the task was created.

    error?: string

    Error message if status is "failed".

    pollInterval?: number

    Suggested polling interval in milliseconds.

    status: TaskStatus

    Current task state.

    statusMessage?: string

    Current task state message, optional.

    taskId: string

    The task identifier.

    ttl: null | number

    Actual retention duration from creation in milliseconds, null for unlimited.

    +
    interface Task {
      createdAt: string;
      error?: string;
      pollInterval?: number;
      status: TaskStatus;
      statusMessage?: string;
      taskId: string;
      ttl: null | number;
    }

    Data associated with a task.

    createdAt: string

    ISO 8601 timestamp when the task was created.

    error?: string

    Error details when status is "failed". +This field provides diagnostic information about what went wrong and should only +be present when the task has failed. Use statusMessage for general state descriptions.

    pollInterval?: number

    Suggested polling interval in milliseconds.

    status: TaskStatus

    Current task state.

    statusMessage?: string

    Optional human-readable message describing the current task state. +This can provide context for any status (e.g., reasons for "cancelled", +summaries for "completed", etc.).

    taskId: string

    The task identifier.

    ttl: null | number

    Actual retention duration from creation in milliseconds, null for unlimited.

    ### `TaskMetadata` diff --git a/schema/draft/schema.json b/schema/draft/schema.json index 0a27ec8d4..5821ae285 100644 --- a/schema/draft/schema.json +++ b/schema/draft/schema.json @@ -3126,7 +3126,7 @@ "type": "string" }, "error": { - "description": "Error message if status is \"failed\".", + "description": "Error details when status is \"failed\".\nThis field provides diagnostic information about what went wrong and should only\nbe present when the task has failed. Use statusMessage for general state descriptions.", "type": "string" }, "pollInterval": { @@ -3138,7 +3138,7 @@ "description": "Current task state." }, "statusMessage": { - "description": "Current task state message, optional.", + "description": "Optional human-readable message describing the current task state.\nThis can provide context for any status (e.g., reasons for \"cancelled\",\nsummaries for \"completed\", etc.).", "type": "string" }, "taskId": { diff --git a/schema/draft/schema.ts b/schema/draft/schema.ts index b8af33e7b..3e2fa5ae1 100644 --- a/schema/draft/schema.ts +++ b/schema/draft/schema.ts @@ -1218,7 +1218,9 @@ export interface Task { status: TaskStatus; /** - * Current task state message, optional. + * Optional human-readable message describing the current task state. + * This can provide context for any status (e.g., reasons for "cancelled", + * summaries for "completed", etc.). */ statusMessage?: string; @@ -1238,7 +1240,9 @@ export interface Task { pollInterval?: number; /** - * Error message if status is "failed". + * Error details when status is "failed". + * This field provides diagnostic information about what went wrong and should only + * be present when the task has failed. Use statusMessage for general state descriptions. */ error?: string; } From 11bc88716612514d8ef876ca67fe28728ca89857 Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Tue, 11 Nov 2025 16:45:42 -0800 Subject: [PATCH 49/79] Fix task capabilities in lifecycle docs again --- docs/specification/draft/basic/lifecycle.mdx | 44 +++++--------------- 1 file changed, 11 insertions(+), 33 deletions(-) diff --git a/docs/specification/draft/basic/lifecycle.mdx b/docs/specification/draft/basic/lifecycle.mdx index d6f7dbde2..a5a69ecb9 100644 --- a/docs/specification/draft/basic/lifecycle.mdx +++ b/docs/specification/draft/basic/lifecycle.mdx @@ -66,20 +66,12 @@ The client **MUST** initiate this phase by sending an `initialize` request conta "sampling": {}, "elicitation": {}, "tasks": { - "sampling": { - "createMessage": true - }, - "elicitation": { - "create": true - }, - "roots": { - "list": true - }, - "tasks": { - "requests": { - "elicitation": { - "create": {} - } + "requests": { + "elicitation": { + "create": {} + }, + "sampling": { + "createMessage": {} } } } @@ -122,25 +114,11 @@ The server **MUST** respond with its own capabilities and information: "listChanged": true }, "tasks": { - "tools": { - "call": true, - "list": true - }, - "resources": { - "read": true, - "list": true - }, - "prompts": { - "get": true, - "list": true - }, - "tasks": { - "list": {}, - "cancel": {}, - "requests": { - "tools": { - "call": {} - } + "list": {}, + "cancel": {}, + "requests": { + "tools": { + "call": {} } } } From 68c0d63c3b7274931f7b405a02c70a4d27cbecde Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Tue, 11 Nov 2025 17:00:38 -0800 Subject: [PATCH 50/79] Adjust cancellation spec to link to tasks spec for task cancellation --- .../specification/draft/basic/utilities/cancellation.mdx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/specification/draft/basic/utilities/cancellation.mdx b/docs/specification/draft/basic/utilities/cancellation.mdx index 1669b418c..1860bc5a3 100644 --- a/docs/specification/draft/basic/utilities/cancellation.mdx +++ b/docs/specification/draft/basic/utilities/cancellation.mdx @@ -34,16 +34,17 @@ notification containing: 1. Cancellation notifications **MUST** only reference requests that: - Were previously issued in the same direction - Are believed to still be in-progress -2. The `initialize` request **MUST NOT** be cancelled by clients -3. Receivers of cancellation notifications **SHOULD**: +1. The `initialize` request **MUST NOT** be cancelled by clients +1. For [task-augmented requests](./tasks), the `tasks/cancel` request **MUST** be used instead of the `notifications/cancelled` notification. Tasks have their own dedicated cancellation mechanism that returns the final task state. +1. Receivers of cancellation notifications **SHOULD**: - Stop processing the cancelled request - Free associated resources - Not send a response for the cancelled request -4. Receivers **MAY** ignore cancellation notifications if: +1. Receivers **MAY** ignore cancellation notifications if: - The referenced request is unknown - Processing has already completed - The request cannot be cancelled -5. The sender of the cancellation notification **SHOULD** ignore any response to the +1. The sender of the cancellation notification **SHOULD** ignore any response to the request that arrives afterward ## Timing Considerations From 544c376578ff4711880529a9ea98b29ad8881c53 Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Wed, 12 Nov 2025 13:20:45 -0800 Subject: [PATCH 51/79] Remove related-task from responses that include the task ID already --- .../draft/basic/utilities/tasks.mdx | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index cfecc1590..15b496f7e 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -184,12 +184,7 @@ To retrieve the state of a task, requestors send a `tasks/get` request: "statusMessage": "The operation is now in progress.", "createdAt": "2025-11-25T10:30:00Z", "ttl": 30000, - "pollInterval": 5000, - "_meta": { - "io.modelcontextprotocol/related-task": { - "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" - } - } + "pollInterval": 5000 } } ``` @@ -368,12 +363,7 @@ To explicitly cancel a task, requestors send a `tasks/cancel` request. "statusMessage": "The task was cancelled by request.", "createdAt": "2025-11-25T10:30:00Z", "ttl": 30000, - "pollInterval": 5000, - "_meta": { - "io.modelcontextprotocol/related-task": { - "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" - } - } + "pollInterval": 5000 } } ``` @@ -461,6 +451,7 @@ While this note is not prescriptive regarding the specific usage of SSE streams, 1. All requests, notifications, and responses related to a task **MUST** include the `io.modelcontextprotocol/related-task` key in their `_meta`, with the value set to an object with a `taskId` matching the associated task ID. 1. 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. 1. For the `tasks/get`, `tasks/list`, `tasks/result`, and `tasks/cancel` operations, the `taskId` parameter in the request **MUST** be used as the source of truth for identifying the target task. Requestors **SHOULD NOT** include `io.modelcontextprotocol/related-task` metadata in these requests, and receivers **MUST** ignore such metadata if present in favor of the RPC method parameter. + Similarly, for the `tasks/get`, `tasks/list`, and `tasks/cancel` operations, receivers **SHOULD NOT** include `io.modelcontextprotocol/related-task` metadata in the result messages, as the `taskId` is already present in the response structure. ### Task Notifications @@ -705,6 +696,9 @@ All requests, responses, and notifications associated with a task **MUST** inclu This associates messages with their originating task across the entire request lifecycle. +However, for the `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: From 3c7e9e42a4384d28d3b8eb8001337edc2982fea9 Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Wed, 12 Nov 2025 13:35:10 -0800 Subject: [PATCH 52/79] Remove notifications/tasks/created Redundant with CreateTaskResult. --- .../draft/basic/utilities/tasks.mdx | 48 ++----------------- docs/specification/draft/schema.mdx | 11 ----- schema/draft/schema.json | 39 --------------- schema/draft/schema.mdx | 4 -- schema/draft/schema.ts | 19 -------- 5 files changed, 4 insertions(+), 117 deletions(-) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index 15b496f7e..974f3508a 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -231,36 +231,6 @@ To retrieve the result of a completed task, requestors send a `tasks/result` req } ``` -### Task Creation Notification - -When a receiver creates a task, it **MAY** send a `notifications/tasks/created` notification to inform the requestor that the task has been created and polling can begin. This notification includes the full task state. - -**Notification:** - -```json -{ - "jsonrpc": "2.0", - "method": "notifications/tasks/created", - "params": { - "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", - "status": "working", - "statusMessage": "The operation is now in progress.", - "createdAt": "2025-11-25T10:30:00Z", - "ttl": 60000, - "pollInterval": 5000, - "_meta": { - "io.modelcontextprotocol/related-task": { - "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" - } - } - } -} -``` - -The notification includes the full `Task` object with all task metadata fields, allowing requestors to immediately access the task state without making an additional `tasks/get` request. - -Requestors **MUST NOT** rely on receiving this notification. Requestors **SHOULD** be prepared to begin polling via `tasks/get` immediately after receiving the `CreateTaskResult` response, regardless of whether this notification is received. - ### Task Status Notification When a task's status changes, receivers **MAY** send a `notifications/tasks/status` notification to inform the requestor of the change. This notification includes the full task state. @@ -276,19 +246,14 @@ When a task's status changes, receivers **MAY** send a `notifications/tasks/stat "status": "completed", "createdAt": "2025-11-25T10:30:00Z", "ttl": 60000, - "pollInterval": 5000, - "_meta": { - "io.modelcontextprotocol/related-task": { - "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" - } - } + "pollInterval": 5000 } } ``` The notification includes the full `Task` object with all task metadata fields, including the updated `status`, `statusMessage` (if present), and `error` (if the status is `failed`). This allows requestors to access the complete task state without making an additional `tasks/get` request. -Requestors **MUST NOT** rely on receiving these notifications, as they are 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. +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 @@ -455,10 +420,9 @@ While this note is not prescriptive regarding the specific usage of SSE streams, ### Task Notifications -1. Receivers **MAY** send a `notifications/tasks/created` notification after creating a task to inform the requestor that the task is ready for polling. 1. Receivers **MAY** send `notifications/tasks/status` notifications when a task's status changes. -1. Requestors **MUST NOT** rely on receiving either notification type, as they are both optional. -1. When sent, these notifications **MUST** include the `io.modelcontextprotocol/related-task` metadata as described in "Associating Task-Related Messages". +1. Requestors **MUST NOT** rely on receiving the `notifications/tasks/status` notification, as it is optional. +1. When sent, the `notifications/tasks/status` notification **SHOULD NOT** include the `io.modelcontextprotocol/related-task` metadata, as the task ID is already present in the notification parameters. ### Task Progress Notifications @@ -490,7 +454,6 @@ sequenceDiagram Note over C,S: 1. Task Creation C->>S: Request with task metadata (ttl) S->>C: CreateTaskResult (taskId, status: working, ttl, pollInterval) - S--)C: notifications/tasks/created (full Task) Note over C,S: 2. Task Polling C->>S: tasks/get (taskId) S->>C: working @@ -522,7 +485,6 @@ sequenceDiagram Note over C,S: Client augments with task metadata C->>S: tools/call (ttl: 3600000) S->>C: CreateTaskResult (task-123, status: working) - S--)C: notifications/tasks/created (task-123, full Task) Note over LLM,C: Client continues processing other requests
    while task executes in background LLM->>C: Request other operation @@ -579,7 +541,6 @@ sequenceDiagram Note over S,C: Server requests client operation (task-augmented) S->>C: sampling/createMessage (ttl: 3600000) C->>S: CreateTaskResult (request-789, status: working) - C--)S: notifications/tasks/created (request-789, full Task) Note over S: Server continues processing
    while waiting for result @@ -622,7 +583,6 @@ sequenceDiagram Note over C,S: 1. Task Creation C->>S: tools/call (request ID: 42, ttl: 60000) S->>C: CreateTaskResult (task-123, status: working) - S--)C: notifications/tasks/created (task-123, full Task) Note over C,S: 2. Task Processing C->>S: tasks/get (task-123) diff --git a/docs/specification/draft/schema.mdx b/docs/specification/draft/schema.mdx index 1687f9bcc..f29eb457b 100644 --- a/docs/specification/draft/schema.mdx +++ b/docs/specification/draft/schema.mdx @@ -273,17 +273,6 @@ This MUST NOT be used for cancelling tasks (use the tasks/cancel re
    interface InitializedNotification {
      jsonrpc: "2.0";
      method: "notifications/initialized";
      params?: NotificationParams;
    }

    This notification is sent from the client to the server after initialization has finished.

    -## `notifications/tasks/created` - -### `TaskCreatedNotification` - -
    interface TaskCreatedNotification {
      jsonrpc: "2.0";
      method: "notifications/tasks/created";
      params: TaskCreatedNotificationParams;
    }

    A notification from the receiver to the requestor, informing them that a task has been created and is ready for polling.

    - -### `TaskCreatedNotificationParams` - -
    TaskCreatedNotificationParams: NotificationParams & Task

    Parameters for a notifications/tasks/created notification.

    - - ## `notifications/tasks/status` ### `TaskStatusNotification` diff --git a/schema/draft/schema.json b/schema/draft/schema.json index e59508ac1..654e2e808 100644 --- a/schema/draft/schema.json +++ b/schema/draft/schema.json @@ -395,9 +395,6 @@ { "$ref": "#/definitions/ProgressNotification" }, - { - "$ref": "#/definitions/TaskCreatedNotification" - }, { "$ref": "#/definitions/TaskStatusNotification" }, @@ -2884,9 +2881,6 @@ { "$ref": "#/definitions/ToolListChangedNotification" }, - { - "$ref": "#/definitions/TaskCreatedNotification" - }, { "$ref": "#/definitions/TaskStatusNotification" }, @@ -3158,39 +3152,6 @@ ], "type": "object" }, - "TaskCreatedNotification": { - "description": "A notification from the receiver to the requestor, informing them that a task has been created and is ready for polling.", - "properties": { - "jsonrpc": { - "const": "2.0", - "type": "string" - }, - "method": { - "const": "notifications/tasks/created", - "type": "string" - }, - "params": { - "$ref": "#/definitions/TaskCreatedNotificationParams" - } - }, - "required": [ - "jsonrpc", - "method", - "params" - ], - "type": "object" - }, - "TaskCreatedNotificationParams": { - "allOf": [ - { - "$ref": "#/definitions/NotificationParams" - }, - { - "$ref": "#/definitions/Task" - } - ], - "description": "Parameters for a `notifications/tasks/created` notification." - }, "TaskMetadata": { "description": "Metadata for augmenting a request with task execution.\nInclude this in the `_meta` field of a request under the key `io.modelcontextprotocol/task`.", "properties": { diff --git a/schema/draft/schema.mdx b/schema/draft/schema.mdx index 10b8bb38a..95d21634e 100644 --- a/schema/draft/schema.mdx +++ b/schema/draft/schema.mdx @@ -40,10 +40,6 @@ title: Schema Reference {/* @category `notifications/initialized` */} -## `notifications/tasks/created` - -{/* @category `notifications/tasks/created` */} - ## `notifications/tasks/status` {/* @category `notifications/tasks/status` */} diff --git a/schema/draft/schema.ts b/schema/draft/schema.ts index 3d3f230a8..d69b653b8 100644 --- a/schema/draft/schema.ts +++ b/schema/draft/schema.ts @@ -1399,23 +1399,6 @@ export interface ListTasksResult extends PaginatedResult { tasks: Task[]; } -/** - * Parameters for a `notifications/tasks/created` notification. - * - * @category `notifications/tasks/created` - */ -export type TaskCreatedNotificationParams = NotificationParams & Task; - -/** - * A notification from the receiver to the requestor, informing them that a task has been created and is ready for polling. - * - * @category `notifications/tasks/created` - */ -export interface TaskCreatedNotification extends JSONRPCNotification { - method: "notifications/tasks/created"; - params: TaskCreatedNotificationParams; -} - /** * Parameters for a `notifications/tasks/status` notification. * @@ -2268,7 +2251,6 @@ export type ClientNotification = | ProgressNotification | InitializedNotification | RootsListChangedNotification - | TaskCreatedNotification | TaskStatusNotification; /** @internal */ @@ -2303,7 +2285,6 @@ export type ServerNotification = | ResourceListChangedNotification | ToolListChangedNotification | PromptListChangedNotification - | TaskCreatedNotification | TaskStatusNotification; /** @internal */ From 07a3a3292c382fab4f7a2e971740100719504c4b Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Wed, 12 Nov 2025 13:52:50 -0800 Subject: [PATCH 53/79] Move task parameters to dedicated field --- .../draft/basic/utilities/tasks.mdx | 14 +++-- docs/specification/draft/schema.mdx | 54 ++++++++++++++----- schema/draft/schema.json | 54 ++++++++++++++++++- schema/draft/schema.ts | 12 ++++- 4 files changed, 112 insertions(+), 22 deletions(-) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index 974f3508a..66a62e430 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -97,7 +97,7 @@ Task-augmented requests follow a two-phase response pattern that differs from no - **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 `CreateTaskResult` containing task metadata. The actual operation result becomes available later through `tasks/result` after the task completes. -To create a task, requestors send a request with the `io.modelcontextprotocol/task` key included in `_meta`. Requestors **MAY** include a `ttl` value representing how long from task creation the requestor would like the task to be retained for. +To create a task, requestors send a request with the `task` field included in the request params. Requestors **MAY** include a `ttl` value representing how long from task creation the requestor would like the task to be retained for. **Request:** @@ -111,10 +111,8 @@ To create a task, requestors send a request with the `io.modelcontextprotocol/ta "arguments": { "city": "New York" }, - "_meta": { - "io.modelcontextprotocol/task": { - "ttl": 60000 - } + "task": { + "ttl": 60000 } } } @@ -626,13 +624,13 @@ Tasks can be in one of the following states: - `failed`: The associated request did not complete successfully. For tool calls specifically, this includes cases where the tool call result has `isError` set to true. - `cancelled`: The request was cancelled before completion -### Task Metadata +### Task Parameters -When augmenting a request with task execution, the `io.modelcontextprotocol/task` key is included in `_meta`: +When augmenting a request with task execution, the `task` field is included in the request parameters: ```json { - "io.modelcontextprotocol/task": { + "task": { "ttl": 60000 } } diff --git a/docs/specification/draft/schema.mdx b/docs/specification/draft/schema.mdx index f29eb457b..051d129d9 100644 --- a/docs/specification/draft/schema.mdx +++ b/docs/specification/draft/schema.mdx @@ -126,7 +126,10 @@ if present).

    interface TaskMetadata {
      ttl?: number;
    }

    Metadata for augmenting a request with task execution. -Include this in the _meta field of a request under the key io.modelcontextprotocol/task.

    ttl?: number

    Requested duration in milliseconds to retain task from creation.

    +Include this in the task field of the request parameters.

    ttl?: number

    Requested duration in milliseconds to retain task from creation.

    ### `TaskStatus` @@ -438,7 +450,10 @@ If present, there may be more results available.

    ### `CreateMessageRequestParams` -
    interface CreateMessageRequestParams {
      _meta?: { progressToken?: ProgressToken; [key: string]: unknown };
      includeContext?: "none" | "thisServer" | "allServers";
      maxTokens: number;
      messages: SamplingMessage[];
      metadata?: object;
      modelPreferences?: ModelPreferences;
      stopSequences?: string[];
      systemPrompt?: string;
      temperature?: number;
    }

    Parameters for a sampling/createMessage request.

    _meta?: { progressToken?: ProgressToken; [key: string]: unknown }

    See General fields: _meta for notes on _meta usage.

    Type Declaration
    • [key: string]: unknown
    • OptionalprogressToken?: ProgressToken

      If specified, the caller is requesting out-of-band progress notifications for this request (as represented by notifications/progress). The value of this parameter is an opaque token that will be attached to any subsequent notifications. The receiver is not obligated to provide these notifications.

    includeContext?: "none" | "thisServer" | "allServers"

    A request to include context from one or more MCP servers (including the caller), to be attached to the prompt. The client MAY ignore this request.

    maxTokens: number

    The requested maximum number of tokens to sample (to prevent runaway completions).

    The client MAY choose to sample fewer tokens than the requested maximum.

    metadata?: object

    Optional metadata to pass through to the LLM provider. The format of this metadata is provider-specific.

    modelPreferences?: ModelPreferences

    The server's preferences for which model to select. The client MAY ignore these preferences.

    systemPrompt?: string

    An optional system prompt the server wants to use for sampling. The client MAY modify or omit this prompt.

    +
    interface CreateMessageRequestParams {
      _meta?: { progressToken?: ProgressToken; [key: string]: unknown };
      includeContext?: "none" | "thisServer" | "allServers";
      maxTokens: number;
      messages: SamplingMessage[];
      metadata?: object;
      modelPreferences?: ModelPreferences;
      stopSequences?: string[];
      systemPrompt?: string;
      task?: TaskMetadata;
      temperature?: number;
    }

    Parameters for a sampling/createMessage request.

    _meta?: { progressToken?: ProgressToken; [key: string]: unknown }

    See General fields: _meta for notes on _meta usage.

    Type Declaration
    • [key: string]: unknown
    • OptionalprogressToken?: ProgressToken

      If specified, the caller is requesting out-of-band progress notifications for this request (as represented by notifications/progress). The value of this parameter is an opaque token that will be attached to any subsequent notifications. The receiver is not obligated to provide these notifications.

    includeContext?: "none" | "thisServer" | "allServers"

    A request to include context from one or more MCP servers (including the caller), to be attached to the prompt. The client MAY ignore this request.

    maxTokens: number

    The requested maximum number of tokens to sample (to prevent runaway completions).

    The client MAY choose to sample fewer tokens than the requested maximum.

    metadata?: object

    Optional metadata to pass through to the LLM provider. The format of this metadata is provider-specific.

    modelPreferences?: ModelPreferences

    The server's preferences for which model to select. The client MAY ignore these preferences.

    systemPrompt?: string

    An optional system prompt the server wants to use for sampling. The client MAY modify or omit this prompt.

    If specified, the caller is requesting task-augmented execution for this request. +The request will return a CreateTaskResult immediately, and the actual result can be +retrieved later via tasks/result.

    Task augmentation is subject to capability negotiation - receivers MUST declare support +for task augmentation of specific request types in their capabilities.

    ### `CreateMessageResult` @@ -626,7 +653,10 @@ the most important factor.

    ### `CallToolRequestParams` -
    interface CallToolRequestParams {
      _meta?: { progressToken?: ProgressToken; [key: string]: unknown };
      arguments?: { [key: string]: unknown };
      name: string;
    }

    Parameters for a tools/call request.

    _meta?: { progressToken?: ProgressToken; [key: string]: unknown }

    See General fields: _meta for notes on _meta usage.

    Type Declaration
    • [key: string]: unknown
    • OptionalprogressToken?: ProgressToken

      If specified, the caller is requesting out-of-band progress notifications for this request (as represented by notifications/progress). The value of this parameter is an opaque token that will be attached to any subsequent notifications. The receiver is not obligated to provide these notifications.

    arguments?: { [key: string]: unknown }

    Arguments to use for the tool call.

    name: string

    The name of the tool.

    +
    interface CallToolRequestParams {
      _meta?: { progressToken?: ProgressToken; [key: string]: unknown };
      arguments?: { [key: string]: unknown };
      name: string;
      task?: TaskMetadata;
    }

    Parameters for a tools/call request.

    _meta?: { progressToken?: ProgressToken; [key: string]: unknown }

    See General fields: _meta for notes on _meta usage.

    Type Declaration
    • [key: string]: unknown
    • OptionalprogressToken?: ProgressToken

      If specified, the caller is requesting out-of-band progress notifications for this request (as represented by notifications/progress). The value of this parameter is an opaque token that will be attached to any subsequent notifications. The receiver is not obligated to provide these notifications.

    arguments?: { [key: string]: unknown }

    Arguments to use for the tool call.

    name: string

    The name of the tool.

    If specified, the caller is requesting task-augmented execution for this request. +The request will return a CreateTaskResult immediately, and the actual result can be +retrieved later via tasks/result.

    Task augmentation is subject to capability negotiation - receivers MUST declare support +for task augmentation of specific request types in their capabilities.

    ### `CallToolResult` diff --git a/schema/draft/schema.json b/schema/draft/schema.json index 654e2e808..3e3eba5bd 100644 --- a/schema/draft/schema.json +++ b/schema/draft/schema.json @@ -171,6 +171,10 @@ "name": { "description": "The name of the tool.", "type": "string" + }, + "task": { + "$ref": "#/definitions/TaskMetadata", + "description": "If specified, the caller is requesting task-augmented execution for this request.\nThe request will return a CreateTaskResult immediately, and the actual result can be\nretrieved later via tasks/result.\n\nTask augmentation is subject to capability negotiation - receivers MUST declare support\nfor task augmentation of specific request types in their capabilities." } }, "required": [ @@ -568,6 +572,10 @@ "$ref": "#/definitions/ResourceTemplateReference" } ] + }, + "task": { + "$ref": "#/definitions/TaskMetadata", + "description": "If specified, the caller is requesting task-augmented execution for this request.\nThe request will return a CreateTaskResult immediately, and the actual result can be\nretrieved later via tasks/result.\n\nTask augmentation is subject to capability negotiation - receivers MUST declare support\nfor task augmentation of specific request types in their capabilities." } }, "required": [ @@ -711,6 +719,10 @@ "description": "An optional system prompt the server wants to use for sampling. The client MAY modify or omit this prompt.", "type": "string" }, + "task": { + "$ref": "#/definitions/TaskMetadata", + "description": "If specified, the caller is requesting task-augmented execution for this request.\nThe request will return a CreateTaskResult immediately, and the actual result can be\nretrieved later via tasks/result.\n\nTask augmentation is subject to capability negotiation - receivers MUST declare support\nfor task augmentation of specific request types in their capabilities." + }, "temperature": { "type": "number" } @@ -845,6 +857,10 @@ "type" ], "type": "object" + }, + "task": { + "$ref": "#/definitions/TaskMetadata", + "description": "If specified, the caller is requesting task-augmented execution for this request.\nThe request will return a CreateTaskResult immediately, and the actual result can be\nretrieved later via tasks/result.\n\nTask augmentation is subject to capability negotiation - receivers MUST declare support\nfor task augmentation of specific request types in their capabilities." } }, "required": [ @@ -1022,6 +1038,10 @@ "name": { "description": "The name of the prompt or prompt template.", "type": "string" + }, + "task": { + "$ref": "#/definitions/TaskMetadata", + "description": "If specified, the caller is requesting task-augmented execution for this request.\nThe request will return a CreateTaskResult immediately, and the actual result can be\nretrieved later via tasks/result.\n\nTask augmentation is subject to capability negotiation - receivers MUST declare support\nfor task augmentation of specific request types in their capabilities." } }, "required": [ @@ -1307,6 +1327,10 @@ "protocolVersion": { "description": "The latest version of the Model Context Protocol that the client supports. The client MAY decide to support older versions as well.", "type": "string" + }, + "task": { + "$ref": "#/definitions/TaskMetadata", + "description": "If specified, the caller is requesting task-augmented execution for this request.\nThe request will return a CreateTaskResult immediately, and the actual result can be\nretrieved later via tasks/result.\n\nTask augmentation is subject to capability negotiation - receivers MUST declare support\nfor task augmentation of specific request types in their capabilities." } }, "required": [ @@ -2006,6 +2030,10 @@ "cursor": { "description": "An opaque token representing the current pagination position.\nIf provided, the server should return results starting after this cursor.", "type": "string" + }, + "task": { + "$ref": "#/definitions/TaskMetadata", + "description": "If specified, the caller is requesting task-augmented execution for this request.\nThe request will return a CreateTaskResult immediately, and the actual result can be\nretrieved later via tasks/result.\n\nTask augmentation is subject to capability negotiation - receivers MUST declare support\nfor task augmentation of specific request types in their capabilities." } }, "type": "object" @@ -2302,6 +2330,10 @@ }, "type": "object" }, + "task": { + "$ref": "#/definitions/TaskMetadata", + "description": "If specified, the caller is requesting task-augmented execution for this request.\nThe request will return a CreateTaskResult immediately, and the actual result can be\nretrieved later via tasks/result.\n\nTask augmentation is subject to capability negotiation - receivers MUST declare support\nfor task augmentation of specific request types in their capabilities." + }, "uri": { "description": "The URI of the resource. The URI can use any protocol; it is up to the server how to interpret it.", "format": "uri", @@ -2388,6 +2420,10 @@ } }, "type": "object" + }, + "task": { + "$ref": "#/definitions/TaskMetadata", + "description": "If specified, the caller is requesting task-augmented execution for this request.\nThe request will return a CreateTaskResult immediately, and the actual result can be\nretrieved later via tasks/result.\n\nTask augmentation is subject to capability negotiation - receivers MUST declare support\nfor task augmentation of specific request types in their capabilities." } }, "type": "object" @@ -2557,6 +2593,10 @@ }, "type": "object" }, + "task": { + "$ref": "#/definitions/TaskMetadata", + "description": "If specified, the caller is requesting task-augmented execution for this request.\nThe request will return a CreateTaskResult immediately, and the actual result can be\nretrieved later via tasks/result.\n\nTask augmentation is subject to capability negotiation - receivers MUST declare support\nfor task augmentation of specific request types in their capabilities." + }, "uri": { "description": "The URI of the resource. The URI can use any protocol; it is up to the server how to interpret it.", "format": "uri", @@ -3008,6 +3048,10 @@ "level": { "$ref": "#/definitions/LoggingLevel", "description": "The level of logging that the client wants to receive from the server. The server should send all logs at this level and higher (i.e., more severe) to the client as notifications/message." + }, + "task": { + "$ref": "#/definitions/TaskMetadata", + "description": "If specified, the caller is requesting task-augmented execution for this request.\nThe request will return a CreateTaskResult immediately, and the actual result can be\nretrieved later via tasks/result.\n\nTask augmentation is subject to capability negotiation - receivers MUST declare support\nfor task augmentation of specific request types in their capabilities." } }, "required": [ @@ -3101,6 +3145,10 @@ }, "type": "object" }, + "task": { + "$ref": "#/definitions/TaskMetadata", + "description": "If specified, the caller is requesting task-augmented execution for this request.\nThe request will return a CreateTaskResult immediately, and the actual result can be\nretrieved later via tasks/result.\n\nTask augmentation is subject to capability negotiation - receivers MUST declare support\nfor task augmentation of specific request types in their capabilities." + }, "uri": { "description": "The URI of the resource. The URI can use any protocol; it is up to the server how to interpret it.", "format": "uri", @@ -3153,7 +3201,7 @@ "type": "object" }, "TaskMetadata": { - "description": "Metadata for augmenting a request with task execution.\nInclude this in the `_meta` field of a request under the key `io.modelcontextprotocol/task`.", + "description": "Metadata for augmenting a request with task execution.\nInclude this in the `task` field of the request parameters.", "properties": { "ttl": { "description": "Requested duration in milliseconds to retain task from creation.", @@ -3557,6 +3605,10 @@ }, "type": "object" }, + "task": { + "$ref": "#/definitions/TaskMetadata", + "description": "If specified, the caller is requesting task-augmented execution for this request.\nThe request will return a CreateTaskResult immediately, and the actual result can be\nretrieved later via tasks/result.\n\nTask augmentation is subject to capability negotiation - receivers MUST declare support\nfor task augmentation of specific request types in their capabilities." + }, "uri": { "description": "The URI of the resource. The URI can use any protocol; it is up to the server how to interpret it.", "format": "uri", diff --git a/schema/draft/schema.ts b/schema/draft/schema.ts index d69b653b8..c484babd9 100644 --- a/schema/draft/schema.ts +++ b/schema/draft/schema.ts @@ -36,6 +36,16 @@ export type Cursor = string; * @internal */ export interface RequestParams { + /** + * If specified, the caller is requesting task-augmented execution for this request. + * The request will return a CreateTaskResult immediately, and the actual result can be + * retrieved later via tasks/result. + * + * Task augmentation is subject to capability negotiation - receivers MUST declare support + * for task augmentation of specific request types in their capabilities. + */ + task?: TaskMetadata; + /** * See [General fields: `_meta`](/specification/draft/basic/index#meta) for notes on `_meta` usage. */ @@ -1234,7 +1244,7 @@ export type TaskStatus = /** * Metadata for augmenting a request with task execution. - * Include this in the `_meta` field of a request under the key `io.modelcontextprotocol/task`. + * Include this in the `task` field of the request parameters. * * @category `tasks` */ From aa79e44f1a9a1e0cdba17c07f557207a45af735b Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Thu, 13 Nov 2025 10:48:46 -0800 Subject: [PATCH 54/79] Remove _meta from CreateTaskResult --- docs/specification/draft/basic/utilities/tasks.mdx | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index 66a62e430..80a0363ed 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -130,12 +130,7 @@ To create a task, requestors send a request with the `task` field included in th "statusMessage": "The operation is now in progress.", "createdAt": "2025-11-25T10:30:00Z", "ttl": 60000, - "pollInterval": 5000, - "_meta": { - "io.modelcontextprotocol/related-task": { - "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840" - } - } + "pollInterval": 5000 } } ``` From 9e5d23b68365ef2dfd012b5d53922c21b4831623 Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Thu, 13 Nov 2025 11:20:15 -0800 Subject: [PATCH 55/79] Clarify taskHint behavior --- docs/specification/draft/basic/utilities/tasks.mdx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index 80a0363ed..1b7065663 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -86,7 +86,12 @@ The set of capabilities in `capabilities.tasks.requests` is exhaustive. If a req Tool calls are given special consideration for the purpose of task augmentation. In the result of `tools/list`, tools declare support for tasks via `annotations.taskHint`. -This is to be interpreted as a fine-grained layer in addition to capabilities. 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, even if they declare tool-level support via `annotations.taskHint`. +This is to be interpreted as a fine-grained layer in addition to capabilities, following these rules: + +1. 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, even if they declare tool-level support via `annotations.taskHint`. +1. If a server's capabilities include `tasks.requests.tools.call: true`, then clients consider the value of `taskHint`, and handle it accordingly: + 1. If `taskHint` is not present or `false`, 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. + 1. If `taskHint` is `true`, clients **SHOULD** attempt to invoke the tool as a task. Servers **MAY** return a `-32601` (Method not found) error if a client does not attempt to do so. ## Protocol Messages From 4508eb2a41f294d4e4c13b78192c87c81f9af066 Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Thu, 13 Nov 2025 11:28:29 -0800 Subject: [PATCH 56/79] Update SSE recommendation for tasks in sHTTP --- docs/specification/draft/basic/utilities/tasks.mdx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index 1b7065663..3b832865e 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -383,7 +383,8 @@ stateDiagram-v2 In the Streamable HTTP (SSE) transport, it is common for servers to close SSE streams upon sending a response message, rendering the stream that task messages will be sent on ambiguous. Implementations have flexibility in how they manage SSE streams during task polling and result retrieval. -Possible approaches include using short-lived streams for each `tasks/get` request or maintaining a longer-lived stream on `tasks/result` (see notes on the `input_required` status), among others. +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](../transports#sending-messages-to-the-server). From 3b3c583fffdbf00b74e58a3693366c920af7a87f Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Thu, 13 Nov 2025 21:51:02 -0800 Subject: [PATCH 57/79] Nest data inside of CreateTaskResult.task --- .../draft/basic/utilities/tasks.mdx | 14 ++++++++------ docs/specification/draft/schema.mdx | 2 +- schema/draft/schema.json | 16 +++++++++++----- schema/draft/schema.ts | 4 +++- 4 files changed, 23 insertions(+), 13 deletions(-) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index 3b832865e..172279556 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -130,12 +130,14 @@ To create a task, requestors send a request with the `task` field included in th "jsonrpc": "2.0", "id": 1, "result": { - "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", - "status": "working", - "statusMessage": "The operation is now in progress.", - "createdAt": "2025-11-25T10:30:00Z", - "ttl": 60000, - "pollInterval": 5000 + "task": { + "taskId": "786512e2-9e0d-44bd-8f29-789f320fe840", + "status": "working", + "statusMessage": "The operation is now in progress.", + "createdAt": "2025-11-25T10:30:00Z", + "ttl": 60000, + "pollInterval": 5000 + } } } ``` diff --git a/docs/specification/draft/schema.mdx b/docs/specification/draft/schema.mdx index 34b050615..17922562e 100644 --- a/docs/specification/draft/schema.mdx +++ b/docs/specification/draft/schema.mdx @@ -389,7 +389,7 @@ The server should then request an updated list of roots using the ListRootsReque ### `CreateTaskResult` -
    CreateTaskResult: Result & Task

    A response to a task-augmented request.

    +
    interface CreateTaskResult {
      _meta?: { [key: string]: unknown };
      task: Task;
      [key: string]: unknown;
    }

    A response to a task-augmented request.

    _meta?: { [key: string]: unknown }

    See General fields: _meta for notes on _meta usage.

    ### `RelatedTaskMetadata` diff --git a/schema/draft/schema.json b/schema/draft/schema.json index 661384bff..7e27b3fc9 100644 --- a/schema/draft/schema.json +++ b/schema/draft/schema.json @@ -784,15 +784,21 @@ "type": "object" }, "CreateTaskResult": { - "allOf": [ - { - "$ref": "#/definitions/Result" + "description": "A response to a task-augmented request.", + "properties": { + "_meta": { + "additionalProperties": {}, + "description": "See [General fields: `_meta`](/specification/draft/basic/index#meta) for notes on `_meta` usage.", + "type": "object" }, - { + "task": { "$ref": "#/definitions/Task" } + }, + "required": [ + "task" ], - "description": "A response to a task-augmented request." + "type": "object" }, "Cursor": { "description": "An opaque token used to represent a cursor for pagination.", diff --git a/schema/draft/schema.ts b/schema/draft/schema.ts index f6ebff8ee..a11ba4ca4 100644 --- a/schema/draft/schema.ts +++ b/schema/draft/schema.ts @@ -1340,7 +1340,9 @@ export interface Task { * * @category `tasks` */ -export type CreateTaskResult = Result & Task; +export interface CreateTaskResult extends Result { + task: Task; +} /** * A request to retrieve the state of a task. From 29a197160866ab40a05539b5d3fb85cd38a8e980 Mon Sep 17 00:00:00 2001 From: Luca Chang <131398524+LucaButBoring@users.noreply.github.com> Date: Fri, 14 Nov 2025 08:52:18 -0800 Subject: [PATCH 58/79] Apply grammatical fixes to tasks spec Co-authored-by: Den Delimarsky <53200638+localden@users.noreply.github.com> --- .../draft/basic/utilities/tasks.mdx | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index 172279556..6c795dfa6 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -9,7 +9,7 @@ title: Tasks Tasks are newly-introduced in this version of the MCP specification and are currently considered **experimental**. -The design of tasks may evolve in future protocol versions. +The design and behavior of tasks may evolve in future protocol versions. @@ -17,9 +17,9 @@ The Model Context Protocol (MCP) allows requestors (which can be either clients ## User Interaction Model -Tasks are designed to be **application-driven**—receivers tightly-control which requests (if any) support task-based execution and manage the lifecycles of those tasks; meanwhile, requestors own the responsibility for augmenting requests with tasks, and for polling on the results of those tasks. +Tasks are designed to be **application-driven** - receivers tightly control which requests (if any) support task-based execution and manage the lifecycles of those tasks; meanwhile, requestors are responsible for augmenting requests with tasks and for polling for the results of those tasks. -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. +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 @@ -142,7 +142,7 @@ To create a task, requestors send a request with the `task` field included in th } ``` -When a receiver accepts a task-augmented request, it returns a `CreateTaskResult` containing task metadata. This 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 receiver accepts a task-augmented request, it returns a `CreateTaskResult` containing task metadata. 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. @@ -151,13 +151,13 @@ When a task is created in response to a `tools/call` request, host applications 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 this use case. This may be formalized as part of `CreateTaskResult` in future protocol versions. +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 -To retrieve the state of a task, requestors send a `tasks/get` request: +To retrieve the state of a task, requestors can send a `tasks/get` request: **Request:** @@ -191,9 +191,9 @@ To retrieve the state of a task, requestors send a `tasks/get` request: ### Retrieving Task Results -After a task completes, the actual operation result is retrieved via `tasks/result`. This is distinct from the initial `CreateTaskResult` response, which contains only task metadata. The result structure matches the original request type (e.g., `CallToolResult` for `tools/call`). +After a task completes the operation result is retrieved via `tasks/result`. This is distinct from the initial `CreateTaskResult` response, which contains only task metadata. The result structure matches the original request type (e.g., `CallToolResult` for `tools/call`). -To retrieve the result of a completed task, requestors send a `tasks/result` request: +To retrieve the result of a completed task, requestors can send a `tasks/result` request: **Request:** @@ -233,7 +233,7 @@ To retrieve the result of a completed task, requestors send a `tasks/result` req ### Task Status Notification -When a task's status changes, receivers **MAY** send a `notifications/tasks/status` notification to inform the requestor of the change. This notification includes the full task state. +When a task status changes, receivers **MAY** send a `notifications/tasks/status` notification to inform the requestor of the change. This notification includes the full task state. **Notification:** @@ -257,7 +257,7 @@ Requestors **MUST NOT** rely on receiving this notifications, as it is optional. ### Listing Tasks -To retrieve a list of tasks, requestors send a `tasks/list` request. This operation supports pagination. +To retrieve a list of tasks, requestors can send a `tasks/list` request. This operation supports pagination. **Request:** @@ -301,7 +301,7 @@ To retrieve a list of tasks, requestors send a `tasks/list` request. This operat ### Cancelling Tasks -To explicitly cancel a task, requestors send a `tasks/cancel` request. +To explicitly cancel a task, requestors can send a `tasks/cancel` request. **Request:** @@ -340,13 +340,13 @@ These requirements apply to all parties that support receiving task-augmented re ### Task Support and Handling 1. 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. -1. Receivers that do declare the task capability for a request type **MAY** return an error for non-task-augmented requests of that type, requiring requestors to use task augmentation. +1. 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 1. Task IDs **MUST** be a string value. 1. Task IDs **MUST** be generated by the receiver when creating a task. -1. Task IDs **MUST** be unique across all tasks controlled by the receiver. +1. Task IDs **MUST** be unique among all tasks controlled by the receiver. ### Task Status Lifecycle @@ -354,7 +354,7 @@ These requirements apply to all parties that support receiving task-augmented re 1. Receivers **MUST** only transition tasks through the following valid paths: 1. From `working`: may move to `input_required`, `completed`, `failed`, or `cancelled` 1. From `input_required`: may move to `working`, `completed`, `failed`, or `cancelled` - 1. Tasks in `completed`, `failed`, or `cancelled` status **MUST NOT** transition to any other status (terminal states) + 1. Tasks with a `completed`, `failed`, or `cancelled` status are in a terminal state and **MUST NOT** transition to any other status **Task Status State Diagram:** @@ -382,7 +382,7 @@ stateDiagram-v2 -In the Streamable HTTP (SSE) transport, it is common for servers to close SSE streams upon sending a response message, rendering the stream that task messages will be sent on ambiguous. +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). @@ -394,7 +394,7 @@ While this note is not prescriptive regarding the specific usage of SSE streams, 1. 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_required` status. 1. The receiver **MUST** include the `io.modelcontextprotocol/related-task` metadata in the request to associate it with the task. -1. When the requestor encounters the `input_required` status, it **SHOULD** call `tasks/result` prematurely. +1. When the requestor encounters the `input_required` status, it **SHOULD** preemptively call `tasks/result`. 1. When the receiver receives all required input, the task **SHOULD** transition out of `input_required` status (typically back to `working`). ### TTL and Resource Management @@ -402,7 +402,7 @@ While this note is not prescriptive regarding the specific usage of SSE streams, 1. Receivers **MUST** include a `createdAt` timestamp (ISO 8601 format) in all task responses to indicate when the task was created. 1. Receivers **MAY** override the requested `ttl` duration. 1. Receivers **MUST** include the actual `ttl` duration (or `null` for unlimited) in `tasks/get` responses. -1. After a task's `ttl` duration has elapsed from creation, receivers **MAY** delete the task and its results, regardless of the task's status. +1. After a task's `ttl` lifetime has elapsed, receivers **MAY** delete the task and its results, regardless of the task status. 1. Receivers **MAY** include a `pollInterval` value (in milliseconds) in `tasks/get` responses to suggest polling intervals. Requestors **SHOULD** respect this value when provided. ### Result Retrieval @@ -414,7 +414,7 @@ While this note is not prescriptive regarding the specific usage of SSE streams, ### Associating Task-Related Messages -1. All requests, notifications, and responses related to a task **MUST** include the `io.modelcontextprotocol/related-task` key in their `_meta`, with the value set to an object with a `taskId` matching the associated task ID. +1. All requests, notifications, and responses related to a task **MUST** include the `io.modelcontextprotocol/related-task` key in their `_meta` field, with the value set to an object with a `taskId` matching the associated task ID. 1. 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. 1. For the `tasks/get`, `tasks/list`, `tasks/result`, and `tasks/cancel` operations, the `taskId` parameter in the request **MUST** be used as the source of truth for identifying the target task. Requestors **SHOULD NOT** include `io.modelcontextprotocol/related-task` metadata in these requests, and receivers **MUST** ignore such metadata if present in favor of the RPC method parameter. Similarly, for the `tasks/get`, `tasks/list`, and `tasks/cancel` operations, receivers **SHOULD NOT** include `io.modelcontextprotocol/related-task` metadata in the result messages, as the `taskId` is already present in the response structure. @@ -427,7 +427,7 @@ While this note is not prescriptive regarding the specific usage of SSE streams, ### Task Progress Notifications -Task-augmented requests support progress notifications as defined in the [progress](./progress) specification. The `progressToken` provided in the initial request remains valid throughout the task's lifetime. +Task-augmented requests support progress notifications as defined in the [progress](./progress) specification. The `progressToken` provided in the initial request remains valid throughout the task lifetime. ### Task Listing @@ -441,7 +441,7 @@ Task-augmented requests support progress notifications as defined in the [progre 1. Receivers **MUST** reject cancellation requests for tasks already in a terminal status (`completed`, `failed`, or `cancelled`) with error code `-32602` (Invalid params). 1. Upon receiving a valid cancellation request, receivers **SHOULD** attempt to stop the task's execution (best effort) and **MUST** transition the task to `cancelled` status before sending the response. 1. Once a task is cancelled, it **MUST** remain in `cancelled` status even if execution continues to completion or fails. -1. The `tasks/cancel` operation does not define deletion behavior. However, receivers **MAY** delete cancelled tasks at their discretion at any time, including immediately after cancellation or after the task's `ttl` expires. +1. The `tasks/cancel` operation does not define deletion behavior. However, receivers **MAY** delete cancelled tasks at their discretion at any time, including immediately after cancellation or after the task `ttl` expires. 1. Requestors **SHOULD NOT** rely on cancelled tasks being retained for any specific duration and should retrieve any needed information before cancelling. ## Message Flow From b0cb3494d91195fac156c6f73f28807d02c7d33a Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Fri, 14 Nov 2025 09:51:29 -0800 Subject: [PATCH 59/79] Add definitions section and fix grammar --- docs/specification/draft/basic/utilities/tasks.mdx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index 6c795dfa6..f73347420 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -13,7 +13,14 @@ The design and behavior of tasks may evolve in future protocol versions. -The Model Context Protocol (MCP) allows requestors (which can be either clients or servers, depending on the direction of communication) to augment their requests with **tasks**. Tasks are durable state machines that carry information about the underlying execution state of the request they wrap, and are intended for requestor polling and deferred result retrieval. Each task is uniquely identifiable by a receiver-generated **task ID**. +The Model Context Protocol (MCP) allows requestors — which can be either clients or servers, depending on the direction of communication — to augment their requests with **tasks**. Tasks are durable state machines that carry information about the underlying execution state of the request they wrap, and are intended for requestor polling and deferred result retrieval. Each task is uniquely identifiable by a receiver-generated **task ID**. + +## 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 From b94efecf4dd5e7ce2d503124c207aa7e053e9739 Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Fri, 14 Nov 2025 10:28:54 -0800 Subject: [PATCH 60/79] Add capability tables for tasks --- .../draft/basic/utilities/tasks.mdx | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index f73347420..e3c9ff5b9 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -34,7 +34,13 @@ Servers and clients that support task-augmented requests **MUST** declare a `tas ### Server Capabilities -Servers declare if they support tasks, and if so, which server-side requests can be augmented with tasks: +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 | ```json { @@ -54,7 +60,14 @@ Servers declare if they support tasks, and if so, which server-side requests can ### Client Capabilities -Clients declare if they support tasks, and if so, which client-side requests can be augmented with tasks: +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 | ```json { From 00566e270dc828cf12038c1c3e4ceaa34884e1b0 Mon Sep 17 00:00:00 2001 From: Luca Chang Date: Fri, 14 Nov 2025 11:16:42 -0800 Subject: [PATCH 61/79] Change taskHint to enum --- docs/specification/draft/basic/utilities/tasks.mdx | 7 ++++--- docs/specification/draft/schema.mdx | 6 +++--- schema/draft/schema.json | 9 +++++++-- schema/draft/schema.ts | 10 +++++++--- 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/docs/specification/draft/basic/utilities/tasks.mdx b/docs/specification/draft/basic/utilities/tasks.mdx index e3c9ff5b9..ec1f7ba4f 100644 --- a/docs/specification/draft/basic/utilities/tasks.mdx +++ b/docs/specification/draft/basic/utilities/tasks.mdx @@ -108,10 +108,11 @@ Tool calls are given special consideration for the purpose of task augmentation. This is to be interpreted as a fine-grained layer in addition to capabilities, following these rules: -1. 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, even if they declare tool-level support via `annotations.taskHint`. +1. 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 the `taskHint` value. 1. If a server's capabilities include `tasks.requests.tools.call: true`, then clients consider the value of `taskHint`, and handle it accordingly: - 1. If `taskHint` is not present or `false`, 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. - 1. If `taskHint` is `true`, clients **SHOULD** attempt to invoke the tool as a task. Servers **MAY** return a `-32601` (Method not found) error if a client does not attempt to do so. + 1. If `taskHint` is 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. + 1. If `taskHint` is `"optional"`, clients **MAY** invoke the tool as a task or as a normal request. + 1. If `taskHint` is `"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. ## Protocol Messages diff --git a/docs/specification/draft/schema.mdx b/docs/specification/draft/schema.mdx index ff39fd1d3..59f65a44f 100644 --- a/docs/specification/draft/schema.mdx +++ b/docs/specification/draft/schema.mdx @@ -732,7 +732,7 @@ if present).