Skip to content

Commit 06367bc

Browse files
committed
Merge remote-tracking branch 'origin/main' into ochafik/map-server-screenshot
2 parents 622eb20 + c2037f3 commit 06367bc

File tree

90 files changed

+2479
-948
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

90 files changed

+2479
-948
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
name: Update E2E Snapshots
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
branch:
7+
description: "Branch to update snapshots on"
8+
required: true
9+
default: "main"
10+
# Temporary: auto-run on this branch to update snapshots
11+
push:
12+
branches:
13+
- "ochafik/fix-e2e-flaky-tests"
14+
paths:
15+
- ".github/workflows/update-snapshots.yml"
16+
17+
permissions:
18+
contents: write
19+
20+
jobs:
21+
update-snapshots:
22+
runs-on: ubuntu-latest
23+
steps:
24+
- uses: actions/checkout@v4
25+
with:
26+
ref: ${{ github.event.inputs.branch || github.ref }}
27+
token: ${{ secrets.GITHUB_TOKEN }}
28+
29+
- uses: oven-sh/setup-bun@v2
30+
with:
31+
bun-version: latest
32+
33+
- uses: actions/setup-node@v4
34+
with:
35+
node-version: "20"
36+
37+
- uses: astral-sh/setup-uv@v5
38+
39+
- run: npm ci
40+
41+
- name: Install Playwright browsers
42+
run: npx playwright install --with-deps chromium
43+
44+
- name: Update snapshots
45+
run: npx playwright test --update-snapshots --reporter=list
46+
47+
- name: Commit updated snapshots
48+
run: |
49+
git config user.name "github-actions[bot]"
50+
git config user.email "github-actions[bot]@users.noreply.github.com"
51+
git add tests/e2e/**/*.png
52+
git diff --staged --quiet || git commit -m "chore: update e2e snapshots [skip ci]"
53+
git push

.husky/pre-commit

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
# Load Node.js environment for GUI apps (GitHub Desktop, etc.)
2+
# that don't inherit shell PATH
3+
export NVM_DIR="$HOME/.nvm"
4+
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # nvm
5+
[ -s "$HOME/.fnm/fnm" ] && eval "$(~/.fnm/fnm env)" # fnm
6+
[ -s "$HOME/.volta/bin/volta" ] && export PATH="$HOME/.volta/bin:$PATH" # volta
7+
[ -d "/opt/homebrew/bin" ] && export PATH="/opt/homebrew/bin:$PATH" # homebrew (macOS ARM)
8+
[ -d "/usr/local/bin" ] && export PATH="/usr/local/bin:$PATH" # homebrew (macOS Intel)
9+
110
# Verify no private registry URLs in package-lock.json
211
if grep -E '"resolved": "https?://' package-lock.json | grep -v registry.npmjs.org > /dev/null; then
312
echo "ERROR: package-lock.json contains non-npmjs.org URLs"

.prettierignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@ examples/basic-host/**/*.ts
22
examples/basic-host/**/*.tsx
33
examples/basic-server-*/**/*.ts
44
examples/basic-server-*/**/*.tsx
5+
examples/quickstart/**/*.ts
56
**/vendor/**
67
SKILL.md

AGENTS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ View (App) <--PostMessageTransport--> Host (AppBridge) <--MCP Client--> MCP Serv
8080

8181
## Documentation
8282

83-
JSDoc `@example` tags should pull type-checked code from companion `.examples.ts` files (e.g., `app.ts``app.examples.ts`). Use ` ```ts source="./file.examples.ts#regionName" ` fences referencing `//#region regionName` blocks, then run `npm run sync:snippets`. Region names follow `exportedName_variant` or `ClassName_methodName_variant` pattern (e.g., `useApp_basicUsage`, `App_hostCapabilities_checkAfterConnection`).
83+
JSDoc `@example` tags should pull type-checked code from companion `.examples.ts` files (e.g., `app.ts``app.examples.ts`). Use ` ```ts source="./file.examples.ts#regionName" ` fences referencing `//#region regionName` blocks; region names follow `exportedName_variant` or `ClassName_methodName_variant` pattern (e.g., `useApp_basicUsage`, `App_hostCapabilities_checkAfterConnection`). For whole-file inclusion (any file type), omit the `#regionName`. Run `npm run sync:snippets` to sync.
8484

8585
Standalone docs in `docs/` (listed in `typedoc.config.mjs` `projectDocuments`) can also have type-checked companion `.ts`/`.tsx` files using the same pattern.
8686

README.md

Lines changed: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,29 +6,33 @@ This repo contains the SDK and [specification](https://github.com/modelcontextpr
66

77
MCP Apps are a proposed standard inspired by [MCP-UI](https://mcpui.dev/) and [OpenAI's Apps SDK](https://developers.openai.com/apps-sdk/) to allow MCP Servers to display interactive UI elements in conversational MCP clients / chatbots.
88

9+
## Why MCP Apps?
10+
11+
MCP tools return text and structured data. That works for many cases, but not when you need an interactive UI, like a chart, form, or video player.
12+
13+
MCP Apps provide a standardized way to deliver interactive UIs from MCP servers. Your UI renders inline in the conversation, in context, in any compliant host.
14+
915
## How It Works
1016

11-
MCP Apps extend the Model Context Protocol to let servers deliver **interactive UIs** to MCP hosts. Here's how it works:
17+
MCP Apps extend the Model Context Protocol by letting tools declare UI resources:
1218

13-
1. **Tool call**The LLM calls a tool on your server
14-
2. **UI Resource** — The tool's definition links to a predeclared `ui://` resource containing its HTML interface
19+
1. **Tool definition**Your tool declares a `ui://` resource containing its HTML interface
20+
2. **Tool call** — The LLM calls the tool on your server
1521
3. **Host renders** — The host fetches the resource and displays it in a sandboxed iframe
1622
4. **Bidirectional communication** — The host passes tool data to the UI via notifications, and the UI can call other tools through the host
1723

18-
This enables dashboards, forms, visualizations, and other rich experiences inside chat interfaces.
19-
20-
## Overview
24+
## Using the SDK
2125

2226
This SDK serves two audiences:
2327

24-
### App Developers
28+
### For App Developers
2529

2630
Build interactive UIs that run inside MCP-enabled chat clients.
2731

2832
- **SDK for Apps**: `@modelcontextprotocol/ext-apps`[API Docs](https://modelcontextprotocol.github.io/ext-apps/api/modules/app.html)
2933
- **React hooks**: `@modelcontextprotocol/ext-apps/react`[API Docs](https://modelcontextprotocol.github.io/ext-apps/api/modules/_modelcontextprotocol_ext-apps_react.html)
3034

31-
### Host Developers
35+
### For Host Developers
3236

3337
Embed and communicate with MCP Apps in your chat application.
3438

@@ -44,17 +48,21 @@ We have [contributed a tentative implementation](https://github.com/MCP-UI-Org/m
4448
npm install -S @modelcontextprotocol/ext-apps
4549
```
4650

47-
### Claude Code Plugin
51+
### Install Agent Skills
4852

49-
A [Claude Code plugin](https://github.com/modelcontextprotocol/ext-apps/tree/main/plugins/mcp-apps) is available to help create MCP Apps. To install, run these commands inside Claude Code:
53+
This repository provides two [Agent Skills](https://agentskills.io/) for building MCP Apps. You can install the skills as a Claude Code plugin:
5054

5155
```
5256
/plugin marketplace add modelcontextprotocol/ext-apps
5357
/plugin install mcp-apps@modelcontextprotocol-ext-apps
5458
```
5559

60+
For more information, including instructions for installing the skills in your favorite AI coding agent, see the [agent skills guide](./docs/agent-skills.md).
61+
5662
## Examples
5763

64+
The [`examples/`](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples) directory contains demo apps showcasing real-world use cases.
65+
5866
<!-- prettier-ignore-start -->
5967
| | | |
6068
|:---:|:---:|:---:|
@@ -76,12 +84,27 @@ A [Claude Code plugin](https://github.com/modelcontextprotocol/ext-apps/tree/mai
7684
| [![Basic](examples/basic-server-react/grid-cell.png "Starter template")](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/basic-server-react) | The same app built with different frameworks — pick your favorite!<br><br>[React](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/basic-server-react) · [Vue](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/basic-server-vue) · [Svelte](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/basic-server-svelte) · [Preact](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/basic-server-preact) · [Solid](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/basic-server-solid) · [Vanilla JS](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/basic-server-vanillajs) |
7785
<!-- prettier-ignore-end -->
7886

79-
The [`examples/`](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples) directory contains additional demo apps showcasing real-world use cases.
87+
### Running the Examples
8088

81-
<details>
82-
<summary>MCP client configuration for all examples</summary>
89+
#### With basic-host
90+
91+
To run all examples locally using [basic-host](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/basic-host) (the reference host implementation included in this repo):
92+
93+
```bash
94+
git clone https://github.com/modelcontextprotocol/ext-apps.git
95+
cd ext-apps
96+
npm install
97+
npm start
98+
```
8399

84-
Add to your MCP client configuration (stdio transport):
100+
Then open http://localhost:8080/.
101+
102+
#### With MCP Clients
103+
104+
To use these examples with MCP clients that support the stdio transport (such as Claude Desktop or VS Code), add this MCP server configuration to your client's settings:
105+
106+
<details>
107+
<summary>MCP client configuration for all examples (using stdio)</summary>
85108

86109
```json
87110
{
@@ -298,18 +321,10 @@ Add to your MCP client configuration (stdio transport):
298321
}
299322
```
300323

301-
> **Note:** The `qr` server requires cloning the repository first. See [qr-server README](examples/qr-server) for details.
302-
303324
</details>
304325

305-
To run all examples locally in dev mode:
306-
307-
```bash
308-
npm install
309-
npm start
310-
```
311-
312-
Then open http://localhost:8080/.
326+
> [!NOTE]
327+
> The `qr` server requires cloning the repository first. See [qr-server README](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/qr-server) for details.
313328
314329
## Resources
315330

docs/agent-skills.md

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
---
2+
title: Agent Skills
3+
---
4+
5+
# Agent Skills
6+
7+
[Agent Skills](https://agentskills.io/) are instruction sets that guide AI coding agents through tasks. When you invoke a skill, the agent takes the lead — it asks clarifying questions, makes decisions based on your codebase, and executes the work.
8+
9+
This repository provides two skills:
10+
11+
- [**create-mcp-app**](https://github.com/modelcontextprotocol/ext-apps/blob/main/plugins/mcp-apps/skills/create-mcp-app/SKILL.md) — scaffolds a new MCP App with an interactive UI
12+
- [**migrate-oai-app**](https://github.com/modelcontextprotocol/ext-apps/blob/main/plugins/mcp-apps/skills/migrate-oai-app/SKILL.md) — migrates an existing OpenAI App to the MCP Apps SDK
13+
14+
## Install the Skills
15+
16+
Choose one of the following installation methods based on your agent:
17+
18+
### Option 1: Claude Code Plugin
19+
20+
Install via Claude Code:
21+
22+
```
23+
/plugin marketplace add modelcontextprotocol/ext-apps
24+
/plugin install mcp-apps@modelcontextprotocol-ext-apps
25+
```
26+
27+
### Option 2: Vercel Skills CLI
28+
29+
Use the [Vercel Skills CLI](https://skills.sh/) to install skills across different AI coding agents:
30+
31+
```bash
32+
npx skills add modelcontextprotocol/ext-apps
33+
```
34+
35+
### Option 3: Manual Installation
36+
37+
Clone the repository:
38+
39+
```bash
40+
git clone https://github.com/modelcontextprotocol/ext-apps.git
41+
```
42+
43+
Then copy the skills from `plugins/mcp-apps/skills/` to your agent's skills directory. See your agent's documentation for the correct location:
44+
45+
- [Claude Code](https://docs.anthropic.com/en/docs/claude-code/skills)
46+
- [VS Code](https://code.visualstudio.com/docs/copilot/customization/agent-skills) / [GitHub Copilot](https://docs.github.com/en/copilot/concepts/agents/about-agent-skills)
47+
- [Codex](https://developers.openai.com/codex/skills/)
48+
- [Gemini CLI](https://geminicli.com/docs/cli/skills/)
49+
- [Cline](https://docs.cline.bot/features/skills#skills)
50+
- [Goose](https://block.github.io/goose/docs/guides/context-engineering/using-skills/)
51+
52+
## Verify Installation
53+
54+
Ask your agent "What skills do you have?" — you should see `create-mcp-app` and `migrate-oai-app` among the available skills.
55+
56+
## Invoke a Skill
57+
58+
Try invoking the skills by asking your agent:
59+
60+
- "Create an MCP App" — scaffolds a new MCP App with an interactive UI
61+
- "Migrate from OpenAI Apps SDK" — converts an existing OpenAI App to use the MCP Apps SDK
62+
63+
The agent will guide you through the process, asking clarifying questions as needed.
64+
65+
## Test Your App
66+
67+
After creating or migrating your MCP App, see the [Testing MCP Apps](./testing-mcp-apps.md) guide to run and debug it locally.

docs/migrate_from_openai_apps.md

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,17 @@ title: Migrate OpenAI App
44

55
# Migrating from OpenAI Apps SDK to MCP Apps SDK
66

7-
This guide helps you migrate from the OpenAI Apps SDK to the MCP Apps SDK (`@modelcontextprotocol/ext-apps`).
7+
This reference maps OpenAI Apps SDK concepts to their MCP Apps SDK (`@modelcontextprotocol/ext-apps`) equivalents. Use the tables below for quick lookup during migration, and refer to the code examples for complete before/after comparisons.
8+
9+
This guide covers server-side changes first (metadata, tools, resources), then client-side changes (setup, context, events).
10+
11+
> [!NOTE]
12+
> Some OpenAI Apps SDK features don't have MCP equivalents yet. These are marked "Not yet implemented" in the tables below.
813
914
## Server-Side
1015

16+
The server-side changes involve updating metadata structure and using helper functions.
17+
1118
### Quick Start Comparison
1219

1320
| OpenAI Apps SDK | MCP Apps SDK |
@@ -190,6 +197,8 @@ function createServer() {
190197

191198
## Client-Side
192199

200+
Client-side migration involves replacing the implicit `window.openai` global with an explicit `App` instance.
201+
193202
### Quick Start Comparison
194203

195204
| OpenAI Apps SDK | MCP Apps SDK |
@@ -282,16 +291,17 @@ function createServer() {
282291
| ------------------------------------------- | -------- | ------------------- |
283292
| `await window.openai.requestModal(options)` || Not yet implemented |
284293
| `window.openai.requestClose()` || Not yet implemented |
294+
| `window.openai.setOpenInAppUrl({ href })` || Not yet implemented |
285295
| `window.openai.view` || Not yet mapped |
286296

287297
### Event Handling
288298

289-
| OpenAI | MCP Apps | Notes |
290-
| ------------------------------ | ------------------------------------------- | -------------------------------- |
291-
| Read `window.openai.*` on load | `app.ontoolinput = (params) => {...}` | Register before `connect()` |
292-
| Read `window.openai.*` on load | `app.ontoolresult = (params) => {...}` | Register before `connect()` |
293-
| Poll or re-read properties | `app.onhostcontextchanged = (ctx) => {...}` | MCP pushes context changes |
294-
|| `app.onteardown = async () => {...}` | MCP adds: cleanup before unmount |
299+
| OpenAI | MCP Apps | Notes |
300+
| --------------------------------------------- | ------------------------------------------- | ------------------------------------------------------------------ |
301+
| `window.openai.toolInput` (read on load) | `app.ontoolinput = (params) => {...}` | OpenAI: sync property; MCP: callback (register before `connect()`) |
302+
| `window.openai.toolOutput` (read on load) | `app.ontoolresult = (params) => {...}` | OpenAI: sync property; MCP: callback (register before `connect()`) |
303+
| `addEventListener("openai:set_globals", ...)` | `app.onhostcontextchanged = (ctx) => {...}` | Both push updates; MCP uses callback, OpenAI uses DOM event |
304+
| | `app.onteardown = async () => {...}` | MCP adds: cleanup before unmount |
295305

296306
### Logging
297307

0 commit comments

Comments
 (0)