Skip to content

[SEP-2663] refactor!: remove 2025-11 experimental tasks#2128

Open
felixweinberger wants to merge 1 commit into
mainfrom
fweinberger/v2-tasks-delete
Open

[SEP-2663] refactor!: remove 2025-11 experimental tasks#2128
felixweinberger wants to merge 1 commit into
mainfrom
fweinberger/v2-tasks-delete

Conversation

@felixweinberger
Copy link
Copy Markdown
Contributor

@felixweinberger felixweinberger commented May 20, 2026

2026-06 stateless stack (v2-stateless label):

# PR
1 #2128 tasks-delete (mechanical)
2 #2129 schema-sync (mechanical)
3 #2130 Dispatcher extraction (zero-Δ refactor)
4 #2131 HTTP-stateless (the substantive review)
5 #2132 stdio/InMemory transports (additive)
6 #2133 docs + changeset
7 #2134 LegacyServer/LegacyClient extraction

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 in Protocol, and experimental.tasks.* accessors.

How Has This Been Tested?

pnpm test:all (1241 tests). Mechanical deletion; grep audit confirms no task references remain in packages/** except microtask/platformBackgroundTask (unrelated JS terms) and taskSupport in ToolExecutionSchema (removed in next PR alongside spec regen).

Breaking Changes

Yes — experimental.tasks.* removed. See docs/migration.md.

Types of changes

  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added or updated documentation as needed

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 20, 2026

🦋 Changeset detected

Latest commit: 96f39c0

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 7 packages
Name Type
@modelcontextprotocol/core Major
@modelcontextprotocol/server Major
@modelcontextprotocol/client Major
@modelcontextprotocol/express Major
@modelcontextprotocol/fastify Major
@modelcontextprotocol/hono Major
@modelcontextprotocol/node Major

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

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 20, 2026

Open in StackBlitz

@modelcontextprotocol/client

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/client@2128

@modelcontextprotocol/codemod

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/codemod@2128

@modelcontextprotocol/server

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/server@2128

@modelcontextprotocol/express

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/express@2128

@modelcontextprotocol/fastify

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/fastify@2128

@modelcontextprotocol/hono

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/hono@2128

@modelcontextprotocol/node

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/node@2128

commit: 96f39c0

@felixweinberger
Copy link
Copy Markdown
Contributor Author

@claude review

Comment thread examples/server/src/ssePollingExample.ts
Comment thread docs/migration.md Outdated
Comment thread packages/core/src/types/schemas.ts Outdated
@felixweinberger
Copy link
Copy Markdown
Contributor Author

@claude review

@felixweinberger felixweinberger force-pushed the fweinberger/v2-tasks-delete branch from 54bbe7b to c223fee Compare May 21, 2026 10:42
Comment thread docs/migration.md
Comment thread docs/client.md
Comment thread examples/client/src/simpleOAuthClient.ts
@felixweinberger felixweinberger force-pushed the fweinberger/v2-tasks-delete branch from c223fee to 65f8c17 Compare May 21, 2026 11:13
@felixweinberger
Copy link
Copy Markdown
Contributor Author

@claude review

Comment thread test/integration/test/client/client.test.ts
…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).
@felixweinberger felixweinberger force-pushed the fweinberger/v2-tasks-delete branch from 65f8c17 to 96f39c0 Compare May 22, 2026 08:53
@felixweinberger felixweinberger marked this pull request as ready for review May 22, 2026 11:22
@felixweinberger felixweinberger requested a review from a team as a code owner May 22, 2026 11:22
@felixweinberger
Copy link
Copy Markdown
Contributor Author

@claude review

Comment thread docs/migration.md
Comment on lines +864 to +866
- `mcpServer.experimental.tasks.registerToolTask(...)`, `ToolTaskHandler`, `TaskRequestHandler`, `CreateTaskRequestHandler`
- `TaskMessageQueue`, `InMemoryTaskMessageQueue`, `Queued*` message types, `CreateTaskServerContext`, `TaskServerContext`, `TaskToolExecution`
- `examples/{client,server}/src/simpleTaskInteractive*.ts`
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 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:

  1. Response-message family. docs/migration-SKILL.md:489 lists the deleted responseMessage.ts exports as ResponseMessage, TaskStatusMessage, TaskCreatedMessage, ResultMessage, takeResult, toArrayAsync. But the deleted file also publicly exported BaseResponseMessage, ErrorMessage, and AsyncGeneratorValue — the first two were explicit re-exports from the deleted lines in packages/core/src/exports/public/index.ts (export type { BaseResponseMessage, ErrorMessage, ResponseMessage, ... }), and AsyncGeneratorValue was reachable through the now-removed export * from './shared/responseMessage.js' barrel in packages/core/src/index.ts.
  2. Queued-message family. docs/migration.md:865 and docs/migration-SKILL.md:488 use a Queued* glob to cover QueuedMessage / QueuedRequest / QueuedNotification / QueuedResponse / QueuedError. That glob does not lexically match BaseQueuedMessage (no Queued prefix), which was also an explicit re-export from exports/public/index.ts and 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

  1. A v1 user has import type { ErrorMessage, BaseQueuedMessage } from '@modelcontextprotocol/core'; — both resolve before this PR via the explicit re-exports in packages/core/src/exports/public/index.ts.
  2. They upgrade and read §12 of docs/migration-SKILL.md. The two relevant rows enumerate ResponseMessage, TaskStatusMessage, TaskCreatedMessage, ResultMessage, takeResult, toArrayAsync and TaskMessageQueue, InMemoryTaskMessageQueue, Queued*, ... — neither name appears.
  3. They conclude their imports are unaffected and rebuild.
  4. tsc fails: Module '\"@modelcontextprotocol/core\"' has no exported member 'ErrorMessage' and 'BaseQueuedMessage' — because the re-exports are deleted and responseMessage.ts / interfaces.ts no longer exist.
  5. 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:863 and docs/migration-SKILL.md:489 → append BaseResponseMessage, ErrorMessage, AsyncGeneratorValue.
  • docs/migration.md:865 and docs/migration-SKILL.md:488 → append BaseQueuedMessage (or change Queued* 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.

Comment on lines 718 to 724
*
* Primitive type aliases — no object keys to compare (8):
* JSONValue, JSONArray, Role, LoggingLevel, ProgressToken, RequestId,
* Cursor, TaskStatus
* Cursor
*/

// -- Simple types (96) --
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 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

  1. Open packages/core/test/spec.types.test.ts at 96f39c0.
  2. Run awk 'NR>=724 && NR<831 && /^type _K_/' … | wc -l → 86 (header says 96).
  3. Same for the other three ranges (831–860 → 10, 860–884 → 17, 884–918 → 16).
  4. Count names in the bullet at lines 719–722 → 7 (header says 8). Cumulative "(23 entries)" at line 711 is 15 + 7 = 22.
  5. 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.

Comment on lines +1 to +6
---
'@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.
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 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 requestStream to call tasks/result for failed tasks instead of yielding a hardcoded ProtocolError. When a task reaches the failed terminal status, the stream now retrieves and yields the actual stored result (matching the behavior for completed tasks), 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 — contained TaskManager.requestStream (the function the changeset names) and the tasks/result handler registration in bind().
  • packages/core/src/shared/responseMessage.ts — the ResponseMessage types yielded by requestStream.
  • packages/client/src/experimental/tasks/client.ts and packages/server/src/experimental/tasks/server.ts — the public requestStream wrappers.
  • The tasks/result method, GetTaskPayloadRequestSchema, and the rest of the tasks request surface from packages/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:

  1. A major entry from sep-2663-tasks-removal.md: "remove 2025-11 experimental tasks (TaskManager, experimental.tasks.* accessors)"
  2. A patch entry from fix-failed-task-result-retrieval.md: "Fix requestStream to call tasks/result for 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

  1. cat .changeset/fix-failed-task-result-retrieval.md → exists, body describes a requestStream / tasks/result fix.
  2. jq '.changesets | index("fix-failed-task-result-retrieval")' .changeset/pre.jsonnull (not consumed; still pending).
  3. git show HEAD --stat | grep taskManagerpackages/core/src/shared/taskManager.ts deleted (915 lines removed) — the file that defined requestStream and the tasks/result handler.
  4. Run changeset version (or wait for the next release cut) → the CHANGELOG gains a ### Patch Changes entry describing the requestStream fix immediately adjacent to the ### Major Changes entry from sep-2663-tasks-removal.md announcing 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.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

v2-stateless 2026-06 SDK: Protocol decomposition + SEP alignment (request-first / stateless)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant