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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
# Force LF line endings for all text files (for consistent prettier formatting)
* text=auto eol=lf

package-lock.json linguist-generated=true
src/generated/** linguist-generated=true
93 changes: 87 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,43 @@ permissions:

jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
name: Linux x64
- os: ubuntu-24.04-arm
name: Linux ARM64
- os: windows-latest
name: Windows x64
- os: windows-11-arm
name: Windows ARM64
- os: macos-latest
name: macOS ARM64

name: Build (${{ matrix.name }})
runs-on: ${{ matrix.os }}

steps:
- 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'

- uses: oven-sh/setup-bun@v2
with:
bun-version: latest

- uses: actions/setup-node@v4
with:
node-version: "20"

- run: npm install

- run: npm run build:all
- run: npm run build

- run: npm run examples:build

- name: Verify generated schemas are up-to-date
shell: bash
run: |
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)
Expand Down Expand Up @@ -67,3 +84,67 @@ jobs:
name: test-results
path: test-results/
retention-days: 7

# Test build in Windows WSL (Ubuntu)
build-wsl:
name: Build (Windows WSL)
runs-on: windows-latest

steps:
- uses: actions/checkout@v4

- uses: Vampire/setup-wsl@v5
with:
distribution: Ubuntu-24.04

- name: Install Node.js in WSL
shell: wsl-bash {0}
run: |
sudo apt-get update
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs

- name: Build and test in WSL
shell: wsl-bash {0}
run: |
npm install
npm run build
npm run examples:build
npm test
npm run prettier

# Test that the package can be installed from git (triggers prepare script)
test-git-install:
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
name: Linux x64
- os: ubuntu-24.04-arm
name: Linux ARM64
- os: windows-latest
name: Windows x64
- os: windows-11-arm
name: Windows ARM64
- os: macos-latest
name: macOS ARM64

name: Test git install (${{ matrix.name }})
runs-on: ${{ matrix.os }}

steps:
- uses: actions/setup-node@v4
with:
node-version: "20"

- name: Create test project and install from git
shell: bash
run: |
mkdir test-project
cd test-project
npm init -y
# 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)"
7 changes: 7 additions & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
# 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"
echo "Run: docker run --rm -i -v \$PWD:/src -w /src node:latest npm i --registry=https://registry.npmjs.org/"
exit 1
fi

npm run build:all
npm run prettier:fix

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ The [`examples/`](https://github.com/modelcontextprotocol/ext-apps/tree/main/exa

To run all examples together:

```
```bash
npm install
npm run examples:start
```
Expand Down
9 changes: 4 additions & 5 deletions examples/basic-host/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
"version": "1.0.0",
"type": "module",
"scripts": {
"build": "concurrently 'INPUT=index.html vite build' 'INPUT=sandbox.html vite build'",
"watch": "concurrently 'INPUT=index.html vite build --watch' 'INPUT=sandbox.html vite build --watch'",
"build": "concurrently \"cross-env INPUT=index.html vite build\" \"cross-env INPUT=sandbox.html vite build\"",
"watch": "concurrently \"cross-env INPUT=index.html vite build --watch\" \"cross-env INPUT=sandbox.html vite build --watch\"",
"serve": "bun serve.ts",
"start": "NODE_ENV=development npm run build && npm run serve",
"dev": "NODE_ENV=development concurrently 'npm run watch' 'npm run serve'"
"start": "cross-env NODE_ENV=development npm run build && npm run serve",
"dev": "cross-env NODE_ENV=development concurrently \"npm run watch\" \"npm run serve\""
},
"dependencies": {
"@modelcontextprotocol/ext-apps": "../..",
Expand All @@ -23,7 +23,6 @@
"@types/react": "^19.2.2",
"@types/react-dom": "^19.2.2",
"@vitejs/plugin-react": "^4.3.4",
"bun": "^1.3.2",
"concurrently": "^9.2.1",
"cors": "^2.8.5",
"express": "^5.1.0",
Expand Down
9 changes: 4 additions & 5 deletions examples/basic-server-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
"private": true,
"type": "module",
"scripts": {
"build": "INPUT=mcp-app.html vite build",
"watch": "INPUT=mcp-app.html vite build --watch",
"build": "cross-env INPUT=mcp-app.html vite build",
"watch": "cross-env INPUT=mcp-app.html vite build --watch",
"serve": "bun server.ts",
"start": "NODE_ENV=development npm run build && npm run serve",
"dev": "NODE_ENV=development concurrently 'npm run watch' 'npm run serve'"
"start": "cross-env NODE_ENV=development npm run build && npm run serve",
"dev": "cross-env NODE_ENV=development concurrently 'npm run watch' 'npm run serve'"
},
"dependencies": {
"@modelcontextprotocol/ext-apps": "../..",
Expand All @@ -24,7 +24,6 @@
"@types/react": "^19.2.2",
"@types/react-dom": "^19.2.2",
"@vitejs/plugin-react": "^4.3.4",
"bun": "^1.3.2",
"concurrently": "^9.2.1",
"cors": "^2.8.5",
"express": "^5.1.0",
Expand Down
6 changes: 3 additions & 3 deletions examples/basic-server-react/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
import type { CallToolResult, ReadResourceResult } from "@modelcontextprotocol/sdk/types.js";
import fs from "node:fs/promises";
import path from "node:path";
import { RESOURCE_MIME_TYPE, type McpUiToolMeta } from "../../dist/src/app";
import { registerAppTool, registerAppResource, RESOURCE_MIME_TYPE, type McpUiToolMeta } from "@modelcontextprotocol/ext-apps/server";
import { startServer } from "../shared/server-utils.js";

const DIST_DIR = path.join(import.meta.dirname, "dist");
Expand All @@ -22,7 +22,7 @@ function createServer(): McpServer {
// MCP Apps require two-part registration: a tool (what the LLM calls) and a
// resource (the UI it renders). The `_meta` field on the tool links to the
// resource URI, telling hosts which UI to display when the tool executes.
server.registerTool(
registerAppTool(server,
"get-time",
{
title: "Get Time",
Expand All @@ -38,7 +38,7 @@ function createServer(): McpServer {
},
);

server.registerResource(
registerAppResource(server,
RESOURCE_URI,
RESOURCE_URI,
{ mimeType: RESOURCE_MIME_TYPE },
Expand Down
2 changes: 1 addition & 1 deletion examples/basic-server-vanillajs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,5 @@ button.addEventListener("click", () => {
});

// Connect to host
app.connect(new PostMessageTransport(window.parent));
app.connect();
```
9 changes: 4 additions & 5 deletions examples/basic-server-vanillajs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
"private": true,
"type": "module",
"scripts": {
"build": "INPUT=mcp-app.html vite build",
"watch": "INPUT=mcp-app.html vite build --watch",
"build": "cross-env INPUT=mcp-app.html vite build",
"watch": "cross-env INPUT=mcp-app.html vite build --watch",
"serve": "bun server.ts",
"start": "NODE_ENV=development npm run build && npm run serve",
"dev": "NODE_ENV=development concurrently 'npm run watch' 'npm run serve'"
"start": "cross-env NODE_ENV=development npm run build && npm run serve",
"dev": "cross-env NODE_ENV=development concurrently 'npm run watch' 'npm run serve'"
},
"dependencies": {
"@modelcontextprotocol/ext-apps": "../..",
Expand All @@ -19,7 +19,6 @@
"@types/cors": "^2.8.19",
"@types/express": "^5.0.0",
"@types/node": "^22.0.0",
"bun": "^1.3.2",
"concurrently": "^9.2.1",
"cors": "^2.8.5",
"express": "^5.1.0",
Expand Down
6 changes: 3 additions & 3 deletions examples/basic-server-vanillajs/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
import type { CallToolResult, ReadResourceResult } from "@modelcontextprotocol/sdk/types.js";
import fs from "node:fs/promises";
import path from "node:path";
import { RESOURCE_MIME_TYPE, type McpUiToolMeta } from "../../dist/src/app";
import { registerAppTool, registerAppResource, RESOURCE_MIME_TYPE, type McpUiToolMeta } from "@modelcontextprotocol/ext-apps/server";
import { startServer } from "../shared/server-utils.js";

const DIST_DIR = path.join(import.meta.dirname, "dist");
Expand All @@ -22,7 +22,7 @@ function createServer(): McpServer {
// MCP Apps require two-part registration: a tool (what the LLM calls) and a
// resource (the UI it renders). The `_meta` field on the tool links to the
// resource URI, telling hosts which UI to display when the tool executes.
server.registerTool(
registerAppTool(server,
"get-time",
{
title: "Get Time",
Expand All @@ -38,7 +38,7 @@ function createServer(): McpServer {
},
);

server.registerResource(
registerAppResource(server,
RESOURCE_URI,
RESOURCE_URI,
{ mimeType: RESOURCE_MIME_TYPE },
Expand Down
4 changes: 2 additions & 2 deletions examples/basic-server-vanillajs/src/mcp-app.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* @file App that demonstrates a few features using MCP Apps SDK with vanilla JS.
*/
import { App, PostMessageTransport } from "@modelcontextprotocol/ext-apps";
import { App } from "@modelcontextprotocol/ext-apps";
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
import "./global.css";
import "./mcp-app.css";
Expand Down Expand Up @@ -98,4 +98,4 @@ openLinkBtn.addEventListener("click", async () => {


// Connect to host
app.connect(new PostMessageTransport(window.parent));
app.connect();
11 changes: 5 additions & 6 deletions examples/budget-allocator-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
"private": true,
"type": "module",
"scripts": {
"build": "INPUT=mcp-app.html vite build",
"watch": "INPUT=mcp-app.html vite build --watch",
"build": "cross-env INPUT=mcp-app.html vite build",
"watch": "cross-env INPUT=mcp-app.html vite build --watch",
"serve:http": "bun server.ts",
"serve:stdio": "bun server.ts --stdio",
"start": "npm run start:http",
"start:http": "NODE_ENV=development npm run build && npm run serve:http",
"start:stdio": "NODE_ENV=development npm run build && npm run serve:stdio",
"dev": "NODE_ENV=development concurrently 'npm run watch' 'npm run serve:http'"
"start:http": "cross-env NODE_ENV=development npm run build && npm run serve:http",
"start:stdio": "cross-env NODE_ENV=development npm run build && npm run serve:stdio",
"dev": "cross-env NODE_ENV=development concurrently 'npm run watch' 'npm run serve:http'"
},
"dependencies": {
"@modelcontextprotocol/ext-apps": "../..",
Expand All @@ -23,7 +23,6 @@
"@types/cors": "^2.8.19",
"@types/express": "^5.0.0",
"@types/node": "^22.0.0",
"bun": "^1.3.2",
"concurrently": "^9.2.1",
"cors": "^2.8.5",
"express": "^5.1.0",
Expand Down
13 changes: 10 additions & 3 deletions examples/budget-allocator-server/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,12 @@ import type {
import fs from "node:fs/promises";
import path from "node:path";
import { z } from "zod";
import { RESOURCE_MIME_TYPE, type McpUiToolMeta } from "../../dist/src/app";
import {
registerAppTool,
registerAppResource,
RESOURCE_MIME_TYPE,
type McpUiToolMeta,
} from "@modelcontextprotocol/ext-apps/server";
import { startServer } from "../shared/server-utils.js";

const DIST_DIR = path.join(import.meta.dirname, "dist");
Expand Down Expand Up @@ -235,7 +240,8 @@ function createServer(): McpServer {
version: "1.0.0",
});

server.registerTool(
registerAppTool(
server,
"get-budget-data",
{
title: "Get Budget Data",
Expand Down Expand Up @@ -277,7 +283,8 @@ function createServer(): McpServer {
},
);

server.registerResource(
registerAppResource(
server,
resourceUri,
resourceUri,
{
Expand Down
4 changes: 2 additions & 2 deletions examples/budget-allocator-server/src/mcp-app.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* Budget Allocator App - Interactive budget allocation with real-time visualization
*/
import { App, PostMessageTransport } from "@modelcontextprotocol/ext-apps";
import { App } from "@modelcontextprotocol/ext-apps";
import { Chart, registerables } from "chart.js";
import "./global.css";
import "./mcp-app.css";
Expand Down Expand Up @@ -631,4 +631,4 @@ window
});

// Connect to host
app.connect(new PostMessageTransport(window.parent));
app.connect();
11 changes: 5 additions & 6 deletions examples/cohort-heatmap-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
"private": true,
"type": "module",
"scripts": {
"build": "INPUT=mcp-app.html vite build",
"watch": "INPUT=mcp-app.html vite build --watch",
"build": "cross-env INPUT=mcp-app.html vite build",
"watch": "cross-env INPUT=mcp-app.html vite build --watch",
"serve:http": "bun server.ts",
"serve:stdio": "bun server.ts --stdio",
"start": "npm run start:http",
"start:http": "NODE_ENV=development npm run build && npm run serve:http",
"start:stdio": "NODE_ENV=development npm run build && npm run serve:stdio",
"dev": "NODE_ENV=development concurrently 'npm run watch' 'npm run serve:http'"
"start:http": "cross-env NODE_ENV=development npm run build && npm run serve:http",
"start:stdio": "cross-env NODE_ENV=development npm run build && npm run serve:stdio",
"dev": "cross-env NODE_ENV=development concurrently 'npm run watch' 'npm run serve:http'"
},
"dependencies": {
"@modelcontextprotocol/ext-apps": "../..",
Expand All @@ -27,7 +27,6 @@
"@types/react": "^19.2.2",
"@types/react-dom": "^19.2.2",
"@vitejs/plugin-react": "^4.3.4",
"bun": "^1.3.2",
"concurrently": "^9.2.1",
"cors": "^2.8.5",
"express": "^5.1.0",
Expand Down
Loading
Loading