fix: Windows compatibility - bun as optional dep, cross-env for examples (#145)

* fix: Windows compatibility for npm scripts and cross-platform CI

Fixes #142 - Windows PowerShell install bug

Changes:
- Replace single quotes with escaped double quotes in generate:schemas
  (cmd.exe passes single quotes literally, breaking prettier glob matching)
- Simplify prettier scripts: remove redundant --ignore-path flags
  (prettier auto-loads .gitignore and .prettierignore by default)
- Remove $(pwd) from prettier scripts (bash-only syntax)
- Add cross-platform CI matrix: Linux x64, Windows x64, macOS ARM64, macOS x64
- Use shell: bash for grep commands in CI (not available in Windows cmd.exe)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* fix: remove bun npm package from all workspaces

The bun npm package tries to install platform-specific binaries which
fails on Windows CI. Since bun is installed via oven-sh/setup-bun action
in CI (and developers install it globally), we don't need the npm package.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* fix: skip examples:build on Windows (uses Unix-only INPUT=... syntax)

The examples use `INPUT=mcp-app.html vite build` which is bash syntax
for setting environment variables. This doesn't work on Windows cmd.exe.
Since examples aren't published to npm, we can skip building them on Windows.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* fix: force LF line endings for cross-platform prettier consistency

Git on Windows auto-converts line endings to CRLF, causing prettier to
report formatting issues. Force LF for all text files.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* ci: add test for git-based npm install (cross-platform)

This verifies that `npm install git+https://...` works on all platforms,
which triggers the prepare script and requires bun to be available.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* ci: add Linux ARM64 and Windows ARM64 to CI matrix

- Added ubuntu-24.04-arm (Linux ARM64)
- Added windows-11-arm (Windows ARM64)

Note: WSL is not available on GitHub-hosted runners (requires nested
virtualization which isn't supported).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* ci: disable Windows ARM64 (Bun lacks stable ARM64 binaries)

The oven-sh/setup-bun action fails with 404 when trying to download
Bun for Windows ARM64. Re-enable when Bun adds proper support.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* ci: add Windows WSL build test

Uses Vampire/setup-wsl action to install Ubuntu-24.04 in WSL and run
the full build/test cycle. This tests the Linux-in-Windows scenario
that was reported in issue #142.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* ci: fix WSL build - install unzip for Bun installer

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* ci: add setup-bun to publish.yml workflow

The pkg-pr-new publish workflow was missing bun setup, causing
"bun: not found" errors during npm ci (which triggers prepare script).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* ci: enable Windows ARM64 with x64-baseline Bun (via emulation)

Windows ARM64 can run x64 binaries via emulation. Use bun-download-url
to force x64-baseline build since native ARM64 Bun isn't available yet.

Reference: https://github.com/oven-sh/bun/issues/9824

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* ci: remove macOS x64 (macos-13 runner retired)

The macos-13 based runner images are now retired.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* docs: add Bun installation instructions per platform

Documents that Bun is required for development, with platform-specific
install commands in collapsible sections.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* docs: note Bun requirement in README examples section

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* feat: add bun as optional dependency (no global install required)

- Add @oven/bun-* platform packages as optionalDependencies
- Create postinstall script to set up bun binary from optional deps
- Handle Windows ARM64 by downloading x64-baseline for emulation
- Remove setup-bun from CI workflows (npm install handles it now)
- Remove manual Bun install instructions from docs

This alternative approach eliminates the need for global Bun installation
or setup-bun action in CI. npm install automatically installs the
platform-appropriate bun binary.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* chore: add debug logging to setup-bun script

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* chore: force stdout flush in setup-bun for CI debugging

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* chore: add more debugging to setup-bun

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* chore: remove accidental test artifacts

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* chore: run setup-bun in prepare script (before build)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* feat: use cross-env for Windows-compatible example builds

- Add cross-env to devDependencies
- Update all example package.json scripts to use cross-env for INPUT and NODE_ENV
- Enable examples:build on Windows in CI (no longer Unix-only)
- Add examples:build to WSL CI job

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* chore: remove unused imports in setup-bun.mjs

Address github-code-quality bot comments.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* fix: use run-bun.mjs wrapper for prepare hook compatibility

During npm install's prepare hook, node_modules/.bin is not in PATH,
so calling 'bun' directly fails. The new run-bun.mjs wrapper finds
bun at node_modules/.bin/bun and runs it with the correct path.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* ci: restore setup-bun action for build jobs

- Add setup-bun action to build and test-git-install jobs
- Disable Windows ARM64 (Bun doesn't support this platform)
- Add bun installation to WSL build

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* fix: remove bun devDep, add libc detection for Linux ARM64

- Remove 'bun' from devDependencies (its postinstall fails on Windows ARM64)
- Add libc detection (glibc vs musl) to setup-bun.mjs
- Only try compatible binaries based on detected libc
- Re-enable Windows ARM64 in CI (now uses x64 emulation fallback)
- Remove setup-bun action from CI (no longer needed)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* ci: simplify WSL build - let setup-bun.mjs handle bun installation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Olivier Chafik 2025-12-16 14:07:38 +00:00 • committed by GitHub
commit 974862237b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 555 additions and 158 deletions

3
.gitattributes vendored
View file

@ -1,2 +1,5 @@
# Force LF line endings for all text files (for consistent prettier formatting)
* text=auto eol=lf
package-lock.json linguist-generated=true package-lock.json linguist-generated=true
src/generated/** linguist-generated=true src/generated/** linguist-generated=true

View file

@ -11,26 +11,43 @@ permissions:
jobs: jobs:
build: 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: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Verify no private URLs in package-lock.json - name: Verify no private URLs in package-lock.json
shell: bash
run: '! grep -E "\"resolved\": \"https?://" package-lock.json | grep -v registry.npmjs.org' 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 - uses: actions/setup-node@v4
with: with:
node-version: "20" node-version: "20"
- run: npm install - 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 - name: Verify generated schemas are up-to-date
shell: bash
run: | run: |
npm run generate:schemas 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) git diff --exit-code src/generated/ || (echo "Generated schemas are out of date. Run 'npm run generate:schemas' and commit." && exit 1)
@ -67,3 +84,67 @@ jobs:
name: test-results name: test-results
path: test-results/ path: test-results/
retention-days: 7 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)"

View file

@ -55,7 +55,7 @@ The [`examples/`](https://github.com/modelcontextprotocol/ext-apps/tree/main/exa
To run all examples together: To run all examples together:
``` ```bash
npm install npm install
npm run examples:start npm run examples:start
``` ```

View file

@ -4,11 +4,11 @@
"version": "1.0.0", "version": "1.0.0",
"type": "module", "type": "module",
"scripts": { "scripts": {
"build": "concurrently 'INPUT=index.html vite build' 'INPUT=sandbox.html vite build'", "build": "concurrently \"cross-env INPUT=index.html vite build\" \"cross-env INPUT=sandbox.html vite build\"",
"watch": "concurrently 'INPUT=index.html vite build --watch' 'INPUT=sandbox.html vite build --watch'", "watch": "concurrently \"cross-env INPUT=index.html vite build --watch\" \"cross-env INPUT=sandbox.html vite build --watch\"",
"serve": "bun serve.ts", "serve": "bun serve.ts",
"start": "NODE_ENV=development npm run build && npm run serve", "start": "cross-env NODE_ENV=development npm run build && npm run serve",
"dev": "NODE_ENV=development concurrently 'npm run watch' 'npm run serve'" "dev": "cross-env NODE_ENV=development concurrently \"npm run watch\" \"npm run serve\""
}, },
"dependencies": { "dependencies": {
"@modelcontextprotocol/ext-apps": "../..", "@modelcontextprotocol/ext-apps": "../..",
@ -23,7 +23,6 @@
"@types/react": "^19.2.2", "@types/react": "^19.2.2",
"@types/react-dom": "^19.2.2", "@types/react-dom": "^19.2.2",
"@vitejs/plugin-react": "^4.3.4", "@vitejs/plugin-react": "^4.3.4",
"bun": "^1.3.2",
"concurrently": "^9.2.1", "concurrently": "^9.2.1",
"cors": "^2.8.5", "cors": "^2.8.5",
"express": "^5.1.0", "express": "^5.1.0",

View file

@ -4,11 +4,11 @@
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "scripts": {
"build": "INPUT=mcp-app.html vite build", "build": "cross-env INPUT=mcp-app.html vite build",
"watch": "INPUT=mcp-app.html vite build --watch", "watch": "cross-env INPUT=mcp-app.html vite build --watch",
"serve": "bun server.ts", "serve": "bun server.ts",
"start": "NODE_ENV=development npm run build && npm run serve", "start": "cross-env NODE_ENV=development npm run build && npm run serve",
"dev": "NODE_ENV=development concurrently 'npm run watch' 'npm run serve'" "dev": "cross-env NODE_ENV=development concurrently 'npm run watch' 'npm run serve'"
}, },
"dependencies": { "dependencies": {
"@modelcontextprotocol/ext-apps": "../..", "@modelcontextprotocol/ext-apps": "../..",
@ -24,7 +24,6 @@
"@types/react": "^19.2.2", "@types/react": "^19.2.2",
"@types/react-dom": "^19.2.2", "@types/react-dom": "^19.2.2",
"@vitejs/plugin-react": "^4.3.4", "@vitejs/plugin-react": "^4.3.4",
"bun": "^1.3.2",
"concurrently": "^9.2.1", "concurrently": "^9.2.1",
"cors": "^2.8.5", "cors": "^2.8.5",
"express": "^5.1.0", "express": "^5.1.0",

View file

@ -4,11 +4,11 @@
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "scripts": {
"build": "INPUT=mcp-app.html vite build", "build": "cross-env INPUT=mcp-app.html vite build",
"watch": "INPUT=mcp-app.html vite build --watch", "watch": "cross-env INPUT=mcp-app.html vite build --watch",
"serve": "bun server.ts", "serve": "bun server.ts",
"start": "NODE_ENV=development npm run build && npm run serve", "start": "cross-env NODE_ENV=development npm run build && npm run serve",
"dev": "NODE_ENV=development concurrently 'npm run watch' 'npm run serve'" "dev": "cross-env NODE_ENV=development concurrently 'npm run watch' 'npm run serve'"
}, },
"dependencies": { "dependencies": {
"@modelcontextprotocol/ext-apps": "../..", "@modelcontextprotocol/ext-apps": "../..",
@ -19,7 +19,6 @@
"@types/cors": "^2.8.19", "@types/cors": "^2.8.19",
"@types/express": "^5.0.0", "@types/express": "^5.0.0",
"@types/node": "^22.0.0", "@types/node": "^22.0.0",
"bun": "^1.3.2",
"concurrently": "^9.2.1", "concurrently": "^9.2.1",
"cors": "^2.8.5", "cors": "^2.8.5",
"express": "^5.1.0", "express": "^5.1.0",

View file

@ -4,14 +4,14 @@
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "scripts": {
"build": "INPUT=mcp-app.html vite build", "build": "cross-env INPUT=mcp-app.html vite build",
"watch": "INPUT=mcp-app.html vite build --watch", "watch": "cross-env INPUT=mcp-app.html vite build --watch",
"serve:http": "bun server.ts", "serve:http": "bun server.ts",
"serve:stdio": "bun server.ts --stdio", "serve:stdio": "bun server.ts --stdio",
"start": "npm run start:http", "start": "npm run start:http",
"start:http": "NODE_ENV=development npm run build && npm run serve:http", "start:http": "cross-env NODE_ENV=development npm run build && npm run serve:http",
"start:stdio": "NODE_ENV=development npm run build && npm run serve:stdio", "start:stdio": "cross-env NODE_ENV=development npm run build && npm run serve:stdio",
"dev": "NODE_ENV=development concurrently 'npm run watch' 'npm run serve:http'" "dev": "cross-env NODE_ENV=development concurrently 'npm run watch' 'npm run serve:http'"
}, },
"dependencies": { "dependencies": {
"@modelcontextprotocol/ext-apps": "../..", "@modelcontextprotocol/ext-apps": "../..",
@ -23,7 +23,6 @@
"@types/cors": "^2.8.19", "@types/cors": "^2.8.19",
"@types/express": "^5.0.0", "@types/express": "^5.0.0",
"@types/node": "^22.0.0", "@types/node": "^22.0.0",
"bun": "^1.3.2",
"concurrently": "^9.2.1", "concurrently": "^9.2.1",
"cors": "^2.8.5", "cors": "^2.8.5",
"express": "^5.1.0", "express": "^5.1.0",

View file

@ -4,14 +4,14 @@
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "scripts": {
"build": "INPUT=mcp-app.html vite build", "build": "cross-env INPUT=mcp-app.html vite build",
"watch": "INPUT=mcp-app.html vite build --watch", "watch": "cross-env INPUT=mcp-app.html vite build --watch",
"serve:http": "bun server.ts", "serve:http": "bun server.ts",
"serve:stdio": "bun server.ts --stdio", "serve:stdio": "bun server.ts --stdio",
"start": "npm run start:http", "start": "npm run start:http",
"start:http": "NODE_ENV=development npm run build && npm run serve:http", "start:http": "cross-env NODE_ENV=development npm run build && npm run serve:http",
"start:stdio": "NODE_ENV=development npm run build && npm run serve:stdio", "start:stdio": "cross-env NODE_ENV=development npm run build && npm run serve:stdio",
"dev": "NODE_ENV=development concurrently 'npm run watch' 'npm run serve:http'" "dev": "cross-env NODE_ENV=development concurrently 'npm run watch' 'npm run serve:http'"
}, },
"dependencies": { "dependencies": {
"@modelcontextprotocol/ext-apps": "../..", "@modelcontextprotocol/ext-apps": "../..",
@ -27,7 +27,6 @@
"@types/react": "^19.2.2", "@types/react": "^19.2.2",
"@types/react-dom": "^19.2.2", "@types/react-dom": "^19.2.2",
"@vitejs/plugin-react": "^4.3.4", "@vitejs/plugin-react": "^4.3.4",
"bun": "^1.3.2",
"concurrently": "^9.2.1", "concurrently": "^9.2.1",
"cors": "^2.8.5", "cors": "^2.8.5",
"express": "^5.1.0", "express": "^5.1.0",

View file

@ -4,14 +4,14 @@
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "scripts": {
"build": "INPUT=mcp-app.html vite build", "build": "cross-env INPUT=mcp-app.html vite build",
"watch": "INPUT=mcp-app.html vite build --watch", "watch": "cross-env INPUT=mcp-app.html vite build --watch",
"serve:http": "bun server.ts", "serve:http": "bun server.ts",
"serve:stdio": "bun server.ts --stdio", "serve:stdio": "bun server.ts --stdio",
"start": "npm run start:http", "start": "npm run start:http",
"start:http": "NODE_ENV=development npm run build && npm run serve:http", "start:http": "cross-env NODE_ENV=development npm run build && npm run serve:http",
"start:stdio": "NODE_ENV=development npm run build && npm run serve:stdio", "start:stdio": "cross-env NODE_ENV=development npm run build && npm run serve:stdio",
"dev": "NODE_ENV=development concurrently 'npm run watch' 'npm run serve:http'" "dev": "cross-env NODE_ENV=development concurrently 'npm run watch' 'npm run serve:http'"
}, },
"dependencies": { "dependencies": {
"@modelcontextprotocol/ext-apps": "../..", "@modelcontextprotocol/ext-apps": "../..",
@ -23,7 +23,6 @@
"@types/cors": "^2.8.19", "@types/cors": "^2.8.19",
"@types/express": "^5.0.0", "@types/express": "^5.0.0",
"@types/node": "^22.0.0", "@types/node": "^22.0.0",
"bun": "^1.3.2",
"concurrently": "^9.2.1", "concurrently": "^9.2.1",
"cors": "^2.8.5", "cors": "^2.8.5",
"express": "^5.1.0", "express": "^5.1.0",

View file

@ -4,14 +4,14 @@
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "scripts": {
"build": "INPUT=mcp-app.html vite build", "build": "cross-env INPUT=mcp-app.html vite build",
"watch": "INPUT=mcp-app.html vite build --watch", "watch": "cross-env INPUT=mcp-app.html vite build --watch",
"serve:http": "bun server.ts", "serve:http": "bun server.ts",
"serve:stdio": "bun server.ts --stdio", "serve:stdio": "bun server.ts --stdio",
"start": "npm run start:http", "start": "npm run start:http",
"start:http": "NODE_ENV=development npm run build && npm run serve:http", "start:http": "cross-env NODE_ENV=development npm run build && npm run serve:http",
"start:stdio": "NODE_ENV=development npm run build && npm run serve:stdio", "start:stdio": "cross-env NODE_ENV=development npm run build && npm run serve:stdio",
"dev": "NODE_ENV=development concurrently 'npm run watch' 'npm run serve:http'" "dev": "cross-env NODE_ENV=development concurrently 'npm run watch' 'npm run serve:http'"
}, },
"dependencies": { "dependencies": {
"@modelcontextprotocol/ext-apps": "../..", "@modelcontextprotocol/ext-apps": "../..",
@ -28,7 +28,6 @@
"@types/react": "^19.2.2", "@types/react": "^19.2.2",
"@types/react-dom": "^19.2.2", "@types/react-dom": "^19.2.2",
"@vitejs/plugin-react": "^4.3.4", "@vitejs/plugin-react": "^4.3.4",
"bun": "^1.3.2",
"concurrently": "^9.2.1", "concurrently": "^9.2.1",
"cors": "^2.8.5", "cors": "^2.8.5",
"express": "^5.1.0", "express": "^5.1.0",

View file

@ -4,14 +4,14 @@
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "scripts": {
"build": "INPUT=mcp-app.html vite build", "build": "cross-env INPUT=mcp-app.html vite build",
"watch": "INPUT=mcp-app.html vite build --watch", "watch": "cross-env INPUT=mcp-app.html vite build --watch",
"serve:http": "bun server.ts", "serve:http": "bun server.ts",
"serve:stdio": "bun server.ts --stdio", "serve:stdio": "bun server.ts --stdio",
"start": "npm run start:http", "start": "npm run start:http",
"start:http": "NODE_ENV=development npm run build && npm run serve:http", "start:http": "cross-env NODE_ENV=development npm run build && npm run serve:http",
"start:stdio": "NODE_ENV=development npm run build && npm run serve:stdio", "start:stdio": "cross-env NODE_ENV=development npm run build && npm run serve:stdio",
"dev": "NODE_ENV=development concurrently 'npm run watch' 'npm run serve:http'" "dev": "cross-env NODE_ENV=development concurrently 'npm run watch' 'npm run serve:http'"
}, },
"dependencies": { "dependencies": {
"@modelcontextprotocol/ext-apps": "../..", "@modelcontextprotocol/ext-apps": "../..",
@ -24,7 +24,6 @@
"@types/cors": "^2.8.19", "@types/cors": "^2.8.19",
"@types/express": "^5.0.0", "@types/express": "^5.0.0",
"@types/node": "^22.0.0", "@types/node": "^22.0.0",
"bun": "^1.3.2",
"concurrently": "^9.2.1", "concurrently": "^9.2.1",
"cors": "^2.8.5", "cors": "^2.8.5",
"express": "^5.1.0", "express": "^5.1.0",

View file

@ -4,14 +4,14 @@
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "scripts": {
"build": "INPUT=mcp-app.html vite build", "build": "cross-env INPUT=mcp-app.html vite build",
"watch": "INPUT=mcp-app.html vite build --watch", "watch": "cross-env INPUT=mcp-app.html vite build --watch",
"serve:http": "bun server.ts", "serve:http": "bun server.ts",
"serve:stdio": "bun server.ts --stdio", "serve:stdio": "bun server.ts --stdio",
"start": "npm run start:http", "start": "npm run start:http",
"start:http": "NODE_ENV=development npm run build && npm run serve:http", "start:http": "cross-env NODE_ENV=development npm run build && npm run serve:http",
"start:stdio": "NODE_ENV=development npm run build && npm run serve:stdio", "start:stdio": "cross-env NODE_ENV=development npm run build && npm run serve:stdio",
"dev": "NODE_ENV=development concurrently 'npm run watch' 'npm run serve:http'" "dev": "cross-env NODE_ENV=development concurrently 'npm run watch' 'npm run serve:http'"
}, },
"dependencies": { "dependencies": {
"@modelcontextprotocol/ext-apps": "../..", "@modelcontextprotocol/ext-apps": "../..",
@ -29,7 +29,6 @@
"@types/react-dom": "^19.2.2", "@types/react-dom": "^19.2.2",
"@types/three": "^0.181.0", "@types/three": "^0.181.0",
"@vitejs/plugin-react": "^4.3.4", "@vitejs/plugin-react": "^4.3.4",
"bun": "^1.3.2",
"concurrently": "^9.2.1", "concurrently": "^9.2.1",
"cors": "^2.8.5", "cors": "^2.8.5",
"express": "^5.1.0", "express": "^5.1.0",

View file

@ -4,14 +4,14 @@
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "scripts": {
"build": "INPUT=mcp-app.html vite build", "build": "cross-env INPUT=mcp-app.html vite build",
"watch": "INPUT=mcp-app.html vite build --watch", "watch": "cross-env INPUT=mcp-app.html vite build --watch",
"serve:http": "bun server.ts", "serve:http": "bun server.ts",
"serve:stdio": "bun server.ts --stdio", "serve:stdio": "bun server.ts --stdio",
"start": "npm run start:http", "start": "npm run start:http",
"start:http": "NODE_ENV=development npm run build && npm run serve:http", "start:http": "cross-env NODE_ENV=development npm run build && npm run serve:http",
"start:stdio": "NODE_ENV=development npm run build && npm run serve:stdio", "start:stdio": "cross-env NODE_ENV=development npm run build && npm run serve:stdio",
"dev": "NODE_ENV=development concurrently 'npm run watch' 'npm run serve:http'" "dev": "cross-env NODE_ENV=development concurrently 'npm run watch' 'npm run serve:http'"
}, },
"dependencies": { "dependencies": {
"@modelcontextprotocol/ext-apps": "../..", "@modelcontextprotocol/ext-apps": "../..",
@ -23,7 +23,6 @@
"@types/cors": "^2.8.19", "@types/cors": "^2.8.19",
"@types/express": "^5.0.0", "@types/express": "^5.0.0",
"@types/node": "^22.0.0", "@types/node": "^22.0.0",
"bun": "^1.3.2",
"concurrently": "^9.2.1", "concurrently": "^9.2.1",
"cors": "^2.8.5", "cors": "^2.8.5",
"express": "^5.1.0", "express": "^5.1.0",

171
package-lock.json generated
View file

@ -7,12 +7,14 @@
"": { "": {
"name": "@modelcontextprotocol/ext-apps", "name": "@modelcontextprotocol/ext-apps",
"version": "0.1.0", "version": "0.1.0",
"hasInstallScript": true,
"license": "MIT", "license": "MIT",
"workspaces": [ "workspaces": [
"examples/*" "examples/*"
], ],
"dependencies": { "dependencies": {
"@modelcontextprotocol/sdk": "^1.24.3", "@modelcontextprotocol/sdk": "^1.24.3",
"prettier": "^3.6.2",
"react": "^19.2.0", "react": "^19.2.0",
"react-dom": "^19.2.0" "react-dom": "^19.2.0"
}, },
@ -21,14 +23,13 @@
"@types/bun": "^1.3.2", "@types/bun": "^1.3.2",
"@types/react": "^19.2.2", "@types/react": "^19.2.2",
"@types/react-dom": "^19.2.2", "@types/react-dom": "^19.2.2",
"bun": "^1.3.2",
"concurrently": "^9.2.1", "concurrently": "^9.2.1",
"cors": "^2.8.5", "cors": "^2.8.5",
"cross-env": "^10.1.0",
"esbuild": "^0.25.12", "esbuild": "^0.25.12",
"express": "^5.1.0", "express": "^5.1.0",
"husky": "^9.1.7", "husky": "^9.1.7",
"nodemon": "^3.1.0", "nodemon": "^3.1.0",
"prettier": "^3.6.2",
"ts-to-zod": "^5.1.0", "ts-to-zod": "^5.1.0",
"tsx": "^4.21.0", "tsx": "^4.21.0",
"typedoc": "^0.28.14", "typedoc": "^0.28.14",
@ -36,6 +37,17 @@
"zod": "^4.1.13" "zod": "^4.1.13"
}, },
"optionalDependencies": { "optionalDependencies": {
"@oven/bun-darwin-aarch64": "^1.3.4",
"@oven/bun-darwin-x64": "^1.3.4",
"@oven/bun-darwin-x64-baseline": "^1.3.4",
"@oven/bun-linux-aarch64": "^1.3.4",
"@oven/bun-linux-aarch64-musl": "^1.3.4",
"@oven/bun-linux-x64": "^1.3.4",
"@oven/bun-linux-x64-baseline": "^1.3.4",
"@oven/bun-linux-x64-musl": "^1.3.4",
"@oven/bun-linux-x64-musl-baseline": "^1.3.4",
"@oven/bun-windows-x64": "^1.3.4",
"@oven/bun-windows-x64-baseline": "^1.3.4",
"@rollup/rollup-darwin-arm64": "^4.53.3", "@rollup/rollup-darwin-arm64": "^4.53.3",
"@rollup/rollup-darwin-x64": "^4.53.3", "@rollup/rollup-darwin-x64": "^4.53.3",
"@rollup/rollup-linux-arm64-gnu": "^4.53.3", "@rollup/rollup-linux-arm64-gnu": "^4.53.3",
@ -62,7 +74,6 @@
"@types/react": "^19.2.2", "@types/react": "^19.2.2",
"@types/react-dom": "^19.2.2", "@types/react-dom": "^19.2.2",
"@vitejs/plugin-react": "^4.3.4", "@vitejs/plugin-react": "^4.3.4",
"bun": "^1.3.2",
"concurrently": "^9.2.1", "concurrently": "^9.2.1",
"cors": "^2.8.5", "cors": "^2.8.5",
"express": "^5.1.0", "express": "^5.1.0",
@ -75,6 +86,8 @@
}, },
"examples/basic-host/node_modules/@types/node": { "examples/basic-host/node_modules/@types/node": {
"version": "22.19.1", "version": "22.19.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.1.tgz",
"integrity": "sha512-LCCV0HdSZZZb34qifBsyWlUmok6W7ouER+oQIGBScS8EsZsQbrtFTUrDX4hOl+CS6p7cnNC4td+qrSVGSCTUfQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -104,7 +117,6 @@
"@types/react": "^19.2.2", "@types/react": "^19.2.2",
"@types/react-dom": "^19.2.2", "@types/react-dom": "^19.2.2",
"@vitejs/plugin-react": "^4.3.4", "@vitejs/plugin-react": "^4.3.4",
"bun": "^1.3.2",
"concurrently": "^9.2.1", "concurrently": "^9.2.1",
"cors": "^2.8.5", "cors": "^2.8.5",
"express": "^5.1.0", "express": "^5.1.0",
@ -115,6 +127,8 @@
}, },
"examples/basic-server-react/node_modules/@types/node": { "examples/basic-server-react/node_modules/@types/node": {
"version": "22.19.1", "version": "22.19.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.1.tgz",
"integrity": "sha512-LCCV0HdSZZZb34qifBsyWlUmok6W7ouER+oQIGBScS8EsZsQbrtFTUrDX4hOl+CS6p7cnNC4td+qrSVGSCTUfQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -139,7 +153,6 @@
"@types/cors": "^2.8.19", "@types/cors": "^2.8.19",
"@types/express": "^5.0.0", "@types/express": "^5.0.0",
"@types/node": "^22.0.0", "@types/node": "^22.0.0",
"bun": "^1.3.2",
"concurrently": "^9.2.1", "concurrently": "^9.2.1",
"cors": "^2.8.5", "cors": "^2.8.5",
"express": "^5.1.0", "express": "^5.1.0",
@ -150,6 +163,8 @@
}, },
"examples/basic-server-vanillajs/node_modules/@types/node": { "examples/basic-server-vanillajs/node_modules/@types/node": {
"version": "22.19.1", "version": "22.19.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.1.tgz",
"integrity": "sha512-LCCV0HdSZZZb34qifBsyWlUmok6W7ouER+oQIGBScS8EsZsQbrtFTUrDX4hOl+CS6p7cnNC4td+qrSVGSCTUfQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -175,7 +190,6 @@
"@types/cors": "^2.8.19", "@types/cors": "^2.8.19",
"@types/express": "^5.0.0", "@types/express": "^5.0.0",
"@types/node": "^22.0.0", "@types/node": "^22.0.0",
"bun": "^1.3.2",
"concurrently": "^9.2.1", "concurrently": "^9.2.1",
"cors": "^2.8.5", "cors": "^2.8.5",
"express": "^5.1.0", "express": "^5.1.0",
@ -186,6 +200,8 @@
}, },
"examples/budget-allocator-server/node_modules/@types/node": { "examples/budget-allocator-server/node_modules/@types/node": {
"version": "22.19.1", "version": "22.19.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.1.tgz",
"integrity": "sha512-LCCV0HdSZZZb34qifBsyWlUmok6W7ouER+oQIGBScS8EsZsQbrtFTUrDX4hOl+CS6p7cnNC4td+qrSVGSCTUfQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -215,7 +231,6 @@
"@types/react": "^19.2.2", "@types/react": "^19.2.2",
"@types/react-dom": "^19.2.2", "@types/react-dom": "^19.2.2",
"@vitejs/plugin-react": "^4.3.4", "@vitejs/plugin-react": "^4.3.4",
"bun": "^1.3.2",
"concurrently": "^9.2.1", "concurrently": "^9.2.1",
"cors": "^2.8.5", "cors": "^2.8.5",
"express": "^5.1.0", "express": "^5.1.0",
@ -226,6 +241,8 @@
}, },
"examples/cohort-heatmap-server/node_modules/@types/node": { "examples/cohort-heatmap-server/node_modules/@types/node": {
"version": "22.19.1", "version": "22.19.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.1.tgz",
"integrity": "sha512-LCCV0HdSZZZb34qifBsyWlUmok6W7ouER+oQIGBScS8EsZsQbrtFTUrDX4hOl+CS6p7cnNC4td+qrSVGSCTUfQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -251,7 +268,6 @@
"@types/cors": "^2.8.19", "@types/cors": "^2.8.19",
"@types/express": "^5.0.0", "@types/express": "^5.0.0",
"@types/node": "^22.0.0", "@types/node": "^22.0.0",
"bun": "^1.3.2",
"concurrently": "^9.2.1", "concurrently": "^9.2.1",
"cors": "^2.8.5", "cors": "^2.8.5",
"express": "^5.1.0", "express": "^5.1.0",
@ -262,6 +278,8 @@
}, },
"examples/customer-segmentation-server/node_modules/@types/node": { "examples/customer-segmentation-server/node_modules/@types/node": {
"version": "22.19.1", "version": "22.19.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.1.tgz",
"integrity": "sha512-LCCV0HdSZZZb34qifBsyWlUmok6W7ouER+oQIGBScS8EsZsQbrtFTUrDX4hOl+CS6p7cnNC4td+qrSVGSCTUfQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -292,7 +310,6 @@
"@types/react": "^19.2.2", "@types/react": "^19.2.2",
"@types/react-dom": "^19.2.2", "@types/react-dom": "^19.2.2",
"@vitejs/plugin-react": "^4.3.4", "@vitejs/plugin-react": "^4.3.4",
"bun": "^1.3.2",
"concurrently": "^9.2.1", "concurrently": "^9.2.1",
"cors": "^2.8.5", "cors": "^2.8.5",
"express": "^5.1.0", "express": "^5.1.0",
@ -303,6 +320,8 @@
}, },
"examples/scenario-modeler-server/node_modules/@types/node": { "examples/scenario-modeler-server/node_modules/@types/node": {
"version": "22.19.1", "version": "22.19.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.1.tgz",
"integrity": "sha512-LCCV0HdSZZZb34qifBsyWlUmok6W7ouER+oQIGBScS8EsZsQbrtFTUrDX4hOl+CS6p7cnNC4td+qrSVGSCTUfQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -329,7 +348,6 @@
"@types/cors": "^2.8.19", "@types/cors": "^2.8.19",
"@types/express": "^5.0.0", "@types/express": "^5.0.0",
"@types/node": "^22.0.0", "@types/node": "^22.0.0",
"bun": "^1.3.2",
"concurrently": "^9.2.1", "concurrently": "^9.2.1",
"cors": "^2.8.5", "cors": "^2.8.5",
"express": "^5.1.0", "express": "^5.1.0",
@ -340,6 +358,8 @@
}, },
"examples/system-monitor-server/node_modules/@types/node": { "examples/system-monitor-server/node_modules/@types/node": {
"version": "22.19.1", "version": "22.19.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.1.tgz",
"integrity": "sha512-LCCV0HdSZZZb34qifBsyWlUmok6W7ouER+oQIGBScS8EsZsQbrtFTUrDX4hOl+CS6p7cnNC4td+qrSVGSCTUfQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -371,7 +391,6 @@
"@types/react-dom": "^19.2.2", "@types/react-dom": "^19.2.2",
"@types/three": "^0.181.0", "@types/three": "^0.181.0",
"@vitejs/plugin-react": "^4.3.4", "@vitejs/plugin-react": "^4.3.4",
"bun": "^1.3.2",
"concurrently": "^9.2.1", "concurrently": "^9.2.1",
"cors": "^2.8.5", "cors": "^2.8.5",
"express": "^5.1.0", "express": "^5.1.0",
@ -382,6 +401,8 @@
}, },
"examples/threejs-server/node_modules/@types/node": { "examples/threejs-server/node_modules/@types/node": {
"version": "22.19.1", "version": "22.19.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.1.tgz",
"integrity": "sha512-LCCV0HdSZZZb34qifBsyWlUmok6W7ouER+oQIGBScS8EsZsQbrtFTUrDX4hOl+CS6p7cnNC4td+qrSVGSCTUfQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -407,7 +428,6 @@
"@types/cors": "^2.8.19", "@types/cors": "^2.8.19",
"@types/express": "^5.0.0", "@types/express": "^5.0.0",
"@types/node": "^22.0.0", "@types/node": "^22.0.0",
"bun": "^1.3.2",
"concurrently": "^9.2.1", "concurrently": "^9.2.1",
"cors": "^2.8.5", "cors": "^2.8.5",
"express": "^5.1.0", "express": "^5.1.0",
@ -764,6 +784,13 @@
"dev": true, "dev": true,
"license": "Apache-2.0" "license": "Apache-2.0"
}, },
"node_modules/@epic-web/invariant": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@epic-web/invariant/-/invariant-1.0.0.tgz",
"integrity": "sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA==",
"dev": true,
"license": "MIT"
},
"node_modules/@esbuild/aix-ppc64": { "node_modules/@esbuild/aix-ppc64": {
"version": "0.25.12", "version": "0.25.12",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz",
@ -1384,7 +1411,6 @@
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"dev": true,
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@ -1398,7 +1424,6 @@
"cpu": [ "cpu": [
"x64" "x64"
], ],
"dev": true,
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@ -1412,7 +1437,6 @@
"cpu": [ "cpu": [
"x64" "x64"
], ],
"dev": true,
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@ -1426,7 +1450,6 @@
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"dev": true,
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@ -1440,7 +1463,6 @@
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"dev": true,
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@ -1454,7 +1476,6 @@
"cpu": [ "cpu": [
"x64" "x64"
], ],
"dev": true,
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@ -1468,7 +1489,6 @@
"cpu": [ "cpu": [
"x64" "x64"
], ],
"dev": true,
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@ -1482,7 +1502,6 @@
"cpu": [ "cpu": [
"x64" "x64"
], ],
"dev": true,
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@ -1496,7 +1515,6 @@
"cpu": [ "cpu": [
"x64" "x64"
], ],
"dev": true,
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@ -1510,7 +1528,6 @@
"cpu": [ "cpu": [
"x64" "x64"
], ],
"dev": true,
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@ -1524,7 +1541,6 @@
"cpu": [ "cpu": [
"x64" "x64"
], ],
"dev": true,
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@ -1970,13 +1986,13 @@
} }
}, },
"node_modules/@types/bun": { "node_modules/@types/bun": {
"version": "1.3.4", "version": "1.3.3",
"resolved": "https://registry.npmjs.org/@types/bun/-/bun-1.3.4.tgz", "resolved": "https://registry.npmjs.org/@types/bun/-/bun-1.3.3.tgz",
"integrity": "sha512-EEPTKXHP+zKGPkhRLv+HI0UEX8/o+65hqARxLy8Ov5rIxMBPNTjeZww00CIihrIQGEQBYg+0roO5qOnS/7boGA==", "integrity": "sha512-ogrKbJ2X5N0kWLLFKeytG0eHDleBYtngtlbu9cyBKFtNL3cnpDZkNdQj8flVf6WTZUX5ulI9AY1oa7ljhSrp+g==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"bun-types": "1.3.4" "bun-types": "1.3.3"
} }
}, },
"node_modules/@types/chai": { "node_modules/@types/chai": {
@ -2067,9 +2083,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "25.0.0", "version": "24.10.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.0.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz",
"integrity": "sha512-rl78HwuZlaDIUSeUKkmogkhebA+8K1Hy7tddZuJ3D0xV8pZSfsYGTsliGUol1JPzu9EKnTxPC4L1fiWouStRew==", "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -2481,9 +2497,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/baseline-browser-mapping": { "node_modules/baseline-browser-mapping": {
"version": "2.9.6", "version": "2.9.4",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.6.tgz", "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.4.tgz",
"integrity": "sha512-v9BVVpOTLB59C9E7aSnmIF8h7qRsFpx+A2nugVMTszEOMcfjlZMsXRm4LF23I3Z9AJxc8ANpIvzbzONoX9VJlg==", "integrity": "sha512-ZCQ9GEWl73BVm8bu5Fts8nt7MHdbt5vY9bP6WGnUh+r3l8M7CgfyTlwsgCbMC66BNxPr6Xoce3j66Ms5YUQTNA==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"bin": { "bin": {
@ -2614,44 +2630,10 @@
"resolved": "examples/budget-allocator-server", "resolved": "examples/budget-allocator-server",
"link": true "link": true
}, },
"node_modules/bun": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/bun/-/bun-1.3.4.tgz",
"integrity": "sha512-xV6KgD5ImquuKsoghzbWmYzeCXmmSgN6yJGz444hri2W+NGKNRFUNrEhy9+/rRXbvNA2qF0K0jAwqFNy1/GhBg==",
"cpu": [
"arm64",
"x64"
],
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"os": [
"darwin",
"linux",
"win32"
],
"bin": {
"bun": "bin/bun.exe",
"bunx": "bin/bunx.exe"
},
"optionalDependencies": {
"@oven/bun-darwin-aarch64": "1.3.4",
"@oven/bun-darwin-x64": "1.3.4",
"@oven/bun-darwin-x64-baseline": "1.3.4",
"@oven/bun-linux-aarch64": "1.3.4",
"@oven/bun-linux-aarch64-musl": "1.3.4",
"@oven/bun-linux-x64": "1.3.4",
"@oven/bun-linux-x64-baseline": "1.3.4",
"@oven/bun-linux-x64-musl": "1.3.4",
"@oven/bun-linux-x64-musl-baseline": "1.3.4",
"@oven/bun-windows-x64": "1.3.4",
"@oven/bun-windows-x64-baseline": "1.3.4"
}
},
"node_modules/bun-types": { "node_modules/bun-types": {
"version": "1.3.4", "version": "1.3.3",
"resolved": "https://registry.npmjs.org/bun-types/-/bun-types-1.3.4.tgz", "resolved": "https://registry.npmjs.org/bun-types/-/bun-types-1.3.3.tgz",
"integrity": "sha512-5ua817+BZPZOlNaRgGBpZJOSAQ9RQ17pkwPD0yR7CfJg+r8DgIILByFifDTa+IPDDxzf5VNhtNlcKqFzDgJvlQ==", "integrity": "sha512-z3Xwlg7j2l9JY27x5Qn3Wlyos8YAp0kKRlrePAOjgjMGS5IG6E7Jnlx736vH9UVI4wUICwwhC9anYL++XeOgTQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -2707,9 +2689,9 @@
} }
}, },
"node_modules/caniuse-lite": { "node_modules/caniuse-lite": {
"version": "1.0.30001760", "version": "1.0.30001759",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001760.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001759.tgz",
"integrity": "sha512-7AAMPcueWELt1p3mi13HR/LHH0TJLT11cnwDJEs3xA4+CK/PLKeO9Kl1oru24htkyUKtkGCvAx4ohB0Ttry8Dw==", "integrity": "sha512-Pzfx9fOKoKvevQf8oCXoyNRQ5QyxJj+3O0Rqx2V5oxT61KGx8+n6hV/IUyJeifUci2clnmmKVpvtiqRzgiWjSw==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@ -3116,6 +3098,24 @@
"node": ">= 0.10" "node": ">= 0.10"
} }
}, },
"node_modules/cross-env": {
"version": "10.1.0",
"resolved": "https://registry.npmjs.org/cross-env/-/cross-env-10.1.0.tgz",
"integrity": "sha512-GsYosgnACZTADcmEyJctkJIoqAhHjttw7RsFrVoJNXbsWWqaq6Ym+7kZjq6mS45O0jij6vtiReppKQEtqWy6Dw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@epic-web/invariant": "^1.0.0",
"cross-spawn": "^7.0.6"
},
"bin": {
"cross-env": "dist/bin/cross-env.js",
"cross-env-shell": "dist/bin/cross-env-shell.js"
},
"engines": {
"node": ">=20"
}
},
"node_modules/cross-spawn": { "node_modules/cross-spawn": {
"version": "7.0.6", "version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
@ -3532,9 +3532,9 @@
} }
}, },
"node_modules/electron-to-chromium": { "node_modules/electron-to-chromium": {
"version": "1.5.267", "version": "1.5.266",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.266.tgz",
"integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==", "integrity": "sha512-kgWEglXvkEfMH7rxP5OSZZwnaDWT7J9EoZCujhnpLbfi0bbNtRkgdX2E3gt0Uer11c61qCYktB3hwkAS325sJg==",
"dev": true, "dev": true,
"license": "ISC" "license": "ISC"
}, },
@ -3760,9 +3760,9 @@
} }
}, },
"node_modules/expect-type": { "node_modules/expect-type": {
"version": "1.3.0", "version": "1.2.2",
"resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.2.tgz",
"integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", "integrity": "sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"engines": { "engines": {
@ -5220,7 +5220,6 @@
"version": "3.7.4", "version": "3.7.4",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.7.4.tgz", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.7.4.tgz",
"integrity": "sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==", "integrity": "sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==",
"dev": true,
"license": "MIT", "license": "MIT",
"bin": { "bin": {
"prettier": "bin/prettier.cjs" "prettier": "bin/prettier.cjs"
@ -5865,9 +5864,9 @@
"link": true "link": true
}, },
"node_modules/systeminformation": { "node_modules/systeminformation": {
"version": "5.27.13", "version": "5.27.11",
"resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.27.13.tgz", "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.27.11.tgz",
"integrity": "sha512-geeE/7eNDoOhdc9j+qCsLlwbcyh0HnqhOZzmfNK4WBioWGUZbhwYrg+YZsZ3UJh4tmybQsnDuqzr3UoumMifew==", "integrity": "sha512-K3Lto/2m3K2twmKHdgx5B+0in9qhXK4YnoT9rIlgwN/4v7OV5c8IjbeAUkuky/6VzCQC7iKCAqi8rZathCdjHg==",
"license": "MIT", "license": "MIT",
"os": [ "os": [
"darwin", "darwin",
@ -7441,9 +7440,9 @@
} }
}, },
"node_modules/zod": { "node_modules/zod": {
"version": "4.1.13", "version": "4.2.1",
"resolved": "https://registry.npmjs.org/zod/-/zod-4.1.13.tgz", "resolved": "https://registry.npmjs.org/zod/-/zod-4.2.1.tgz",
"integrity": "sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig==", "integrity": "sha512-0wZ1IRqGGhMP76gLqz8EyfBXKk0J2qo2+H3fi4mcUP/KtTocoX08nmIAHl1Z2kJIZbZee8KOpBCSNPRgauucjw==",
"license": "MIT", "license": "MIT",
"funding": { "funding": {
"url": "https://github.com/sponsors/colinhacks" "url": "https://github.com/sponsors/colinhacks"

View file

@ -32,8 +32,9 @@
"examples/*" "examples/*"
], ],
"scripts": { "scripts": {
"generate:schemas": "tsx scripts/generate-schemas.ts && prettier --write 'src/generated/**/*'", "postinstall": "node scripts/setup-bun.mjs || echo 'setup-bun.mjs failed or not available'",
"build": "npm run generate:schemas && bun build.bun.ts", "generate:schemas": "tsx scripts/generate-schemas.ts && prettier --write \"src/generated/**/*\"",
"build": "npm run generate:schemas && node scripts/run-bun.mjs build.bun.ts",
"prepack": "npm run build", "prepack": "npm run build",
"build:all": "npm run build && npm run examples:build", "build:all": "npm run build && npm run examples:build",
"test": "bun test src", "test": "bun test src",
@ -46,12 +47,11 @@
"examples:start": "NODE_ENV=development npm run build && bun examples/run-all.ts start", "examples:start": "NODE_ENV=development npm run build && bun examples/run-all.ts start",
"examples:dev": "NODE_ENV=development bun examples/run-all.ts dev", "examples:dev": "NODE_ENV=development bun examples/run-all.ts dev",
"watch": "nodemon --watch src --ext ts,tsx --exec 'bun build.bun.ts'", "watch": "nodemon --watch src --ext ts,tsx --exec 'bun build.bun.ts'",
"prepare": "npm run build && husky", "prepare": "node scripts/setup-bun.mjs && npm run build && husky",
"docs": "typedoc", "docs": "typedoc",
"docs:watch": "typedoc --watch", "docs:watch": "typedoc --watch",
"prettier:base-cmd": "prettier -u --ignore-path ./.gitignore --ignore-path ./.prettierignore", "prettier": "prettier -u \"**/*.{js,jsx,ts,tsx,mjs,json,md,yml,yaml}\" --check",
"prettier": "yarn prettier:base-cmd \"$(pwd)/**/*.{js,jsx,ts,tsx,mjs,json,md,yml,yaml}\" --check", "prettier:fix": "prettier -u \"**/*.{js,jsx,ts,tsx,mjs,json,md,yml,yaml}\" --write"
"prettier:fix": "yarn prettier:base-cmd \"$(pwd)/**/*.{js,jsx,ts,tsx,mjs,json,md,yml,yaml}\" --write --list-different"
}, },
"author": "Olivier Chafik", "author": "Olivier Chafik",
"devDependencies": { "devDependencies": {
@ -59,9 +59,9 @@
"@types/bun": "^1.3.2", "@types/bun": "^1.3.2",
"@types/react": "^19.2.2", "@types/react": "^19.2.2",
"@types/react-dom": "^19.2.2", "@types/react-dom": "^19.2.2",
"bun": "^1.3.2",
"concurrently": "^9.2.1", "concurrently": "^9.2.1",
"cors": "^2.8.5", "cors": "^2.8.5",
"cross-env": "^10.1.0",
"esbuild": "^0.25.12", "esbuild": "^0.25.12",
"express": "^5.1.0", "express": "^5.1.0",
"husky": "^9.1.7", "husky": "^9.1.7",
@ -76,12 +76,23 @@
"zod": "^3.25.0 || ^4.0.0" "zod": "^3.25.0 || ^4.0.0"
}, },
"dependencies": { "dependencies": {
"prettier": "^3.6.2",
"@modelcontextprotocol/sdk": "^1.24.3", "@modelcontextprotocol/sdk": "^1.24.3",
"prettier": "^3.6.2",
"react": "^19.2.0", "react": "^19.2.0",
"react-dom": "^19.2.0" "react-dom": "^19.2.0"
}, },
"optionalDependencies": { "optionalDependencies": {
"@oven/bun-darwin-aarch64": "^1.3.4",
"@oven/bun-darwin-x64": "^1.3.4",
"@oven/bun-darwin-x64-baseline": "^1.3.4",
"@oven/bun-linux-aarch64": "^1.3.4",
"@oven/bun-linux-aarch64-musl": "^1.3.4",
"@oven/bun-linux-x64": "^1.3.4",
"@oven/bun-linux-x64-baseline": "^1.3.4",
"@oven/bun-linux-x64-musl": "^1.3.4",
"@oven/bun-linux-x64-musl-baseline": "^1.3.4",
"@oven/bun-windows-x64": "^1.3.4",
"@oven/bun-windows-x64-baseline": "^1.3.4",
"@rollup/rollup-darwin-arm64": "^4.53.3", "@rollup/rollup-darwin-arm64": "^4.53.3",
"@rollup/rollup-darwin-x64": "^4.53.3", "@rollup/rollup-darwin-x64": "^4.53.3",
"@rollup/rollup-linux-arm64-gnu": "^4.53.3", "@rollup/rollup-linux-arm64-gnu": "^4.53.3",

51
scripts/run-bun.mjs Normal file
View file

@ -0,0 +1,51 @@
#!/usr/bin/env node
/**
* Wrapper script to run bun with the correct path.
* This is needed because during npm install's prepare hook,
* node_modules/.bin is not in PATH yet.
*/
import { spawn } from "child_process";
import { existsSync } from "fs";
import { join, dirname } from "path";
import { fileURLToPath } from "url";
const __dirname = dirname(fileURLToPath(import.meta.url));
const projectRoot = join(__dirname, "..");
const isWindows = process.platform === "win32";
const bunExe = isWindows ? "bun.exe" : "bun";
// Find bun binary
const bunPaths = [
join(projectRoot, "node_modules", ".bin", bunExe),
// Fallback to system bun
"bun",
];
let bunPath = null;
for (const p of bunPaths) {
if (p === "bun" || existsSync(p)) {
bunPath = p;
break;
}
}
if (!bunPath) {
console.error("Could not find bun binary");
process.exit(1);
}
// Run bun with the provided arguments
const args = process.argv.slice(2);
const child = spawn(bunPath, args, {
stdio: "inherit",
shell: isWindows,
});
child.on("exit", (code) => {
process.exit(code ?? 0);
});
child.on("error", (err) => {
console.error("Failed to run bun:", err.message);
process.exit(1);
});

262
scripts/setup-bun.mjs Normal file
View file

@ -0,0 +1,262 @@
#!/usr/bin/env node
// Immediate log to verify script execution
console.log("[setup-bun] Script loaded");
/**
* Postinstall script to set up bun from platform-specific optional dependencies.
* Handles Windows ARM64 by downloading x64-baseline via emulation.
*/
import {
existsSync,
mkdirSync,
symlinkSync,
unlinkSync,
copyFileSync,
chmodSync,
writeFileSync,
} from "fs";
import { join, dirname } from "path";
import { spawnSync } from "child_process";
import { fileURLToPath } from "url";
import { get } from "https";
import { createGunzip } from "zlib";
const __dirname = dirname(fileURLToPath(import.meta.url));
const projectRoot = join(__dirname, "..");
const nodeModules = join(projectRoot, "node_modules");
const binDir = join(nodeModules, ".bin");
const os = process.platform;
const arch = process.arch;
const isWindows = os === "win32";
const bunExe = isWindows ? "bun.exe" : "bun";
// Detect libc type on Linux (glibc vs musl)
function detectLibc() {
if (os !== "linux") return null;
// Check for musl-specific loader
const muslLoaders = [
`/lib/ld-musl-${arch === "arm64" ? "aarch64" : "x86_64"}.so.1`,
"/lib/ld-musl-x86_64.so.1",
"/lib/ld-musl-aarch64.so.1",
];
for (const loader of muslLoaders) {
if (existsSync(loader)) {
console.log(` Detected musl libc (found ${loader})`);
return "musl";
}
}
// Default to glibc on Linux
console.log(" Detected glibc (no musl loader found)");
return "glibc";
}
// Platform to package mapping (matches @oven/bun-* package names)
// For Linux, separate glibc and musl packages
const platformPackages = {
darwin: {
arm64: ["bun-darwin-aarch64"],
x64: ["bun-darwin-x64", "bun-darwin-x64-baseline"],
},
linux: {
arm64: {
glibc: ["bun-linux-aarch64"],
musl: ["bun-linux-aarch64-musl"],
},
x64: {
glibc: ["bun-linux-x64", "bun-linux-x64-baseline"],
musl: ["bun-linux-x64-musl", "bun-linux-x64-musl-baseline"],
},
},
win32: {
x64: ["bun-windows-x64", "bun-windows-x64-baseline"],
arm64: ["bun-windows-x64-baseline"], // x64 runs via emulation on ARM64
},
};
function findBunBinary() {
let packages = platformPackages[os]?.[arch];
// For Linux, select packages based on libc type
if (os === "linux" && packages && typeof packages === "object") {
const libc = detectLibc();
packages = packages[libc] || [];
}
packages = packages || [];
console.log(
`Looking for bun packages: ${packages.join(", ") || "(none for this platform)"}`,
);
for (const pkg of packages) {
const binPath = join(nodeModules, "@oven", pkg, "bin", bunExe);
console.log(` Checking: ${binPath}`);
if (existsSync(binPath)) {
console.log(` Found bun at: ${binPath}`);
return binPath;
} else {
console.log(` Not found`);
}
}
return null;
}
async function downloadBunForWindowsArm64() {
// Windows ARM64 can run x64 binaries via emulation
const pkg = "bun-windows-x64-baseline";
const version = "1.3.4";
const url = `https://registry.npmjs.org/@oven/${pkg}/-/${pkg}-${version}.tgz`;
const destDir = join(nodeModules, "@oven", pkg);
console.log(`Downloading ${pkg} for Windows ARM64 emulation...`);
return new Promise((resolve, reject) => {
get(url, (response) => {
if (response.statusCode === 302 || response.statusCode === 301) {
get(response.headers.location, handleResponse).on("error", reject);
} else {
handleResponse(response);
}
function handleResponse(res) {
if (res.statusCode !== 200) {
reject(new Error(`Failed to download: ${res.statusCode}`));
return;
}
const chunks = [];
const gunzip = createGunzip();
res.pipe(gunzip);
gunzip.on("data", (chunk) => chunks.push(chunk));
gunzip.on("end", () => {
try {
extractTar(Buffer.concat(chunks), destDir);
const binPath = join(destDir, "bin", bunExe);
if (existsSync(binPath)) {
resolve(binPath);
} else {
reject(new Error("Binary not found after extraction"));
}
} catch (err) {
reject(err);
}
});
gunzip.on("error", reject);
}
}).on("error", reject);
});
}
function extractTar(buffer, destDir) {
// Simple tar extraction (512-byte blocks)
let offset = 0;
while (offset < buffer.length) {
const name = buffer
.toString("utf-8", offset, offset + 100)
.replace(/\0.*$/, "")
.replace("package/", "");
const size = parseInt(
buffer.toString("utf-8", offset + 124, offset + 136).trim(),
8,
);
offset += 512;
if (!isNaN(size) && size > 0 && name) {
const filePath = join(destDir, name);
const fileDir = dirname(filePath);
if (!existsSync(fileDir)) {
mkdirSync(fileDir, { recursive: true });
}
const content = buffer.subarray(offset, offset + size);
writeFileSync(filePath, content);
// Make executable
if (name.endsWith(bunExe) || name === "bin/bun") {
try {
chmodSync(filePath, 0o755);
} catch {}
}
offset += Math.ceil(size / 512) * 512;
}
}
}
function setupBinLink(bunPath) {
if (!existsSync(binDir)) {
mkdirSync(binDir, { recursive: true });
}
const bunLink = join(binDir, bunExe);
const bunxLink = join(binDir, isWindows ? "bunx.exe" : "bunx");
// Remove existing links
for (const link of [bunLink, bunxLink]) {
try {
unlinkSync(link);
} catch {}
}
if (isWindows) {
// On Windows, copy the binary (symlinks may not work without admin)
copyFileSync(bunPath, bunLink);
copyFileSync(bunPath, bunxLink);
} else {
// On Unix, use symlinks
symlinkSync(bunPath, bunLink);
symlinkSync(bunPath, bunxLink);
}
console.log(`Bun linked to: ${bunLink}`);
}
// Force immediate output
process.stdout.write("[setup-bun] Script starting...\n");
async function main() {
process.stdout.write(`[setup-bun] Setting up bun for ${os} ${arch}...\n`);
process.stdout.write(`[setup-bun] Project root: ${projectRoot}\n`);
process.stdout.write(`[setup-bun] Node modules: ${nodeModules}\n`);
let bunPath = findBunBinary();
if (!bunPath && os === "win32" && arch === "arm64") {
try {
bunPath = await downloadBunForWindowsArm64();
} catch (err) {
console.error("Failed to download bun for Windows ARM64:", err.message);
}
}
if (!bunPath) {
console.log("No bun binary found in optional dependencies.");
console.log("Bun will need to be installed separately.");
console.log("See: https://bun.sh/docs/installation");
process.exit(0); // Don't fail the install
}
try {
setupBinLink(bunPath);
// Verify installation
const result = spawnSync(bunPath, ["--version"], { encoding: "utf-8" });
if (result.status === 0) {
console.log(`Bun ${result.stdout.trim()} installed successfully!`);
}
} catch (err) {
console.error("Failed to set up bun:", err.message);
process.exit(0); // Don't fail the install
}
}
main().catch((err) => {
console.error(err);
process.exit(0); // Don't fail the install
});