# MCP TypeScript SDK changelog > The official TypeScript SDK for building Model Context Protocol servers and clients. - Vendor: Anthropic - Category: Frameworks & Libraries - Official site: https://github.com/modelcontextprotocol/typescript-sdk - Tracked by: What's New (https://whatsnew.fyi/product/mcp-typescript-sdk) - Harvested from: GitHub (modelcontextprotocol/typescript-sdk) - Entries below: 9 (newest first) What's New is an index, not a publisher: every entry below links to the vendor's own release notes, which are the authoritative source. Entries are labelled where they are hand-curated sample data, pre-releases, or drawn from a secondary source such as a developer blog. ## Releases ### 2.0.0 - Date: 2026-07-27 - Version: 2.0.0 - Original notes: https://github.com/modelcontextprotocol/typescript-sdk/releases/tag/%40modelcontextprotocol/server%402.0.0 - Permalink: https://whatsnew.fyi/product/mcp-typescript-sdk/releases/2.0.0 - **added** — Export the Protocol base class and mergeCapabilities from the @modelcontextprotocol/client and @modelcontextprotocol/server package roots - **added** — Add configurable SSE keep-alive comment frames to Streamable HTTP transports and apply createMcpHandler's existing keepAliveMs option to every HTTP SSE stream it serves - **added** — Add runtime-neutral Bearer authentication to @modelcontextprotocol/server with requireBearerAuth for web-standard fetch request hosts - **changed** — Move schema source modules into @modelcontextprotocol/core and resolve them as a regular runtime dependency instead of bundling a private copy into each package - **changed** — Allow inputRequired.elicit() to accept a Standard Schema such as a Zod object for requestedSchema, with support for email, uri, date, and date-time formats - **changed** — Align the 2026-07-28 wire with the final revision: serverInfo moves from the DiscoverResult body to the result _meta, and the per-request envelope's clientInfo demotes from required to SHOULD - **changed** — Break DiscoverResult type to no longer declare serverInfo and make RequestMetaEnvelope's clientInfo optional - **added** — Add new public constant SERVER_INFO_META_KEY for 'io.modelcontextprotocol/serverInfo' ###### Minor Changes - [#2501](https://github.com/modelcontextprotocol/typescript-sdk/pull/2501) [`1480241`](https://github.com/modelcontextprotocol/typescript-sdk/commit/1480241e2a2a7f0ceee8e7723b2adcf88579bb36) Thanks [@felixweinberger](https://github.com/felixweinberger)! - Export the `Protocol` base class and `mergeCapabilities` from the `@modelcontextprotocol/client` and `@modelcontextprotocol/server` package roots, restoring the v1 import for consumers that subclass `Protocol` (e.g. the MCP Apps SDK). The client and server packages each bundle their own compiled copy of the class, so import it from one package consistently within a process. The codemod now rewrites `Protocol` and `mergeCapabilities` imports from `shared/protocol.js` to the client or server package root, like the module's other symbols, instead of dropping them with an action-required marker. - [#2477](https://github.com/modelcontextprotocol/typescript-sdk/pull/2477) [`8e1d2e9`](https://github.com/modelcontextprotocol/typescript-sdk/commit/8e1d2e92b1720d2520122b3a5f20ea084edaf3c4) Thanks [@felixweinberger](https://github.com/felixweinberger)! - Move the schema source modules (spec schemas, OAuth schemas, protocol constants) into `@modelcontextprotocol/core` and resolve them from there as a regular runtime dependency instead of bundling a private copy into each package. An application importing more than one of the packages now evaluates a single shared schema graph with shared object identity. `@modelcontextprotocol/core` gains a `./internal` subpath (SDK-internal contract; may change in any release) and the four packages now version together. - [#2513](https://github.com/modelcontextprotocol/typescript-sdk/pull/2513) [`f413763`](https://github.com/modelcontextprotocol/typescript-sdk/commit/f4137630c05dc9a4fb14d4d3777f5cb167bd6313) Thanks [@felixweinberger](https://github.com/felixweinberger)! - Align the 2026-07-28 wire with the final revision (spec PR #3002): `serverInfo` moves from the `DiscoverResult` body to the result `_meta`, and the per-request envelope's `clientInfo` demotes from required to SHOULD. Before this change the SDK shipped the pre-#3002 shape in both directions: the client hard-rejected a conforming server's `DiscoverResult` (missing body `serverInfo` failed parse, so the probe misclassified the server as legacy and attempted an `initialize` handshake against it — a hard connect failure against a modern-only server such as go-sdk v1.7.0-pre.3), and the server rejected conforming clients that omit `clientInfo`. Now: - The 2026 wire schemas are the final revision exactly: no body `serverInfo` on `DiscoverResult`, envelope `clientInfo` optional (a present-but-malformed value still fails validation). - Servers stamp `_meta['io.modelcontextprotocol/serverInfo']` on every 2026-era response (spec SHOULD; a handler-authored value wins, the 2025-era wire is untouched). This includes the entry-built `subscriptions/listen` graceful-close results — the spec's `SubscriptionsListenResultMeta` extends `ResultMetaObject`. - Clients keep sending `clientInfo` and read server identity from the discover result's `_meta` only. A server that stamps no identity is anonymous: `getServerVersion()` is `undefined` and the response cache partitions under a per-connection surrogate. A malformed `_meta` serverInfo value is treated as absent on receive (the spec marks the field self-reported, unverified, and display-only). - Breaking type changes: `DiscoverResult` no longer declares `serverInfo`; `RequestMetaEnvelope`'s `clientInfo` is optional. New public constant `SERVER_INFO_META_KEY` (`'io.modelcontextprotocol/serverInfo'`). - [#2369](https://github.com/modelcontextprotocol/typescript-sdk/pull/2369) [`24be404`](https://github.com/modelcontextprotocol/typescript-sdk/commit/24be4040d454a9c5983901229068477c7a9ea796) Thanks [@mattzcarey](https://github.com/mattzcarey)! - Allow `inputRequired.elicit()` to accept a Standard Schema su _[Truncated at 4000 characters — full notes: https://github.com/modelcontextprotocol/typescript-sdk/releases/tag/%40modelcontextprotocol/server%402.0.0]_ ### 2.0.0-beta.5 - Date: 2026-07-21 - Version: 2.0.0-beta.5 - Original notes: https://github.com/modelcontextprotocol/typescript-sdk/releases/tag/%40modelcontextprotocol/server%402.0.0-beta.5 - Permalink: https://whatsnew.fyi/product/mcp-typescript-sdk/releases/2.0.0-beta.5 - Labels: Pre-release - **added** — Export the Protocol base class and mergeCapabilities from the @modelcontextprotocol/client and @modelcontextprotocol/server package roots - **changed** — The codemod now rewrites Protocol and mergeCapabilities imports from shared/protocol.js to the client or server package root instead of dropping them - **changed** — Align the 2026-07-28 wire with the final revision: serverInfo moves from the DiscoverResult body to the result _meta, and the per-request envelope's clientInfo demotes from required to optional - **changed** — Servers now stamp _meta['io.modelcontextprotocol/serverInfo'] on every 2026-era response including subscriptions/listen graceful-close results - **changed** — Clients keep sending clientInfo and read server identity from the discover result's _meta only, with anonymous servers returning undefined from getServerVersion() - **changed** — DiscoverResult no longer declares serverInfo and RequestMetaEnvelope's clientInfo is optional - **added** — Add public constant SERVER_INFO_META_KEY with value 'io.modelcontextprotocol/serverInfo' ###### Minor Changes - [#2501](https://github.com/modelcontextprotocol/typescript-sdk/pull/2501) [`1480241`](https://github.com/modelcontextprotocol/typescript-sdk/commit/1480241e2a2a7f0ceee8e7723b2adcf88579bb36) Thanks [@felixweinberger](https://github.com/felixweinberger)! - Export the `Protocol` base class and `mergeCapabilities` from the `@modelcontextprotocol/client` and `@modelcontextprotocol/server` package roots, restoring the v1 import for consumers that subclass `Protocol` (e.g. the MCP Apps SDK). The client and server packages each bundle their own compiled copy of the class, so import it from one package consistently within a process. The codemod now rewrites `Protocol` and `mergeCapabilities` imports from `shared/protocol.js` to the client or server package root, like the module's other symbols, instead of dropping them with an action-required marker. - [#2513](https://github.com/modelcontextprotocol/typescript-sdk/pull/2513) [`f413763`](https://github.com/modelcontextprotocol/typescript-sdk/commit/f4137630c05dc9a4fb14d4d3777f5cb167bd6313) Thanks [@felixweinberger](https://github.com/felixweinberger)! - Align the 2026-07-28 wire with the final revision (spec PR #3002): `serverInfo` moves from the `DiscoverResult` body to the result `_meta`, and the per-request envelope's `clientInfo` demotes from required to SHOULD. Before this change the SDK shipped the pre-#3002 shape in both directions: the client hard-rejected a conforming server's `DiscoverResult` (missing body `serverInfo` failed parse, so the probe misclassified the server as legacy and attempted an `initialize` handshake against it — a hard connect failure against a modern-only server such as go-sdk v1.7.0-pre.3), and the server rejected conforming clients that omit `clientInfo`. Now: - The 2026 wire schemas are the final revision exactly: no body `serverInfo` on `DiscoverResult`, envelope `clientInfo` optional (a present-but-malformed value still fails validation). - Servers stamp `_meta['io.modelcontextprotocol/serverInfo']` on every 2026-era response (spec SHOULD; a handler-authored value wins, the 2025-era wire is untouched). This includes the entry-built `subscriptions/listen` graceful-close results — the spec's `SubscriptionsListenResultMeta` extends `ResultMetaObject`. - Clients keep sending `clientInfo` and read server identity from the discover result's `_meta` only. A server that stamps no identity is anonymous: `getServerVersion()` is `undefined` and the response cache partitions under a per-connection surrogate. A malformed `_meta` serverInfo value is treated as absent on receive (the spec marks the field self-reported, unverified, and display-only). - Breaking type changes: `DiscoverResult` no longer declares `serverInfo`; `RequestMetaEnvelope`'s `clientInfo` is optional. New public constant `SERVER_INFO_META_KEY` (`'io.modelcontextprotocol/serverInfo'`). ###### Patch Changes - Updated dependencies [[`f413763`](https://github.com/modelcontextprotocol/typescript-sdk/commit/f4137630c05dc9a4fb14d4d3777f5cb167bd6313)]: - @modelcontextprotocol/core@2.0.0-beta.5 ### 2.0.0-beta.4 - Date: 2026-07-13 - Version: 2.0.0-beta.4 - Original notes: https://github.com/modelcontextprotocol/typescript-sdk/releases/tag/%40modelcontextprotocol/server%402.0.0-beta.4 - Permalink: https://whatsnew.fyi/product/mcp-typescript-sdk/releases/2.0.0-beta.4 - Labels: Pre-release - **changed** — Move schema source modules (spec schemas, OAuth schemas, protocol constants) into @modelcontextprotocol/core and resolve them from there as a regular runtime dependency instead of bundling a private copy into each package - **added** — Add preloadSchemas(), an explicit opt-in to eager wire-schema construction, called automatically in Cloudflare Workers builds - **changed** — Wire schemas are now built lazily by default instead of at import time - **changed** — The server package gains a dedicated browser shim for lazy schema construction, separate from the workerd shim - **changed** — Construct the default Ajv validation engine lazily on first validation instead of at startup - **changed** — Build protocol-revision wire schemas lazily on first validation using a module-level memoized factory ###### Minor Changes - [#2477](https://github.com/modelcontextprotocol/typescript-sdk/pull/2477) [`8e1d2e9`](https://github.com/modelcontextprotocol/typescript-sdk/commit/8e1d2e92b1720d2520122b3a5f20ea084edaf3c4) Thanks [@felixweinberger](https://github.com/felixweinberger)! - Move the schema source modules (spec schemas, OAuth schemas, protocol constants) into `@modelcontextprotocol/core` and resolve them from there as a regular runtime dependency instead of bundling a private copy into each package. An application importing more than one of the packages now evaluates a single shared schema graph with shared object identity. `@modelcontextprotocol/core` gains a `./internal` subpath (SDK-internal contract; may change in any release) and the four packages now version together. - [#2483](https://github.com/modelcontextprotocol/typescript-sdk/pull/2483) [`3f07a32`](https://github.com/modelcontextprotocol/typescript-sdk/commit/3f07a325c6741b2374ce2255846dfa0c25f74d03) Thanks [@felixweinberger](https://github.com/felixweinberger)! - Add `preloadSchemas()`, an explicit opt-in to eager wire-schema construction, and call it automatically in the Cloudflare Workers builds. The wire schemas are built lazily by default, which is the right trade on process-per-invocation runtimes — but on isolate platforms that bill request CPU while module evaluation runs during isolate warm-up, laziness moves construction into the first request each fresh isolate serves. Calling `preloadSchemas()` at module scope (it is synchronous and idempotent) moves that one-time cost back to module evaluation; the packages' workerd export condition now does this automatically, while the Node and browser builds stay lazy. The server package gains a dedicated browser shim for this (its `browser` condition previously reused the workerd shim), so browser bundles keep lazy construction. ###### Patch Changes - [#2458](https://github.com/modelcontextprotocol/typescript-sdk/pull/2458) [`7c49b47`](https://github.com/modelcontextprotocol/typescript-sdk/commit/7c49b47fb3a58b51cec8fd0b337f656515f1a2b7) Thanks [@felixweinberger](https://github.com/felixweinberger)! - Construct the default Ajv validation engine lazily on first validation. Creating a `Client` or `Server` no longer pays the ajv + ajv-formats instantiation cost at startup when no JSON Schema validation ever runs. - [#2476](https://github.com/modelcontextprotocol/typescript-sdk/pull/2476) [`e0a0ab7`](https://github.com/modelcontextprotocol/typescript-sdk/commit/e0a0ab74d9baed74572c9f435313fb6daef1b989) Thanks [@felixweinberger](https://github.com/felixweinberger)! - Build protocol-revision wire schemas lazily on first validation instead of at import. Each revision's schema set is now constructed by a module-level memoized factory, so importing the client or server package no longer pays the construction cost of both frozen wire-schema graphs up front. Method membership in the revision registries stays static, the schemas themselves are unchanged, and registry lookups keep returning reference-identical schema objects. - Updated dependencies [[`8e1d2e9`](https://github.com/modelcontextprotocol/typescript-sdk/commit/8e1d2e92b1720d2520122b3a5f20ea084edaf3c4)]: - @modelcontextprotocol/core@2.0.0-beta.4 ### 2.0.0-beta.3 - Date: 2026-07-09 - Version: 2.0.0-beta.3 - Original notes: https://github.com/modelcontextprotocol/typescript-sdk/releases/tag/%40modelcontextprotocol/server%402.0.0-beta.3 - Permalink: https://whatsnew.fyi/product/mcp-typescript-sdk/releases/2.0.0-beta.3 - Labels: Pre-release - **added** — Allow `inputRequired.elicit()` to accept a Standard Schema such as a Zod object for `requestedSchema`, with support for Zod formats mapping to `email`, `uri`, `date`, and `date-time` - **added** — Add runtime-neutral Bearer authentication to `@modelcontextprotocol/server` with `requireBearerAuth`, `verifyBearerToken`, and `bearerAuthChallengeResponse` for web-standard `fetch(request)` hosts - **added** — Add runtime-neutral OAuth discovery serving to `@modelcontextprotocol/server` with `oauthMetadataResponse` and `buildOAuthProtectedResourceMetadata` for RFC 9728 and RFC 8414 metadata documents - **changed** — Express middleware Bearer authentication now applies RFC 7235 quoted-string sanitization to `WWW-Authenticate` challenge values - **changed** — OAuth metadata serving validates requests lazily, tolerates trailing slashes, supports HEAD requests, and marks reflected CORS preflights with `Vary` - **changed** — Insecure issuer escape hatch changed from module-scope environment read to explicit `dangerouslyAllowInsecureIssuerUrl` option in OAuth metadata core - **fixed** — Restore v1 parse tolerance for `CallToolResult.content` to default to `[]` when absent in inbound legacy-era `tools/call` results - **fixed** — Fix CommonJS `validators/ajv` subpath to properly export the bundled provider's `Ajv` class - **fixed** — Reject POSTs with non-`application/json` `Content-Type` media type with `415 Unsupported Media Type` and parse the header correctly instead of substring-matching ###### Minor Changes - [#2369](https://github.com/modelcontextprotocol/typescript-sdk/pull/2369) [`24be404`](https://github.com/modelcontextprotocol/typescript-sdk/commit/24be4040d454a9c5983901229068477c7a9ea796) Thanks [@mattzcarey](https://github.com/mattzcarey)! - Allow `inputRequired.elicit()` to accept a Standard Schema such as a Zod object for `requestedSchema`. The builder converts it to MCP's restricted form-elicitation JSON Schema, while the same schema can validate and type the response through `acceptedContent()` on handler re-entry. Zod formats mapping to `email`, `uri`, `date`, and `date-time` are supported. Shapes the restricted schema cannot express reject before anything is sent — nested objects, `.regex()` and customized zod format patterns, exclusive number bounds (`.positive()`/`.gt()`), literal unions (use `z.enum` or `z.literal(['a', 'b'])`), and non-spec root keywords like `z.strictObject()`'s `additionalProperties`. - [#2420](https://github.com/modelcontextprotocol/typescript-sdk/pull/2420) [`7635115`](https://github.com/modelcontextprotocol/typescript-sdk/commit/7635115d0112c3f980b45a9773a4770660af8aae) Thanks [@felixweinberger](https://github.com/felixweinberger)! - Add runtime-neutral Bearer authentication to `@modelcontextprotocol/server`: `requireBearerAuth` gates web-standard `fetch(request)` hosts (Cloudflare Workers, Deno, Bun, Hono), built on the exported `verifyBearerToken` and `bearerAuthChallengeResponse` pieces, with `OAuthTokenVerifier` now defined here. The Express middleware adapts the same core and is unchanged in behavior, except that `WWW-Authenticate` challenge values are now RFC 7235 quoted-string sanitized (quotes and backslashes escaped, control and non-ASCII characters replaced); `@modelcontextprotocol/express` re-exports `OAuthTokenVerifier` as before. - [#2422](https://github.com/modelcontextprotocol/typescript-sdk/pull/2422) [`61866d7`](https://github.com/modelcontextprotocol/typescript-sdk/commit/61866d7a5ff4475663ceb525c88447c497c1b92a) Thanks [@felixweinberger](https://github.com/felixweinberger)! - Add runtime-neutral OAuth discovery serving to `@modelcontextprotocol/server`: `oauthMetadataResponse` serves the RFC 9728 Protected Resource Metadata and RFC 8414 Authorization Server metadata documents from web-standard `fetch(request)` hosts, built on the exported `buildOAuthProtectedResourceMetadata`, with `getOAuthProtectedResourceMetadataUrl` now defined here. The Express metadata router adapts the same core and is unchanged in behavior; the insecure-issuer escape hatch is an explicit `dangerouslyAllowInsecureIssuerUrl` option in the neutral core instead of a module-scope environment read. The web-standard matcher validates lazily so unmatched traffic always falls through, tolerates a trailing slash, supports HEAD, and marks reflected CORS preflights with `Vary`. ###### Patch Changes - [#2456](https://github.com/modelcontextprotocol/typescript-sdk/pull/2456) [`44797d7`](https://github.com/modelcontextprotocol/typescript-sdk/commit/44797d77792953d0ce70b68922bb6bb69e697c32) Thanks [@felixweinberger](https://github.com/felixweinberger)! - Restore the v1 parse tolerance for `CallToolResult.content`: an inbound legacy-era `tools/call` result without `content` defaults to `[]` instead of failing validation. Deployed servers — accepted by SDK v1 for years — return `structuredContent`-only (or otherwise content-less) results, and the strict parse turned every such call into an `INVALID_RESULT` error before application code could run. The silent-empty-success hazard the strictness guarded is preserved where it matters: the 2025 era's wire-seam schema refuses to default `content` for a body carrying another result family's vocabulary (`task`, `inputRequests`, `requestState` — the era is frozen, so the list is complete), and the 2026-era wire schemas stay strict — modern-revision servers have no legacy excuse. Task interop through an exp _[Truncated at 4000 characters — full notes: https://github.com/modelcontextprotocol/typescript-sdk/releases/tag/%40modelcontextprotocol/server%402.0.0-beta.3]_ ### 2.0.0-beta.2 - Date: 2026-07-02 - Version: 2.0.0-beta.2 - Original notes: https://github.com/modelcontextprotocol/typescript-sdk/releases/tag/%40modelcontextprotocol/server%402.0.0-beta.2 - Permalink: https://whatsnew.fyi/product/mcp-typescript-sdk/releases/2.0.0-beta.2 - Labels: Pre-release - **changed** — Ship CommonJS builds alongside ESM by emitting both .mjs/.d.mts and .cjs/.d.cts for each package and updating the exports map to add a require condition so require('@modelcontextprotocol/…') works from CommonJS consumers - **changed** — Return HTTP 400 for a MissingRequiredClientCapabilityError (-32021) produced after dispatch instead of surfacing it in-band on HTTP 200 ###### Patch Changes - [#2405](https://github.com/modelcontextprotocol/typescript-sdk/pull/2405) [`f172626`](https://github.com/modelcontextprotocol/typescript-sdk/commit/f172626a8e98b2ae2f0f690e4afb4dc74dbf6011) Thanks [@mattzcarey](https://github.com/mattzcarey)! - Ship CommonJS builds alongside ESM. Each package now emits both `.mjs`/`.d.mts` and `.cjs`/`.d.cts` (via tsdown `format: ['esm', 'cjs']`), and its `exports` map adds a `require` condition so `require('@modelcontextprotocol/…')` works from CommonJS consumers. Output extensions are normalized across all packages (`@modelcontextprotocol/core` moves from `.js`/`.d.ts` to `.mjs`/`.d.mts`); the public import paths are unchanged. - [#2399](https://github.com/modelcontextprotocol/typescript-sdk/pull/2399) [`3c7ddaf`](https://github.com/modelcontextprotocol/typescript-sdk/commit/3c7ddafa05d8f17fb52168bf4638f09251c3d0ff) Thanks [@felixweinberger](https://github.com/felixweinberger)! - Return HTTP 400 for a `MissingRequiredClientCapabilityError` (`-32021`) produced after dispatch. The spec mandates `400 Bad Request` for this error with no condition on where it arose, but only the pre-dispatch capability gate honored that; the post-handler emission — the `input_required` gate rejecting an embedded request whose required capability the caller did not declare — surfaced in-band on HTTP 200. The JSON-RPC error body is unchanged, every other error code (including a handler relaying a downstream peer's `-32020`/`-32022`) keeps the origin-keyed in-band behavior, and the mapping only applies while the response is uncommitted: an exchange that already streamed — or one hosted with `responseMode: 'sse'`, which opens its stream at dispatch end — keeps its committed 200 and carries the error in-stream. ### 2.0.0-beta.1 - Date: 2026-06-30 - Version: 2.0.0-beta.1 - Original notes: https://github.com/modelcontextprotocol/typescript-sdk/releases/tag/%40modelcontextprotocol/server%402.0.0-beta.1 - Permalink: https://whatsnew.fyi/product/mcp-typescript-sdk/releases/2.0.0-beta.1 - Labels: Pre-release - **added** — Support for the MCP 2026-07-28 specification revision ###### Patch Changes - [#2402](https://github.com/modelcontextprotocol/typescript-sdk/pull/2402) [`a400259`](https://github.com/modelcontextprotocol/typescript-sdk/commit/a4002596b914c675d17ac22471d1287976dbb52a) Thanks [@felixweinberger](https://github.com/felixweinberger)! - First beta release of SDK v2 with support for the MCP 2026-07-28 specification revision. See the migration guides for upgrading from v1 (`docs/migration/upgrade-to-v2.md`) and adopting the 2026-07-28 revision (`docs/migration/support-2026-07-28.md`). ### 2.0.0-alpha.4 - Date: 2026-06-30 - Version: 2.0.0-alpha.4 - Original notes: https://github.com/modelcontextprotocol/typescript-sdk/releases/tag/%40modelcontextprotocol/server%402.0.0-alpha.4 - Permalink: https://whatsnew.fyi/product/mcp-typescript-sdk/releases/2.0.0-alpha.4 - Labels: Pre-release - **changed** — Split the wire layer into per-era codecs and make protocol-revision deletions physical, with resultType no longer modeled by neutral wire schema and EmptyResultSchema now rejecting resultType bodies - **changed** — Make CallToolResult.content and ToolResultContent.content required at the wire boundary, rejecting handler results without content with -32602 instead of silently defaulting - **changed** — Custom handlers now receive _meta minus reserved envelope keys instead of having it deleted before params validation - **changed** — Rescope specTypeSchemas to the neutral model with result validators no longer accepting resultType and task message-type validators removed from public set - **changed** — Remove task vocabulary from role aggregate types and schemas while keeping deprecated Task* types importable - **changed** — Make era-mismatched spec methods fail physically with -32601 for inbound era-deleted methods and SdkErrorCode.MethodNotSupportedByProtocolVersion for outbound sends - **changed** — Change createMcpHandler to return web-standards-only handler with fetch, close, notify, and bus properties - **removed** — Remove duck-typed .node(req, res, parsedBody?) face from createMcpHandler - **added** — Export toNodeHandler from @modelcontextprotocol/node to adapt createMcpHandler for Node frameworks - **added** — Add optional onerror callback to toNodeHandler for adapter-level error fallback observability - **changed** — Move NodeIncomingMessageLike and NodeServerResponseLike from @modelcontextprotocol/server to @modelcontextprotocol/node - **changed** — Hide wire-only protocol members from public surface by removing resultType from public result types - **changed** — Strip complete results to public shape and reject other result kinds like input_required with SdkErrorCode.UnsupportedResultType - **changed** — Lift reserved _meta envelope keys from inbound requests and notifications before handlers run - **changed** — Surface lifted envelope material at ctx.mcpReq.envelope, ctx.mcpReq.inputResponses, and ctx.mcpReq.requestState for requests - **deprecated** — Mark task wire vocabulary as deprecated and exclude from typed method maps - **changed** — Type callTool as plain CallToolResult without task result types - **fixed** — Return JSON-RPC error code -32602 for resources/read with unknown URI on every protocol revision with error.data.uri echoing the requested URI - **changed** — Map handler-thrown -32002 to -32602 on the wire via WireCodec.encodeErrorCode - **deprecated** — Keep ProtocolErrorCode.ResourceNotFound (-32002) importable as receive-tolerated vocabulary ###### Major Changes - [#2286](https://github.com/modelcontextprotocol/typescript-sdk/pull/2286) [`1823aae`](https://github.com/modelcontextprotocol/typescript-sdk/commit/1823aae891837ebb5e3db885ec635f9efefd5771) Thanks [@felixweinberger](https://github.com/felixweinberger)! - Split the wire layer into per-era codecs and make protocol-revision deletions physical. Deliberate wire/schema behavior changes (see docs/migration/support-2026-07-28.md "Per-era wire codecs"): - `resultType` is no longer modeled by any neutral wire schema: `EmptyResultSchema` (strict) now rejects `{resultType}` bodies; on 2025-era connections a foreign `resultType` is stripped before validation instead of rejected; the member exists only inside the 2026-era codec, which requires it. - `CallToolResult.content` / `ToolResultContent.content` are required at the wire boundary (`content.default([])` removed): handler results without `content` are rejected with `-32602` instead of silently defaulted, and content-less wire results fail the client parse loudly. - Custom (3-arg) handlers now receive `_meta` minus the reserved envelope keys instead of having it deleted before params validation. - `specTypeSchemas` re-scoped to the neutral model: result validators no longer accept `resultType`; task message-type validators and `RequestMetaEnvelope` left the public set (`SpecTypeName` narrowed). - Role aggregate types/schemas (`ClientRequest`, `ServerResult`, …) no longer carry task vocabulary; the deprecated `Task*` types remain importable unchanged. - Era-mismatched spec methods fail physically: inbound era-deleted methods get `-32601` even with a handler registered; outbound sends throw `SdkErrorCode.MethodNotSupportedByProtocolVersion` locally. - Value guards (`isCallToolResult`, …) are documented as neutral-shape consumer checks, not wire validators. - [#2286](https://github.com/modelcontextprotocol/typescript-sdk/pull/2286) [`1823aae`](https://github.com/modelcontextprotocol/typescript-sdk/commit/1823aae891837ebb5e3db885ec635f9efefd5771) Thanks [@felixweinberger](https://github.com/felixweinberger)! - `createMcpHandler` now returns a web-standards-only `{ fetch, close, notify, bus }` handler — the shape Workers/Bun/Deno expect from `export default`. The duck-typed `.node(req, res, parsedBody?)` face is removed; Node frameworks (Express, Fastify, plain `node:http`) wrap the handler once with the new `toNodeHandler(handler, { onerror? })` exported from `@modelcontextprotocol/node`, which converts the Node request to a web-standard `Request`, calls `handler.fetch`, and writes the `Response` back honoring write backpressure. The optional `onerror` receives the adapter-level error fallback (request conversion / `handler.fetch` throw) before the `500` response is written, restoring observability parity with the removed `.node` face. `NodeIncomingMessageLike` and `NodeServerResponseLike` move from `@modelcontextprotocol/server` to `@modelcontextprotocol/node`. - [#2286](https://github.com/modelcontextprotocol/typescript-sdk/pull/2286) [`1823aae`](https://github.com/modelcontextprotocol/typescript-sdk/commit/1823aae891837ebb5e3db885ec635f9efefd5771) Thanks [@felixweinberger](https://github.com/felixweinberger)! - Hide wire-only protocol members from the public surface, at the type level and at runtime. `resultType` (the 2026-07-28 result discrimination field) is no longer declared on any public result type — the wire schemas keep parsing it, and the client funnel now consumes it raw-first: `'complete'` results are stripped to the public shape and any other kind (e.g. `input_required`) rejects with the new `SdkErrorCode.UnsupportedResultType` instead of masking into an empty success. The reserved `_meta` envelope keys are lifted out of inbound requests and notifications before handlers run, and the multi-round-trip retry fields (`inputResponses`, `requestState`) out of inbound requests only (the spec reser _[Truncated at 4000 characters — full notes: https://github.com/modelcontextprotocol/typescript-sdk/releases/tag/%40modelcontextprotocol/server%402.0.0-alpha.4]_ ### 2.0.0-alpha.2 - Date: 2026-04-01 - Version: 2.0.0-alpha.2 - Original notes: https://github.com/modelcontextprotocol/typescript-sdk/releases/tag/%40modelcontextprotocol/server%402.0.0-alpha.2 - Permalink: https://whatsnew.fyi/product/mcp-typescript-sdk/releases/2.0.0-alpha.2 - Labels: Pre-release ###### Patch Changes - [#1840](https://github.com/modelcontextprotocol/typescript-sdk/pull/1840) [`424cbae`](https://github.com/modelcontextprotocol/typescript-sdk/commit/424cbaeee13b7fe18d38048295135395b9ad81bb) Thanks [@KKonstantinov](https://github.com/KKonstantinov)! - tsdown exports resolution fix ### 2.0.0-alpha.1 - Date: 2026-04-01 - Version: 2.0.0-alpha.1 - Original notes: https://github.com/modelcontextprotocol/typescript-sdk/releases/tag/%40modelcontextprotocol/server%402.0.0-alpha.1 - Permalink: https://whatsnew.fyi/product/mcp-typescript-sdk/releases/2.0.0-alpha.1 - Labels: Pre-release ###### Major Changes - [#1389](https://github.com/modelcontextprotocol/typescript-sdk/pull/1389) [`108f2f3`](https://github.com/modelcontextprotocol/typescript-sdk/commit/108f2f3ab6a1267587c7c4f900b6eca3cc2dae51) Thanks [@DePasqualeOrg](https://github.com/DePasqualeOrg)! - Fix error handling for unknown tools and resources per MCP spec. **Tools:** Unknown or disabled tool calls now return JSON-RPC protocol errors with code `-32602` (InvalidParams) instead of `CallToolResult` with `isError: true`. Callers who checked `result.isError` for unknown tools should catch rejected promises instead. **Resources:** Unknown resource reads now return error code `-32002` (ResourceNotFound) instead of `-32602` (InvalidParams). Added `ProtocolErrorCode.ResourceNotFound`. ###### Minor Changes - [#1673](https://github.com/modelcontextprotocol/typescript-sdk/pull/1673) [`462c3fc`](https://github.com/modelcontextprotocol/typescript-sdk/commit/462c3fc47dffac908d2ba27784d47ff010fa065e) Thanks [@KKonstantinov](https://github.com/KKonstantinov)! - refactor: extract task orchestration from Protocol into TaskManager **Breaking changes:** - `taskStore`, `taskMessageQueue`, `defaultTaskPollInterval`, and `maxTaskQueueSize` moved from `ProtocolOptions` to `capabilities.tasks` on `ClientOptions`/`ServerOptions` - [#1689](https://github.com/modelcontextprotocol/typescript-sdk/pull/1689) [`0784be1`](https://github.com/modelcontextprotocol/typescript-sdk/commit/0784be1a67fb3cc2aba0182d88151264f4ea73c8) Thanks [@felixweinberger](https://github.com/felixweinberger)! - Support Standard Schema for tool and prompt schemas Tool and prompt registration now accepts any schema library that implements the [Standard Schema spec](https://standardschema.dev/): Zod v4, Valibot, ArkType, and others. `RegisteredTool.inputSchema`, `RegisteredTool.outputSchema`, and `RegisteredPrompt.argsSchema` now use `StandardSchemaWithJSON` (requires both `~standard.validate` and `~standard.jsonSchema`) instead of the Zod-specific `AnySchema` type. **Zod v4 schemas continue to work unchanged** — Zod v4 implements the required interfaces natively. ```typescript import { type } from 'arktype'; server.registerTool( 'greet', { inputSchema: type({ name: 'string' }) }, async ({ name }) => ({ content: [{ type: 'text', text: `Hello, ${name}!` }] }) ); ``` For raw JSON Schema (e.g. TypeBox output), use the new `fromJsonSchema` adapter: ```typescript import { fromJsonSchema, AjvJsonSchemaValidator } from '@modelcontextprotocol/core'; server.registerTool( 'greet', { inputSchema: fromJsonSchema({ type: 'object', properties: { name: { type: 'string' } } }, new AjvJsonSchemaValidator()) }, handler ); ``` **Breaking changes:** - `experimental.tasks.getTaskResult()` no longer accepts a `resultSchema` parameter. Returns `GetTaskPayloadResult` (a loose `Result`); cast to the expected type at the call site. - Removed unused exports from `@modelcontextprotocol/core`: `SchemaInput`, `schemaToJson`, `parseSchemaAsync`, `getSchemaShape`, `getSchemaDescription`, `isOptionalSchema`, `unwrapOptionalSchema`. Use the new `standardSchemaToJsonSchema` and `validateStandardSchema` instead. - `completable()` remains Zod-specific (it relies on Zod's `.shape` introspection). ###### Patch Changes - [#1758](https://github.com/modelcontextprotocol/typescript-sdk/pull/1758) [`e86b183`](https://github.com/modelcontextprotocol/typescript-sdk/commit/e86b1835ccf213c3799ac19f4111d01816912333) Thanks [@KKonstantinov](https://github.com/KKonstantinov)! - tasks - disallow requesting a null TTL - [#1363](https://github.com/modelcontextprotocol/typescript-sdk/pull/1363) [`0a75810`](https://github.com/modelcontextprotocol/typescript-sdk/commit/0a75810b26e24bae6b9cfb41e12ac770aeaa1da4) Than _[Truncated at 4000 characters — full notes: https://github.com/modelcontextprotocol/typescript-sdk/releases/tag/%40modelcontextprotocol/server%402.0.0-alpha.1]_