Skip to content

Commit c86ddf2

Browse files
committed
Merge origin/main into ochafik/swift-sdk
2 parents 6271126 + 9748622 commit c86ddf2

Some content is hidden

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

76 files changed

+8948
-3345
lines changed

.gitattributes

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
1+
# Force LF line endings for all text files (for consistent prettier formatting)
2+
* text=auto eol=lf
3+
14
package-lock.json linguist-generated=true
5+
src/generated/** linguist-generated=true

.github/workflows/ci.yml

Lines changed: 119 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,37 +6,113 @@ on:
66
pull_request:
77
branches: [main]
88

9+
permissions:
10+
contents: read
11+
912
jobs:
1013
build:
11-
runs-on: ubuntu-latest
14+
strategy:
15+
fail-fast: false
16+
matrix:
17+
include:
18+
- os: ubuntu-latest
19+
name: Linux x64
20+
- os: ubuntu-24.04-arm
21+
name: Linux ARM64
22+
- os: windows-latest
23+
name: Windows x64
24+
- os: windows-11-arm
25+
name: Windows ARM64
26+
- os: macos-latest
27+
name: macOS ARM64
28+
29+
name: Build (${{ matrix.name }})
30+
runs-on: ${{ matrix.os }}
31+
1232
steps:
1333
- uses: actions/checkout@v4
1434

1535
- name: Verify no private URLs in package-lock.json
36+
shell: bash
1637
run: '! grep -E "\"resolved\": \"https?://" package-lock.json | grep -v registry.npmjs.org'
1738

18-
- uses: oven-sh/setup-bun@v2
19-
with:
20-
bun-version: latest
21-
2239
- uses: actions/setup-node@v4
2340
with:
2441
node-version: "20"
2542

2643
- run: npm install
2744

28-
- run: npm run build:all
45+
- run: npm run build
46+
47+
- run: npm run examples:build
2948

3049
- name: Verify generated schemas are up-to-date
50+
shell: bash
3151
run: |
3252
npm run generate:schemas
33-
npm run prettier:fix
3453
git diff --exit-code src/generated/ || (echo "Generated schemas are out of date. Run 'npm run generate:schemas' and commit." && exit 1)
3554
3655
- run: npm test
3756

3857
- run: npm run prettier
3958

59+
e2e:
60+
runs-on: ubuntu-latest
61+
steps:
62+
- uses: actions/checkout@v4
63+
64+
- uses: oven-sh/setup-bun@v2
65+
with:
66+
bun-version: latest
67+
68+
- uses: actions/setup-node@v4
69+
with:
70+
node-version: "20"
71+
72+
- run: npm ci
73+
74+
- name: Install Playwright browsers
75+
run: npx playwright install --with-deps chromium
76+
77+
- name: Run E2E tests
78+
run: npx playwright test --reporter=list
79+
80+
- name: Upload test results
81+
uses: actions/upload-artifact@v4
82+
if: failure()
83+
with:
84+
name: test-results
85+
path: test-results/
86+
retention-days: 7
87+
88+
# Test build in Windows WSL (Ubuntu)
89+
build-wsl:
90+
name: Build (Windows WSL)
91+
runs-on: windows-latest
92+
93+
steps:
94+
- uses: actions/checkout@v4
95+
96+
- uses: Vampire/setup-wsl@v5
97+
with:
98+
distribution: Ubuntu-24.04
99+
100+
- name: Install Node.js in WSL
101+
shell: wsl-bash {0}
102+
run: |
103+
sudo apt-get update
104+
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
105+
sudo apt-get install -y nodejs
106+
107+
- name: Build and test in WSL
108+
shell: wsl-bash {0}
109+
run: |
110+
npm install
111+
npm run build
112+
npm run examples:build
113+
npm test
114+
npm run prettier
115+
40116
swift:
41117
runs-on: macos-latest
42118
steps:
@@ -49,3 +125,39 @@ jobs:
49125
- name: Test Swift SDK
50126
working-directory: swift
51127
run: swift test
128+
129+
# Test that the package can be installed from git (triggers prepare script)
130+
test-git-install:
131+
strategy:
132+
fail-fast: false
133+
matrix:
134+
include:
135+
- os: ubuntu-latest
136+
name: Linux x64
137+
- os: ubuntu-24.04-arm
138+
name: Linux ARM64
139+
- os: windows-latest
140+
name: Windows x64
141+
- os: windows-11-arm
142+
name: Windows ARM64
143+
- os: macos-latest
144+
name: macOS ARM64
145+
146+
name: Test git install (${{ matrix.name }})
147+
runs-on: ${{ matrix.os }}
148+
149+
steps:
150+
- uses: actions/setup-node@v4
151+
with:
152+
node-version: "20"
153+
154+
- name: Create test project and install from git
155+
shell: bash
156+
run: |
157+
mkdir test-project
158+
cd test-project
159+
npm init -y
160+
# Install from the PR branch
161+
npm install "git+https://github.com/${{ github.repository }}#${{ github.head_ref || github.ref_name }}"
162+
# Verify the package is usable (ESM import)
163+
node --input-type=module -e "import { App } from '@modelcontextprotocol/ext-apps'; console.log('Import successful:', typeof App)"

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,8 @@ bun.lockb
66
.vscode/
77
docs/api/
88
tmp/
9+
intermediate-findings/
10+
11+
# Playwright
12+
playwright-report/
13+
test-results/

.husky/pre-commit

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
# Verify no private registry URLs in package-lock.json
2+
if grep -E '"resolved": "https?://' package-lock.json | grep -v registry.npmjs.org > /dev/null; then
3+
echo "ERROR: package-lock.json contains non-npmjs.org URLs"
4+
echo "Run: docker run --rm -i -v \$PWD:/src -w /src node:latest npm i --registry=https://registry.npmjs.org/"
5+
exit 1
6+
fi
7+
18
npm run build:all
29
npm run prettier:fix
310

.prettierrc.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"semi": true,
3+
"trailingComma": "all",
4+
"singleQuote": false,
5+
"printWidth": 80,
6+
"tabWidth": 2
7+
}

CONTRIBUTING.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,45 @@ Or build and run examples:
4040
npm run examples:start
4141
```
4242

43+
## Testing
44+
45+
### Unit Tests
46+
47+
Run unit tests with Bun:
48+
49+
```bash
50+
npm test
51+
```
52+
53+
### E2E Tests
54+
55+
E2E tests use Playwright to verify all example servers work correctly with screenshot comparisons.
56+
57+
```bash
58+
# Run all E2E tests
59+
npm run test:e2e
60+
61+
# Run a specific server's tests
62+
npm run test:e2e -- --grep "Budget Allocator"
63+
64+
# Run tests in interactive UI mode
65+
npm run test:e2e:ui
66+
```
67+
68+
### Updating Golden Screenshots
69+
70+
When UI changes are intentional, update the golden screenshots:
71+
72+
```bash
73+
# Update all screenshots
74+
npm run test:e2e:update
75+
76+
# Update screenshots for a specific server
77+
npm run test:e2e:update -- --grep "Three.js"
78+
```
79+
80+
**Note**: Golden screenshots are platform-agnostic. Tests use canvas masking and tolerance thresholds to handle minor cross-platform rendering differences.
81+
4382
## Code of Conduct
4483

4584
This project follows our [Code of Conduct](CODE_OF_CONDUCT.md). Please review it before contributing.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ The [`examples/`](https://github.com/modelcontextprotocol/ext-apps/tree/main/exa
5555

5656
To run all examples together:
5757

58-
```
58+
```bash
5959
npm install
6060
npm run examples:start
6161
```

docs/quickstart.md

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ import cors from "cors";
102102
import express from "express";
103103
import fs from "node:fs/promises";
104104
import path from "node:path";
105-
import { z } from "zod";
105+
import * as z from "zod";
106106

107107
const server = new McpServer({
108108
name: "My MCP App Server",
@@ -130,17 +130,22 @@ server.registerTool(
130130
},
131131
);
132132

133-
server.registerResource(resourceUri, resourceUri, {}, async () => {
134-
const html = await fs.readFile(
135-
path.join(import.meta.dirname, "dist", "mcp-app.html"),
136-
"utf-8",
137-
);
138-
return {
139-
contents: [
140-
{ uri: resourceUri, mimeType: "text/html;profile=mcp-app", text: html },
141-
],
142-
};
143-
});
133+
server.registerResource(
134+
resourceUri,
135+
resourceUri,
136+
{ mimeType: "text/html;profile=mcp-app" },
137+
async () => {
138+
const html = await fs.readFile(
139+
path.join(import.meta.dirname, "dist", "mcp-app.html"),
140+
"utf-8",
141+
);
142+
return {
143+
contents: [
144+
{ uri: resourceUri, mimeType: "text/html;profile=mcp-app", text: html },
145+
],
146+
};
147+
},
148+
);
144149

145150
// Express server for MCP endpoint
146151
const app = express();

examples/basic-host/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
<head>
44
<meta charset="UTF-8">
55
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<meta name="color-scheme" content="light dark">
67
<title>MCP Apps Host</title>
78
<link rel="stylesheet" href="/src/global.css">
89
</head>

examples/basic-host/package.json

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,25 @@
44
"version": "1.0.0",
55
"type": "module",
66
"scripts": {
7-
"build": "concurrently 'INPUT=index.html vite build' 'INPUT=sandbox.html vite build'",
8-
"watch": "concurrently 'INPUT=index.html vite build --watch' 'INPUT=sandbox.html vite build --watch'",
7+
"build": "concurrently \"cross-env INPUT=index.html vite build\" \"cross-env INPUT=sandbox.html vite build\"",
8+
"watch": "concurrently \"cross-env INPUT=index.html vite build --watch\" \"cross-env INPUT=sandbox.html vite build --watch\"",
99
"serve": "bun serve.ts",
10-
"start": "NODE_ENV=development npm run build && npm run serve",
11-
"dev": "NODE_ENV=development concurrently 'npm run watch' 'npm run serve'"
10+
"start": "cross-env NODE_ENV=development npm run build && npm run serve",
11+
"dev": "cross-env NODE_ENV=development concurrently \"npm run watch\" \"npm run serve\""
1212
},
1313
"dependencies": {
1414
"@modelcontextprotocol/ext-apps": "../..",
1515
"@modelcontextprotocol/sdk": "^1.22.0",
1616
"react": "^19.2.0",
1717
"react-dom": "^19.2.0",
18-
"zod": "^3.25.0"
18+
"zod": "^4.1.13"
1919
},
2020
"devDependencies": {
2121
"@types/express": "^5.0.0",
2222
"@types/node": "^22.0.0",
2323
"@types/react": "^19.2.2",
2424
"@types/react-dom": "^19.2.2",
2525
"@vitejs/plugin-react": "^4.3.4",
26-
"bun": "^1.3.2",
2726
"concurrently": "^9.2.1",
2827
"cors": "^2.8.5",
2928
"express": "^5.1.0",

0 commit comments

Comments
 (0)