[SEP-2663] refactor!: remove 2025-11 experimental tasks#2128
[SEP-2663] refactor!: remove 2025-11 experimental tasks#2128felixweinberger wants to merge 1 commit into
Conversation
🦋 Changeset detectedLatest commit: 96f39c0 The changes in this PR will be included in the next version bump. This PR includes changesets to release 7 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
@modelcontextprotocol/client
@modelcontextprotocol/codemod
@modelcontextprotocol/server
@modelcontextprotocol/express
@modelcontextprotocol/fastify
@modelcontextprotocol/hono
@modelcontextprotocol/node
commit: |
|
@claude review |
|
@claude review |
54bbe7b to
c223fee
Compare
c223fee to
65f8c17
Compare
|
@claude review |
…ences) Removes the 2025-11 experimental tasks side-channel through Protocol: TaskManager, processInbound*/processOutbound*, task interception, the experimental.tasks.* client/server accessors, and all task-augmented request handling. Also extends beyond the implementation deletion to scrub remaining references in examples, docs, and comments. The only task-related symbol remaining in packages/*.ts is `taskSupport` in ToolExecutionSchema, kept solely to match spec.types.ts (which still declares it); both are removed together in the next commit (spec regen). CHANGELOG entries are preserved (historical record). Migration docs retain a brief removal note. `microtask`/`platformBackgroundTask` are JS/platform terminology, not MCP tasks. Satisfies: SEP-2663 (core-removal half; tasks are now Extensions Track).
65f8c17 to
96f39c0
Compare
|
@claude review |
| - `mcpServer.experimental.tasks.registerToolTask(...)`, `ToolTaskHandler`, `TaskRequestHandler`, `CreateTaskRequestHandler` | ||
| - `TaskMessageQueue`, `InMemoryTaskMessageQueue`, `Queued*` message types, `CreateTaskServerContext`, `TaskServerContext`, `TaskToolExecution` | ||
| - `examples/{client,server}/src/simpleTaskInteractive*.ts` |
There was a problem hiding this comment.
🟡 The §12 removal lists in docs/migration.md (~line 863–865) and docs/migration-SKILL.md (~lines 488–489) omit a few public exports that this PR also deletes: BaseResponseMessage, ErrorMessage, and AsyncGeneratorValue from responseMessage.ts, and BaseQueuedMessage from the task interfaces (the Queued* glob doesn't lexically cover it). Adding these to the removal rows would make the migration index complete for users who imported them directly.
Extended reasoning...
What's missing
The §12 removal table this PR adds is meant to be an enumerated index of every public symbol the v2 user can no longer import. Two entries are incomplete:
- Response-message family.
docs/migration-SKILL.md:489lists the deletedresponseMessage.tsexports asResponseMessage, TaskStatusMessage, TaskCreatedMessage, ResultMessage, takeResult, toArrayAsync. But the deleted file also publicly exportedBaseResponseMessage,ErrorMessage, andAsyncGeneratorValue— the first two were explicit re-exports from the deleted lines inpackages/core/src/exports/public/index.ts(export type { BaseResponseMessage, ErrorMessage, ResponseMessage, ... }), andAsyncGeneratorValuewas reachable through the now-removedexport * from './shared/responseMessage.js'barrel inpackages/core/src/index.ts. - Queued-message family.
docs/migration.md:865anddocs/migration-SKILL.md:488use aQueued*glob to coverQueuedMessage / QueuedRequest / QueuedNotification / QueuedResponse / QueuedError. That glob does not lexically matchBaseQueuedMessage(noQueuedprefix), which was also an explicit re-export fromexports/public/index.tsand is deleted by this PR.
Why it matters
A v1 user who has import type { ErrorMessage } from '@modelcontextprotocol/core' (e.g. to type a callToolStream error branch) or import type { BaseQueuedMessage } from '@modelcontextprotocol/core' (e.g. to write a custom TaskMessageQueue) reads §12 to learn what broke. The table presents itself as an explicit enumeration, so a name that doesn't appear is implicitly "still there." They get a TS2305: Module has no exported member build break that the migration guide doesn't predict.
The migration.md bullet at line 863 hedges with "and the ResponseMessage types they yielded," which arguably covers ErrorMessage / BaseResponseMessage / ResultMessage as a category — but the SKILL.md table has no such hedge and lists names exhaustively. Neither doc covers BaseQueuedMessage or AsyncGeneratorValue at all.
Step-by-step proof
- A v1 user has
import type { ErrorMessage, BaseQueuedMessage } from '@modelcontextprotocol/core';— both resolve before this PR via the explicit re-exports inpackages/core/src/exports/public/index.ts. - They upgrade and read §12 of
docs/migration-SKILL.md. The two relevant rows enumerateResponseMessage, TaskStatusMessage, TaskCreatedMessage, ResultMessage, takeResult, toArrayAsyncandTaskMessageQueue, InMemoryTaskMessageQueue, Queued*, ...— neither name appears. - They conclude their imports are unaffected and rebuild.
tscfails:Module '\"@modelcontextprotocol/core\"' has no exported member 'ErrorMessage'and'BaseQueuedMessage'— because the re-exports are deleted andresponseMessage.ts/interfaces.tsno longer exist.- The user now distrusts the table and has to grep the package to find the rest.
Why nothing else catches it
The migration guide is prose; nothing in CI cross-checks its removal lists against the actual delta in the public export surface. The grep audit cited in the PR description was scoped to packages/**, not to the docs.
Fix
Add the missing names to the existing rows — a one-line edit in each file:
docs/migration.md:863anddocs/migration-SKILL.md:489→ appendBaseResponseMessage,ErrorMessage,AsyncGeneratorValue.docs/migration.md:865anddocs/migration-SKILL.md:488→ appendBaseQueuedMessage(or changeQueued*to*Queued*).
These are obscure helper/base types and a user importing them would almost certainly also import one of the listed names alongside them, so this is a completeness nit, not a blocker.
| * | ||
| * Primitive type aliases — no object keys to compare (8): | ||
| * JSONValue, JSONArray, Role, LoggingLevel, ProgressToken, RequestId, | ||
| * Cursor, TaskStatus | ||
| * Cursor | ||
| */ | ||
|
|
||
| // -- Simple types (96) -- |
There was a problem hiding this comment.
🟡 Several section-header counts in spec.types.test.ts are now stale after the task-type _K_* assertions and TaskStatus primitive alias were removed: "(23 entries)" → 22, "Primitive type aliases … (8)" → 7 (line 719 and the // Primitive aliases (8) comment at line 943), "Simple types (96)" → 86, "WithJSONRPC-wrapped notification types (11)" → 10, "WithJSONRPCRequest-wrapped request types (21)" → 17, "TypedResultResponse-wrapped types (21)" → 16. Update the parenthesized counts so the drift-guard headers stay accurate.
Extended reasoning...
What's stale
This file uses parenthesized counts in section-header comments as a lightweight drift guard so a future reader can sanity-check that no _K_* key-parity assertion was accidentally dropped. The PR deletes the per-task assertions (_K_Task, _K_CreateTaskResult, _K_GetTask*, _K_ListTasks*, _K_CancelTask*, _K_TaskStatusNotification*, _K_TaskAugmentedRequestParams, _K_TaskMetadata, _K_RelatedTaskMetadata) and removes TaskStatus from the primitive-alias list, but leaves every count unchanged.
Verified counts at HEAD
Counting ^type _K_ lines per section after the PR:
| Comment | Says | Actual |
|---|---|---|
line 711 Excluded from key-level assertions (23 entries) |
23 | 22 (15 union + 7 primitive) |
line 719 Primitive type aliases — no object keys to compare (8) |
8 | 7 (TaskStatus removed at line 721) |
line 724 // -- Simple types (96) -- |
96 | 86 |
line 831 // -- WithJSONRPC-wrapped notification types (11) -- |
11 | 10 (TaskStatusNotification removed) |
line 860 // -- WithJSONRPCRequest-wrapped request types (21) -- |
21 | 17 (GetTaskRequest, GetTaskPayloadRequest, ListTasksRequest, CancelTaskRequest removed) |
line 884 // -- TypedResultResponse-wrapped types (21) -- |
21 | 16 (the five *TaskResultResponse entries removed) |
line 943 // Primitive aliases (8) (in KEY_PARITY_EXCLUDED) |
8 | 7 |
Why this matters
The PR clearly edited this file deliberately — it added @ts-expect-error markers for the SEP-2663 union mismatches, populated MISSING_SDK_TYPES with the removed task types, and dropped TaskStatus from KEY_PARITY_EXCLUDED — but the surrounding header counts were left untouched. The whole point of these counts is to make a missing assertion obvious; stale counts now actively mislead anyone auditing the section coverage (e.g., the next person doing a spec-types sweep would see "96" and think 10 assertions disappeared by accident).
Why nothing catches it
The counts are pure prose comments. Nothing in CI parses or enforces them, so pnpm test:all passes regardless. They only ever pay off when a human reads the file.
Step-by-step proof
- Open
packages/core/test/spec.types.test.tsat96f39c0. - Run
awk 'NR>=724 && NR<831 && /^type _K_/' … | wc -l→ 86 (header says 96). - Same for the other three ranges (831–860 → 10, 860–884 → 17, 884–918 → 16).
- Count names in the bullet at lines 719–722 → 7 (header says 8). Cumulative "(23 entries)" at line 711 is 15 + 7 = 22.
- Count names after
// Primitive aliases (8)at line 943 → 7.
Fix
Update the parenthesized counts to 22, 7, 86, 10, 17, and 16 respectively (and the // Primitive aliases (8) at line 943 to 7). Pure-comment change, no behavioral impact.
| --- | ||
| '@modelcontextprotocol/core': major | ||
| '@modelcontextprotocol/server': major | ||
| '@modelcontextprotocol/client': major | ||
| --- | ||
| SEP-2663: remove 2025-11 experimental tasks (TaskManager, experimental.tasks.* accessors). Tasks are now Extensions Track. |
There was a problem hiding this comment.
🟡 This PR adds the SEP-2663 removal changeset, but a sibling pending changeset .changeset/fix-failed-task-result-retrieval.md (not yet consumed — absent from pre.json's changesets list) still describes a fix to requestStream / tasks/result polling, an API surface this same PR deletes. The next changeset version run will emit a CHANGELOG "fix" entry for an API that no longer exists, right next to the major-bump entry announcing its removal — delete the orphaned changeset alongside the code it patched.
Extended reasoning...
What's stale
.changeset/fix-failed-task-result-retrieval.md is still present in the repo and reads:
Fix
requestStreamto calltasks/resultfor failed tasks instead of yielding a hardcodedProtocolError. When a task reaches thefailedterminal status, the stream now retrieves and yields the actual stored result (matching the behavior forcompletedtasks), as required by the spec.
It is not listed in .changeset/pre.json's changesets array, which means it has not been consumed by any prerelease bump and is still pending. The next changeset version run will pick it up.
Why this PR makes it wrong
This PR deletes the entire surface that changeset describes a fix for:
packages/core/src/shared/taskManager.ts— containedTaskManager.requestStream(the function the changeset names) and thetasks/resulthandler registration inbind().packages/core/src/shared/responseMessage.ts— theResponseMessagetypes yielded byrequestStream.packages/client/src/experimental/tasks/client.tsandpackages/server/src/experimental/tasks/server.ts— the publicrequestStreamwrappers.- The
tasks/resultmethod,GetTaskPayloadRequestSchema, and the rest of the tasks request surface frompackages/core/src/types/schemas.ts.
After this PR there is no requestStream, no tasks/result, and no failed-task polling path anywhere in the SDK — the changeset is documenting a fix to deleted code.
What happens if it's left in
When the maintainers next run changeset version, both pending changesets are consumed into the same release. The generated CHANGELOG for @modelcontextprotocol/core will then contain, side by side:
- A major entry from
sep-2663-tasks-removal.md: "remove 2025-11 experimental tasks (TaskManager, experimental.tasks.* accessors)" - A patch entry from
fix-failed-task-result-retrieval.md: "FixrequestStreamto calltasks/resultfor failed tasks…"
Entry 2 promises behavior for an API that entry 1 just announced was removed. A consumer reading the changelog has no way to tell the patch entry is a no-op; they may go looking for requestStream to take advantage of the fix and find it doesn't exist.
Why the PR's audit didn't catch it
The PR description states the grep audit was scoped to packages/** ("grep audit confirms no task references remain in packages/**"). .changeset/ lives at the repo root and was outside the scope of that audit. The repo's own Recurring Catches note flags exactly this class of problem: changeset prose that promises behavior the code no longer ships.
Step-by-step proof
cat .changeset/fix-failed-task-result-retrieval.md→ exists, body describes arequestStream/tasks/resultfix.jq '.changesets | index("fix-failed-task-result-retrieval")' .changeset/pre.json→null(not consumed; still pending).git show HEAD --stat | grep taskManager→packages/core/src/shared/taskManager.tsdeleted (915 lines removed) — the file that definedrequestStreamand thetasks/resulthandler.- Run
changeset version(or wait for the next release cut) → the CHANGELOG gains a### Patch Changesentry describing therequestStreamfix immediately adjacent to the### Major Changesentry fromsep-2663-tasks-removal.mdannouncing that API's removal.
Fix
Delete .changeset/fix-failed-task-result-retrieval.md in this PR. The fix it describes has been overtaken by the wholesale removal; it has no place in the next release's changelog. (The other task-related changesets — extract-task-manager.md, fix-task-session-isolation.md — are already in pre.json's consumed list and need no action.)
Removes the 2025-11 experimental tasks implementation per SEP-2663 (tasks moved to Extensions Track).
Motivation and Context
SEP-2663 removes tasks from the core protocol. This deletes
TaskManager, the task interception hooks inProtocol, andexperimental.tasks.*accessors.How Has This Been Tested?
pnpm test:all(1241 tests). Mechanical deletion; grep audit confirms notaskreferences remain inpackages/**exceptmicrotask/platformBackgroundTask(unrelated JS terms) andtaskSupportinToolExecutionSchema(removed in next PR alongside spec regen).Breaking Changes
Yes —
experimental.tasks.*removed. Seedocs/migration.md.Types of changes
Checklist