Consumers on 1.x wrote setRequestHandler(Schema, handler) and
setNotificationHandler(Schema, handler) with a whole-message Zod schema.
SDK 2.0 keys handlers by method name, so App and AppBridge now accept
that form as a third, deprecated overload: a small helper detects the
schema, extracts the method literal, forwards to the 2.x
(method, { params }, handler) form, and hands the legacy handler the
reassembled { method, params } message plus a 1.x-shaped extra
(signal, requestId, sessionId, _meta). A one-time console warning
points at the new form. The double-registration guard applies to both
forms.
The AppRequest, AppNotification and AppResult unions that 1.x fed to
the SDK's Protocol generics come back as deprecated type aliases, since
they leaked through the root entry and cost nothing to keep.
Both go away in 3.0.
6.5 KiB
| title | group | description |
|---|---|---|
| Migrate to v2 | Getting Started | Upgrade from ext-apps 1.x to 2.x — new base MCP SDK peer packages, API changes for Views and hosts, and what stays wire-compatible. |
Migrating from ext-apps 1.x to 2.x
ext-apps 2.x is built on the base MCP TypeScript SDK 2.x, which replaced the
single @modelcontextprotocol/sdk package with @modelcontextprotocol/client,
server, core, node and express. The MCP Apps wire protocol did not
change; the breaking changes are in dependencies and in the TypeScript API.
Host compatibility
The ui/* messages exchanged over the iframe channel are byte-identical to
1.x. A 2.x View runs in a 1.x host and a 2.x host renders 1.x Views. The only
host-side deltas are in error responses (see below).
Peer dependencies by role
| Role | Install |
|---|---|
| View author | @modelcontextprotocol/ext-apps, @modelcontextprotocol/client@^2.0.0, zod@^4.2.0 (+ react/react-dom for ./react) |
| Host author | same as View author |
| MCP server author | View author packages + @modelcontextprotocol/server@^2.0.0; @modelcontextprotocol/node and express for HTTP transports |
CDN / *-with-deps |
nothing extra: ./app-with-deps and ./react-with-deps bundle client, core and zod (about 25% larger than the 1.x bundles) |
@modelcontextprotocol/client is a required peer (App and AppBridge extend
its Protocol class); @modelcontextprotocol/core is a required peer that client already depends on, so npm installs it without you listing it;
@modelcontextprotocol/server stays optional and is only needed for the
./server helpers. Node.js 20+ is required.
Breaking changes
- Peer packages.
@modelcontextprotocol/sdk@^1is replaced by the split 2.x packages above, all at^2.0.0. Remove the 1.x package from your project; the two SDKs do not interoperate. - zod 3 dropped. The peer range is
zod@^4.2.0. Tool schemas must implement Standard JSON Schema (~standard.jsonSchema): zod v4, ArkType, Valibot. Raw zod shapes ({ q: z.string() }) still work withregisterAppToolbut are deprecated; wrap them withz.object({...}). App/AppBridgeextendProtocolfrom@modelcontextprotocol/client.ProtocolWithEventsis gone; use the SDK'sProtocol. TheAppRequest,AppNotificationandAppResultunions are kept as deprecated type aliases (nothing in 2.x consumes them) and will be removed in 3.0.- Handler context. Custom handlers receive the SDK 2.x context:
extra.signal→extra.mcpReq.signal,extra.requestId→extra.mcpReq.id. setRequestHandler/setNotificationHandlertake method names.app.setRequestHandler(SomeRequestSchema, handler)becomesapp.setRequestHandler("some/method", { params: SomeParamsSchema }, (params, ctx) => …)for custom methods (the handler receives the parsed params); the two-argumentsetRequestHandler("tools/call", handler)form exists only for spec-defined method names. The 1.x(Schema, handler)form still works onAppandAppBridgeas a deprecated overload: it logs a one-time warning, hands the handler the whole{ method, params }message as before, and gives request handlers a 1.x-shapedextra(signal,requestId,sessionId,_meta). It will be removed in 3.0.- Errors. Remote JSON-RPC errors are
ProtocolError(numericcode); local conditions areSdkErrorwith a stringcode: request timeout →"REQUEST_TIMEOUT", connection closed →"CONNECTION_CLOSED". Cancelling a request with anAbortSignalalso rejects with"REQUEST_TIMEOUT"(the message is the abort reason). Messages no longer carry theMCP error N:prefix.
Host-side wire deltas
Observed when a 2.x AppBridge answers a View; a 1.x View sees these too.
| Situation | 1.x host | 2.x host |
|---|---|---|
A handler throws -32002 (resource not found) |
error.code: -32002 |
error.code: -32602 (the SDK never emits -32002) |
Invalid params on a ui/* request |
-32603 with a zod issue dump |
-32602 Invalid params for <method>: … |
| Error message text | MCP error -32602: … prefix |
plain message |
tools/call to an unknown tool through a 2.x McpServer |
result.isError: true |
JSON-RPC error -32602 (callServerTool rejects) |
schema.json
The published ./schema.json export is regenerated from the 2.x core schemas:
McpUiToolResultNotification.params.structuredContentis any JSON value (wastype: "object").McpUiToolResultNotification.params._metadocumentsio.modelcontextprotocol/serverInfoand no longer listsprogressToken/related-task(both still pass through).McpUiHostContext.toolInfo.tool.outputSchemais a loose object (only$schemais documented);inputSchema.propertiesvalues are now typed as JSON values.- A recursive JSON-value definition (
__schema0) is added under the$defsofMcpUiHostContext,McpUiHostContextChangedNotificationandMcpUiInitializeResult.
Checklist
npm uninstall @modelcontextprotocol/sdkand install the packages for your role from the table above.- Replace
sdk/...imports with the split packages (sdk/server/mcp.js→@modelcontextprotocol/server,sdk/server/streamableHttp.js→NodeStreamableHTTPServerTransportfrom@modelcontextprotocol/node,sdk/server/stdio.js→@modelcontextprotocol/server/stdio,sdk/types.js→@modelcontextprotocol/clientorserverfor the types,@modelcontextprotocol/corefor the zod schemas). - Wrap raw zod shapes with
z.object({...}). - Update custom handlers to the
extra.mcpReq.*context and method-keyedsetRequestHandlercalls. - Replace
McpError/ numeric-code checks withProtocolError/SdkError.