Skip to content

Commit b9a9ac4

Browse files
committed
Remove cancellation changes and convert deletion into cancel RPC method
1 parent 13c6835 commit b9a9ac4

File tree

5 files changed

+215
-174
lines changed

5 files changed

+215
-174
lines changed

docs/specification/draft/basic/utilities/cancellation.mdx

Lines changed: 9 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,9 @@ indicate that a previously-issued request should be terminated.
1515
When a party wants to cancel an in-progress request, it sends a `notifications/cancelled`
1616
notification containing:
1717

18-
- For non-task requests: The ID of the request to cancel
19-
- For task cancellation: The ID of the task to cancel
18+
- The ID of the request to cancel
2019
- An optional reason string that can be logged or displayed
2120

22-
### Cancelling Non-Task Requests
23-
2421
```json
2522
{
2623
"jsonrpc": "2.0",
@@ -32,49 +29,23 @@ notification containing:
3229
}
3330
```
3431

35-
### Cancelling Tasks
36-
37-
For task-augmented requests, once the `CreateTaskResult` is returned, the original request is complete and `requestId` becomes ambiguous. Therefore, task cancellation **MUST** use `taskId`:
38-
39-
```json
40-
{
41-
"jsonrpc": "2.0",
42-
"method": "notifications/cancelled",
43-
"params": {
44-
"taskId": "786512e2-9e0d-44bd-8f29-789f320fe840",
45-
"reason": "User requested cancellation"
46-
}
47-
}
48-
```
49-
5032
## Behavior Requirements
5133

52-
### General Requirements
53-
54-
1. Cancellation notifications **MUST** only reference requests or tasks that:
34+
1. Cancellation notifications **MUST** only reference requests that:
5535
- Were previously issued in the same direction
5636
- Are believed to still be in-progress
5737
2. The `initialize` request **MUST NOT** be cancelled by clients
5838
3. Receivers of cancellation notifications **SHOULD**:
59-
- Stop processing the cancelled request or task
39+
- Stop processing the cancelled request
6040
- Free associated resources
61-
- For non-task requests: Not send a response for the cancelled request
62-
- For tasks: Move the task to `cancelled` status
41+
- Not send a response for the cancelled request
6342
4. Receivers **MAY** ignore cancellation notifications if:
64-
- The referenced request or task is unknown
65-
- Processing has already completed (for non-task requests) or reached a terminal status (for tasks)
66-
- The request or task cannot be cancelled
43+
- The referenced request is unknown
44+
- Processing has already completed
45+
- The request cannot be cancelled
6746
5. The sender of the cancellation notification **SHOULD** ignore any response to the
6847
request that arrives afterward
6948

70-
### Task-Specific Requirements
71-
72-
1. For task cancellation, `taskId` **MUST** be provided (not `requestId`)
73-
2. `requestId` **MUST NOT** be used for task cancellation once `CreateTaskResult` has been returned
74-
3. When a receiver receives a `notifications/cancelled` notification with a `taskId`, it **SHOULD** immediately move the task to `cancelled` status
75-
4. If a cancellation notification arrives after a task has already reached a terminal status (`completed`, `failed`, or `cancelled`), receivers **SHOULD** ignore the notification
76-
5. Requestors **SHOULD** poll with `tasks/get` after sending a cancellation notification to confirm the task has transitioned to `cancelled` status
77-
7849
## Timing Considerations
7950

8051
Due to network latency, cancellation notifications may arrive after request processing
@@ -106,10 +77,9 @@ sequenceDiagram
10677

10778
Invalid cancellation notifications **SHOULD** be ignored:
10879

109-
- Unknown request IDs or task IDs
110-
- Already completed requests or tasks in terminal status
80+
- Unknown request IDs
81+
- Already completed requests
11182
- Malformed notifications
112-
- Using `requestId` for task cancellation (should use `taskId` instead)
11383

11484
This maintains the "fire and forget" nature of notifications while allowing for race
11585
conditions in asynchronous communication.

docs/specification/draft/basic/utilities/tasks.mdx

Lines changed: 70 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ Servers declare if they support tasks, and if so, which server-side requests can
2727
"capabilities": {
2828
"tasks": {
2929
"list": {},
30-
"delete": {},
30+
"cancel": {},
3131
"requests": {
3232
"tools": {
3333
"call": {}
@@ -47,7 +47,7 @@ Clients declare if they support tasks, and if so, which client-side requests can
4747
"capabilities": {
4848
"tasks": {
4949
"list": {},
50-
"delete": {},
50+
"cancel": {},
5151
"requests": {
5252
"sampling": {
5353
"createMessage": {}
@@ -73,7 +73,7 @@ The set of capabilities in `capabilities.tasks.requests` is exhaustive. If a req
7373

7474
`capabilities.tasks.list` controls if the `tasks/list` operation is supported by the party.
7575

76-
`capabilities.tasks.delete` controls if the `tasks/delete` operation is supported by the party.
76+
`capabilities.tasks.cancel` controls if the `tasks/cancel` operation is supported by the party.
7777

7878
### Tool-Level Negotiation
7979

@@ -314,17 +314,17 @@ To retrieve a list of tasks, requestors send a `tasks/list` request. This operat
314314
}
315315
```
316316

317-
### Deleting Tasks
317+
### Cancelling Tasks
318318

319-
To explicitly delete a task and its associated results, requestors send a `tasks/delete` request.
319+
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.
320320

321-
**Request:**
321+
**Request (basic cancellation):**
322322

323323
```json
324324
{
325325
"jsonrpc": "2.0",
326326
"id": 6,
327-
"method": "tasks/delete",
327+
"method": "tasks/cancel",
328328
"params": {
329329
"taskId": "786512e2-9e0d-44bd-8f29-789f320fe840"
330330
}
@@ -338,6 +338,41 @@ To explicitly delete a task and its associated results, requestors send a `tasks
338338
"jsonrpc": "2.0",
339339
"id": 6,
340340
"result": {
341+
"status": "cancelled",
342+
"executionStopped": true,
343+
"_meta": {
344+
"modelcontextprotocol.io/related-task": {
345+
"taskId": "786512e2-9e0d-44bd-8f29-789f320fe840"
346+
}
347+
}
348+
}
349+
}
350+
```
351+
352+
**Request (cancellation with deletion):**
353+
354+
```json
355+
{
356+
"jsonrpc": "2.0",
357+
"id": 7,
358+
"method": "tasks/cancel",
359+
"params": {
360+
"taskId": "786512e2-9e0d-44bd-8f29-789f320fe840",
361+
"delete": true
362+
}
363+
}
364+
```
365+
366+
**Response:**
367+
368+
```json
369+
{
370+
"jsonrpc": "2.0",
371+
"id": 7,
372+
"result": {
373+
"status": "cancelled",
374+
"executionStopped": true,
375+
"deleted": true,
341376
"_meta": {
342377
"modelcontextprotocol.io/related-task": {
343378
"taskId": "786512e2-9e0d-44bd-8f29-789f320fe840"
@@ -417,37 +452,27 @@ stateDiagram-v2
417452

418453
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.
419454
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.
420-
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.
455+
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.
421456

422457
### Task Progress Notifications
423458

424459
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.
425460

426-
### Task Cancellation
427-
428-
1. Requestors **MAY** send `notifications/cancelled` at any time during task execution.
429-
1. For task cancellation, the `notifications/cancelled` notification **MUST** include a `taskId` field:
430-
1. The `taskId` **MUST** correspond to a task previously created in the same direction.
431-
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.
432-
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.
433-
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.
434-
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.
435-
1. After a task reaches `cancelled` status and its `keepAlive` duration has elapsed, receivers **MAY** delete the task and its metadata.
436-
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.
437-
438461
### Task Listing
439462

440463
1. Receivers **SHOULD** use cursor-based pagination to limit the number of tasks returned in a single response.
441464
1. Receivers **MUST** include a `nextCursor` in the response if more tasks are available.
442465
1. Requestors **MUST** treat cursors as opaque tokens and not attempt to parse or modify them.
443466
1. If a task is retrievable via `tasks/get` for a requestor, it **MUST** be retrievable via `tasks/list` for that requestor.
444467

445-
### Task Deletion
468+
### Task Cancellation
446469

447-
1. Receivers **MAY** accept or reject delete requests for any task at their discretion.
448-
1. If a receiver accepts a delete request, it **SHOULD** delete the task and all associated results and metadata.
449-
1. Receivers **MAY** choose not to support deletion at all, or only support deletion for tasks in certain statuses (e.g., only terminal statuses).
450-
1. Requestors **SHOULD** delete tasks containing sensitive data promptly rather than relying solely on `keepAlive` expiration for cleanup.
470+
1. Receivers **MUST** reject cancellation requests for tasks already in a terminal status (`completed`, `failed`, or `cancelled`) with error code `-32602` (Invalid params).
471+
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.
472+
1. Once a task is cancelled, it **MUST** remain in `cancelled` status even if execution continues to completion or fails.
473+
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.
474+
1. If the `delete` parameter is `false` or omitted, receivers **MUST** retain the task in `cancelled` status subject to the `keepAlive` duration.
475+
1. Requestors **SHOULD** use the `delete` parameter to clean up tasks containing sensitive data promptly rather than relying solely on `keepAlive` expiration.
451476

452477
## Message Flow
453478

@@ -591,6 +616,7 @@ sequenceDiagram
591616
592617
Note over C,S: 1. Task Creation
593618
C->>S: tools/call (request ID: 42, task-123)
619+
S->>C: CreateTaskResult (task-123, status: working)
594620
S--)C: notifications/tasks/created
595621
596622
Note over C,S: 2. Task Processing
@@ -599,21 +625,19 @@ sequenceDiagram
599625
600626
Note over C,S: 3. Client Cancellation
601627
Note over C: User requests cancellation
602-
C--)S: notifications/cancelled (taskId: task-123)
628+
C->>S: tasks/cancel (taskId: task-123)
603629
604-
Note over S: Server processes cancellation
630+
Note over S: Server stops execution (best effort)
605631
Note over S: Task moves to cancelled status
606632
607-
Note over C,S: 4. Confirmation Polling
608-
C->>S: tasks/get (task-123)
609-
S->>C: cancelled
633+
S->>C: Result (status: cancelled, executionStopped: true)
610634
611-
Note over C: Client confirms cancellation succeeded
635+
Note over C: Client receives confirmation
612636
613637
Note over S: After keepAlive period, task cleaned up
614638
```
615639

616-
### Task Deletion Flow
640+
### Task Cancellation with Deletion Flow
617641

618642
```mermaid
619643
sequenceDiagram
@@ -622,7 +646,7 @@ sequenceDiagram
622646
623647
Note over C,S: 1. Task Creation and Completion
624648
C->>S: tools/call (task-123)
625-
S->>C: CreateTaskResult (task-123, status: submitted)
649+
S->>C: CreateTaskResult (task-123, status: working)
626650
S--)C: notifications/tasks/created
627651
Note over S: Task processing...
628652
C->>S: tasks/get (task-123)
@@ -632,13 +656,15 @@ sequenceDiagram
632656
C->>S: tasks/result (task-123)
633657
S->>C: Result content
634658
635-
Note over C,S: 3. Explicit Deletion
659+
Note over C,S: 3. Cancellation with Deletion
636660
Note over C: Client decides to clean up task
637-
C->>S: tasks/delete (task-123)
638-
S->>C: Success (empty result)
661+
C->>S: tasks/cancel (task-123, delete: true)
639662
663+
Note over S: Task moves to cancelled status
640664
Note over S: Task and results immediately deleted
641665
666+
S->>C: Result (status: cancelled, deleted: true)
667+
642668
Note over C,S: 4. Verification (optional)
643669
C->>S: tasks/get (task-123)
644670
S->>C: Error: Task not found
@@ -706,9 +732,9 @@ Tasks use two error reporting mechanisms:
706732

707733
Receivers **MUST** return standard JSON-RPC errors for the following protocol error cases:
708734

709-
- Invalid or nonexistent `taskId` in `tasks/get`, `tasks/list`, `tasks/result`, or `tasks/delete`: `-32602` (Invalid params)
735+
- Invalid or nonexistent `taskId` in `tasks/get`, `tasks/list`, `tasks/result`, or `tasks/cancel`: `-32602` (Invalid params)
710736
- Invalid or nonexistent cursor in `tasks/list`: `-32602` (Invalid params)
711-
- Receiver rejects a `tasks/delete` request: `-32600` (Invalid request)
737+
- Attempt to cancel a task already in a terminal status: `-32602` (Invalid params)
712738
- Internal errors: `-32603` (Internal error)
713739

714740
Additionally, receivers **MAY** return the following errors:
@@ -762,15 +788,15 @@ Receivers are not obligated to retain task metadata indefinitely. It is complian
762788

763789
</Note>
764790

765-
**Example: Task deletion rejected by receiver**
791+
**Example: Task cancellation rejected (already terminal)**
766792

767793
```json
768794
{
769795
"jsonrpc": "2.0",
770796
"id": 74,
771797
"error": {
772-
"code": -32600,
773-
"message": "Task deletion not supported for tasks in 'working' status"
798+
"code": -32602,
799+
"message": "Cannot cancel task: already in terminal status 'completed'"
774800
}
775801
}
776802
```
@@ -808,20 +834,20 @@ The `tasks/result` endpoint returns exactly what the underlying request would ha
808834
1. Receivers **SHOULD** scope task IDs to prevent unauthorized access:
809835
1. Bind tasks to the session that created them (if sessions are supported)
810836
1. Bind tasks to the authentication context (if authentication is used)
811-
1. Reject `tasks/get`, `tasks/list`, `tasks/result`, or `tasks/delete` requests for tasks from different sessions or auth contexts
837+
1. Reject `tasks/get`, `tasks/list`, `tasks/result`, or `tasks/cancel` requests for tasks from different sessions or auth contexts
812838
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.
813839
1. Receivers **SHOULD** implement rate limiting on:
814840
1. Task creation to prevent resource exhaustion
815841
1. Task status polling to prevent denial of service
816842
1. Task result retrieval attempts
817843
1. Task listing requests to prevent denial of service
818-
1. Task deletion requests to prevent abuse
844+
1. Task cancellation requests to prevent abuse
819845

820846
### Resource Management
821847

822848
<Warning>
823849

824-
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.
850+
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.
825851

826852
</Warning>
827853

0 commit comments

Comments
 (0)