diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index fb41938..6848e4c 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -114,6 +114,21 @@ jobs:
grep -q "Ready" /tmp/mcpb-smoke.log
working-directory: examples/pdf-server
+ dependency-isolation:
+ name: Dependency isolation
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v6
+
+ - uses: actions/setup-node@v6
+ with:
+ node-version: "22"
+ cache: npm
+
+ - run: npm ci
+
+ - run: npm run test:dependency-isolation
+
e2e:
runs-on: ubuntu-latest
steps:
@@ -132,8 +147,10 @@ jobs:
- run: npm ci
+ # Headless runs without a channel use chromium-headless-shell, so the
+ # full Chromium build (about 165 MB) would only be downloaded, never run.
- name: Install Playwright browsers
- run: npx playwright install --with-deps chromium
+ run: npx playwright install --with-deps --only-shell chromium
- name: Run E2E tests
run: npx playwright test --reporter=list
@@ -165,9 +182,14 @@ jobs:
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt-get install -y nodejs
+ # The checkout lives on the Windows drive, which WSL reaches over 9P;
+ # writing node_modules there is what makes this job slow (npm ci alone
+ # took about 3 minutes). Copy the tree onto the distro's ext4 filesystem
+ # first, as Microsoft's WSL guidance recommends for anything I/O heavy.
- name: Build and test in WSL
shell: wsl-bash {0}
run: |
+ cp -r "$(pwd)" ~/ext-apps && cd ~/ext-apps
npm ci
npm run build
npm run examples:build
diff --git a/AGENTS.md b/AGENTS.md
index 6bfc8cd..219b947 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -60,8 +60,8 @@ rm -fR package-lock.json node_modules && \
### Key Source Files
-- `src/app.ts` - `App` class extends MCP Protocol, handles guest initialization, tool calls, messaging
-- `src/app-bridge.ts` - `AppBridge` class for hosts, proxies MCP requests, sends tool input/results to guests
+- `src/app.ts` - `App` subclasses `Protocol` from `@modelcontextprotocol/client`, handles View initialization, tool calls, and messaging
+- `src/app-bridge.ts` - `AppBridge` subclasses `Protocol` from `@modelcontextprotocol/client` for the iframe channel and proxies through a separate outer `Client`
- `src/server/index.ts` - Helpers for MCP servers to register tools/resources with UI metadata
- `src/types.ts` - Protocol types re-exported from `spec.types.ts` and Zod schemas from `generated/schema.ts` (auto-generated during build)
- `src/message-transport.ts` - `PostMessageTransport` for iframe communication
@@ -70,12 +70,12 @@ rm -fR package-lock.json node_modules && \
### Protocol Flow
```
-View (App) <--PostMessageTransport--> Host (AppBridge) <--MCP Client--> MCP Server
+View (App/Protocol) <--PostMessageTransport--> Host (AppBridge/Protocol) <--separate MCP Client--> MCP Server
```
1. Host creates iframe with view HTML
2. View creates `App` instance and calls `connect()` with `PostMessageTransport`
-3. View sends `ui/initialize` request, receives host capabilities and context
+3. View sends `ui/initialize` (the only handshake on the iframe channel) and receives authoritative Apps capabilities and context
4. Host sends `sendToolInput()` with tool arguments after initialization
5. View can call server tools via `app.callServerTool()` or send messages via `app.sendMessage()`
6. Host sends `sendToolResult()` when tool execution completes
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 6592106..e28dcd1 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -502,7 +502,7 @@ Alternatively, use the [workflow dispatch](https://github.com/modelcontextprotoc
## Code of Conduct
-This project follows our [Code of Conduct](CODE_OF_CONDUCT.md). Please review it before contributing.
+This project follows our [Code of Conduct](https://github.com/modelcontextprotocol/.github/blob/main/CODE_OF_CONDUCT.md). Please review it before contributing.
## Reporting Issues
diff --git a/README.md b/README.md
index 7348e15..ab4004d 100644
--- a/README.md
+++ b/README.md
@@ -11,7 +11,7 @@
Why
·
- Quickstart
+ Quickstart
·
API Docs
·
@@ -89,6 +89,8 @@ it will guide you through the rest.
+
+
> [!NOTE]
@@ -120,12 +122,36 @@ resources:
## Getting Started
+Requires Node.js 20+. The base MCP SDK packages are `^2.0.0` peers of
+`ext-apps` (`@modelcontextprotocol/core` is a required peer that `client` already depends on, so npm installs it for you).
+
+For a View or host:
+
```bash
-npm install -S @modelcontextprotocol/ext-apps
+npm install -S @modelcontextprotocol/ext-apps \
+ @modelcontextprotocol/client@^2.0.0 \
+ zod@^4.2.0
```
+For an MCP server, add the server package (and, for HTTP transports, the Node
+and Express adapters):
+
+```bash
+npm install -S @modelcontextprotocol/ext-apps \
+ @modelcontextprotocol/client@^2.0.0 \
+ @modelcontextprotocol/server@^2.0.0 \
+ @modelcontextprotocol/node@^2.0.0 \
+ @modelcontextprotocol/express@^2.0.0 \
+ zod@^4.2.0
+```
+
+The wire protocol is unchanged between `ext-apps` 1.x and 2.x: a 2.x View works
+in a 1.x host and a 2.x host renders 1.x Views. See the
+[migration guide](https://apps.extensions.modelcontextprotocol.io/api/documents/migrate-to-v2.html)
+when upgrading from 1.x.
+
**New here?** Start with the
-[Quickstart Guide](https://apps.extensions.modelcontextprotocol.io/api/documents/Quickstart.html)
+[Quickstart Guide](https://apps.extensions.modelcontextprotocol.io/api/documents/quickstart.html)
to build your first MCP App.
## Using the SDK
@@ -139,7 +165,7 @@ UI metadata.
| `@modelcontextprotocol/ext-apps` | Build interactive Views (App class, PostMessageTransport) | [API Docs →](https://apps.extensions.modelcontextprotocol.io/api/modules/app.html) |
| `@modelcontextprotocol/ext-apps/react` | React hooks for Views (useApp, useHostStyles, etc.) | [API Docs →](https://apps.extensions.modelcontextprotocol.io/api/modules/_modelcontextprotocol_ext-apps_react.html) |
| `@modelcontextprotocol/ext-apps/app-bridge` | Embed and communicate with Views in your chat client | [API Docs →](https://apps.extensions.modelcontextprotocol.io/api/modules/app-bridge.html) |
-| `@modelcontextprotocol/ext-apps/server` | Register tools and resources on your MCP server | [API Docs →](https://apps.extensions.modelcontextprotocol.io/api/modules/server.html) |
+| `@modelcontextprotocol/ext-apps/server` | Register tools and resources on your MCP server | [API Docs →](https://apps.extensions.modelcontextprotocol.io/api/modules/server-helpers.html) |
There's no _supported_ host implementation in this repo (beyond the
[examples/basic-host](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/basic-host)
@@ -246,7 +272,7 @@ point your client at a local build:
## Resources
-- [Quickstart Guide](https://apps.extensions.modelcontextprotocol.io/api/documents/Quickstart.html)
+- [Quickstart Guide](https://apps.extensions.modelcontextprotocol.io/api/documents/quickstart.html)
- [API Documentation](https://apps.extensions.modelcontextprotocol.io/api/)
- [Specification (2026-01-26)](https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/2026-01-26/apps.mdx)
([Draft](https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/draft/apps.mdx))
diff --git a/build.bun.ts b/build.bun.ts
index a129d5d..61361e6 100644
--- a/build.bun.ts
+++ b/build.bun.ts
@@ -1,6 +1,9 @@
#!/usr/bin/env bun
import { $ } from "bun";
-import { cpSync, mkdirSync } from "node:fs";
+import { cpSync, mkdirSync, rmSync } from "node:fs";
+
+// Avoid publishing artifacts left behind by an earlier build or branch.
+rmSync("dist", { recursive: true, force: true });
// Run TypeScript compiler for type declarations
await $`tsc`;
@@ -31,9 +34,15 @@ function buildJs(
});
}
-// zod is a peerDependency — keep it external so consumers share a single
-// zod instance (instanceof ZodError / schema.extend() break with duplicate copies).
-const PEER_EXTERNALS = ["@modelcontextprotocol/sdk", "zod"];
+// Peer dependencies stay external in the standard entry points so consumers
+// share one base MCP SDK and Zod instance. The *-with-deps entry points keep
+// bundling these dependencies for standalone browser use.
+const PEER_EXTERNALS = [
+ "@modelcontextprotocol/client",
+ "@modelcontextprotocol/core",
+ "@modelcontextprotocol/server",
+ "zod",
+];
await Promise.all([
buildJs("src/app.ts", {
diff --git a/docs/authorization.md b/docs/authorization.md
index 59fc26c..df7adc6 100644
--- a/docs/authorization.md
+++ b/docs/authorization.md
@@ -150,7 +150,7 @@ registerAppTool(
"get_account_balance",
{
description: "Get account balance",
- inputSchema: { accountId: z.string() },
+ inputSchema: z.object({ accountId: z.string() }),
},
async ({ accountId }) => {
if (!authInfo) {
diff --git a/docs/migrate-to-2.md b/docs/migrate-to-2.md
new file mode 100644
index 0000000..f9341d0
--- /dev/null
+++ b/docs/migrate-to-2.md
@@ -0,0 +1,130 @@
+---
+title: Migrate to v2
+group: Getting Started
+description: 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).
+
+## What stays the same
+
+`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).
+
+## 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`; 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.
+
+## Breaking changes
+
+- **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.signal` → `extra.mcpReq.signal`, `extra.requestId` →
+ `extra.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).
+
+## 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 : …` |
+| 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.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`.
+
+## Checklist
+
+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.js` →
+ `NodeStreamableHTTPServerTransport` 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`.
diff --git a/docs/migrate_from_openai_apps.md b/docs/migrate_from_openai_apps.md
index d91281b..22d5d9f 100644
--- a/docs/migrate_from_openai_apps.md
+++ b/docs/migrate_from_openai_apps.md
@@ -66,7 +66,7 @@ The server-side changes involve updating metadata structure and using helper fun
#### Before (OpenAI)
```typescript
-import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
+import { McpServer } from "@modelcontextprotocol/server";
import { z } from "zod";
function createServer() {
@@ -78,7 +78,7 @@ function createServer() {
{
title: "Shopping Cart",
description: "Display the user's shopping cart",
- inputSchema: { userId: z.string() },
+ inputSchema: z.object({ userId: z.string() }),
annotations: { readOnlyHint: true },
_meta: {
"openai/outputTemplate": "ui://view/cart.html",
@@ -126,7 +126,7 @@ function createServer() {
#### After (MCP Apps)
```typescript
-import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
+import { McpServer } from "@modelcontextprotocol/server";
import {
registerAppTool,
registerAppResource,
@@ -144,7 +144,7 @@ function createServer() {
{
title: "Shopping Cart",
description: "Display the user's shopping cart",
- inputSchema: { userId: z.string() },
+ inputSchema: z.object({ userId: z.string() }),
annotations: { readOnlyHint: true },
_meta: { ui: { resourceUri: "ui://view/cart.html" } },
},
diff --git a/docs/overview.md b/docs/overview.md
index 28f5b23..8eda95d 100644
--- a/docs/overview.md
+++ b/docs/overview.md
@@ -56,7 +56,11 @@ flowchart LR
- **Host** — The chat client (e.g., Claude Desktop) that connects to servers, embeds Views in iframes, and proxies communication between them.
- **View** — The UI running inside a sandboxed iframe. It receives tool data from the Host and can call server tools or send messages back to the chat.
-The View acts as an MCP client, the Host acts as a proxy, and the Server is a standard MCP server.
+The View's `App` and the Host's `AppBridge` both subclass the `Protocol` class
+exported by `@modelcontextprotocol/client` for the iframe channel. A separate outer `Client` connects
+the Host to the actual MCP Server. Keeping those two connections separate
+preserves the Apps-only iframe handshake and prevents iframe capabilities from
+leaking into the server connection.
## Lifecycle
@@ -93,7 +97,7 @@ sequenceDiagram
```
1. **Discovery** — The Host learns about tools and their UI resources when connecting to the server.
-2. **Initialization** — When a UI tool is called, the Host renders the iframe. The View sends `ui/initialize` and receives host context (theme, capabilities, container dimensions). This handshake ensures the View is ready before receiving data.
+2. **Initialization** — When a UI tool is called, the Host renders the iframe. The View sends `ui/initialize` (the only handshake on the iframe channel) and receives host context (theme, capabilities, container dimensions). `ui/initialize` is authoritative for Apps capabilities and identity, and `ui/notifications/initialized` is the public View-ready signal.
3. **Data delivery** — The Host sends tool arguments and, once available, tool results to the View. Results include both `content` (text for the model's context) and optionally `structuredContent` (data optimized for UI rendering). This separation lets servers provide rich data to the UI without bloating the model's context.
4. **Interactive phase** — The user interacts with the View. The View can call tools, send messages, or update context.
5. **Teardown** — Before unmounting, the Host notifies the View so it can save state or release resources.
diff --git a/docs/patterns.md b/docs/patterns.md
index 87a6d82..884de26 100644
--- a/docs/patterns.md
+++ b/docs/patterns.md
@@ -19,7 +19,7 @@ registerAppTool(
"update-quantity",
{
description: "Update item quantity in cart",
- inputSchema: { itemId: z.string(), quantity: z.number() },
+ inputSchema: z.object({ itemId: z.string(), quantity: z.number() }),
_meta: {
ui: {
resourceUri: "ui://shop/cart.html",
@@ -127,14 +127,14 @@ registerAppTool(
{
title: "Read Data Bytes",
description: "Load binary data in chunks",
- inputSchema: {
+ inputSchema: z.object({
id: z.string().describe("Resource identifier"),
offset: z.number().min(0).default(0).describe("Byte offset"),
byteCount: z
.number()
.default(MAX_CHUNK_BYTES)
.describe("Bytes to read"),
- },
+ }),
outputSchema: DataChunkSchema,
// Hidden from model - only callable by the App
_meta: { ui: { visibility: ["app"] } },
@@ -281,10 +281,7 @@ server.registerResource(
```ts source="./patterns.tsx#binaryBlobResourceClient"
-const result = await app.request(
- { method: "resources/read", params: { uri: `video://${videoId}` } },
- ReadResourceResultSchema,
-);
+const result = await app.readServerResource({ uri: `video://${videoId}` });
const content = result.contents[0];
if (!content || !("blob" in content)) {
diff --git a/docs/patterns.tsx b/docs/patterns.tsx
index 6b87692..bb9eaa4 100644
--- a/docs/patterns.tsx
+++ b/docs/patterns.tsx
@@ -17,16 +17,12 @@ import { randomUUID } from "node:crypto";
import type {
CallToolResult,
ReadResourceResult,
-} from "@modelcontextprotocol/sdk/types.js";
-import { ReadResourceResultSchema } from "@modelcontextprotocol/sdk/types.js";
+} from "@modelcontextprotocol/server";
import type { McpUiHostContext } from "../src/types.js";
import { useEffect, useState } from "react";
import { useApp } from "../src/react/index.js";
import { registerAppTool } from "../src/server/index.js";
-import {
- McpServer,
- ResourceTemplate,
-} from "@modelcontextprotocol/sdk/server/mcp.js";
+import { McpServer, ResourceTemplate } from "@modelcontextprotocol/server";
import { z } from "zod";
/**
@@ -117,14 +113,14 @@ function chunkedDataServer(server: McpServer) {
{
title: "Read Data Bytes",
description: "Load binary data in chunks",
- inputSchema: {
+ inputSchema: z.object({
id: z.string().describe("Resource identifier"),
offset: z.number().min(0).default(0).describe("Byte offset"),
byteCount: z
.number()
.default(MAX_CHUNK_BYTES)
.describe("Bytes to read"),
- },
+ }),
outputSchema: DataChunkSchema,
// Hidden from model - only callable by the App
_meta: { ui: { visibility: ["app"] } },
@@ -252,10 +248,7 @@ function binaryBlobResourceServer(
*/
async function binaryBlobResourceClient(app: App, videoId: string) {
//#region binaryBlobResourceClient
- const result = await app.request(
- { method: "resources/read", params: { uri: `video://${videoId}` } },
- ReadResourceResultSchema,
- );
+ const result = await app.readServerResource({ uri: `video://${videoId}` });
const content = result.contents[0];
if (!content || !("blob" in content)) {
diff --git a/docs/quickstart.md b/docs/quickstart.md
index 3e00796..a021912 100644
--- a/docs/quickstart.md
+++ b/docs/quickstart.md
@@ -21,7 +21,7 @@ This tutorial assumes you've built an MCP server before and are comfortable with
We'll use the [MCP TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk) to build the server.
-You'll also need Node.js 18+.
+You'll also need Node.js 20+.
## 1. Set up the project
@@ -37,7 +37,7 @@ Install the dependencies you'll need:
```bash
npm init -y
-npm install @modelcontextprotocol/ext-apps @modelcontextprotocol/sdk express cors
+npm install @modelcontextprotocol/ext-apps @modelcontextprotocol/client@^2.0.0 @modelcontextprotocol/server@^2.0.0 @modelcontextprotocol/node@^2.0.0 @modelcontextprotocol/express@^2.0.0 zod@^4.2.0 express cors
npm install -D typescript vite vite-plugin-singlefile @types/express @types/cors @types/node tsx concurrently cross-env
```
@@ -59,6 +59,7 @@ npm pkg set scripts.start='concurrently --raw "cross-env NODE_ENV=development IN
```json source="../examples/quickstart/tsconfig.json"
{
"compilerOptions": {
+ "types": ["node", "vite/client"],
"target": "ESNext",
"lib": ["ESNext", "DOM", "DOM.Iterable"],
"module": "ESNext",
@@ -87,6 +88,7 @@ npm pkg set scripts.start='concurrently --raw "cross-env NODE_ENV=development IN
```json source="../examples/quickstart/tsconfig.server.json"
{
"compilerOptions": {
+ "types": ["node"],
"target": "ES2022",
"lib": ["ES2022"],
"module": "NodeNext",
@@ -178,9 +180,10 @@ import {
registerAppTool,
RESOURCE_MIME_TYPE,
} from "@modelcontextprotocol/ext-apps/server";
-import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
+import { McpServer } from "@modelcontextprotocol/server";
import fs from "node:fs/promises";
import path from "node:path";
+import { z } from "zod";
const DIST_DIR = path.join(import.meta.dirname, "dist");
@@ -205,7 +208,7 @@ export function createServer(): McpServer {
{
title: "Get Time",
description: "Returns the current server time.",
- inputSchema: {},
+ inputSchema: z.object({}),
_meta: { ui: { resourceUri } }, // Links this tool to its UI resource
},
async () => {
@@ -240,10 +243,10 @@ export function createServer(): McpServer {
```ts source="../examples/quickstart/main.ts"
-import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js";
-import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
-import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
-import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
+import { createMcpExpressApp } from "@modelcontextprotocol/express";
+import { NodeStreamableHTTPServerTransport } from "@modelcontextprotocol/node";
+import type { McpServer } from "@modelcontextprotocol/server";
+import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
import cors from "cors";
import type { Request, Response } from "express";
import { createServer } from "./server.js";
@@ -263,7 +266,7 @@ export async function startStreamableHTTPServer(
app.all("/mcp", async (req: Request, res: Response) => {
const server = createServer();
- const transport = new StreamableHTTPServerTransport({
+ const transport = new NodeStreamableHTTPServerTransport({
sessionIdGenerator: undefined,
});
diff --git a/docs/testing-mcp-apps.md b/docs/testing-mcp-apps.md
index df1396c..a8eb333 100644
--- a/docs/testing-mcp-apps.md
+++ b/docs/testing-mcp-apps.md
@@ -28,6 +28,10 @@ The [`basic-host`](https://github.com/modelcontextprotocol/ext-apps/tree/main/ex
cd examples/basic-host
```
+ The root install runs the package build, including type-checking the
+ documentation snippets against the pinned base MCP SDK 2.x packages. Do
+ not bypass a failed build before testing the host.
+
2. Start basic-host, pointing it to your MCP server:
```bash
diff --git a/examples/basic-host/package.json b/examples/basic-host/package.json
index 1b45dcf..cefe9d5 100644
--- a/examples/basic-host/package.json
+++ b/examples/basic-host/package.json
@@ -1,7 +1,7 @@
{
"homepage": "https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/basic-host",
"name": "@modelcontextprotocol/ext-apps-basic-host",
- "version": "1.7.4",
+ "version": "2.0.0",
"type": "module",
"scripts": {
"build": "tsc --noEmit && concurrently \"cross-env INPUT=index.html vite build\" \"cross-env INPUT=sandbox.html vite build\"",
@@ -11,11 +11,11 @@
"dev": "cross-env NODE_ENV=development concurrently \"npm run watch\" \"npm run serve\""
},
"dependencies": {
- "@modelcontextprotocol/ext-apps": "^1.7.0",
- "@modelcontextprotocol/sdk": "^1.29.0",
+ "@modelcontextprotocol/client": "2.0.0",
+ "@modelcontextprotocol/ext-apps": "^2.0.0",
"react": "^19.2.0",
"react-dom": "^19.2.0",
- "zod": "^4.1.13"
+ "zod": "^4.2.0"
},
"devDependencies": {
"@types/express": "^5.0.0",
diff --git a/examples/basic-host/src/implementation.ts b/examples/basic-host/src/implementation.ts
index 31e3698..5f680ff 100644
--- a/examples/basic-host/src/implementation.ts
+++ b/examples/basic-host/src/implementation.ts
@@ -1,8 +1,12 @@
import { RESOURCE_MIME_TYPE, getToolUiResourceUri, type McpUiSandboxProxyReadyNotification, AppBridge, PostMessageTransport, type McpUiResourceCsp, type McpUiResourcePermissions, buildAllowAttribute, type McpUiUpdateModelContextRequest, type McpUiMessageRequest } from "@modelcontextprotocol/ext-apps/app-bridge";
-import { Client } from "@modelcontextprotocol/sdk/client/index.js";
-import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
-import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
-import type { CallToolResult, Resource, Tool } from "@modelcontextprotocol/sdk/types.js";
+import {
+ Client,
+ SSEClientTransport,
+ StreamableHTTPClientTransport,
+ type CallToolResult,
+ type Resource,
+ type Tool,
+} from "@modelcontextprotocol/client";
import { getTheme, onThemeChange } from "./theme";
import { HOST_STYLE_VARIABLES } from "./host-styles";
diff --git a/examples/basic-host/src/index.tsx b/examples/basic-host/src/index.tsx
index 3d488a7..00c0d52 100644
--- a/examples/basic-host/src/index.tsx
+++ b/examples/basic-host/src/index.tsx
@@ -1,5 +1,5 @@
import { getToolUiResourceUri, McpUiToolMetaSchema } from "@modelcontextprotocol/ext-apps/app-bridge";
-import type { Tool } from "@modelcontextprotocol/sdk/types.js";
+import type { Tool } from "@modelcontextprotocol/client";
import { Component, type ErrorInfo, type ReactNode, StrictMode, Suspense, use, useEffect, useMemo, useRef, useState } from "react";
import { createRoot } from "react-dom/client";
import { callTool, connectToServer, hasAppHtml, initializeApp, loadSandboxProxy, log, newAppBridge, type ServerInfo, type ToolCallInfo, type ModelContext, type AppMessage } from "./implementation";
diff --git a/examples/basic-host/tsconfig.json b/examples/basic-host/tsconfig.json
index 9d7c3bc..3c143ca 100644
--- a/examples/basic-host/tsconfig.json
+++ b/examples/basic-host/tsconfig.json
@@ -1,5 +1,6 @@
{
"compilerOptions": {
+ "types": ["node", "vite/client"],
"target": "ESNext",
"lib": ["ESNext", "DOM", "DOM.Iterable"],
"module": "ESNext",
diff --git a/examples/basic-server-preact/main.ts b/examples/basic-server-preact/main.ts
index 7642632..ffdff52 100644
--- a/examples/basic-server-preact/main.ts
+++ b/examples/basic-server-preact/main.ts
@@ -4,10 +4,10 @@
* Or: node dist/index.js [--stdio]
*/
-import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
-import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js";
-import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
-import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
+import { createMcpExpressApp } from "@modelcontextprotocol/express";
+import { NodeStreamableHTTPServerTransport } from "@modelcontextprotocol/node";
+import type { McpServer } from "@modelcontextprotocol/server";
+import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
import cors from "cors";
import type { Request, Response } from "express";
import { createServer } from "./server.js";
@@ -27,7 +27,7 @@ export async function startStreamableHTTPServer(
app.all("/mcp", async (req: Request, res: Response) => {
const server = createServer();
- const transport = new StreamableHTTPServerTransport({
+ const transport = new NodeStreamableHTTPServerTransport({
sessionIdGenerator: undefined,
});
diff --git a/examples/basic-server-preact/package.json b/examples/basic-server-preact/package.json
index 5127202..60aa40d 100644
--- a/examples/basic-server-preact/package.json
+++ b/examples/basic-server-preact/package.json
@@ -1,11 +1,11 @@
{
"name": "@modelcontextprotocol/server-basic-preact",
- "version": "1.7.4",
+ "version": "2.0.0",
"type": "module",
"description": "Basic MCP App Server example using Preact",
"repository": {
"type": "git",
- "url": "https://github.com/modelcontextprotocol/ext-apps",
+ "url": "git+https://github.com/modelcontextprotocol/ext-apps.git",
"directory": "examples/basic-server-preact"
},
"license": "MIT",
@@ -24,12 +24,15 @@
"prepublishOnly": "npm run build"
},
"dependencies": {
- "@modelcontextprotocol/ext-apps": "^1.7.0",
- "@modelcontextprotocol/sdk": "^1.29.0",
+ "@modelcontextprotocol/client": "2.0.0",
+ "@modelcontextprotocol/express": "2.0.0",
+ "@modelcontextprotocol/ext-apps": "^2.0.0",
+ "@modelcontextprotocol/node": "2.0.0",
+ "@modelcontextprotocol/server": "2.0.0",
"cors": "^2.8.5",
"express": "^5.1.0",
"preact": "^10.0.0",
- "zod": "^4.1.13"
+ "zod": "^4.2.0"
},
"devDependencies": {
"@preact/preset-vite": "^2.0.0",
diff --git a/examples/basic-server-preact/server.ts b/examples/basic-server-preact/server.ts
index bf14ea5..dfec94a 100644
--- a/examples/basic-server-preact/server.ts
+++ b/examples/basic-server-preact/server.ts
@@ -1,8 +1,12 @@
-import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
-import type { CallToolResult, ReadResourceResult } from "@modelcontextprotocol/sdk/types.js";
+import {
+ McpServer,
+ type CallToolResult,
+ type ReadResourceResult,
+} from "@modelcontextprotocol/server";
import fs from "node:fs/promises";
import path from "node:path";
import { registerAppTool, registerAppResource, RESOURCE_MIME_TYPE } from "@modelcontextprotocol/ext-apps/server";
+import { z } from "zod";
// Works both from source (server.ts) and compiled (dist/server.js)
const DIST_DIR = import.meta.filename.endsWith(".ts")
? path.join(import.meta.dirname, "dist")
@@ -28,7 +32,7 @@ export function createServer(): McpServer {
{
title: "Get Time",
description: "Returns the current server time as an ISO 8601 string.",
- inputSchema: {},
+ inputSchema: z.object({}),
_meta: { ui: { resourceUri } }, // Links this tool to its UI resource
},
async (): Promise => {
diff --git a/examples/basic-server-preact/src/mcp-app.tsx b/examples/basic-server-preact/src/mcp-app.tsx
index a8bdc68..351a8ec 100644
--- a/examples/basic-server-preact/src/mcp-app.tsx
+++ b/examples/basic-server-preact/src/mcp-app.tsx
@@ -8,7 +8,7 @@ import {
applyHostStyleVariables,
type McpUiHostContext,
} from "@modelcontextprotocol/ext-apps";
-import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
+import type { CallToolResult } from "@modelcontextprotocol/client";
import { useCallback, useEffect, useState } from "preact/hooks";
import { render } from "preact";
import styles from "./mcp-app.module.css";
diff --git a/examples/basic-server-preact/tsconfig.json b/examples/basic-server-preact/tsconfig.json
index 32182d9..9bf9389 100644
--- a/examples/basic-server-preact/tsconfig.json
+++ b/examples/basic-server-preact/tsconfig.json
@@ -1,5 +1,6 @@
{
"compilerOptions": {
+ "types": ["node", "vite/client"],
"target": "ESNext",
"lib": ["ESNext", "DOM", "DOM.Iterable"],
"module": "ESNext",
diff --git a/examples/basic-server-preact/tsconfig.server.json b/examples/basic-server-preact/tsconfig.server.json
index 05ddd8e..27eb28f 100644
--- a/examples/basic-server-preact/tsconfig.server.json
+++ b/examples/basic-server-preact/tsconfig.server.json
@@ -1,5 +1,6 @@
{
"compilerOptions": {
+ "types": ["node"],
"target": "ES2022",
"lib": ["ES2022"],
"module": "NodeNext",
diff --git a/examples/basic-server-react/main.ts b/examples/basic-server-react/main.ts
index ec187b6..21c5e18 100644
--- a/examples/basic-server-react/main.ts
+++ b/examples/basic-server-react/main.ts
@@ -4,10 +4,10 @@
* Or: node dist/index.js [--stdio]
*/
-import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js";
-import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
-import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
-import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
+import { createMcpExpressApp } from "@modelcontextprotocol/express";
+import { NodeStreamableHTTPServerTransport } from "@modelcontextprotocol/node";
+import type { McpServer } from "@modelcontextprotocol/server";
+import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
import cors from "cors";
import type { Request, Response } from "express";
import { createServer } from "./server.js";
@@ -27,7 +27,7 @@ export async function startStreamableHTTPServer(
app.all("/mcp", async (req: Request, res: Response) => {
const server = createServer();
- const transport = new StreamableHTTPServerTransport({
+ const transport = new NodeStreamableHTTPServerTransport({
sessionIdGenerator: undefined,
});
diff --git a/examples/basic-server-react/package.json b/examples/basic-server-react/package.json
index e4d1233..ea51a8a 100644
--- a/examples/basic-server-react/package.json
+++ b/examples/basic-server-react/package.json
@@ -1,11 +1,11 @@
{
"name": "@modelcontextprotocol/server-basic-react",
- "version": "1.7.4",
+ "version": "2.0.0",
"type": "module",
"description": "Basic MCP App Server example using React",
"repository": {
"type": "git",
- "url": "https://github.com/modelcontextprotocol/ext-apps",
+ "url": "git+https://github.com/modelcontextprotocol/ext-apps.git",
"directory": "examples/basic-server-react"
},
"license": "MIT",
@@ -34,13 +34,16 @@
"prepublishOnly": "npm run build"
},
"dependencies": {
- "@modelcontextprotocol/ext-apps": "^1.7.0",
- "@modelcontextprotocol/sdk": "^1.29.0",
+ "@modelcontextprotocol/client": "2.0.0",
+ "@modelcontextprotocol/express": "2.0.0",
+ "@modelcontextprotocol/ext-apps": "^2.0.0",
+ "@modelcontextprotocol/node": "2.0.0",
+ "@modelcontextprotocol/server": "2.0.0",
"cors": "^2.8.5",
"express": "^5.1.0",
"react": "^19.2.0",
"react-dom": "^19.2.0",
- "zod": "^4.1.13"
+ "zod": "^4.2.0"
},
"devDependencies": {
"@types/cors": "^2.8.19",
diff --git a/examples/basic-server-react/server.ts b/examples/basic-server-react/server.ts
index 23f6dda..d77c908 100644
--- a/examples/basic-server-react/server.ts
+++ b/examples/basic-server-react/server.ts
@@ -1,8 +1,12 @@
import { registerAppResource, registerAppTool, RESOURCE_MIME_TYPE } from "@modelcontextprotocol/ext-apps/server";
-import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
-import type { CallToolResult, ReadResourceResult } from "@modelcontextprotocol/sdk/types.js";
+import {
+ McpServer,
+ type CallToolResult,
+ type ReadResourceResult,
+} from "@modelcontextprotocol/server";
import fs from "node:fs/promises";
import path from "node:path";
+import { z } from "zod";
// Works both from source (server.ts) and compiled (dist/server.js)
const DIST_DIR = import.meta.filename.endsWith(".ts")
@@ -29,7 +33,7 @@ export function createServer(): McpServer {
{
title: "Get Time",
description: "Returns the current server time as an ISO 8601 string.",
- inputSchema: {},
+ inputSchema: z.object({}),
_meta: { ui: { resourceUri } }, // Links this tool to its UI resource
},
async (): Promise => {
diff --git a/examples/basic-server-react/src/mcp-app.tsx b/examples/basic-server-react/src/mcp-app.tsx
index 6bb5540..2b5fbef 100644
--- a/examples/basic-server-react/src/mcp-app.tsx
+++ b/examples/basic-server-react/src/mcp-app.tsx
@@ -3,7 +3,7 @@
*/
import type { App, McpUiHostContext } from "@modelcontextprotocol/ext-apps";
import { useApp } from "@modelcontextprotocol/ext-apps/react";
-import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
+import type { CallToolResult } from "@modelcontextprotocol/client";
import { StrictMode, useCallback, useEffect, useState } from "react";
import { createRoot } from "react-dom/client";
import styles from "./mcp-app.module.css";
diff --git a/examples/basic-server-react/tsconfig.json b/examples/basic-server-react/tsconfig.json
index fc3c210..3ecbdad 100644
--- a/examples/basic-server-react/tsconfig.json
+++ b/examples/basic-server-react/tsconfig.json
@@ -1,5 +1,6 @@
{
"compilerOptions": {
+ "types": ["node", "vite/client"],
"target": "ESNext",
"lib": ["ESNext", "DOM", "DOM.Iterable"],
"module": "ESNext",
diff --git a/examples/basic-server-react/tsconfig.server.json b/examples/basic-server-react/tsconfig.server.json
index 05ddd8e..27eb28f 100644
--- a/examples/basic-server-react/tsconfig.server.json
+++ b/examples/basic-server-react/tsconfig.server.json
@@ -1,5 +1,6 @@
{
"compilerOptions": {
+ "types": ["node"],
"target": "ES2022",
"lib": ["ES2022"],
"module": "NodeNext",
diff --git a/examples/basic-server-solid/main.ts b/examples/basic-server-solid/main.ts
index c8d9de2..095ef8d 100644
--- a/examples/basic-server-solid/main.ts
+++ b/examples/basic-server-solid/main.ts
@@ -4,10 +4,10 @@
* Or: node dist/index.js [--stdio]
*/
-import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
-import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js";
-import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
-import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
+import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
+import { createMcpExpressApp } from "@modelcontextprotocol/express";
+import type { McpServer } from "@modelcontextprotocol/server";
+import { NodeStreamableHTTPServerTransport } from "@modelcontextprotocol/node";
import cors from "cors";
import type { Request, Response } from "express";
import { createServer } from "./server.js";
@@ -27,7 +27,7 @@ export async function startStreamableHTTPServer(
app.all("/mcp", async (req: Request, res: Response) => {
const server = createServer();
- const transport = new StreamableHTTPServerTransport({
+ const transport = new NodeStreamableHTTPServerTransport({
sessionIdGenerator: undefined,
});
diff --git a/examples/basic-server-solid/package.json b/examples/basic-server-solid/package.json
index 8f75ac8..b3ca909 100644
--- a/examples/basic-server-solid/package.json
+++ b/examples/basic-server-solid/package.json
@@ -1,11 +1,11 @@
{
"name": "@modelcontextprotocol/server-basic-solid",
- "version": "1.7.4",
+ "version": "2.0.0",
"type": "module",
"description": "Basic MCP App Server example using Solid",
"repository": {
"type": "git",
- "url": "https://github.com/modelcontextprotocol/ext-apps",
+ "url": "git+https://github.com/modelcontextprotocol/ext-apps.git",
"directory": "examples/basic-server-solid"
},
"license": "MIT",
@@ -24,12 +24,15 @@
"prepublishOnly": "npm run build"
},
"dependencies": {
- "@modelcontextprotocol/ext-apps": "^1.7.0",
- "@modelcontextprotocol/sdk": "^1.29.0",
+ "@modelcontextprotocol/client": "2.0.0",
+ "@modelcontextprotocol/express": "2.0.0",
+ "@modelcontextprotocol/ext-apps": "^2.0.0",
+ "@modelcontextprotocol/node": "2.0.0",
+ "@modelcontextprotocol/server": "2.0.0",
"cors": "^2.8.5",
"express": "^5.1.0",
"solid-js": "1.9.10",
- "zod": "^4.1.13"
+ "zod": "^4.2.0"
},
"devDependencies": {
"@types/cors": "^2.8.19",
diff --git a/examples/basic-server-solid/server.ts b/examples/basic-server-solid/server.ts
index 2ed2d93..addb522 100644
--- a/examples/basic-server-solid/server.ts
+++ b/examples/basic-server-solid/server.ts
@@ -1,8 +1,12 @@
-import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
-import type { CallToolResult, ReadResourceResult } from "@modelcontextprotocol/sdk/types.js";
+import {
+ McpServer,
+ type CallToolResult,
+ type ReadResourceResult,
+} from "@modelcontextprotocol/server";
import fs from "node:fs/promises";
import path from "node:path";
import { registerAppTool, registerAppResource, RESOURCE_MIME_TYPE } from "@modelcontextprotocol/ext-apps/server";
+import { z } from "zod";
// Works both from source (server.ts) and compiled (dist/server.js)
const DIST_DIR = import.meta.filename.endsWith(".ts")
? path.join(import.meta.dirname, "dist")
@@ -28,7 +32,7 @@ export function createServer(): McpServer {
{
title: "Get Time",
description: "Returns the current server time as an ISO 8601 string.",
- inputSchema: {},
+ inputSchema: z.object({}),
_meta: { ui: { resourceUri } }, // Links this tool to its UI resource
},
async (): Promise => {
diff --git a/examples/basic-server-solid/src/mcp-app.tsx b/examples/basic-server-solid/src/mcp-app.tsx
index 66d47f3..2d78b7b 100644
--- a/examples/basic-server-solid/src/mcp-app.tsx
+++ b/examples/basic-server-solid/src/mcp-app.tsx
@@ -8,7 +8,7 @@ import {
applyHostStyleVariables,
type McpUiHostContext,
} from "@modelcontextprotocol/ext-apps";
-import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
+import type { CallToolResult } from "@modelcontextprotocol/client";
import { createEffect, createSignal, onMount, Show } from "solid-js";
import { render } from "solid-js/web";
import styles from "./mcp-app.module.css";
diff --git a/examples/basic-server-solid/tsconfig.json b/examples/basic-server-solid/tsconfig.json
index 84f0efe..bb13a01 100644
--- a/examples/basic-server-solid/tsconfig.json
+++ b/examples/basic-server-solid/tsconfig.json
@@ -1,5 +1,6 @@
{
"compilerOptions": {
+ "types": ["node", "vite/client"],
"target": "ESNext",
"lib": ["ESNext", "DOM", "DOM.Iterable"],
"module": "ESNext",
diff --git a/examples/basic-server-solid/tsconfig.server.json b/examples/basic-server-solid/tsconfig.server.json
index 05ddd8e..27eb28f 100644
--- a/examples/basic-server-solid/tsconfig.server.json
+++ b/examples/basic-server-solid/tsconfig.server.json
@@ -1,5 +1,6 @@
{
"compilerOptions": {
+ "types": ["node"],
"target": "ES2022",
"lib": ["ES2022"],
"module": "NodeNext",
diff --git a/examples/basic-server-svelte/main.ts b/examples/basic-server-svelte/main.ts
index 6c50a25..734ec0c 100644
--- a/examples/basic-server-svelte/main.ts
+++ b/examples/basic-server-svelte/main.ts
@@ -4,10 +4,10 @@
* Or: node dist/index.js [--stdio]
*/
-import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
-import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js";
-import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
-import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
+import { createMcpExpressApp } from "@modelcontextprotocol/express";
+import { NodeStreamableHTTPServerTransport } from "@modelcontextprotocol/node";
+import type { McpServer } from "@modelcontextprotocol/server";
+import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
import cors from "cors";
import type { Request, Response } from "express";
import { createServer } from "./server.js";
@@ -27,7 +27,7 @@ export async function startStreamableHTTPServer(
app.all("/mcp", async (req: Request, res: Response) => {
const server = createServer();
- const transport = new StreamableHTTPServerTransport({
+ const transport = new NodeStreamableHTTPServerTransport({
sessionIdGenerator: undefined,
});
diff --git a/examples/basic-server-svelte/package.json b/examples/basic-server-svelte/package.json
index f877bf7..19fe4c9 100644
--- a/examples/basic-server-svelte/package.json
+++ b/examples/basic-server-svelte/package.json
@@ -1,11 +1,11 @@
{
"name": "@modelcontextprotocol/server-basic-svelte",
- "version": "1.7.4",
+ "version": "2.0.0",
"type": "module",
"description": "Basic MCP App Server example using Svelte",
"repository": {
"type": "git",
- "url": "https://github.com/modelcontextprotocol/ext-apps",
+ "url": "git+https://github.com/modelcontextprotocol/ext-apps.git",
"directory": "examples/basic-server-svelte"
},
"license": "MIT",
@@ -24,12 +24,15 @@
"prepublishOnly": "npm run build"
},
"dependencies": {
- "@modelcontextprotocol/ext-apps": "^1.7.0",
- "@modelcontextprotocol/sdk": "^1.29.0",
+ "@modelcontextprotocol/client": "2.0.0",
+ "@modelcontextprotocol/express": "2.0.0",
+ "@modelcontextprotocol/ext-apps": "^2.0.0",
+ "@modelcontextprotocol/node": "2.0.0",
+ "@modelcontextprotocol/server": "2.0.0",
"cors": "^2.8.5",
"express": "^5.1.0",
"svelte": "^5.0.0",
- "zod": "^4.1.13"
+ "zod": "^4.2.0"
},
"devDependencies": {
"@sveltejs/vite-plugin-svelte": "^5.0.0",
diff --git a/examples/basic-server-svelte/server.ts b/examples/basic-server-svelte/server.ts
index da603ca..9414285 100644
--- a/examples/basic-server-svelte/server.ts
+++ b/examples/basic-server-svelte/server.ts
@@ -1,8 +1,12 @@
-import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
-import type { CallToolResult, ReadResourceResult } from "@modelcontextprotocol/sdk/types.js";
+import {
+ McpServer,
+ type CallToolResult,
+ type ReadResourceResult,
+} from "@modelcontextprotocol/server";
import fs from "node:fs/promises";
import path from "node:path";
import { registerAppTool, registerAppResource, RESOURCE_MIME_TYPE } from "@modelcontextprotocol/ext-apps/server";
+import { z } from "zod";
// Works both from source (server.ts) and compiled (dist/server.js)
const DIST_DIR = import.meta.filename.endsWith(".ts")
? path.join(import.meta.dirname, "dist")
@@ -28,7 +32,7 @@ export function createServer(): McpServer {
{
title: "Get Time",
description: "Returns the current server time as an ISO 8601 string.",
- inputSchema: {},
+ inputSchema: z.object({}),
_meta: { ui: { resourceUri } }, // Links this tool to its UI resource
},
async (): Promise => {
diff --git a/examples/basic-server-svelte/src/App.svelte b/examples/basic-server-svelte/src/App.svelte
index fde128d..cabcc31 100644
--- a/examples/basic-server-svelte/src/App.svelte
+++ b/examples/basic-server-svelte/src/App.svelte
@@ -7,7 +7,7 @@ import {
applyHostStyleVariables,
type McpUiHostContext,
} from "@modelcontextprotocol/ext-apps";
-import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
+import type { CallToolResult } from "@modelcontextprotocol/client";
function extractTime(result: CallToolResult): string {
const { text } = result.content?.find((c) => c.type === "text")!;
diff --git a/examples/basic-server-svelte/tsconfig.json b/examples/basic-server-svelte/tsconfig.json
index 5edb66a..4fd3cd7 100644
--- a/examples/basic-server-svelte/tsconfig.json
+++ b/examples/basic-server-svelte/tsconfig.json
@@ -1,5 +1,6 @@
{
"compilerOptions": {
+ "types": ["node", "vite/client"],
"target": "ESNext",
"lib": ["ESNext", "DOM", "DOM.Iterable"],
"module": "ESNext",
diff --git a/examples/basic-server-svelte/tsconfig.server.json b/examples/basic-server-svelte/tsconfig.server.json
index 05ddd8e..27eb28f 100644
--- a/examples/basic-server-svelte/tsconfig.server.json
+++ b/examples/basic-server-svelte/tsconfig.server.json
@@ -1,5 +1,6 @@
{
"compilerOptions": {
+ "types": ["node"],
"target": "ES2022",
"lib": ["ES2022"],
"module": "NodeNext",
diff --git a/examples/basic-server-vanillajs/main.ts b/examples/basic-server-vanillajs/main.ts
index 286fa34..4de7331 100644
--- a/examples/basic-server-vanillajs/main.ts
+++ b/examples/basic-server-vanillajs/main.ts
@@ -4,10 +4,10 @@
* Or: node dist/index.js [--stdio]
*/
-import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
-import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js";
-import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
-import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
+import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
+import { createMcpExpressApp } from "@modelcontextprotocol/express";
+import type { McpServer } from "@modelcontextprotocol/server";
+import { NodeStreamableHTTPServerTransport } from "@modelcontextprotocol/node";
import cors from "cors";
import type { Request, Response } from "express";
import { createServer } from "./server.js";
@@ -27,7 +27,7 @@ export async function startStreamableHTTPServer(
app.all("/mcp", async (req: Request, res: Response) => {
const server = createServer();
- const transport = new StreamableHTTPServerTransport({
+ const transport = new NodeStreamableHTTPServerTransport({
sessionIdGenerator: undefined,
});
diff --git a/examples/basic-server-vanillajs/package.json b/examples/basic-server-vanillajs/package.json
index 5d47f2c..ebfebbb 100644
--- a/examples/basic-server-vanillajs/package.json
+++ b/examples/basic-server-vanillajs/package.json
@@ -1,11 +1,11 @@
{
"name": "@modelcontextprotocol/server-basic-vanillajs",
- "version": "1.7.4",
+ "version": "2.0.0",
"type": "module",
"description": "Basic MCP App Server example using vanilla JavaScript",
"repository": {
"type": "git",
- "url": "https://github.com/modelcontextprotocol/ext-apps",
+ "url": "git+https://github.com/modelcontextprotocol/ext-apps.git",
"directory": "examples/basic-server-vanillajs"
},
"license": "MIT",
@@ -24,11 +24,14 @@
"prepublishOnly": "npm run build"
},
"dependencies": {
- "@modelcontextprotocol/ext-apps": "^1.7.0",
- "@modelcontextprotocol/sdk": "^1.29.0",
+ "@modelcontextprotocol/client": "2.0.0",
+ "@modelcontextprotocol/express": "2.0.0",
+ "@modelcontextprotocol/ext-apps": "^2.0.0",
+ "@modelcontextprotocol/node": "2.0.0",
+ "@modelcontextprotocol/server": "2.0.0",
"cors": "^2.8.5",
"express": "^5.1.0",
- "zod": "^4.1.13"
+ "zod": "^4.2.0"
},
"devDependencies": {
"@types/cors": "^2.8.19",
diff --git a/examples/basic-server-vanillajs/server.ts b/examples/basic-server-vanillajs/server.ts
index 5b2daf7..693d861 100644
--- a/examples/basic-server-vanillajs/server.ts
+++ b/examples/basic-server-vanillajs/server.ts
@@ -1,6 +1,9 @@
import { registerAppResource, registerAppTool, RESOURCE_MIME_TYPE } from "@modelcontextprotocol/ext-apps/server";
-import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
-import type { CallToolResult, ReadResourceResult } from "@modelcontextprotocol/sdk/types.js";
+import {
+ McpServer,
+ type CallToolResult,
+ type ReadResourceResult,
+} from "@modelcontextprotocol/server";
import fs from "node:fs/promises";
import path from "node:path";
import { z } from "zod";
@@ -29,7 +32,7 @@ export function createServer(): McpServer {
{
title: "Get Time",
description: "Returns the current server time as an ISO 8601 string.",
- inputSchema: {},
+ inputSchema: z.object({}),
outputSchema: z.object({
time: z.string(),
}),
diff --git a/examples/basic-server-vanillajs/src/mcp-app.ts b/examples/basic-server-vanillajs/src/mcp-app.ts
index c3168c2..6b5084a 100644
--- a/examples/basic-server-vanillajs/src/mcp-app.ts
+++ b/examples/basic-server-vanillajs/src/mcp-app.ts
@@ -8,7 +8,7 @@ import {
applyHostStyleVariables,
type McpUiHostContext,
} from "@modelcontextprotocol/ext-apps";
-import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
+import type { CallToolResult } from "@modelcontextprotocol/client";
import "./global.css";
import "./mcp-app.css";
diff --git a/examples/basic-server-vanillajs/tsconfig.json b/examples/basic-server-vanillajs/tsconfig.json
index 535267b..b028ff5 100644
--- a/examples/basic-server-vanillajs/tsconfig.json
+++ b/examples/basic-server-vanillajs/tsconfig.json
@@ -1,5 +1,6 @@
{
"compilerOptions": {
+ "types": ["node", "vite/client"],
"target": "ESNext",
"lib": ["ESNext", "DOM", "DOM.Iterable"],
"module": "ESNext",
diff --git a/examples/basic-server-vanillajs/tsconfig.server.json b/examples/basic-server-vanillajs/tsconfig.server.json
index 05ddd8e..27eb28f 100644
--- a/examples/basic-server-vanillajs/tsconfig.server.json
+++ b/examples/basic-server-vanillajs/tsconfig.server.json
@@ -1,5 +1,6 @@
{
"compilerOptions": {
+ "types": ["node"],
"target": "ES2022",
"lib": ["ES2022"],
"module": "NodeNext",
diff --git a/examples/basic-server-vue/main.ts b/examples/basic-server-vue/main.ts
index 669a071..d774269 100644
--- a/examples/basic-server-vue/main.ts
+++ b/examples/basic-server-vue/main.ts
@@ -4,10 +4,10 @@
* Or: node dist/index.js [--stdio]
*/
-import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
-import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js";
-import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
-import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
+import { createMcpExpressApp } from "@modelcontextprotocol/express";
+import { NodeStreamableHTTPServerTransport } from "@modelcontextprotocol/node";
+import type { McpServer } from "@modelcontextprotocol/server";
+import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
import cors from "cors";
import type { Request, Response } from "express";
import { createServer } from "./server.js";
@@ -27,7 +27,7 @@ export async function startStreamableHTTPServer(
app.all("/mcp", async (req: Request, res: Response) => {
const server = createServer();
- const transport = new StreamableHTTPServerTransport({
+ const transport = new NodeStreamableHTTPServerTransport({
sessionIdGenerator: undefined,
});
diff --git a/examples/basic-server-vue/package.json b/examples/basic-server-vue/package.json
index d27ddc9..858dd89 100644
--- a/examples/basic-server-vue/package.json
+++ b/examples/basic-server-vue/package.json
@@ -1,11 +1,11 @@
{
"name": "@modelcontextprotocol/server-basic-vue",
- "version": "1.7.4",
+ "version": "2.0.0",
"type": "module",
"description": "Basic MCP App Server example using Vue",
"repository": {
"type": "git",
- "url": "https://github.com/modelcontextprotocol/ext-apps",
+ "url": "git+https://github.com/modelcontextprotocol/ext-apps.git",
"directory": "examples/basic-server-vue"
},
"license": "MIT",
@@ -24,12 +24,15 @@
"prepublishOnly": "npm run build"
},
"dependencies": {
- "@modelcontextprotocol/ext-apps": "^1.7.0",
- "@modelcontextprotocol/sdk": "^1.29.0",
+ "@modelcontextprotocol/client": "2.0.0",
+ "@modelcontextprotocol/express": "2.0.0",
+ "@modelcontextprotocol/ext-apps": "^2.0.0",
+ "@modelcontextprotocol/node": "2.0.0",
+ "@modelcontextprotocol/server": "2.0.0",
"cors": "^2.8.5",
"express": "^5.1.0",
"vue": "^3.5.0",
- "zod": "^4.1.13"
+ "zod": "^4.2.0"
},
"devDependencies": {
"@types/cors": "^2.8.19",
diff --git a/examples/basic-server-vue/server.ts b/examples/basic-server-vue/server.ts
index 5aa72de..9adb911 100644
--- a/examples/basic-server-vue/server.ts
+++ b/examples/basic-server-vue/server.ts
@@ -1,8 +1,12 @@
-import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
-import type { CallToolResult, ReadResourceResult } from "@modelcontextprotocol/sdk/types.js";
+import {
+ McpServer,
+ type CallToolResult,
+ type ReadResourceResult,
+} from "@modelcontextprotocol/server";
import fs from "node:fs/promises";
import path from "node:path";
import { registerAppTool, registerAppResource, RESOURCE_MIME_TYPE } from "@modelcontextprotocol/ext-apps/server";
+import { z } from "zod";
// Works both from source (server.ts) and compiled (dist/server.js)
const DIST_DIR = import.meta.filename.endsWith(".ts")
? path.join(import.meta.dirname, "dist")
@@ -28,7 +32,7 @@ export function createServer(): McpServer {
{
title: "Get Time",
description: "Returns the current server time as an ISO 8601 string.",
- inputSchema: {},
+ inputSchema: z.object({}),
_meta: { ui: { resourceUri } }, // Links this tool to its UI resource
},
async (): Promise => {
diff --git a/examples/basic-server-vue/src/App.vue b/examples/basic-server-vue/src/App.vue
index 196ad64..a45c262 100644
--- a/examples/basic-server-vue/src/App.vue
+++ b/examples/basic-server-vue/src/App.vue
@@ -7,7 +7,7 @@ import {
applyHostStyleVariables,
type McpUiHostContext,
} from "@modelcontextprotocol/ext-apps";
-import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
+import type { CallToolResult } from "@modelcontextprotocol/client";
function extractTime(result: CallToolResult): string {
const { text } = result.content?.find((c) => c.type === "text")!;
diff --git a/examples/basic-server-vue/tsconfig.json b/examples/basic-server-vue/tsconfig.json
index 5edb66a..4fd3cd7 100644
--- a/examples/basic-server-vue/tsconfig.json
+++ b/examples/basic-server-vue/tsconfig.json
@@ -1,5 +1,6 @@
{
"compilerOptions": {
+ "types": ["node", "vite/client"],
"target": "ESNext",
"lib": ["ESNext", "DOM", "DOM.Iterable"],
"module": "ESNext",
diff --git a/examples/basic-server-vue/tsconfig.server.json b/examples/basic-server-vue/tsconfig.server.json
index 05ddd8e..27eb28f 100644
--- a/examples/basic-server-vue/tsconfig.server.json
+++ b/examples/basic-server-vue/tsconfig.server.json
@@ -1,5 +1,6 @@
{
"compilerOptions": {
+ "types": ["node"],
"target": "ES2022",
"lib": ["ES2022"],
"module": "NodeNext",
diff --git a/examples/budget-allocator-server/main.ts b/examples/budget-allocator-server/main.ts
index cc488f0..02c03cb 100644
--- a/examples/budget-allocator-server/main.ts
+++ b/examples/budget-allocator-server/main.ts
@@ -4,10 +4,10 @@
* Or: node dist/index.js [--stdio]
*/
-import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
-import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js";
-import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
-import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
+import { createMcpExpressApp } from "@modelcontextprotocol/express";
+import { NodeStreamableHTTPServerTransport } from "@modelcontextprotocol/node";
+import type { McpServer } from "@modelcontextprotocol/server";
+import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
import cors from "cors";
import type { Request, Response } from "express";
import { createServer } from "./server.js";
@@ -27,7 +27,7 @@ export async function startStreamableHTTPServer(
app.all("/mcp", async (req: Request, res: Response) => {
const server = createServer();
- const transport = new StreamableHTTPServerTransport({
+ const transport = new NodeStreamableHTTPServerTransport({
sessionIdGenerator: undefined,
});
diff --git a/examples/budget-allocator-server/package.json b/examples/budget-allocator-server/package.json
index 19a1d25..6e41622 100644
--- a/examples/budget-allocator-server/package.json
+++ b/examples/budget-allocator-server/package.json
@@ -1,11 +1,11 @@
{
"name": "@modelcontextprotocol/server-budget-allocator",
- "version": "1.7.4",
+ "version": "2.0.0",
"type": "module",
"description": "Budget allocator MCP App Server with interactive visualization",
"repository": {
"type": "git",
- "url": "https://github.com/modelcontextprotocol/ext-apps",
+ "url": "git+https://github.com/modelcontextprotocol/ext-apps.git",
"directory": "examples/budget-allocator-server"
},
"license": "MIT",
@@ -26,12 +26,14 @@
"serve": "bun --watch main.ts"
},
"dependencies": {
- "@modelcontextprotocol/ext-apps": "^1.7.0",
- "@modelcontextprotocol/sdk": "^1.29.0",
+ "@modelcontextprotocol/express": "2.0.0",
+ "@modelcontextprotocol/ext-apps": "^2.0.0",
+ "@modelcontextprotocol/node": "2.0.0",
+ "@modelcontextprotocol/server": "2.0.0",
"chart.js": "^4.4.0",
"cors": "^2.8.5",
"express": "^5.1.0",
- "zod": "^4.1.13"
+ "zod": "^4.2.0"
},
"devDependencies": {
"@types/cors": "^2.8.19",
diff --git a/examples/budget-allocator-server/server.ts b/examples/budget-allocator-server/server.ts
index 04fba11..01f5dbf 100755
--- a/examples/budget-allocator-server/server.ts
+++ b/examples/budget-allocator-server/server.ts
@@ -4,11 +4,11 @@
* Provides budget configuration, 24 months of historical allocation data,
* and industry benchmarks by company stage.
*/
-import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
-import type {
- CallToolResult,
- ReadResourceResult,
-} from "@modelcontextprotocol/sdk/types.js";
+import {
+ McpServer,
+ type CallToolResult,
+ type ReadResourceResult,
+} from "@modelcontextprotocol/server";
import fs from "node:fs/promises";
import path from "node:path";
import { z } from "zod";
@@ -270,7 +270,7 @@ export function createServer(): McpServer {
title: "Get Budget Data",
description:
"Returns budget configuration with 24 months of historical allocations and industry benchmarks by company stage. The widget is interactive and exposes tools for reading/modifying allocations, adjusting budgets, and comparing against industry benchmarks.",
- inputSchema: {},
+ inputSchema: z.object({}),
outputSchema: BudgetDataResponseSchema,
_meta: { ui: { resourceUri } },
},
diff --git a/examples/budget-allocator-server/tsconfig.json b/examples/budget-allocator-server/tsconfig.json
index 535267b..b028ff5 100644
--- a/examples/budget-allocator-server/tsconfig.json
+++ b/examples/budget-allocator-server/tsconfig.json
@@ -1,5 +1,6 @@
{
"compilerOptions": {
+ "types": ["node", "vite/client"],
"target": "ESNext",
"lib": ["ESNext", "DOM", "DOM.Iterable"],
"module": "ESNext",
diff --git a/examples/budget-allocator-server/tsconfig.server.json b/examples/budget-allocator-server/tsconfig.server.json
index 05ddd8e..27eb28f 100644
--- a/examples/budget-allocator-server/tsconfig.server.json
+++ b/examples/budget-allocator-server/tsconfig.server.json
@@ -1,5 +1,6 @@
{
"compilerOptions": {
+ "types": ["node"],
"target": "ES2022",
"lib": ["ES2022"],
"module": "NodeNext",
diff --git a/examples/cohort-heatmap-server/main.ts b/examples/cohort-heatmap-server/main.ts
index d59903b..8b33603 100644
--- a/examples/cohort-heatmap-server/main.ts
+++ b/examples/cohort-heatmap-server/main.ts
@@ -4,10 +4,10 @@
* Or: node dist/index.js [--stdio]
*/
-import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
-import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js";
-import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
-import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
+import { createMcpExpressApp } from "@modelcontextprotocol/express";
+import { NodeStreamableHTTPServerTransport } from "@modelcontextprotocol/node";
+import type { McpServer } from "@modelcontextprotocol/server";
+import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
import cors from "cors";
import type { Request, Response } from "express";
import { createServer } from "./server.js";
@@ -27,7 +27,7 @@ export async function startStreamableHTTPServer(
app.all("/mcp", async (req: Request, res: Response) => {
const server = createServer();
- const transport = new StreamableHTTPServerTransport({
+ const transport = new NodeStreamableHTTPServerTransport({
sessionIdGenerator: undefined,
});
diff --git a/examples/cohort-heatmap-server/package.json b/examples/cohort-heatmap-server/package.json
index 8d1268b..7e2d2e2 100644
--- a/examples/cohort-heatmap-server/package.json
+++ b/examples/cohort-heatmap-server/package.json
@@ -1,11 +1,11 @@
{
"name": "@modelcontextprotocol/server-cohort-heatmap",
- "version": "1.7.4",
+ "version": "2.0.0",
"type": "module",
"description": "Cohort heatmap MCP App Server for retention analysis",
"repository": {
"type": "git",
- "url": "https://github.com/modelcontextprotocol/ext-apps",
+ "url": "git+https://github.com/modelcontextprotocol/ext-apps.git",
"directory": "examples/cohort-heatmap-server"
},
"license": "MIT",
@@ -26,13 +26,15 @@
"serve": "bun --watch main.ts"
},
"dependencies": {
- "@modelcontextprotocol/ext-apps": "^1.7.0",
- "@modelcontextprotocol/sdk": "^1.29.0",
+ "@modelcontextprotocol/express": "2.0.0",
+ "@modelcontextprotocol/ext-apps": "^2.0.0",
+ "@modelcontextprotocol/node": "2.0.0",
+ "@modelcontextprotocol/server": "2.0.0",
"cors": "^2.8.5",
"express": "^5.1.0",
"react": "^19.2.0",
"react-dom": "^19.2.0",
- "zod": "^4.1.13"
+ "zod": "^4.2.0"
},
"devDependencies": {
"@types/cors": "^2.8.19",
diff --git a/examples/cohort-heatmap-server/server.ts b/examples/cohort-heatmap-server/server.ts
index 6d07144..129e2dc 100644
--- a/examples/cohort-heatmap-server/server.ts
+++ b/examples/cohort-heatmap-server/server.ts
@@ -1,5 +1,7 @@
-import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
-import type { ReadResourceResult } from "@modelcontextprotocol/sdk/types.js";
+import {
+ McpServer,
+ type ReadResourceResult,
+} from "@modelcontextprotocol/server";
import fs from "node:fs/promises";
import path from "node:path";
import { z } from "zod";
@@ -178,8 +180,8 @@ export function createServer(): McpServer {
title: "Get Cohort Retention Data",
description:
"Returns cohort retention heatmap data showing customer retention over time by signup month",
- inputSchema: GetCohortDataInputSchema.shape,
- outputSchema: CohortDataSchema.shape,
+ inputSchema: GetCohortDataInputSchema,
+ outputSchema: CohortDataSchema,
_meta: { ui: { resourceUri } },
},
async ({ metric, periodType, cohortCount, maxPeriods }) => {
diff --git a/examples/cohort-heatmap-server/tsconfig.json b/examples/cohort-heatmap-server/tsconfig.json
index fc3c210..3ecbdad 100644
--- a/examples/cohort-heatmap-server/tsconfig.json
+++ b/examples/cohort-heatmap-server/tsconfig.json
@@ -1,5 +1,6 @@
{
"compilerOptions": {
+ "types": ["node", "vite/client"],
"target": "ESNext",
"lib": ["ESNext", "DOM", "DOM.Iterable"],
"module": "ESNext",
diff --git a/examples/cohort-heatmap-server/tsconfig.server.json b/examples/cohort-heatmap-server/tsconfig.server.json
index 05ddd8e..27eb28f 100644
--- a/examples/cohort-heatmap-server/tsconfig.server.json
+++ b/examples/cohort-heatmap-server/tsconfig.server.json
@@ -1,5 +1,6 @@
{
"compilerOptions": {
+ "types": ["node"],
"target": "ES2022",
"lib": ["ES2022"],
"module": "NodeNext",
diff --git a/examples/customer-segmentation-server/main.ts b/examples/customer-segmentation-server/main.ts
index 130076c..c788757 100644
--- a/examples/customer-segmentation-server/main.ts
+++ b/examples/customer-segmentation-server/main.ts
@@ -4,10 +4,10 @@
* Or: node dist/index.js [--stdio]
*/
-import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
-import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js";
-import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
-import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
+import { createMcpExpressApp } from "@modelcontextprotocol/express";
+import { NodeStreamableHTTPServerTransport } from "@modelcontextprotocol/node";
+import type { McpServer } from "@modelcontextprotocol/server";
+import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
import cors from "cors";
import type { Request, Response } from "express";
import { createServer } from "./server.js";
@@ -27,7 +27,7 @@ export async function startStreamableHTTPServer(
app.all("/mcp", async (req: Request, res: Response) => {
const server = createServer();
- const transport = new StreamableHTTPServerTransport({
+ const transport = new NodeStreamableHTTPServerTransport({
sessionIdGenerator: undefined,
});
diff --git a/examples/customer-segmentation-server/package.json b/examples/customer-segmentation-server/package.json
index 4511de9..bac3b89 100644
--- a/examples/customer-segmentation-server/package.json
+++ b/examples/customer-segmentation-server/package.json
@@ -1,11 +1,11 @@
{
"name": "@modelcontextprotocol/server-customer-segmentation",
- "version": "1.7.4",
+ "version": "2.0.0",
"type": "module",
"description": "Customer segmentation MCP App Server with filtering",
"repository": {
"type": "git",
- "url": "https://github.com/modelcontextprotocol/ext-apps",
+ "url": "git+https://github.com/modelcontextprotocol/ext-apps.git",
"directory": "examples/customer-segmentation-server"
},
"license": "MIT",
@@ -26,12 +26,14 @@
"serve": "bun --watch main.ts"
},
"dependencies": {
- "@modelcontextprotocol/ext-apps": "^1.7.0",
- "@modelcontextprotocol/sdk": "^1.29.0",
+ "@modelcontextprotocol/express": "2.0.0",
+ "@modelcontextprotocol/ext-apps": "^2.0.0",
+ "@modelcontextprotocol/node": "2.0.0",
+ "@modelcontextprotocol/server": "2.0.0",
"chart.js": "^4.4.0",
"cors": "^2.8.5",
"express": "^5.1.0",
- "zod": "^4.1.13"
+ "zod": "^4.2.0"
},
"devDependencies": {
"@types/cors": "^2.8.19",
diff --git a/examples/customer-segmentation-server/server.ts b/examples/customer-segmentation-server/server.ts
index 244415d..7cc1c1f 100644
--- a/examples/customer-segmentation-server/server.ts
+++ b/examples/customer-segmentation-server/server.ts
@@ -1,8 +1,8 @@
-import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
-import type {
- CallToolResult,
- ReadResourceResult,
-} from "@modelcontextprotocol/sdk/types.js";
+import {
+ McpServer,
+ type CallToolResult,
+ type ReadResourceResult,
+} from "@modelcontextprotocol/server";
import fs from "node:fs/promises";
import path from "node:path";
import { z } from "zod";
@@ -100,8 +100,8 @@ export function createServer(): McpServer {
title: "Get Customer Data",
description:
"Returns customer data with segment information for visualization. Optionally filter by segment.",
- inputSchema: GetCustomerDataInputSchema.shape,
- outputSchema: GetCustomerDataOutputSchema.shape,
+ inputSchema: GetCustomerDataInputSchema,
+ outputSchema: GetCustomerDataOutputSchema,
_meta: { ui: { resourceUri } },
},
async ({ segment }): Promise => {
diff --git a/examples/customer-segmentation-server/tsconfig.json b/examples/customer-segmentation-server/tsconfig.json
index 535267b..b028ff5 100644
--- a/examples/customer-segmentation-server/tsconfig.json
+++ b/examples/customer-segmentation-server/tsconfig.json
@@ -1,5 +1,6 @@
{
"compilerOptions": {
+ "types": ["node", "vite/client"],
"target": "ESNext",
"lib": ["ESNext", "DOM", "DOM.Iterable"],
"module": "ESNext",
diff --git a/examples/customer-segmentation-server/tsconfig.server.json b/examples/customer-segmentation-server/tsconfig.server.json
index 05ddd8e..27eb28f 100644
--- a/examples/customer-segmentation-server/tsconfig.server.json
+++ b/examples/customer-segmentation-server/tsconfig.server.json
@@ -1,5 +1,6 @@
{
"compilerOptions": {
+ "types": ["node"],
"target": "ES2022",
"lib": ["ES2022"],
"module": "NodeNext",
diff --git a/examples/debug-server/main.ts b/examples/debug-server/main.ts
index 3c89a97..9fb0825 100644
--- a/examples/debug-server/main.ts
+++ b/examples/debug-server/main.ts
@@ -4,10 +4,10 @@
* Or: node dist/index.js [--stdio]
*/
-import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
-import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js";
-import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
-import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
+import { createMcpExpressApp } from "@modelcontextprotocol/express";
+import { NodeStreamableHTTPServerTransport } from "@modelcontextprotocol/node";
+import type { McpServer } from "@modelcontextprotocol/server";
+import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
import cors from "cors";
import type { Request, Response } from "express";
import { createServer } from "./server.js";
@@ -27,7 +27,7 @@ export async function startStreamableHTTPServer(
app.all("/mcp", async (req: Request, res: Response) => {
const server = createServer();
- const transport = new StreamableHTTPServerTransport({
+ const transport = new NodeStreamableHTTPServerTransport({
sessionIdGenerator: undefined,
});
diff --git a/examples/debug-server/package.json b/examples/debug-server/package.json
index 3417a8f..e28f4d3 100644
--- a/examples/debug-server/package.json
+++ b/examples/debug-server/package.json
@@ -1,11 +1,11 @@
{
"name": "@modelcontextprotocol/server-debug",
- "version": "1.7.4",
+ "version": "2.0.0",
"type": "module",
"description": "Debug MCP App Server for testing all SDK capabilities",
"repository": {
"type": "git",
- "url": "https://github.com/modelcontextprotocol/ext-apps",
+ "url": "git+https://github.com/modelcontextprotocol/ext-apps.git",
"directory": "examples/debug-server"
},
"license": "MIT",
@@ -34,9 +34,11 @@
"prepublishOnly": "npm run build"
},
"dependencies": {
- "@modelcontextprotocol/ext-apps": "^1.7.0",
- "@modelcontextprotocol/sdk": "^1.29.0",
- "zod": "^4.1.13"
+ "@modelcontextprotocol/express": "2.0.0",
+ "@modelcontextprotocol/ext-apps": "^2.0.0",
+ "@modelcontextprotocol/node": "2.0.0",
+ "@modelcontextprotocol/server": "2.0.0",
+ "zod": "^4.2.0"
},
"devDependencies": {
"@types/cors": "^2.8.19",
diff --git a/examples/debug-server/server.ts b/examples/debug-server/server.ts
index fd3452a..068f94d 100644
--- a/examples/debug-server/server.ts
+++ b/examples/debug-server/server.ts
@@ -3,11 +3,11 @@ import {
registerAppTool,
RESOURCE_MIME_TYPE,
} from "@modelcontextprotocol/ext-apps/server";
-import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
-import type {
- CallToolResult,
- ReadResourceResult,
-} from "@modelcontextprotocol/sdk/types.js";
+import {
+ McpServer,
+ type CallToolResult,
+ type ReadResourceResult,
+} from "@modelcontextprotocol/server";
import fs from "node:fs/promises";
import { appendFileSync } from "node:fs";
import path from "node:path";
diff --git a/examples/debug-server/tsconfig.json b/examples/debug-server/tsconfig.json
index 535267b..b028ff5 100644
--- a/examples/debug-server/tsconfig.json
+++ b/examples/debug-server/tsconfig.json
@@ -1,5 +1,6 @@
{
"compilerOptions": {
+ "types": ["node", "vite/client"],
"target": "ESNext",
"lib": ["ESNext", "DOM", "DOM.Iterable"],
"module": "ESNext",
diff --git a/examples/debug-server/tsconfig.server.json b/examples/debug-server/tsconfig.server.json
index 05ddd8e..27eb28f 100644
--- a/examples/debug-server/tsconfig.server.json
+++ b/examples/debug-server/tsconfig.server.json
@@ -1,5 +1,6 @@
{
"compilerOptions": {
+ "types": ["node"],
"target": "ES2022",
"lib": ["ES2022"],
"module": "NodeNext",
diff --git a/examples/integration-server/main.ts b/examples/integration-server/main.ts
index c45787e..9a42842 100644
--- a/examples/integration-server/main.ts
+++ b/examples/integration-server/main.ts
@@ -4,10 +4,10 @@
* Or: node dist/index.js [--stdio]
*/
-import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
-import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js";
-import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
-import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
+import { createMcpExpressApp } from "@modelcontextprotocol/express";
+import { NodeStreamableHTTPServerTransport } from "@modelcontextprotocol/node";
+import type { McpServer } from "@modelcontextprotocol/server";
+import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
import cors from "cors";
import type { Request, Response } from "express";
import { createServer } from "./server.js";
@@ -27,7 +27,7 @@ export async function startStreamableHTTPServer(
app.all("/mcp", async (req: Request, res: Response) => {
const server = createServer();
- const transport = new StreamableHTTPServerTransport({
+ const transport = new NodeStreamableHTTPServerTransport({
sessionIdGenerator: undefined,
});
diff --git a/examples/integration-server/package.json b/examples/integration-server/package.json
index f6715a4..7e04f4a 100644
--- a/examples/integration-server/package.json
+++ b/examples/integration-server/package.json
@@ -1,6 +1,6 @@
{
"name": "integration-server",
- "version": "1.7.4",
+ "version": "2.0.0",
"private": true,
"type": "module",
"scripts": {
@@ -15,13 +15,16 @@
"serve": "bun --watch main.ts"
},
"dependencies": {
- "@modelcontextprotocol/ext-apps": "^1.7.0",
- "@modelcontextprotocol/sdk": "^1.29.0",
+ "@modelcontextprotocol/client": "2.0.0",
+ "@modelcontextprotocol/express": "2.0.0",
+ "@modelcontextprotocol/ext-apps": "^2.0.0",
+ "@modelcontextprotocol/node": "2.0.0",
+ "@modelcontextprotocol/server": "2.0.0",
"cors": "^2.8.5",
"express": "^5.1.0",
"react": "^19.2.0",
"react-dom": "^19.2.0",
- "zod": "^4.1.13"
+ "zod": "^4.2.0"
},
"devDependencies": {
"@types/cors": "^2.8.19",
diff --git a/examples/integration-server/server.ts b/examples/integration-server/server.ts
index e44689d..346f4f7 100644
--- a/examples/integration-server/server.ts
+++ b/examples/integration-server/server.ts
@@ -3,11 +3,11 @@ import {
registerAppTool,
RESOURCE_MIME_TYPE,
} from "@modelcontextprotocol/ext-apps/server";
-import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
-import type {
- CallToolResult,
- ReadResourceResult,
-} from "@modelcontextprotocol/sdk/types.js";
+import {
+ McpServer,
+ type CallToolResult,
+ type ReadResourceResult,
+} from "@modelcontextprotocol/server";
import fs from "node:fs/promises";
import path from "node:path";
import { z } from "zod";
@@ -33,7 +33,7 @@ export function createServer(): McpServer {
{
title: "Get Time",
description: "Returns the current server time.",
- inputSchema: {},
+ inputSchema: z.object({}),
outputSchema: z.object({
time: z.string(),
}),
@@ -72,7 +72,7 @@ export function createServer(): McpServer {
);
// Sample downloadable resource — used to demo ResourceLink in ui/download-file
- server.resource(
+ server.registerResource(
SAMPLE_DOWNLOAD_URI,
SAMPLE_DOWNLOAD_URI,
{
diff --git a/examples/integration-server/src/mcp-app.tsx b/examples/integration-server/src/mcp-app.tsx
index 7f0b18c..281a356 100644
--- a/examples/integration-server/src/mcp-app.tsx
+++ b/examples/integration-server/src/mcp-app.tsx
@@ -3,7 +3,7 @@
*/
import type { App, McpUiHostContext } from "@modelcontextprotocol/ext-apps";
import { useApp } from "@modelcontextprotocol/ext-apps/react";
-import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
+import type { CallToolResult } from "@modelcontextprotocol/client";
import { StrictMode, useCallback, useEffect, useState } from "react";
import { createRoot } from "react-dom/client";
import styles from "./mcp-app.module.css";
diff --git a/examples/integration-server/tsconfig.json b/examples/integration-server/tsconfig.json
index fc3c210..3ecbdad 100644
--- a/examples/integration-server/tsconfig.json
+++ b/examples/integration-server/tsconfig.json
@@ -1,5 +1,6 @@
{
"compilerOptions": {
+ "types": ["node", "vite/client"],
"target": "ESNext",
"lib": ["ESNext", "DOM", "DOM.Iterable"],
"module": "ESNext",
diff --git a/examples/integration-server/tsconfig.server.json b/examples/integration-server/tsconfig.server.json
index 05ddd8e..27eb28f 100644
--- a/examples/integration-server/tsconfig.server.json
+++ b/examples/integration-server/tsconfig.server.json
@@ -1,5 +1,6 @@
{
"compilerOptions": {
+ "types": ["node"],
"target": "ES2022",
"lib": ["ES2022"],
"module": "NodeNext",
diff --git a/examples/lazy-auth-server/package.json b/examples/lazy-auth-server/package.json
index f3ed6cd..dbd4601 100644
--- a/examples/lazy-auth-server/package.json
+++ b/examples/lazy-auth-server/package.json
@@ -1,11 +1,11 @@
{
"name": "@modelcontextprotocol/server-lazy-auth",
- "version": "1.7.4",
+ "version": "2.0.0",
"type": "module",
"description": "MCP App example demonstrating lazy (on-demand) OAuth: public tools work unauthenticated, protected tools return 401 + WWW-Authenticate so the host runs the OAuth flow only when needed",
"repository": {
"type": "git",
- "url": "https://github.com/modelcontextprotocol/ext-apps",
+ "url": "git+https://github.com/modelcontextprotocol/ext-apps.git",
"directory": "examples/lazy-auth-server"
},
"license": "MIT",
@@ -22,11 +22,13 @@
"prepublishOnly": "npm run build"
},
"dependencies": {
- "@modelcontextprotocol/ext-apps": "^1.7.0",
- "@modelcontextprotocol/sdk": "^1.29.0",
+ "@modelcontextprotocol/ext-apps": "^2.0.0",
+ "@modelcontextprotocol/node": "2.0.0",
+ "@modelcontextprotocol/server": "2.0.0",
"cors": "^2.8.5",
"express": "^5.1.0",
- "jose": "^6.0.0"
+ "jose": "^6.0.0",
+ "zod": "^4.2.0"
},
"devDependencies": {
"@types/cors": "^2.8.19",
diff --git a/examples/lazy-auth-server/server.ts b/examples/lazy-auth-server/server.ts
index fe7b1ac..5240008 100644
--- a/examples/lazy-auth-server/server.ts
+++ b/examples/lazy-auth-server/server.ts
@@ -21,13 +21,13 @@ import {
registerAppTool,
RESOURCE_MIME_TYPE,
} from "@modelcontextprotocol/ext-apps/server";
-import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
-import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
-import { UrlElicitationRequiredError } from "@modelcontextprotocol/sdk/types.js";
-import type {
- CallToolResult,
- ReadResourceResult,
-} from "@modelcontextprotocol/sdk/types.js";
+import { NodeStreamableHTTPServerTransport } from "@modelcontextprotocol/node";
+import {
+ McpServer,
+ UrlElicitationRequiredError,
+ type CallToolResult,
+ type ReadResourceResult,
+} from "@modelcontextprotocol/server";
import cors from "cors";
import express, { type Express, type Request, type Response } from "express";
import { SignJWT, jwtVerify } from "jose";
@@ -35,6 +35,7 @@ import crypto from "node:crypto";
import fs from "node:fs/promises";
import path from "node:path";
import { fileURLToPath } from "node:url";
+import { z } from "zod";
// Works both from source (server.ts) and compiled (dist/server.js). Derived
// from import.meta.url rather than import.meta.filename/dirname, which are
@@ -414,20 +415,36 @@ async function handleAuthorize(req: Request, res: Response) {
if (state) denyUrl.searchParams.set("state", state);
res.type("text/html").send(/*html*/ `
Authorize
+
+.actions{display:flex;flex-wrap:wrap;gap:12px;-webkit-user-select:none;user-select:none;-webkit-touch-callout:none}
+.btn{box-sizing:border-box;flex:1;min-height:56px;min-width:56px;display:flex;align-items:center;justify-content:center;
+padding:12px 20px;font-size:16px;font-weight:bold;border:none;border-radius:8px;cursor:pointer;
+text-decoration:none;color:#fff;touch-action:manipulation;-webkit-tap-highlight-color:transparent}
+.btn:active{filter:brightness(0.8)}
+.approve{background:#1a7a3e}.deny{background:#b91c1c}
🔑 Mock Authorization
An application is requesting access:
- Client
- ${escapeHtml(client_id ?? "(none)")}
- Scope
- ${escapeHtml(scope ?? "(default)")}
- Redirect
- ${escapeHtml(redirect_uri)}
-
-
-