MCP Apps
    Preparing search index...
    • Getting Started

    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.

    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).

    App / AppBridge constructors, the on* setters, addEventListener, callServerTool, readServerResource, registerAppResource, the React hooks and the _meta.ui.resourceUri handling are unchanged. Published .d.ts files now resolve under moduleResolution: NodeNext / Node16 without workarounds (#705).

    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; for HTTP transports also @modelcontextprotocol/node@^2.0.0 (NodeStreamableHTTPServerTransport) and @modelcontextprotocol/express@^2.0.0 (createMcpExpressApp, which peers on express)
    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.

    • Peer packages. @modelcontextprotocol/sdk@^1 is replaced by the split 2.x packages above, all at ^2.0.0. Remove the 1.x package from your project: the two SDKs share no classes or types (a 1.x McpError or Client cannot be passed to 2.x code), even though they speak the same wire protocol.
    • zod 3 dropped. The peer range is zod@^4.2.0. Tool schemas must implement Standard JSON Schema (~standard.jsonSchema): zod 4.2+, ArkType, Valibot. zod 4.0 and 4.1 do not expose ~standard.jsonSchema and are rejected too. Raw zod shapes ({ q: z.string() }) still work with registerAppTool but are deprecated; wrap them with z.object({...}).
    • App / AppBridge extend Protocol from @modelcontextprotocol/client. ProtocolWithEvents is gone; use the SDK's Protocol. The AppRequest, AppNotification and AppResult unions are kept as deprecated type aliases (nothing in 2.x consumes them) and will be removed in 3.0.
    • Handler context. Custom request handlers, registerAppTool callbacks (server) and app.registerTool callbacks (View) receive the SDK 2.x context: extra.signalextra.mcpReq.signal, extra.requestIdextra.mcpReq.id; extra.sessionId is unchanged and extra.authInfo moved to extra.http?.authInfo.
    • setRequestHandler / setNotificationHandler take method names. app.setRequestHandler(SomeRequestSchema, handler) becomes app.setRequestHandler("some/method", { params: SomeParamsSchema }, (params, ctx) => …) for custom methods (the handler receives the parsed params); the two-argument setRequestHandler("tools/call", handler) form exists only for spec-defined method names. The 1.x (Schema, handler) form still works on App and AppBridge as 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-shaped extra (signal, requestId, sessionId, _meta, sendRequest, sendNotification, authInfo; exported as LegacyRequestHandlerExtra). It will be removed in 3.0.
    • Double-registration guard covers the SDK's own handlers. Registering a handler for notifications/progress or notifications/cancelled (which the base Protocol already owns) now throws already registered, as ping and the on*-owned methods did in 1.x. Use addEventListener or the SDK's progress callbacks instead of replacing these.
    • Errors. Remote JSON-RPC errors are ProtocolError (numeric code); local conditions are SdkError with a string code: request timeout → "REQUEST_TIMEOUT", connection closed → "CONNECTION_CLOSED". Cancelling a request with an AbortSignal also rejects with "REQUEST_TIMEOUT" (the message is the abort reason). Messages no longer carry the MCP error N: prefix. A resource-not-found reply that carries data.uri arrives as ResourceNotFoundError (a ProtocolError subclass, code -32602, with a .uri getter).

    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)

    The published ./schema.json export is regenerated from the 2.x core schemas:

    • McpUiToolResultNotification.params.structuredContent is any JSON value (was type: "object").
    • McpUiToolResultNotification.params._meta documents io.modelcontextprotocol/serverInfo and no longer lists progressToken / related-task (both still pass through).
    • McpUiHostContext.toolInfo.tool.outputSchema is a loose object (only $schema is documented); inputSchema.properties values are now typed as JSON values.
    • A recursive JSON-value definition (__schema0) is added under the $defs of McpUiHostContext, McpUiHostContextChangedNotification and McpUiInitializeResult.
    1. npm uninstall @modelcontextprotocol/sdk and install the packages for your role from the table above.
    2. Replace sdk/... imports with the split packages (sdk/server/mcp.js@modelcontextprotocol/server, sdk/server/streamableHttp.jsNodeStreamableHTTPServerTransport from @modelcontextprotocol/node, sdk/server/stdio.js@modelcontextprotocol/server/stdio, hand-written Express routing → createMcpExpressApp from @modelcontextprotocol/express, sdk/types.js@modelcontextprotocol/client or server for the types, @modelcontextprotocol/core for the zod schemas).
    3. Wrap raw zod shapes with z.object({...}).
    4. Update custom handlers to the extra.mcpReq.* context and method-keyed setRequestHandler calls.
    5. Replace McpError / numeric-code checks with ProtocolError / SdkError.