Compare commits
457 changed files with 6111 additions and 69328 deletions
|
|
@ -1,14 +0,0 @@
|
|||
{
|
||||
"name": "mcp-apps",
|
||||
"description": "Plugins for MCP Apps development",
|
||||
"owner": {
|
||||
"name": "MCP Apps"
|
||||
},
|
||||
"plugins": [
|
||||
{
|
||||
"name": "mcp-apps",
|
||||
"source": "./plugins/mcp-apps",
|
||||
"description": "Skills for creating MCP Apps with the MCP Apps SDK"
|
||||
}
|
||||
]
|
||||
}
|
||||
120
.github/workflows/ci.yml
vendored
120
.github/workflows/ci.yml
vendored
|
|
@ -10,36 +10,6 @@ permissions:
|
|||
contents: read
|
||||
|
||||
jobs:
|
||||
prettier-fix:
|
||||
name: Auto-fix formatting
|
||||
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ github.head_ref }}
|
||||
token: ${{ github.token }}
|
||||
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: "22"
|
||||
cache: npm
|
||||
|
||||
- run: npm ci
|
||||
|
||||
- run: npm run prettier:fix
|
||||
|
||||
- name: Commit formatting changes
|
||||
run: |
|
||||
git diff --quiet && exit 0
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git add -A
|
||||
git commit -m "style: auto-fix prettier formatting"
|
||||
git push
|
||||
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
|
@ -60,29 +30,20 @@ jobs:
|
|||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Verify no private URLs in package-lock.json
|
||||
shell: bash
|
||||
run: '! grep -E "\"resolved\": \"https?://" package-lock.json | grep -v registry.npmjs.org'
|
||||
|
||||
- name: Verify example dependency versions
|
||||
shell: bash
|
||||
run: node scripts/check-versions.mjs
|
||||
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "22"
|
||||
cache: npm
|
||||
node-version: "20"
|
||||
|
||||
- run: npm ci
|
||||
- run: npm install
|
||||
|
||||
- run: npm run build
|
||||
|
||||
- name: Validate TypeDoc links
|
||||
if: runner.os == 'Linux' && matrix.name == 'Linux x64'
|
||||
run: npm exec typedoc -- --treatValidationWarningsAsErrors --emit none
|
||||
|
||||
- run: npm run examples:build
|
||||
|
||||
- name: Verify generated schemas are up-to-date
|
||||
|
|
@ -91,72 +52,33 @@ jobs:
|
|||
npm run generate:schemas
|
||||
git diff --exit-code src/generated/ || (echo "Generated schemas are out of date. Run 'npm run generate:schemas' and commit." && exit 1)
|
||||
|
||||
- name: Verify synced snippets are up-to-date
|
||||
shell: bash
|
||||
run: |
|
||||
npm run sync:snippets
|
||||
git diff --exit-code src/ docs/ || (echo "Synced snippets are out of date. Run 'npm run sync:snippets' and commit." && exit 1)
|
||||
|
||||
- run: npm test
|
||||
|
||||
- run: npm run prettier
|
||||
|
||||
- name: Build MCPB bundle (pdf-server)
|
||||
if: runner.os == 'Linux' && matrix.name == 'Linux x64'
|
||||
run: node build-mcpb.mjs
|
||||
working-directory: examples/pdf-server
|
||||
|
||||
- name: Smoke-test MCPB bundle starts
|
||||
if: runner.os == 'Linux' && matrix.name == 'Linux x64'
|
||||
run: |
|
||||
unzip -q pdf-server.mcpb -d .mcpb-smoke
|
||||
node .mcpb-smoke/dist/index.js --stdio < /dev/null 2>&1 | tee /tmp/mcpb-smoke.log
|
||||
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:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: oven-sh/setup-bun@v2
|
||||
with:
|
||||
bun-version: latest
|
||||
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "22"
|
||||
cache: npm
|
||||
|
||||
- uses: astral-sh/setup-uv@v7
|
||||
node-version: "20"
|
||||
|
||||
- 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 --only-shell chromium
|
||||
run: npx playwright install --with-deps chromium
|
||||
|
||||
- name: Run E2E tests
|
||||
run: npx playwright test --reporter=list
|
||||
|
||||
- name: Upload test results
|
||||
uses: actions/upload-artifact@v6
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: test-results
|
||||
|
|
@ -169,9 +91,9 @@ jobs:
|
|||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: Vampire/setup-wsl@v6
|
||||
- uses: Vampire/setup-wsl@v5
|
||||
with:
|
||||
distribution: Ubuntu-24.04
|
||||
|
||||
|
|
@ -179,18 +101,13 @@ jobs:
|
|||
shell: wsl-bash {0}
|
||||
run: |
|
||||
sudo apt-get update
|
||||
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
|
||||
curl -fsSL https://deb.nodesource.com/setup_20.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 install
|
||||
npm run build
|
||||
npm run examples:build
|
||||
npm test
|
||||
|
|
@ -217,20 +134,17 @@ jobs:
|
|||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "22"
|
||||
node-version: "20"
|
||||
|
||||
- name: Create test project and install from git
|
||||
shell: bash
|
||||
env:
|
||||
HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name || github.repository }}
|
||||
HEAD_REF: ${{ github.head_ref || github.ref_name }}
|
||||
run: |
|
||||
mkdir test-project
|
||||
cd test-project
|
||||
npm init -y
|
||||
# Install from the PR branch (use head repo for fork PRs)
|
||||
npm install "git+https://github.com/${HEAD_REPO}#${HEAD_REF}"
|
||||
# Install from the PR branch
|
||||
npm install "git+https://github.com/${{ github.repository }}#${{ github.head_ref || github.ref_name }}"
|
||||
# Verify the package is usable (ESM import)
|
||||
node --input-type=module -e "import { App } from '@modelcontextprotocol/ext-apps'; console.log('Import successful:', typeof App)"
|
||||
|
|
|
|||
65
.github/workflows/docs-preview.yml
vendored
65
.github/workflows/docs-preview.yml
vendored
|
|
@ -1,65 +0,0 @@
|
|||
name: Docs Preview
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened, closed]
|
||||
paths:
|
||||
- "docs/**"
|
||||
- "src/**"
|
||||
- "README.md"
|
||||
- "typedoc.config.mjs"
|
||||
- "scripts/typedoc-*.mjs"
|
||||
- ".github/workflows/docs-preview.yml"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
concurrency:
|
||||
group: docs-preview-${{ github.event.pull_request.number }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build-and-deploy:
|
||||
# Refuse to run for fork PRs — forks do not have access to the Cloudflare
|
||||
# secrets, so deploys would fail anyway.
|
||||
if: >-
|
||||
github.event.action != 'closed' &&
|
||||
github.event.pull_request.head.repo.full_name == github.repository
|
||||
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 build
|
||||
|
||||
- run: npm run docs
|
||||
|
||||
- name: Deploy preview
|
||||
uses: modelcontextprotocol/actions/cloudflare-pages-preview/deploy@main
|
||||
with:
|
||||
directory: docs
|
||||
project-name: mcp-ext-apps-docs-preview
|
||||
api-token: ${{ secrets.CF_PAGES_PREVIEW_API_TOKEN }}
|
||||
account-id: ${{ secrets.CF_PAGES_PREVIEW_ACCOUNT_ID }}
|
||||
comment-title: "📖 Docs Preview Deployed"
|
||||
comment-marker: "<!-- docs-preview-comment -->"
|
||||
|
||||
cleanup:
|
||||
if: >-
|
||||
github.event.action == 'closed' &&
|
||||
github.event.pull_request.head.repo.full_name == github.repository
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: modelcontextprotocol/actions/cloudflare-pages-preview/cleanup@main
|
||||
with:
|
||||
project-name: mcp-ext-apps-docs-preview
|
||||
api-token: ${{ secrets.CF_PAGES_PREVIEW_API_TOKEN }}
|
||||
account-id: ${{ secrets.CF_PAGES_PREVIEW_ACCOUNT_ID }}
|
||||
comment-marker: "<!-- docs-preview-comment -->"
|
||||
10
.github/workflows/docs.yml
vendored
10
.github/workflows/docs.yml
vendored
|
|
@ -12,13 +12,12 @@ jobs:
|
|||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- uses: oven-sh/setup-bun@v2
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "22"
|
||||
cache: npm
|
||||
- run: npm ci
|
||||
node-version: "20"
|
||||
- run: npm install
|
||||
- run: npm run build
|
||||
- run: npm run docs
|
||||
- uses: peaceiris/actions-gh-pages@v4
|
||||
|
|
@ -27,4 +26,3 @@ jobs:
|
|||
publish_dir: ./docs
|
||||
publish_branch: gh-pages
|
||||
keep_files: true
|
||||
cname: apps.extensions.modelcontextprotocol.io
|
||||
|
|
|
|||
110
.github/workflows/npm-publish.yml
vendored
110
.github/workflows/npm-publish.yml
vendored
|
|
@ -14,11 +14,11 @@ jobs:
|
|||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- uses: oven-sh/setup-bun@v2
|
||||
with:
|
||||
bun-version: latest
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "22"
|
||||
cache: npm
|
||||
|
|
@ -31,21 +31,17 @@ jobs:
|
|||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- uses: oven-sh/setup-bun@v2
|
||||
with:
|
||||
bun-version: latest
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "22"
|
||||
cache: npm
|
||||
- run: npm ci
|
||||
- run: npm test
|
||||
|
||||
# All publish jobs depend directly on [build, test] (not on each other) so
|
||||
# they all enter "waiting for approval" together and can be approved in a
|
||||
# single "Review deployments" click.
|
||||
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'release'
|
||||
|
|
@ -57,11 +53,11 @@ jobs:
|
|||
id-token: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- uses: oven-sh/setup-bun@v2
|
||||
with:
|
||||
bun-version: latest
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "22"
|
||||
cache: npm
|
||||
|
|
@ -87,97 +83,3 @@ jobs:
|
|||
- run: npm publish --provenance --access public ${{ steps.npm-tag.outputs.tag }}
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_SECRET }}
|
||||
|
||||
publish-examples:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'release'
|
||||
environment: Release
|
||||
needs: [build, test]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
example:
|
||||
- basic-server-preact
|
||||
- basic-server-react
|
||||
- basic-server-solid
|
||||
- basic-server-svelte
|
||||
- basic-server-vanillajs
|
||||
- basic-server-vue
|
||||
- budget-allocator-server
|
||||
- cohort-heatmap-server
|
||||
- customer-segmentation-server
|
||||
- debug-server
|
||||
- lazy-auth-server
|
||||
- map-server
|
||||
- pdf-server
|
||||
- scenario-modeler-server
|
||||
- shadertoy-server
|
||||
- sheet-music-server
|
||||
- system-monitor-server
|
||||
- threejs-server
|
||||
- transcript-server
|
||||
- video-resource-server
|
||||
- wiki-explorer-server
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: oven-sh/setup-bun@v2
|
||||
with:
|
||||
bun-version: latest
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: "22"
|
||||
cache: npm
|
||||
registry-url: "https://registry.npmjs.org"
|
||||
- run: npm ci
|
||||
|
||||
- name: Build example
|
||||
run: npm run build --workspace examples/${{ matrix.example }}
|
||||
|
||||
- name: Determine npm tag
|
||||
id: npm-tag
|
||||
run: |
|
||||
VERSION=$(node -p "require('./package.json').version")
|
||||
if [[ "$VERSION" == *"-"* ]]; then
|
||||
echo "tag=--tag beta" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "tag=" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Publish example
|
||||
run: npm publish --workspace examples/${{ matrix.example }} --provenance --access public ${{ steps.npm-tag.outputs.tag }}
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_SECRET }}
|
||||
|
||||
publish-mcpb:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'release'
|
||||
environment: Release
|
||||
needs: [build, test]
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: oven-sh/setup-bun@v2
|
||||
with:
|
||||
bun-version: latest
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: "22"
|
||||
cache: npm
|
||||
- run: npm ci
|
||||
|
||||
- name: Build pdf-server + MCPB bundle
|
||||
run: npm run build:mcpb --workspace examples/pdf-server
|
||||
|
||||
- name: Upload MCPB to release
|
||||
run: gh release upload "${{ github.event.release.tag_name }}" examples/pdf-server/*.mcpb --clobber
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
|
|
|
|||
30
.github/workflows/publish.yml
vendored
30
.github/workflows/publish.yml
vendored
|
|
@ -13,35 +13,11 @@ jobs:
|
|||
pkg-publish:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
cache: npm
|
||||
- run: npm ci
|
||||
- run: npm run build
|
||||
- run: npm run examples:build
|
||||
- run: |
|
||||
npx pkg-pr-new publish \
|
||||
. \
|
||||
./examples/basic-server-preact \
|
||||
./examples/basic-server-react \
|
||||
./examples/basic-server-solid \
|
||||
./examples/basic-server-svelte \
|
||||
./examples/basic-server-vanillajs \
|
||||
./examples/basic-server-vue \
|
||||
./examples/budget-allocator-server \
|
||||
./examples/cohort-heatmap-server \
|
||||
./examples/customer-segmentation-server \
|
||||
./examples/debug-server \
|
||||
./examples/lazy-auth-server \
|
||||
./examples/map-server \
|
||||
./examples/pdf-server \
|
||||
./examples/scenario-modeler-server \
|
||||
./examples/shadertoy-server \
|
||||
./examples/sheet-music-server \
|
||||
./examples/system-monitor-server \
|
||||
./examples/threejs-server \
|
||||
./examples/transcript-server \
|
||||
./examples/video-resource-server \
|
||||
./examples/wiki-explorer-server
|
||||
- run: npx pkg-pr-new publish
|
||||
|
|
|
|||
108
.github/workflows/update-snapshots.yml
vendored
108
.github/workflows/update-snapshots.yml
vendored
|
|
@ -1,108 +0,0 @@
|
|||
name: Update E2E Snapshots
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
branch:
|
||||
description: "Branch to update snapshots on"
|
||||
required: true
|
||||
default: "main"
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
update-snapshots:
|
||||
# Run on workflow_dispatch OR when a maintainer comments "/update-snapshots" on a PR.
|
||||
# author_association check prevents arbitrary commenters from triggering a job with
|
||||
# contents:write that pushes a [skip ci] commit to the PR branch.
|
||||
if: >
|
||||
github.event_name == 'workflow_dispatch' ||
|
||||
(github.event.issue.pull_request &&
|
||||
contains(github.event.comment.body, '/update-snapshots') &&
|
||||
contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association))
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Get PR branch
|
||||
if: github.event_name == 'issue_comment'
|
||||
id: pr
|
||||
uses: actions/github-script@v8
|
||||
with:
|
||||
script: |
|
||||
const pr = await github.rest.pulls.get({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: context.issue.number
|
||||
});
|
||||
core.setOutput('ref', pr.data.head.ref);
|
||||
core.setOutput('sha', pr.data.head.sha);
|
||||
|
||||
- name: Add reaction to comment
|
||||
if: github.event_name == 'issue_comment'
|
||||
uses: actions/github-script@v8
|
||||
with:
|
||||
script: |
|
||||
await github.rest.reactions.createForIssueComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
comment_id: context.payload.comment.id,
|
||||
content: 'rocket'
|
||||
});
|
||||
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ github.event.inputs.branch || steps.pr.outputs.ref || github.ref }}
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- uses: oven-sh/setup-bun@v2
|
||||
with:
|
||||
bun-version: latest
|
||||
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: "22"
|
||||
cache: npm
|
||||
|
||||
- uses: astral-sh/setup-uv@v7
|
||||
|
||||
- run: npm ci
|
||||
|
||||
- name: Install Playwright browsers
|
||||
run: npx playwright install --with-deps chromium
|
||||
|
||||
- name: Update snapshots
|
||||
run: npx playwright test --update-snapshots --reporter=list
|
||||
|
||||
- name: Commit updated snapshots
|
||||
id: commit
|
||||
run: |
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git add tests/e2e/**/*.png
|
||||
if git diff --staged --quiet; then
|
||||
echo "changed=false" >> $GITHUB_OUTPUT
|
||||
echo "No snapshot changes to commit"
|
||||
else
|
||||
git commit -m "chore: update e2e snapshots [skip ci]"
|
||||
git push
|
||||
echo "changed=true" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Comment on PR
|
||||
if: github.event_name == 'issue_comment'
|
||||
uses: actions/github-script@v8
|
||||
with:
|
||||
script: |
|
||||
const changed = '${{ steps.commit.outputs.changed }}' === 'true';
|
||||
const body = changed
|
||||
? '✅ Snapshots updated and pushed to this branch.'
|
||||
: '✅ No snapshot changes needed - all snapshots are up to date.';
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
body
|
||||
});
|
||||
7
.gitignore
vendored
7
.gitignore
vendored
|
|
@ -11,10 +11,3 @@ intermediate-findings/
|
|||
# Playwright
|
||||
playwright-report/
|
||||
test-results/
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# MCPB bundles (built artifacts)
|
||||
*.mcpb
|
||||
.mcpb-stage/
|
||||
.mcpb-smoke/
|
||||
|
|
@ -1,12 +1,3 @@
|
|||
# Load Node.js environment for GUI apps (GitHub Desktop, etc.)
|
||||
# that don't inherit shell PATH
|
||||
export NVM_DIR="$HOME/.nvm"
|
||||
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # nvm
|
||||
[ -s "$HOME/.fnm/fnm" ] && eval "$(~/.fnm/fnm env)" # fnm
|
||||
[ -s "$HOME/.volta/bin/volta" ] && export PATH="$HOME/.volta/bin:$PATH" # volta
|
||||
[ -d "/opt/homebrew/bin" ] && export PATH="/opt/homebrew/bin:$PATH" # homebrew (macOS ARM)
|
||||
[ -d "/usr/local/bin" ] && export PATH="/usr/local/bin:$PATH" # homebrew (macOS Intel)
|
||||
|
||||
# Verify no private registry URLs in package-lock.json
|
||||
if grep -E '"resolved": "https?://' package-lock.json | grep -v registry.npmjs.org > /dev/null; then
|
||||
echo "ERROR: package-lock.json contains non-npmjs.org URLs"
|
||||
|
|
@ -14,16 +5,8 @@ if grep -E '"resolved": "https?://' package-lock.json | grep -v registry.npmjs.o
|
|||
exit 1
|
||||
fi
|
||||
|
||||
# Capture staged files so we only re-stage what the user intended to commit
|
||||
# (avoids sweeping unrelated WIP into the commit). --diff-filter=d skips
|
||||
# deletions so the xargs git add below doesn't fail on removed paths.
|
||||
STAGED=$(git diff --name-only --cached --diff-filter=d)
|
||||
|
||||
npm run build:all
|
||||
npm run prettier:fix
|
||||
|
||||
# Re-stage originally-staged files (prettier may have reformatted them)
|
||||
echo "$STAGED" | xargs -r git add
|
||||
|
||||
# Also stage generated files (regenerated by build:all from spec.types.ts)
|
||||
# Stage any changes to generated files (they may have been reformatted by prettier)
|
||||
git add src/generated/
|
||||
|
|
|
|||
1
.npmrc
1
.npmrc
|
|
@ -1 +0,0 @@
|
|||
registry=https://registry.npmjs.org/
|
||||
|
|
@ -1,9 +1,6 @@
|
|||
examples/basic-host/**/*.ts
|
||||
examples/basic-host/**/*.tsx
|
||||
examples/basic-server-*/**/*.ts
|
||||
examples/basic-server-*/**/*.tsx
|
||||
examples/quickstart/**/*.ts
|
||||
**/vendor/**
|
||||
**/.build/**
|
||||
**/.claude/**
|
||||
SKILL.md
|
||||
examples/basic-server-react/**/*.ts
|
||||
examples/basic-server-react/**/*.tsx
|
||||
examples/basic-server-vanillajs/**/*.ts
|
||||
examples/basic-server-vanillajs/**/*.tsx
|
||||
|
|
|
|||
103
AGENTS.md
103
AGENTS.md
|
|
@ -1,103 +0,0 @@
|
|||
# MCP Apps SDK
|
||||
|
||||
## Project Overview
|
||||
|
||||
MCP Apps SDK (`@modelcontextprotocol/ext-apps`) enables MCP servers to display interactive UIs in conversational clients.
|
||||
|
||||
Key abstractions:
|
||||
|
||||
- **View** - UI running in an iframe, uses `App` class with `PostMessageTransport` to communicate with host
|
||||
- **Host** - Chat client embedding the iframe, uses `AppBridge` class to proxy MCP requests
|
||||
- **Server** - MCP server that registers tools/resources with UI metadata
|
||||
|
||||
Specification (stable): `specification/2026-01-26/apps.mdx`
|
||||
|
||||
## Commands
|
||||
|
||||
```bash
|
||||
# Install dependencies
|
||||
npm install
|
||||
|
||||
# Build the SDK only (generates schemas + bundles, does not build examples)
|
||||
npm run build
|
||||
|
||||
# Build everything (SDK + all examples)
|
||||
npm run build:all
|
||||
|
||||
# Type check + build a single example
|
||||
npm run --workspace examples/<example-name> build
|
||||
|
||||
# Run all examples (starts server at http://localhost:8080)
|
||||
npm start
|
||||
|
||||
# Run E2E tests (primary testing mechanism - starts examples server automatically)
|
||||
npm run test:e2e
|
||||
|
||||
# Run unit tests (E2E tests have broader coverage; unit tests cover specific modules)
|
||||
npm test
|
||||
|
||||
# Check JSDoc comment syntax and `{@link}` references
|
||||
npm exec typedoc -- --treatValidationWarningsAsErrors --emit none
|
||||
|
||||
# Regenerate package-lock.json
|
||||
# Note: repo .npmrc pins registry to npmjs.org, so a plain `npm i` is safe even
|
||||
# if your global npm config points elsewhere. The Docker step below is optional
|
||||
# — it locks linux-amd64 optionalDependencies (sharp, rollup, bun) for CI.
|
||||
rm -fR package-lock.json node_modules && \
|
||||
docker run --rm -it --platform linux/amd64 -v $PWD:/src:rw -w /src node:latest npm i && \
|
||||
rm -fR node_modules && \
|
||||
npm i --cache=~/.npm-mcp-apps --registry=https://registry.npmjs.org/
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
### SDK Entry Points
|
||||
|
||||
- `@modelcontextprotocol/ext-apps` - Main SDK for Apps (`App` class, `PostMessageTransport`)
|
||||
- `@modelcontextprotocol/ext-apps/react` - React hooks (`useApp`, `useHostStyleVariables`, etc.)
|
||||
- `@modelcontextprotocol/ext-apps/app-bridge` - SDK for hosts (`AppBridge` class)
|
||||
- `@modelcontextprotocol/ext-apps/server` - Server helpers (`registerAppTool`, `registerAppResource`)
|
||||
|
||||
### Key Source Files
|
||||
|
||||
- `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
|
||||
- `src/react/` - React hooks: `useApp`, `useHostStyles`, `useAutoResize`, `useDocumentTheme`
|
||||
|
||||
### Protocol Flow
|
||||
|
||||
```
|
||||
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` (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
|
||||
7. Host calls `teardownResource()` before unmounting iframe
|
||||
|
||||
## Documentation
|
||||
|
||||
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.
|
||||
|
||||
Standalone docs in `docs/` (listed in `typedoc.config.mjs` `projectDocuments`) can also have type-checked companion `.ts`/`.tsx` files using the same pattern.
|
||||
|
||||
## Full Examples
|
||||
|
||||
Uses npm workspaces. Full examples in `examples/` are separate packages:
|
||||
|
||||
- `basic-server-*` - Starter templates (vanillajs, react, vue, svelte, preact, solid). Use these as the basis for new examples.
|
||||
- `basic-host` - Reference host implementation
|
||||
- Other examples showcase specific features (charts, 3D, video, etc.)
|
||||
|
||||
## Claude Code Plugin
|
||||
|
||||
The `plugins/mcp-apps/` directory contains a Claude Code plugin distributed via the plugin marketplace. It provides the following Claude Code skills files:
|
||||
|
||||
- `plugins/mcp-apps/skills/create-mcp-app/SKILL.md` — for creating an MCP App
|
||||
- `plugins/mcp-apps/skills/migrate-oai-app/SKILL.md` — for migrating an app from the OpenAI Apps SDK to the MCP Apps SDK
|
||||
|
|
@ -1 +0,0 @@
|
|||
AGENTS.md
|
||||
458
CONTRIBUTING.md
458
CONTRIBUTING.md
|
|
@ -25,15 +25,6 @@ We welcome contributions to the MCP Apps SDK! This document outlines the process
|
|||
- Update documentation as needed
|
||||
- Keep changes focused and atomic
|
||||
- Provide a clear description of changes
|
||||
- **Keep "Allow edits by maintainers" checked** when opening your PR — this lets maintainers rebase your branch and lets the [`/update-snapshots` workflow](#updating-snapshots-in-ci) push updated screenshots to it
|
||||
|
||||
## Examples Policy
|
||||
|
||||
The examples in `examples/` are maintained by the core team. **We do not accept pull requests that add new example servers from outside contributors.** Each example carries an ongoing maintenance cost — keeping it building, tested, and up to date with SDK changes — so we are deliberate about what we add.
|
||||
|
||||
If you have an idea for an example that would provide significant educational value, please [open an issue](https://github.com/modelcontextprotocol/ext-apps/issues) describing what the example would demonstrate and why it would be useful, and maintainers will evaluate the request.
|
||||
|
||||
PRs that add new examples without a prior approved issue may be closed.
|
||||
|
||||
## Running Examples
|
||||
|
||||
|
|
@ -49,408 +40,6 @@ Or build and run examples:
|
|||
npm run examples:start
|
||||
```
|
||||
|
||||
### With MCP Clients
|
||||
|
||||
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:
|
||||
|
||||
<details>
|
||||
<summary>MCP client configuration for all examples (using stdio)</summary>
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"basic-react": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"--silent",
|
||||
"--registry=https://registry.npmjs.org/",
|
||||
"@modelcontextprotocol/server-basic-react",
|
||||
"--stdio"
|
||||
]
|
||||
},
|
||||
"basic-vanillajs": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"--silent",
|
||||
"--registry=https://registry.npmjs.org/",
|
||||
"@modelcontextprotocol/server-basic-vanillajs",
|
||||
"--stdio"
|
||||
]
|
||||
},
|
||||
"basic-vue": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"--silent",
|
||||
"--registry=https://registry.npmjs.org/",
|
||||
"@modelcontextprotocol/server-basic-vue",
|
||||
"--stdio"
|
||||
]
|
||||
},
|
||||
"basic-svelte": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"--silent",
|
||||
"--registry=https://registry.npmjs.org/",
|
||||
"@modelcontextprotocol/server-basic-svelte",
|
||||
"--stdio"
|
||||
]
|
||||
},
|
||||
"basic-preact": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"--silent",
|
||||
"--registry=https://registry.npmjs.org/",
|
||||
"@modelcontextprotocol/server-basic-preact",
|
||||
"--stdio"
|
||||
]
|
||||
},
|
||||
"basic-solid": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"--silent",
|
||||
"--registry=https://registry.npmjs.org/",
|
||||
"@modelcontextprotocol/server-basic-solid",
|
||||
"--stdio"
|
||||
]
|
||||
},
|
||||
"budget-allocator": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"--silent",
|
||||
"--registry=https://registry.npmjs.org/",
|
||||
"@modelcontextprotocol/server-budget-allocator",
|
||||
"--stdio"
|
||||
]
|
||||
},
|
||||
"cohort-heatmap": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"--silent",
|
||||
"--registry=https://registry.npmjs.org/",
|
||||
"@modelcontextprotocol/server-cohort-heatmap",
|
||||
"--stdio"
|
||||
]
|
||||
},
|
||||
"customer-segmentation": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"--silent",
|
||||
"--registry=https://registry.npmjs.org/",
|
||||
"@modelcontextprotocol/server-customer-segmentation",
|
||||
"--stdio"
|
||||
]
|
||||
},
|
||||
"map": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"--silent",
|
||||
"--registry=https://registry.npmjs.org/",
|
||||
"@modelcontextprotocol/server-map",
|
||||
"--stdio"
|
||||
]
|
||||
},
|
||||
"pdf": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"--silent",
|
||||
"--registry=https://registry.npmjs.org/",
|
||||
"@modelcontextprotocol/server-pdf",
|
||||
"--stdio"
|
||||
]
|
||||
},
|
||||
"scenario-modeler": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"--silent",
|
||||
"--registry=https://registry.npmjs.org/",
|
||||
"@modelcontextprotocol/server-scenario-modeler",
|
||||
"--stdio"
|
||||
]
|
||||
},
|
||||
"shadertoy": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"--silent",
|
||||
"--registry=https://registry.npmjs.org/",
|
||||
"@modelcontextprotocol/server-shadertoy",
|
||||
"--stdio"
|
||||
]
|
||||
},
|
||||
"sheet-music": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"--silent",
|
||||
"--registry=https://registry.npmjs.org/",
|
||||
"@modelcontextprotocol/server-sheet-music",
|
||||
"--stdio"
|
||||
]
|
||||
},
|
||||
"system-monitor": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"--silent",
|
||||
"--registry=https://registry.npmjs.org/",
|
||||
"@modelcontextprotocol/server-system-monitor",
|
||||
"--stdio"
|
||||
]
|
||||
},
|
||||
"threejs": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"--silent",
|
||||
"--registry=https://registry.npmjs.org/",
|
||||
"@modelcontextprotocol/server-threejs",
|
||||
"--stdio"
|
||||
]
|
||||
},
|
||||
"transcript": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"--silent",
|
||||
"--registry=https://registry.npmjs.org/",
|
||||
"@modelcontextprotocol/server-transcript",
|
||||
"--stdio"
|
||||
]
|
||||
},
|
||||
"video-resource": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"--silent",
|
||||
"--registry=https://registry.npmjs.org/",
|
||||
"@modelcontextprotocol/server-video-resource",
|
||||
"--stdio"
|
||||
]
|
||||
},
|
||||
"wiki-explorer": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"--silent",
|
||||
"--registry=https://registry.npmjs.org/",
|
||||
"@modelcontextprotocol/server-wiki-explorer",
|
||||
"--stdio"
|
||||
]
|
||||
},
|
||||
"qr": {
|
||||
"command": "uv",
|
||||
"args": [
|
||||
"run",
|
||||
"/path/to/ext-apps/examples/qr-server/server.py",
|
||||
"--stdio"
|
||||
]
|
||||
},
|
||||
"say": {
|
||||
"command": "uv",
|
||||
"args": [
|
||||
"run",
|
||||
"--default-index",
|
||||
"https://pypi.org/simple",
|
||||
"https://raw.githubusercontent.com/modelcontextprotocol/ext-apps/refs/heads/main/examples/say-server/server.py",
|
||||
"--stdio"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
> [!NOTE]
|
||||
> 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.
|
||||
|
||||
### Local Development
|
||||
|
||||
To test local modifications with MCP clients, first clone and install the repository:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/modelcontextprotocol/ext-apps.git
|
||||
cd ext-apps
|
||||
npm install
|
||||
```
|
||||
|
||||
Then configure your MCP client to build and run the local server. Replace `~/src/ext-apps` with your actual clone path.
|
||||
|
||||
Most example servers have a `start:stdio` script that builds and launches in stdio mode:
|
||||
|
||||
<details>
|
||||
<summary>MCP client configuration for local development (all examples)</summary>
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"basic-react": {
|
||||
"command": "bash",
|
||||
"args": [
|
||||
"-c",
|
||||
"cd ~/src/ext-apps/examples/basic-server-react && npm --silent run start:stdio"
|
||||
]
|
||||
},
|
||||
"basic-vanillajs": {
|
||||
"command": "bash",
|
||||
"args": [
|
||||
"-c",
|
||||
"cd ~/src/ext-apps/examples/basic-server-vanillajs && npm --silent run start:stdio"
|
||||
]
|
||||
},
|
||||
"basic-vue": {
|
||||
"command": "bash",
|
||||
"args": [
|
||||
"-c",
|
||||
"cd ~/src/ext-apps/examples/basic-server-vue && npm --silent run start:stdio"
|
||||
]
|
||||
},
|
||||
"basic-svelte": {
|
||||
"command": "bash",
|
||||
"args": [
|
||||
"-c",
|
||||
"cd ~/src/ext-apps/examples/basic-server-svelte && npm --silent run start:stdio"
|
||||
]
|
||||
},
|
||||
"basic-preact": {
|
||||
"command": "bash",
|
||||
"args": [
|
||||
"-c",
|
||||
"cd ~/src/ext-apps/examples/basic-server-preact && npm --silent run start:stdio"
|
||||
]
|
||||
},
|
||||
"basic-solid": {
|
||||
"command": "bash",
|
||||
"args": [
|
||||
"-c",
|
||||
"cd ~/src/ext-apps/examples/basic-server-solid && npm --silent run start:stdio"
|
||||
]
|
||||
},
|
||||
"budget-allocator": {
|
||||
"command": "bash",
|
||||
"args": [
|
||||
"-c",
|
||||
"cd ~/src/ext-apps/examples/budget-allocator-server && npm --silent run start:stdio"
|
||||
]
|
||||
},
|
||||
"cohort-heatmap": {
|
||||
"command": "bash",
|
||||
"args": [
|
||||
"-c",
|
||||
"cd ~/src/ext-apps/examples/cohort-heatmap-server && npm --silent run start:stdio"
|
||||
]
|
||||
},
|
||||
"customer-segmentation": {
|
||||
"command": "bash",
|
||||
"args": [
|
||||
"-c",
|
||||
"cd ~/src/ext-apps/examples/customer-segmentation-server && npm --silent run start:stdio"
|
||||
]
|
||||
},
|
||||
"map": {
|
||||
"command": "bash",
|
||||
"args": [
|
||||
"-c",
|
||||
"cd ~/src/ext-apps/examples/map-server && npm --silent run start:stdio"
|
||||
]
|
||||
},
|
||||
"pdf": {
|
||||
"command": "bash",
|
||||
"args": [
|
||||
"-c",
|
||||
"cd ~/src/ext-apps/examples/pdf-server && npm --silent run start:stdio"
|
||||
]
|
||||
},
|
||||
"scenario-modeler": {
|
||||
"command": "bash",
|
||||
"args": [
|
||||
"-c",
|
||||
"cd ~/src/ext-apps/examples/scenario-modeler-server && npm --silent run start:stdio"
|
||||
]
|
||||
},
|
||||
"shadertoy": {
|
||||
"command": "bash",
|
||||
"args": [
|
||||
"-c",
|
||||
"cd ~/src/ext-apps/examples/shadertoy-server && npm --silent run start:stdio"
|
||||
]
|
||||
},
|
||||
"sheet-music": {
|
||||
"command": "bash",
|
||||
"args": [
|
||||
"-c",
|
||||
"cd ~/src/ext-apps/examples/sheet-music-server && npm --silent run start:stdio"
|
||||
]
|
||||
},
|
||||
"system-monitor": {
|
||||
"command": "bash",
|
||||
"args": [
|
||||
"-c",
|
||||
"cd ~/src/ext-apps/examples/system-monitor-server && npm --silent run start:stdio"
|
||||
]
|
||||
},
|
||||
"threejs": {
|
||||
"command": "bash",
|
||||
"args": [
|
||||
"-c",
|
||||
"cd ~/src/ext-apps/examples/threejs-server && npm --silent run start:stdio"
|
||||
]
|
||||
},
|
||||
"transcript": {
|
||||
"command": "bash",
|
||||
"args": [
|
||||
"-c",
|
||||
"cd ~/src/ext-apps/examples/transcript-server && npm --silent run start:stdio"
|
||||
]
|
||||
},
|
||||
"video-resource": {
|
||||
"command": "bash",
|
||||
"args": [
|
||||
"-c",
|
||||
"cd ~/src/ext-apps/examples/video-resource-server && npm --silent run start:stdio"
|
||||
]
|
||||
},
|
||||
"wiki-explorer": {
|
||||
"command": "bash",
|
||||
"args": [
|
||||
"-c",
|
||||
"cd ~/src/ext-apps/examples/wiki-explorer-server && npm --silent run start:stdio"
|
||||
]
|
||||
},
|
||||
"qr": {
|
||||
"command": "bash",
|
||||
"args": [
|
||||
"-c",
|
||||
"uv run ~/src/ext-apps/examples/qr-server/server.py --stdio"
|
||||
]
|
||||
},
|
||||
"say": {
|
||||
"command": "bash",
|
||||
"args": [
|
||||
"-c",
|
||||
"uv run --index https://pypi.org/simple ~/src/ext-apps/examples/say-server/server.py --stdio"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
This configuration rebuilds each server on launch, ensuring your local changes are picked up.
|
||||
|
||||
## Testing
|
||||
|
||||
### Unit Tests
|
||||
|
|
@ -490,19 +79,9 @@ npm run test:e2e:update -- --grep "Three.js"
|
|||
|
||||
**Note**: Golden screenshots are platform-agnostic. Tests use canvas masking and tolerance thresholds to handle minor cross-platform rendering differences.
|
||||
|
||||
#### Updating Snapshots in CI
|
||||
|
||||
If E2E tests fail in CI due to screenshot mismatches, you can update snapshots directly from your PR:
|
||||
|
||||
1. Comment `/update-snapshots` on the PR
|
||||
2. The workflow will update snapshots and push to your branch
|
||||
3. A comment will confirm when complete
|
||||
|
||||
Alternatively, use the [workflow dispatch](https://github.com/modelcontextprotocol/ext-apps/actions/workflows/update-snapshots.yml) to manually trigger updates for any branch.
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
This project follows our [Code of Conduct](https://github.com/modelcontextprotocol/.github/blob/main/CODE_OF_CONDUCT.md). Please review it before contributing.
|
||||
This project follows our [Code of Conduct](CODE_OF_CONDUCT.md). Please review it before contributing.
|
||||
|
||||
## Reporting Issues
|
||||
|
||||
|
|
@ -539,17 +118,40 @@ Before publishing releases, ensure the following are configured:
|
|||
|
||||
### Publishing a Release
|
||||
|
||||
1. **Bump the version** across the root and all workspace packages:
|
||||
Releases are published automatically via GitHub Actions when a GitHub Release is created.
|
||||
|
||||
#### Steps to publish:
|
||||
|
||||
1. **Update the version** in `package.json`:
|
||||
|
||||
```bash
|
||||
npm run bump -- minor # or: patch | major | prerelease --preid=beta | 1.7.0
|
||||
# For a regular release
|
||||
npm version patch # or minor, or major
|
||||
|
||||
# For a beta release
|
||||
npm version prerelease --preid=beta
|
||||
```
|
||||
|
||||
Commit and open a PR with a grouped changelog in the body (see prior `chore: bump …` PRs for the format).
|
||||
2. **Commit the version bump** (if not done by `npm version`):
|
||||
|
||||
2. **Merge the PR**, then [draft a GitHub Release](https://github.com/modelcontextprotocol/ext-apps/releases/new) — create a `vX.Y.Z` tag on `main`, paste the changelog, publish.
|
||||
```bash
|
||||
git add package.json
|
||||
git commit -m "Bump version to X.Y.Z"
|
||||
git push origin main
|
||||
```
|
||||
|
||||
3. **Approve the deployment** — publishing the Release triggers the [npm-publish workflow](https://github.com/modelcontextprotocol/ext-apps/actions/workflows/npm-publish.yml); all publish jobs wait together for a single "Review deployments" approval.
|
||||
3. **Create a GitHub Release**:
|
||||
- Go to [Releases](https://github.com/modelcontextprotocol/ext-apps/releases)
|
||||
- Click "Draft a new release"
|
||||
- Create a new tag matching the version (e.g., `v0.1.0`)
|
||||
- Set the target branch (usually `main`)
|
||||
- Write release notes describing the changes
|
||||
- Click "Publish release"
|
||||
|
||||
4. **Monitor the workflow**:
|
||||
- The [npm-publish workflow](https://github.com/modelcontextprotocol/ext-apps/actions/workflows/npm-publish.yml) will trigger automatically
|
||||
- It runs build and test jobs before publishing
|
||||
- On success, the package is published to npm with provenance
|
||||
|
||||
#### npm Tags
|
||||
|
||||
|
|
@ -573,7 +175,7 @@ To release a patch for an older version:
|
|||
|
||||
### Testing Pre-releases
|
||||
|
||||
Every commit and PR automatically publishes a preview package via [pkg-pr-new](https://github.com/stackblitz-labs/pkg.pr.new). Check the PR comments or workflow logs for the install command.
|
||||
Every commit and PR automatically publishes a preview package via [pkg-pr-new](https://github.com/pkg-pr-new/pkg-pr-new). Check the PR comments or workflow logs for the install command.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
197
LICENSE
197
LICENSE
|
|
@ -1,193 +1,6 @@
|
|||
The MCP project is undergoing a licensing transition from the MIT License to the Apache License, Version 2.0 ("Apache-2.0"). All new code and specification contributions to the project are licensed under Apache-2.0. Documentation contributions (excluding specifications) are licensed under CC-BY-4.0.
|
||||
|
||||
Contributions for which relicensing consent has been obtained are licensed under Apache-2.0. Contributions made by authors who originally licensed their work under the MIT License and who have not yet granted explicit permission to relicense remain licensed under the MIT License.
|
||||
|
||||
No rights beyond those granted by the applicable original license are conveyed for such contributions.
|
||||
|
||||
---
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to the Licensor for inclusion in the Work by the copyright
|
||||
owner or by an individual or Legal Entity authorized to submit on behalf
|
||||
of the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
---
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024-2025 Model Context Protocol a Series of LF Projects, LLC.
|
||||
Copyright (c) 2025 Anthropic, PBC
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
@ -206,11 +19,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
---
|
||||
|
||||
Creative Commons Attribution 4.0 International (CC-BY-4.0)
|
||||
|
||||
Documentation in this project (excluding specifications) is licensed under
|
||||
CC-BY-4.0. See https://creativecommons.org/licenses/by/4.0/legalcode for
|
||||
the full license text.
|
||||
|
|
|
|||
282
README.md
282
README.md
|
|
@ -1,284 +1,70 @@
|
|||
<!-- LOGO -->
|
||||
<div align="center">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="media/mcp-white.svg">
|
||||
<source media="(prefers-color-scheme: light)" srcset="media/mcp.svg">
|
||||
<img src="media/mcp.svg" alt="MCP Apps" width="128">
|
||||
</picture>
|
||||
<h1>MCP Apps</h1>
|
||||
<p>
|
||||
Build interactive UIs for MCP tools — charts, forms, dashboards — that render inline in Claude, ChatGPT and any other compliant chat client.
|
||||
<br /><br />
|
||||
<a href="#why-mcp-apps">Why</a>
|
||||
·
|
||||
<a href="https://apps.extensions.modelcontextprotocol.io/api/documents/quickstart.html">Quickstart</a>
|
||||
·
|
||||
<a href="https://apps.extensions.modelcontextprotocol.io/api/">API Docs</a>
|
||||
·
|
||||
<a href="https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/2026-01-26/apps.mdx">Spec</a>
|
||||
·
|
||||
<a href="CONTRIBUTING.md">Contributing</a>
|
||||
</p>
|
||||
</div>
|
||||
# @modelcontextprotocol/ext-apps
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/modelcontextprotocol/ext-apps/actions/workflows/ci.yml"><img src="https://github.com/modelcontextprotocol/ext-apps/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
|
||||
<a href="LICENSE"><img src="https://img.shields.io/badge/license-Apache%202.0-blue" alt="License: Apache 2.0"></a>
|
||||
<a href="https://www.npmjs.com/package/@modelcontextprotocol/ext-apps"><img src="https://img.shields.io/npm/v/@modelcontextprotocol/ext-apps.svg" alt="npm version"></a>
|
||||
<a href="https://www.npmjs.com/package/@modelcontextprotocol/ext-apps"><img src="https://img.shields.io/npm/dm/@modelcontextprotocol/ext-apps.svg" alt="npm downloads"></a>
|
||||
<a href="https://github.com/modelcontextprotocol/ext-apps"><img src="https://img.shields.io/github/stars/modelcontextprotocol/ext-apps" alt="GitHub stars"></a>
|
||||
<a href="https://apps.extensions.modelcontextprotocol.io/api/"><img src="https://img.shields.io/badge/docs-API%20Reference-blue" alt="API Documentation"></a>
|
||||
</p>
|
||||
[](https://www.npmjs.com/package/@modelcontextprotocol/ext-apps) [](https://modelcontextprotocol.github.io/ext-apps/api/)
|
||||
|
||||
<p align="center">
|
||||
<img src="media/excalidraw.gif" alt="MCP Apps demo" width="600">
|
||||
<br><em>Excalidraw built with MCP Apps, running in Claude</em>
|
||||
</p>
|
||||
This repo contains the SDK and [specification](https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/draft/apps.mdx) for MCP Apps Extension ([SEP-1865](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/1865)).
|
||||
|
||||
## Table of Contents
|
||||
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.
|
||||
|
||||
- [Build with Agent Skills](#build-with-agent-skills)
|
||||
- [Supported Clients](#supported-clients)
|
||||
- [Why MCP Apps?](#why-mcp-apps)
|
||||
- [How It Works](#how-it-works)
|
||||
- [Getting Started](#getting-started)
|
||||
- [Using the SDK](#using-the-sdk)
|
||||
- [Examples](#examples)
|
||||
- [Specification](#specification)
|
||||
- [Resources](#resources)
|
||||
- [Contributing](#contributing)
|
||||
## Overview
|
||||
|
||||
## Build with Agent Skills
|
||||
This SDK serves two audiences:
|
||||
|
||||
The fastest way to build an MCP App is to let your AI coding agent do it. This
|
||||
repo ships four [Agent Skills](https://agentskills.io/) — install them once,
|
||||
then just ask:
|
||||
### App Developers
|
||||
|
||||
| Skill | What it does | Try it |
|
||||
| --------------------------------------------------------------------------- | ----------------------------------------------------------- | ------------------------------------- |
|
||||
| [`create-mcp-app`](./plugins/mcp-apps/skills/create-mcp-app/SKILL.md) | Scaffolds a new MCP App with an interactive UI from scratch | _"Create an MCP App"_ |
|
||||
| [`migrate-oai-app`](./plugins/mcp-apps/skills/migrate-oai-app/SKILL.md) | Converts an existing OpenAI App to use MCP Apps | _"Migrate from OpenAI Apps SDK"_ |
|
||||
| [`add-app-to-server`](./plugins/mcp-apps/skills/add-app-to-server/SKILL.md) | Adds interactive UI to an existing MCP server's tools | _"Add UI to my MCP server"_ |
|
||||
| [`convert-web-app`](./plugins/mcp-apps/skills/convert-web-app/SKILL.md) | Turns an existing web app into a hybrid web + MCP App | _"Add MCP App support to my web app"_ |
|
||||
Build interactive UIs that run inside MCP-enabled chat clients.
|
||||
|
||||
### Install the Skills
|
||||
- **SDK for Apps**: `@modelcontextprotocol/ext-apps` — [API Docs](https://modelcontextprotocol.github.io/ext-apps/api/modules/app.html)
|
||||
- **React hooks**: `@modelcontextprotocol/ext-apps/react` — [API Docs](https://modelcontextprotocol.github.io/ext-apps/api/modules/_modelcontextprotocol_ext-apps_react.html)
|
||||
|
||||
**Claude Code** — install via the plugin marketplace:
|
||||
### Host Developers
|
||||
|
||||
```
|
||||
/plugin marketplace add modelcontextprotocol/ext-apps
|
||||
/plugin install mcp-apps@modelcontextprotocol-ext-apps
|
||||
```
|
||||
Embed and communicate with MCP Apps in your chat application.
|
||||
|
||||
**Other agents** — any AI coding agent that supports
|
||||
[Agent Skills](https://agentskills.io/) can use these skills. See the
|
||||
[agent skills guide](./docs/agent-skills.md) for manual installation
|
||||
instructions.
|
||||
- **SDK for Hosts**: `@modelcontextprotocol/ext-apps/app-bridge` — [API Docs](https://modelcontextprotocol.github.io/ext-apps/api/modules/app-bridge.html)
|
||||
|
||||
Once installed, verify by asking your agent _"What skills do you have?"_ — you
|
||||
should see `create-mcp-app`, `migrate-oai-app`, `add-app-to-server`, and
|
||||
`convert-web-app` in the list. Then just ask it to create or migrate an app and
|
||||
it will guide you through the rest.
|
||||
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) example).
|
||||
|
||||
## Supported Clients
|
||||
We have [contributed a tentative implementation](https://github.com/MCP-UI-Org/mcp-ui/pull/147) of hosting / iframing / sandboxing logic to the [MCP-UI](https://github.com/idosal/mcp-ui) repository, and expect OSS clients may use it, while other clients might roll their own hosting logic.
|
||||
|
||||
<p align="center">
|
||||
<a href="https://developers.openai.com/apps-sdk/mcp-apps-in-chatgpt/"><img src="https://img.shields.io/badge/ChatGPT-docs-74aa9c?logo=openai&logoColor=white" alt="ChatGPT"></a>
|
||||
<a href="https://claude.com/docs/connectors/building/mcp-apps/getting-started"><img src="https://img.shields.io/badge/Claude-docs-d97706?logo=claude&logoColor=white" alt="Claude"></a>
|
||||
<a href="https://code.visualstudio.com/blogs/2026/01/26/mcp-apps-support"><img src="https://img.shields.io/badge/VS_Code-docs-007ACC?logo=visualstudiocode&logoColor=white" alt="VS Code"></a>
|
||||
<a href="https://block.github.io/goose/docs/tutorials/building-mcp-apps/"><img src="https://img.shields.io/badge/Goose-docs-000000?logo=goose&logoColor=white" alt="Goose"></a>
|
||||
<a href="https://learning.postman.com/docs/postman-ai/mcp-requests/interact"><img src="https://img.shields.io/badge/Postman-docs-FF6C37?logo=postman&logoColor=white" alt="Postman"></a>
|
||||
<a href="https://www.mcpjam.com/blog/mcp-apps-example"><img src="https://img.shields.io/badge/MCPJam-docs-8B5CF6" alt="MCPJam"></a>
|
||||
<a href="https://manufact.com/inspector"><img src="https://img.shields.io/badge/mcp--use-inspector-E5F3FD" alt="mcp-use"></a>
|
||||
<a href="https://docs.alpic.ai/distribution/playground"><img src="https://img.shields.io/badge/Alpic-playground-E90060?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAMAAABHPGVmAAAAKlBMVEUKDhz%2F%2F%2F%2BjpaogJDFBRE%2Fw8PHHyMvh4eNmaHF1d4CUlpuFho2ztLhWWWP5YkbJAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB1klEQVR42u2Y0ZKDIAxFBQQF8f9%2FdyW7dhAu7U7Iy87mzvShGfXU3CTGLotKpVKpVCqV6h%2FI2VuxfF3tUwcdVEccA2LNS%2BWCq2mUykG%2BCtg5iNmv76mllOApCPHrFQgNxJf8HHIQs10XdFtDKcEKPQ0x4brg6htKWGr0PIR8jq0tj4oQgJiIzD8rtATErMAWMj%2FxIYcBPjuPgoENcW3Jks%2BdLeXS32jLmise%2BZxQ8GRD%2BkkCbSlByi0Pgm3p0P6nJ1meXJ%2F8K1tKo7qUOFM4wdxEMMS4iSp9sqFJQrZ4hOZBTEa5gbaQ%2BTwI%2FcCu8TOq482xIWZkSx8MfAi0xcOEJTZkULKohXjm29epGU2SIGK%2BfT9J%2Bjre%2BRBYsiUYBSHkaEI2B0EInRx%2BkbApiB89EaMgBNdx7u5vDoJH79ne3yQElqxvEzYLKY%2Bl81PCZiFUsvlDwqYhw80uSkJg4z8Ttsss3OltwgQgMGGPlpSAwITVM0wCgius6iARCGzJcn%2BHJCSMXraCIATPsPW2SggCh364a1sIgveUew%2BTgtBGsuE9zDspyLBZ3M5aVCOCUDFlqXUbrm8j7%2FnvJ2B9G3kf%2BZBlt0iu%2Fr%2BNxHqRU6lUKpVKpVL9UX0BOrAPfcbTY8UAAAAASUVORK5CYII%3D" alt="Alpic Playground"></a>
|
||||
</p>
|
||||
|
||||
> [!NOTE]
|
||||
> MCP Apps is an extension to the
|
||||
> [core MCP specification](https://modelcontextprotocol.io/specification). Host
|
||||
> support varies — see the
|
||||
> [clients page](https://modelcontextprotocol.io/clients) for the full list.
|
||||
|
||||
## Why MCP Apps?
|
||||
|
||||
MCP tools return text and structured data. That works for many cases, but not
|
||||
when you need an interactive UI, like a chart, form, design canvas or video player.
|
||||
|
||||
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.
|
||||
|
||||
## How It Works
|
||||
|
||||
MCP Apps extend the Model Context Protocol by letting tools declare UI
|
||||
resources:
|
||||
|
||||
1. **Tool definition** — Your tool declares a `ui://` resource containing its
|
||||
HTML interface
|
||||
2. **Tool call** — The LLM calls the tool on your server
|
||||
3. **Host renders** — The host fetches the resource and displays it in a
|
||||
sandboxed iframe
|
||||
4. **Bidirectional communication** — The host passes tool data to the UI via
|
||||
notifications, and the UI can call other tools through the host
|
||||
|
||||
## 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:
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install -S @modelcontextprotocol/ext-apps \
|
||||
@modelcontextprotocol/client@^2.0.0 \
|
||||
zod@^4.2.0
|
||||
npm install -S @modelcontextprotocol/ext-apps
|
||||
```
|
||||
|
||||
For an MCP server, add the server package (and, for HTTP transports, the Node
|
||||
and Express adapters):
|
||||
Or edit your `package.json` manually:
|
||||
|
||||
```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
|
||||
```json
|
||||
{
|
||||
"dependencies": {
|
||||
"@modelcontextprotocol/ext-apps": "^0.0.1"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
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)
|
||||
to build your first MCP App.
|
||||
|
||||
## Using the SDK
|
||||
|
||||
The SDK serves three roles: app developers building interactive Views, host
|
||||
developers embedding those Views, and MCP server authors registering tools with
|
||||
UI metadata.
|
||||
|
||||
| Package | Purpose | Docs |
|
||||
| ------------------------------------------- | --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
|
||||
| `@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-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)
|
||||
example).
|
||||
|
||||
The [MCP-UI](https://github.com/idosal/mcp-ui) client SDK offers a
|
||||
fully-featured MCP Apps framework used by a few hosts. Clients may choose to use
|
||||
it or roll their own implementation.
|
||||
|
||||
## Examples
|
||||
|
||||
The
|
||||
[`examples/`](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples)
|
||||
directory contains demo apps showcasing real-world use cases.
|
||||
Start with these foundational examples to learn the SDK:
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
| | | |
|
||||
|:---:|:---:|:---:|
|
||||
| [](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/map-server) | [](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/threejs-server) | [](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/shadertoy-server) |
|
||||
| [**Map**](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/map-server) | [**Three.js**](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/threejs-server) | [**ShaderToy**](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/shadertoy-server) |
|
||||
| [](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/sheet-music-server) | [](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/wiki-explorer-server) | [](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/cohort-heatmap-server) |
|
||||
| [**Sheet Music**](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/sheet-music-server) | [**Wiki Explorer**](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/wiki-explorer-server) | [**Cohort Heatmap**](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/cohort-heatmap-server) |
|
||||
| [](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/scenario-modeler-server) | [](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/budget-allocator-server) | [](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/customer-segmentation-server) |
|
||||
| [**Scenario Modeler**](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/scenario-modeler-server) | [**Budget Allocator**](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/budget-allocator-server) | [**Customer Segmentation**](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/customer-segmentation-server) |
|
||||
| [](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/system-monitor-server) | [](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/transcript-server) | [](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/video-resource-server) |
|
||||
| [**System Monitor**](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/system-monitor-server) | [**Transcript**](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/transcript-server) | [**Video Resource**](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/video-resource-server) |
|
||||
| [](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/pdf-server) | [](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/qr-server) | [](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/say-server) |
|
||||
| [**PDF Server**](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/pdf-server) | [**QR Code (Python)**](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/qr-server) | [**Say Demo**](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/say-server) |
|
||||
- [`examples/basic-server-vanillajs`](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/basic-server-vanillajs) — Example MCP server with tools that return UI Apps (vanilla JS)
|
||||
- [`examples/basic-server-react`](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/basic-server-react) — Example MCP server with tools that return UI Apps (React)
|
||||
- [`examples/basic-host`](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/basic-host) — Bare-bones example of hosting MCP Apps
|
||||
|
||||
### Starter Templates
|
||||
The [`examples/`](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples) directory contains additional demo apps showcasing real-world use cases.
|
||||
|
||||
| | |
|
||||
|:---:|:---|
|
||||
| [](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) |
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
### Running the Examples
|
||||
|
||||
#### With basic-host
|
||||
|
||||
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):
|
||||
To run all examples together:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/modelcontextprotocol/ext-apps.git
|
||||
cd ext-apps
|
||||
npm install
|
||||
npm start
|
||||
npm run examples:start
|
||||
```
|
||||
|
||||
Then open http://localhost:8080/.
|
||||
|
||||
#### With MCP Clients
|
||||
|
||||
Every Node.js example is published as `@modelcontextprotocol/server-<name>`. To
|
||||
add one to an MCP client that supports stdio (Claude Desktop, VS Code, etc.),
|
||||
use this pattern:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"<name>": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-<name>", "--stdio"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
For example, to add the map server: `@modelcontextprotocol/server-map`. The
|
||||
Python examples (`qr-server`, `say-server`) use `uv run` instead — see their
|
||||
READMEs for details.
|
||||
|
||||
#### Local Development
|
||||
|
||||
To test local modifications with an MCP client, clone the repo, install, then
|
||||
point your client at a local build:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"<name>": {
|
||||
"command": "bash",
|
||||
"args": [
|
||||
"-c",
|
||||
"cd ~/code/ext-apps/examples/<name>-server && npm run build >&2 && node dist/index.js --stdio"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Specification
|
||||
|
||||
<div align="center">
|
||||
|
||||
| Version | Status | Link |
|
||||
| -------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **2026-01-26** | Stable | [specification/2026-01-26/apps.mdx](https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/2026-01-26/apps.mdx) |
|
||||
| **draft** | Development | [specification/draft/apps.mdx](https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/draft/apps.mdx) |
|
||||
|
||||
</div>
|
||||
|
||||
## Resources
|
||||
|
||||
- [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))
|
||||
- [Quickstart Guide](https://modelcontextprotocol.github.io/ext-apps/api/documents/Quickstart.html)
|
||||
- [API Documentation](https://modelcontextprotocol.github.io/ext-apps/api/)
|
||||
- [Draft Specification](https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/draft/apps.mdx)
|
||||
- [SEP-1865 Discussion](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/1865)
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions are welcome! Please read [CONTRIBUTING.md](CONTRIBUTING.md) for
|
||||
guidelines on how to get started, submit pull requests, and report issues.
|
||||
|
|
|
|||
64
RELEASES.md
64
RELEASES.md
|
|
@ -1,64 +0,0 @@
|
|||
# Release Notes
|
||||
|
||||
## 0.3.0
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
- **`viewport` replaced with `containerDimensions`** — The `viewport` property in host context has been replaced with `containerDimensions`, which provides a clearer distinction between fixed dimensions and maximum constraints. The new type allows specifying either `height` or `maxHeight`, and either `width` or `maxWidth` by @martinalong in [#153](https://github.com/modelcontextprotocol/ext-apps/pull/153)
|
||||
|
||||
### New Examples
|
||||
|
||||
- **Video resource server** — Demonstrates video resource handling with proper mimeType declarations by @antonpk1 in [#175](https://github.com/modelcontextprotocol/ext-apps/pull/175)
|
||||
- **Sheet music server** — Interactive sheet music notation example by @jonathanhefner in [#196](https://github.com/modelcontextprotocol/ext-apps/pull/196)
|
||||
|
||||
### Developer Experience
|
||||
|
||||
- **`npm start` alias** — Added `npm start` as alias for `npm run examples:start` by @jonathanhefner in [#183](https://github.com/modelcontextprotocol/ext-apps/pull/183)
|
||||
- **Examples cleanup** — Improved consistency across example servers by @jonathanhefner in [#182](https://github.com/modelcontextprotocol/ext-apps/pull/182)
|
||||
- **Documentation fixes** — Fixed tsc command in docs to use tsconfig.json by @blackgirlbytes in [#188](https://github.com/modelcontextprotocol/ext-apps/pull/188)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **Move prettier to dev dependency** — Fixed incorrect dependency classification by @niclim in [#179](https://github.com/modelcontextprotocol/ext-apps/pull/179)
|
||||
- **Fix build errors in examples** — Resolved build issues across example servers by @jonathanhefner in [#180](https://github.com/modelcontextprotocol/ext-apps/pull/180)
|
||||
|
||||
**Full Changelog**: https://github.com/modelcontextprotocol/ext-apps/compare/v0.2.2...v0.3.0
|
||||
|
||||
---
|
||||
|
||||
## 0.2.2
|
||||
|
||||
Changes from 0.1.x to 0.2.2.
|
||||
|
||||
### Highlights
|
||||
|
||||
- **Server helpers** — New `registerAppTool()` and `registerAppResource()` simplify server setup with proper type safety. `connect()` now defaults to `PostMessageTransport(window.parent)`, enabling simpler initialization with just `await app.connect()` by @ochafik in [#165](https://github.com/modelcontextprotocol/ext-apps/pull/165)
|
||||
- **Tool visibility control** — New `visibility` array field controls whether tools are visible to the agent, apps, or both. Restructured `_meta` format from flat `"ui/resourceUri"` to nested `_meta.ui.resourceUri` by @jonathanhefner in [#131](https://github.com/modelcontextprotocol/ext-apps/pull/131)
|
||||
- **Host-provided theming** — Apps receive 36 standardized CSS variables for colors, typography, and spacing via `styles.variables`, enabling visual consistency with the host by @martinalong in [#127](https://github.com/modelcontextprotocol/ext-apps/pull/127)
|
||||
- **Display mode requests** — Apps can request display mode changes (e.g., fullscreen) via `requestDisplayMode`, with hosts able to accept or reject by @martinalong in [#152](https://github.com/modelcontextprotocol/ext-apps/pull/152)
|
||||
- **Custom fonts support** — Apps can receive custom fonts via `styles.css.fonts` and apply them using `applyHostFonts()` or `useHostFonts()` helpers by @martinalong in [#159](https://github.com/modelcontextprotocol/ext-apps/pull/159)
|
||||
|
||||
### API Changes
|
||||
|
||||
- **MCP SDK as peer dependency** — Consumers control their SDK version, reducing duplication by @ochafik in [#168](https://github.com/modelcontextprotocol/ext-apps/pull/168)
|
||||
- **React as peer dependency** — Supports React 17, 18, and 19 by @ochafik in [#164](https://github.com/modelcontextprotocol/ext-apps/pull/164)
|
||||
- **Renamed request methods** — Removed `send` prefix: `openLink()` and `teardownResource()`. Deprecated aliases maintained by @ochafik in [#161](https://github.com/modelcontextprotocol/ext-apps/pull/161)
|
||||
- **Optional Client in AppBridge** — Enables custom forwarding scenarios without direct MCP client access by @ochafik in [#146](https://github.com/modelcontextprotocol/ext-apps/pull/146)
|
||||
- **Zod v3 and v4 support** — Bring your own Zod by @alpic-ai in [#49](https://github.com/modelcontextprotocol/ext-apps/pull/49)
|
||||
- **Zod schemas now version-agnostic** — Generated schemas work with both Zod 3.25+ and v4, using `z.object().passthrough()` instead of v4-only `z.looseObject()` by @ochafik in [#178](https://github.com/modelcontextprotocol/ext-apps/pull/178)
|
||||
|
||||
### Platform & DX
|
||||
|
||||
- **Windows compatibility** — Bun as optional dependency with automatic setup, `cross-env` for examples. Just run `npm install` by @ochafik in [#145](https://github.com/modelcontextprotocol/ext-apps/pull/145)
|
||||
- **Widened `@oven/bun-*` version range** — Lowered the minimum from `^1.3.4` to `^1.2.21`, helping contributors whose registries may not have the latest packages by @ochafik in [#176](https://github.com/modelcontextprotocol/ext-apps/pull/176)
|
||||
- **SSE transport support** — All examples now support both stdio and HTTP transports with SSE endpoints for older clients by @ochafik in [#136](https://github.com/modelcontextprotocol/ext-apps/pull/136)
|
||||
- **Playwright E2E tests** — Screenshot golden testing across all 9 example servers with parallel execution (~28s) by @ochafik in [#115](https://github.com/modelcontextprotocol/ext-apps/pull/115)
|
||||
- **hostContext exposure** — Access `hostContext` directly from the `App` class by @ochafik in [#139](https://github.com/modelcontextprotocol/ext-apps/pull/139)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **Responsive UIs** — Fixed narrow viewport handling for mobile and sidebar experiences by @ochafik in [#135](https://github.com/modelcontextprotocol/ext-apps/pull/135)
|
||||
- **Sandbox notification fix** — Fixed `sandbox-ready` notification name to match implementation by @ochafik in [#160](https://github.com/modelcontextprotocol/ext-apps/pull/160)
|
||||
- **Fixed non-UI tool registration** — Use `server.registerTool` for tools without UI and fix missing imports across examples by @ochafik in [#173](https://github.com/modelcontextprotocol/ext-apps/pull/173)
|
||||
|
||||
**Full Changelog**: https://github.com/modelcontextprotocol/ext-apps/compare/v0.1.1...v0.2.2
|
||||
21
SECURITY.md
21
SECURITY.md
|
|
@ -1,21 +0,0 @@
|
|||
# Security Policy
|
||||
|
||||
Thank you for helping keep the Model Context Protocol and its ecosystem secure.
|
||||
|
||||
## Reporting Security Issues
|
||||
|
||||
If you discover a security vulnerability in this repository, please report it through
|
||||
the [GitHub Security Advisory process](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities/privately-reporting-a-security-vulnerability)
|
||||
for this repository.
|
||||
|
||||
Please **do not** report security vulnerabilities through public GitHub issues, discussions,
|
||||
or pull requests.
|
||||
|
||||
## What to Include
|
||||
|
||||
To help us triage and respond quickly, please include:
|
||||
|
||||
- A description of the vulnerability
|
||||
- Steps to reproduce the issue
|
||||
- The potential impact
|
||||
- Any suggested fixes (optional)
|
||||
41
build.bun.ts
41
build.bun.ts
|
|
@ -1,25 +1,13 @@
|
|||
#!/usr/bin/env bun
|
||||
import { $ } from "bun";
|
||||
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`;
|
||||
|
||||
// Copy schema.json (tsc is emitDeclarationOnly, Bun.build doesn't emit JSON assets).
|
||||
// Needed for the "./schema.json" package export.
|
||||
mkdirSync("dist/src/generated", { recursive: true });
|
||||
cpSync("src/generated/schema.json", "dist/src/generated/schema.json");
|
||||
|
||||
const isDevelopment = Bun.env.NODE_ENV === "development";
|
||||
|
||||
// Build all JavaScript/TypeScript files
|
||||
function buildJs(
|
||||
entrypoint: string,
|
||||
opts: Partial<Parameters<(typeof Bun)["build"]>[0]> = {},
|
||||
) {
|
||||
function buildJs(entrypoint: string, opts: Record<string, any> = {}) {
|
||||
return Bun.build({
|
||||
entrypoints: [entrypoint],
|
||||
outdir: "dist",
|
||||
|
|
@ -34,40 +22,21 @@ function buildJs(
|
|||
});
|
||||
}
|
||||
|
||||
// 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", {
|
||||
outdir: "dist/src",
|
||||
external: PEER_EXTERNALS,
|
||||
}),
|
||||
buildJs("src/app.ts", {
|
||||
outdir: "dist/src",
|
||||
naming: { entry: "app-with-deps.js" },
|
||||
external: ["@modelcontextprotocol/sdk"],
|
||||
}),
|
||||
buildJs("src/app-bridge.ts", {
|
||||
outdir: "dist/src",
|
||||
external: PEER_EXTERNALS,
|
||||
external: ["@modelcontextprotocol/sdk"],
|
||||
}),
|
||||
buildJs("src/react/index.tsx", {
|
||||
outdir: "dist/src/react",
|
||||
external: ["react", "react-dom", ...PEER_EXTERNALS],
|
||||
}),
|
||||
buildJs("src/react/index.tsx", {
|
||||
outdir: "dist/src/react",
|
||||
external: ["react", "react-dom"],
|
||||
naming: { entry: "react-with-deps.js" },
|
||||
external: ["react", "react-dom", "@modelcontextprotocol/sdk"],
|
||||
}),
|
||||
buildJs("src/server/index.ts", {
|
||||
outdir: "dist/src/server",
|
||||
external: PEER_EXTERNALS,
|
||||
external: ["@modelcontextprotocol/sdk"],
|
||||
}),
|
||||
]);
|
||||
|
|
|
|||
|
|
@ -1,73 +0,0 @@
|
|||
---
|
||||
title: Agent Skills
|
||||
group: Getting Started
|
||||
description: Use Agent Skills to build, migrate, and extend MCP Apps with AI coding agents. Install skills that scaffold new apps, convert OpenAI Apps, and add UI to existing servers.
|
||||
---
|
||||
|
||||
# Agent Skills
|
||||
|
||||
[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.
|
||||
|
||||
This repository provides four skills:
|
||||
|
||||
- [**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
|
||||
- [**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
|
||||
- [**add-app-to-server**](https://github.com/modelcontextprotocol/ext-apps/blob/main/plugins/mcp-apps/skills/add-app-to-server/SKILL.md) — adds interactive UI to an existing MCP server's tools
|
||||
- [**convert-web-app**](https://github.com/modelcontextprotocol/ext-apps/blob/main/plugins/mcp-apps/skills/convert-web-app/SKILL.md) — converts an existing web application into an MCP App
|
||||
|
||||
## Install the Skills
|
||||
|
||||
Choose one of the following installation methods based on your agent:
|
||||
|
||||
### Option 1: Claude Code Plugin
|
||||
|
||||
Install via Claude Code:
|
||||
|
||||
```
|
||||
/plugin marketplace add modelcontextprotocol/ext-apps
|
||||
/plugin install mcp-apps@modelcontextprotocol-ext-apps
|
||||
```
|
||||
|
||||
### Option 2: Vercel Skills CLI
|
||||
|
||||
Use the [Vercel Skills CLI](https://skills.sh/) to install skills across different AI coding agents:
|
||||
|
||||
```bash
|
||||
npx skills add modelcontextprotocol/ext-apps
|
||||
```
|
||||
|
||||
### Option 3: Manual Installation
|
||||
|
||||
Clone the repository:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/modelcontextprotocol/ext-apps.git
|
||||
```
|
||||
|
||||
Then copy the skills from `plugins/mcp-apps/skills/` to your agent's skills directory. See your agent's documentation for the correct location:
|
||||
|
||||
- [Claude Code](https://docs.anthropic.com/en/docs/claude-code/skills)
|
||||
- [VS Code](https://code.visualstudio.com/docs/copilot/customization/agent-skills) / [GitHub Copilot](https://docs.github.com/en/copilot/concepts/agents/about-agent-skills)
|
||||
- [Codex](https://developers.openai.com/codex/skills/)
|
||||
- [Gemini CLI](https://geminicli.com/docs/cli/skills/)
|
||||
- [Cline](https://docs.cline.bot/features/skills#skills)
|
||||
- [Goose](https://block.github.io/goose/docs/guides/context-engineering/using-skills/)
|
||||
|
||||
## Verify Installation
|
||||
|
||||
Ask your agent "What skills do you have?" — you should see `create-mcp-app`, `migrate-oai-app`, `add-app-to-server`, and `convert-web-app` among the available skills.
|
||||
|
||||
## Invoke a Skill
|
||||
|
||||
Try invoking the skills by asking your agent:
|
||||
|
||||
- "Create an MCP App" — scaffolds a new MCP App with an interactive UI
|
||||
- "Migrate from OpenAI Apps SDK" — converts an existing OpenAI App to use the MCP Apps SDK
|
||||
- "Add UI to my MCP server" — adds interactive UI to an existing MCP server's tools
|
||||
- "Convert my web app to an MCP App" — converts an existing web application into an MCP App
|
||||
|
||||
The agent will guide you through the process, asking clarifying questions as needed.
|
||||
|
||||
## Test Your App
|
||||
|
||||
After creating or migrating your MCP App, see the [Testing MCP Apps](./testing-mcp-apps.md) guide to run and debug it locally.
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue