Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:

permissions:
contents: read
Expand Down
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,15 @@ resources:
## Getting Started

```bash
npm install -S @modelcontextprotocol/ext-apps
npm install -S @modelcontextprotocol/ext-apps \
@modelcontextprotocol/client @modelcontextprotocol/server @modelcontextprotocol/core
```

Peer dependencies are the MCP TypeScript SDK v2 packages
(`@modelcontextprotocol/client`, `/server`, `/core` at `2.0.0-beta.3`). Install
the ones your entry point needs — Views use `client` + `core`, server helpers
use `server`, and `app-bridge` uses all three.

**New here?** Start with the
[Quickstart Guide](https://apps.extensions.modelcontextprotocol.io/api/documents/Quickstart.html)
to build your first MCP App.
Expand Down
12 changes: 9 additions & 3 deletions build.bun.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,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 deps stay external so consumers share a single instance (zod
// instanceof / schema.extend() break with duplicates; MCP packages must
// match the host's installed v2 SDK). Bundled into *-with-deps variants.
const PEER_EXTERNALS = [
"@modelcontextprotocol/client",
"@modelcontextprotocol/core",
"@modelcontextprotocol/server",
"zod",
];

await Promise.all([
buildJs("src/app.ts", {
Expand Down
4 changes: 2 additions & 2 deletions docs/migrate_from_openai_apps.md
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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,
Expand Down
9 changes: 3 additions & 6 deletions docs/patterns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,13 @@ 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 { ReadResourceResultSchema } from "@modelcontextprotocol/core";
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";

/**
Expand Down
14 changes: 7 additions & 7 deletions docs/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -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/server @modelcontextprotocol/node @modelcontextprotocol/express express cors
npm install -D typescript vite vite-plugin-singlefile @types/express @types/cors @types/node tsx concurrently cross-env
```

Expand Down Expand Up @@ -178,7 +178,7 @@ 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";

Expand Down Expand Up @@ -240,10 +240,10 @@ export function createServer(): McpServer {

<!-- prettier-ignore -->
```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 type { McpServer } from "@modelcontextprotocol/server";
import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
import { NodeStreamableHTTPServerTransport } from "@modelcontextprotocol/node";
import cors from "cors";
import type { Request, Response } from "express";
import { createServer } from "./server.js";
Expand All @@ -263,7 +263,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,
});

Expand Down
2 changes: 1 addition & 1 deletion examples/basic-host/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
"dev": "cross-env NODE_ENV=development concurrently \"npm run watch\" \"npm run serve\""
},
"dependencies": {
"@modelcontextprotocol/client": "2.0.0-beta.3",
"@modelcontextprotocol/ext-apps": "^1.7.0",
"@modelcontextprotocol/sdk": "^1.29.0",
"react": "^19.2.0",
"react-dom": "^19.2.0",
"zod": "^4.1.13"
Expand Down
14 changes: 9 additions & 5 deletions examples/basic-host/src/implementation.ts
Original file line number Diff line number Diff line change
@@ -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";

Expand Down Expand Up @@ -94,7 +98,7 @@ export function callTool(
input: Record<string, unknown>,
): ToolCallInfo {
log.info("Calling tool", name, "with input", input);
const resultPromise = serverInfo.client.callTool({ name, arguments: input }) as Promise<CallToolResult>;
const resultPromise = serverInfo.client.callTool({ name, arguments: input });

const tool = serverInfo.tools.get(name);
if (!tool) {
Expand Down
2 changes: 1 addition & 1 deletion examples/basic-host/src/index.tsx
Original file line number Diff line number Diff line change
@@ -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";
Expand Down
10 changes: 5 additions & 5 deletions examples/basic-server-preact/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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,
});

Expand Down
5 changes: 4 additions & 1 deletion examples/basic-server-preact/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,11 @@
"prepublishOnly": "npm run build"
},
"dependencies": {
"@modelcontextprotocol/client": "2.0.0-beta.3",
"@modelcontextprotocol/express": "2.0.0-beta.3",
"@modelcontextprotocol/ext-apps": "^1.7.0",
"@modelcontextprotocol/sdk": "^1.29.0",
"@modelcontextprotocol/node": "2.0.0-beta.3",
"@modelcontextprotocol/server": "2.0.0-beta.3",
"cors": "^2.8.5",
"express": "^5.1.0",
"preact": "^10.0.0",
Expand Down
4 changes: 2 additions & 2 deletions examples/basic-server-preact/server.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import type { CallToolResult, ReadResourceResult } from "@modelcontextprotocol/sdk/types.js";
import { McpServer } from "@modelcontextprotocol/server";
import type { CallToolResult, 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";
Expand Down
2 changes: 1 addition & 1 deletion examples/basic-server-preact/src/mcp-app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
10 changes: 5 additions & 5 deletions examples/basic-server-react/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 type { McpServer } from "@modelcontextprotocol/server";
import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
import { NodeStreamableHTTPServerTransport } from "@modelcontextprotocol/node";
import cors from "cors";
import type { Request, Response } from "express";
import { createServer } from "./server.js";
Expand All @@ -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,
});

Expand Down
4 changes: 3 additions & 1 deletion examples/basic-server-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@
"prepublishOnly": "npm run build"
},
"dependencies": {
"@modelcontextprotocol/express": "2.0.0-beta.3",
"@modelcontextprotocol/ext-apps": "^1.7.0",
"@modelcontextprotocol/sdk": "^1.29.0",
"@modelcontextprotocol/node": "2.0.0-beta.3",
"@modelcontextprotocol/server": "2.0.0-beta.3",
"cors": "^2.8.5",
"express": "^5.1.0",
"react": "^19.2.0",
Expand Down
4 changes: 2 additions & 2 deletions examples/basic-server-react/server.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
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 } from "@modelcontextprotocol/server";
import type { CallToolResult, ReadResourceResult } from "@modelcontextprotocol/server";
import fs from "node:fs/promises";
import path from "node:path";

Expand Down
10 changes: 5 additions & 5 deletions examples/basic-server-react/src/mcp-app.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
/**
* @file App that demonstrates a few features using MCP Apps SDK + React.
*/
import type { App, McpUiHostContext } from "@modelcontextprotocol/ext-apps";
import type { App, CallToolResult, McpUiHostContext } from "@modelcontextprotocol/ext-apps";
import { useApp } from "@modelcontextprotocol/ext-apps/react";
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
import { StrictMode, useCallback, useEffect, useState } from "react";
import { createRoot } from "react-dom/client";
import styles from "./mcp-app.module.css";


function extractTime(callToolResult: CallToolResult): string {
const { text } = callToolResult.content?.find((c) => c.type === "text")!;
return text;
const sc = callToolResult.structuredContent as { time?: string } | undefined;
if (sc?.time) return sc.time;
const { text } = callToolResult.content?.find((c) => c.type === "text") ?? {};
return text ?? "";
}


Expand Down
10 changes: 5 additions & 5 deletions examples/basic-server-solid/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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,
});

Expand Down
5 changes: 4 additions & 1 deletion examples/basic-server-solid/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,11 @@
"prepublishOnly": "npm run build"
},
"dependencies": {
"@modelcontextprotocol/client": "2.0.0-beta.3",
"@modelcontextprotocol/express": "2.0.0-beta.3",
"@modelcontextprotocol/ext-apps": "^1.7.0",
"@modelcontextprotocol/sdk": "^1.29.0",
"@modelcontextprotocol/node": "2.0.0-beta.3",
"@modelcontextprotocol/server": "2.0.0-beta.3",
"cors": "^2.8.5",
"express": "^5.1.0",
"solid-js": "1.9.10",
Expand Down
4 changes: 2 additions & 2 deletions examples/basic-server-solid/server.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import type { CallToolResult, ReadResourceResult } from "@modelcontextprotocol/sdk/types.js";
import { McpServer } from "@modelcontextprotocol/server";
import type { CallToolResult, 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";
Expand Down
2 changes: 1 addition & 1 deletion examples/basic-server-solid/src/mcp-app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
10 changes: 5 additions & 5 deletions examples/basic-server-svelte/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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,
});

Expand Down
5 changes: 4 additions & 1 deletion examples/basic-server-svelte/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,11 @@
"prepublishOnly": "npm run build"
},
"dependencies": {
"@modelcontextprotocol/client": "2.0.0-beta.3",
"@modelcontextprotocol/express": "2.0.0-beta.3",
"@modelcontextprotocol/ext-apps": "^1.7.0",
"@modelcontextprotocol/sdk": "^1.29.0",
"@modelcontextprotocol/node": "2.0.0-beta.3",
"@modelcontextprotocol/server": "2.0.0-beta.3",
"cors": "^2.8.5",
"express": "^5.1.0",
"svelte": "^5.0.0",
Expand Down
4 changes: 2 additions & 2 deletions examples/basic-server-svelte/server.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import type { CallToolResult, ReadResourceResult } from "@modelcontextprotocol/sdk/types.js";
import { McpServer } from "@modelcontextprotocol/server";
import type { CallToolResult, 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";
Expand Down
2 changes: 1 addition & 1 deletion examples/basic-server-svelte/src/App.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -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")!;
Expand Down
Loading
Loading