Commit graph ext-apps/examples
Author SHA1 Message Date
Olivier Chafik
bea0ae27f5
feat: add server helpers, make connect() to default to parent post transport (#165)
* feat: add server helpers and optional connect() transport

Add `src/server/` with convenience functions for registering MCP App tools
and resources:

- `registerAppTool(server, name, config, handler)`
- `registerAppResource(server, name, uri, config, callback)`

The `transport` parameter in `App.connect()` is now optional, defaulting to
`PostMessageTransport(window.parent)`.

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

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

* Update src/server/index.ts

Co-authored-by: Jonathan Hefner <jonathan@hefner.pro>

* fix: refine server helper types

- Make RESOURCE_URI_META_KEY required in McpUiAppToolConfig (tools need a UI resource)
- Make _meta optional in McpUiAppResourceConfig (not all resources need custom metadata)

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

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

* refactor: simplify RESOURCE_URI_META_KEY re-export

* refactor: consolidate export statements

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Jonathan Hefner <jonathan@hefner.pro>
2025-12-16 21:25:26 +00:00
Olivier Chafik
974862237b
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>
2025-12-16 14:07:38 +00:00
martinalong
6397ec1511
Add way to pass fonts 2025-12-15 22:54:53 -08:00
martinalong
8f591b69f2
Update naming of functions to reflect styles.variables nesting 2025-12-15 11:42:22 -08:00
martinalong
aa79cb7c5e
Finalized variable set 2025-12-15 11:42:19 -08:00
martinalong
445a5836cf
Make it styles.variables instead of styles 2025-12-15 11:42:18 -08:00
martinalong
2fa243ae8c
Updates example to use theme colors and adds border radius 2025-12-15 11:42:18 -08:00
martinalong
35781865af
Add color-scheme meta tag to all example apps
Prevents iframe from automatically applying a default background color.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-15 11:42:18 -08:00
Anton Pidkuiko
8550545ccb
fix: add mimeType to resource declarations in examples (#149)
According to spec, mimeType should be present in both the resource
declaration and the resource content. This adds the missing mimeType
to the registerResource() declaration (third parameter) in all example
servers and the quickstart documentation.

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

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: ochafik <olivier.chafik@gmail.com>
2025-12-15 12:09:47 +00:00
Olivier Chafik
c9e37204de
tests: add Playwright E2E tests with screenshot golden testing (+ fix examples session handling) (#115)
* Add Playwright E2E tests with screenshot golden testing

- Add E2E tests for all 8 MCP server examples
- Screenshot golden images for visual regression testing
- CI workflow for running E2E tests
- npm scripts: test:e2e, test:e2e:update, test:e2e:ui

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

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

* Add default demo code for Three.js example

When no code is provided, show a rotating green cube demo.

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

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

* Add E2E testing documentation to CONTRIBUTING.md

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

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

* Update Three.js golden screenshot with 3D cube

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

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

* Add explicit permissions to CI workflow

Set minimal read-only permissions for security best practices.

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

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

* Fix test.setTimeout() to be inside describe blocks

Playwright requires setTimeout to be called within a test or describe block.

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

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

* Simplify E2E tests - remove excessive timeouts

- Remove explicit setTimeout calls (default 30s is sufficient)
- Replace waitForTimeout(5000/6000) with proper waitForAppLoad()
- Wait for inner iframe visibility instead of fixed delays
- Keep only 500ms stabilization for screenshot animations

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

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

* Auto-generate missing snapshots in CI

Use updateSnapshots: 'missing' in CI to handle cross-platform
screenshot differences (macOS vs Linux).

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

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

* Use platform-agnostic golden screenshots

- Remove -chromium-darwin suffix from snapshot filenames
- Configure snapshotPathTemplate for cross-platform compatibility
- Increase tolerance to 5% for rendering differences between platforms

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

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

* Refactor tests to use forEach instead of for-of loop

May help with Playwright test discovery issues in CI.

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

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

* Use npm ci and list reporter in CI

- Use npm ci for exact package versions
- Use --reporter=list instead of html to avoid potential re-evaluation issues
- Only upload test-results on failure

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

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

* Exclude e2e tests from bun test

Run bun test only on src/ directory to avoid running Playwright tests
with Bun's test runner.

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

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

* Fix prettier formatting

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

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

* Add interaction tests for basic server apps

Test that clicking buttons in the MCP App triggers the corresponding
host callbacks:
- Send Message → host logs "Message from MCP App"
- Send Log → host logs "Log message from MCP App"
- Open Link → host logs "Open link request"

Tests both React and Vanilla JS implementations.

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

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

* Mask dynamic content in E2E screenshot tests

Add Playwright mask option to handle servers with dynamic/random content:
- basic-react/vanillajs: mask server time display
- system-monitor: mask CPU chart, memory stats, uptime
- cohort-heatmap: mask heatmap grid (random data)
- customer-segmentation: mask scatter chart (random data)

This addresses PR feedback about handling examples with non-deterministic
output. Masking replaces the previous 10% tolerance with proper exclusion
of dynamic elements, allowing tighter 1% tolerance for the rest of the UI.

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

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

* Add wiki-explorer to E2E tests with default URL param

- Add default URL "https://en.wikipedia.org/wiki/Model_Context_Protocol" to
  wiki-explorer-server's get-first-degree-links tool inputSchema
- Update basic-host to automatically populate input field with tool defaults
  extracted from inputSchema.properties
- Add wiki-explorer-server to E2E test suite with dynamic masking for the
  force-directed graph

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

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

* Use .default() for threejs tool schema instead of .optional()

This exposes the default code and height values in the JSON Schema,
allowing basic-host to auto-populate the input field with defaults.

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

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

* Enable parallel E2E tests with timeouts and canvas masking

- Enable fullyParallel with 4 workers locally (2 in CI)
- Add 30s timeout per test
- Mask threejs canvas for stable screenshots
- Update snapshots to reflect default values in input fields

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

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

* Add pre-commit check for private registry URLs in package-lock.json

Same check as in CI to catch issues before push.

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

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

* Increase screenshot diff tolerance to 6% for cross-platform rendering

Font rendering differs between macOS and Linux, causing ~5% pixel differences.

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

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

* Revert pre-commit artifactory check (moved to separate PR #133)

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

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

* Format threejs server.ts

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

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

* Update CONTRIBUTING.md to reflect platform-agnostic screenshots

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

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

* fix(e2e): use factory pattern for MCP servers to support parallel connections

McpServer only supports one transport at a time. When multiple browser
contexts connected in parallel, calling server.connect(transport) for
each session overwrote the previous transport's callbacks, causing
connection corruption and test timeouts.

Changes:
- server-utils.ts: accept factory function instead of single instance
- All 9 example servers: wrap server creation in createServer() function
- playwright.config.ts: re-enable parallel execution (4 workers)
- servers.spec.ts: add toBeEnabled wait for server connection
- Update screenshot baselines for basic-vanillajs and cohort-heatmap

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

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-13 20:57:27 +00:00
Olivier Chafik
cfd1d1dc43
fix: Make MCP App UIs responsive for narrow viewports (#135)
Changed from min-width: 425px to:
- width: 100%
- max-width: 425px
- box-sizing: border-box

This allows the apps to shrink on narrow viewports (like mobile
or when embedded in native WebViews) instead of causing horizontal
scrolling.

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

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-13 12:12:06 +00:00
Jonathan Hefner
8448ffe4fc
Merge pull request #49 from alpic-ai/update-zod-major
Add BYO zod version support
2025-12-12 13:53:11 -06:00
Olivier Chafik
3a30e94501
feat(examples): add SSE transport support and shared server utility (#136)
* feat(examples): add SSE transport support to all example servers

Add backwards-compatible SSE transport support alongside the current
Streamable HTTP transport. Each server now exposes:

- /mcp (GET, POST, DELETE) - Streamable HTTP transport (current spec)
- /sse (GET) - Legacy SSE transport stream endpoint
- /messages (POST) - Legacy SSE transport message endpoint

This enables older clients using the deprecated HTTP+SSE protocol
(version 2024-11-05) to connect to the example servers.

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

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

* refactor(examples): migrate 6 servers to use shared server utility

Refactored the following example servers to use the shared startServer utility from examples/shared/server-utils.ts:
- threejs-server
- system-monitor-server
- cohort-heatmap-server
- budget-allocator-server
- customer-segmentation-server
- scenario-modeler-server

Changes for each server:
- Removed direct imports: SSEServerTransport, StdioServerTransport, StreamableHTTPServerTransport, cors, express
- Removed PORT constant (now handled by shared utility)
- Added import for startServer from ../shared/server-utils.js
- Replaced entire async main() function with single startServer() call
- Preserved all business logic (tool registration, resource registration, helper functions)

This reduces code duplication by ~700 lines and ensures consistent transport handling across all example servers.

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

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

* refactor(examples): migrate remaining servers to shared utility

Complete the migration of example servers to use the shared
server-utils.ts module for transport setup:

- basic-server-react
- basic-server-vanillajs
- wiki-explorer-server
- Add shared/server-utils.ts

This centralizes all transport handling (stdio, Streamable HTTP, SSE)
in one place, reducing code duplication across ~500 lines.

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

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

* fix(examples): improve server-utils with stateful sessions and security

Address critical issues in the shared server utility:

1. Stateful sessions: Use sessionIdGenerator + onsessioninitialized
   to persist StreamableHTTPServerTransport across requests
2. Unified session store: Single Map for both transport types with
   proper type discrimination
3. Error handling: Try/catch on all endpoints with JSON-RPC errors
4. DNS rebinding protection: Use SDK's createMcpExpressApp helper

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

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

* fix(examples): allow connections from any host for development

Use host: "0.0.0.0" in createMcpExpressApp to disable DNS rebinding
protection, allowing connections from Android emulators and other
devices on the network. Also re-add CORS middleware.

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

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

* refactor(examples): use getPort() helper for transport selection

- Add getPort() helper that returns undefined for --stdio, else port
- Caller now explicitly passes port to startServer()
- port: undefined → stdio mode, port: number → HTTP mode

This makes the transport selection explicit at the call site.

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

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

* fix(examples): startServer returns promise that resolves/rejects on listen

Use httpServer.on('listening') and httpServer.on('error') events
to properly resolve or reject the returned promise.

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

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

* fix(examples): add error handling to startServer calls

Exit with code 1 if server fails to start (e.g., port in use).

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

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

* refactor(examples): update server files to use main() pattern with stdio support

Update all example server files to use the new main() pattern that supports both HTTP and stdio transports:
- Add StdioServerTransport import
- Remove getPort import (replaced with direct env var parsing)
- Replace direct startServer call with async main() function
- Add --stdio flag detection to choose between transports
- Use PORT env var with default 3001 for HTTP mode

Updated servers:
- basic-server-vanillajs
- wiki-explorer-server
- threejs-server
- system-monitor-server
- cohort-heatmap-server
- budget-allocator-server
- customer-segmentation-server
- scenario-modeler-server

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

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

* fix(examples): use correct default ports matching run-all.ts

Each server now defaults to its assigned port from run-all.ts:
- basic-server-react: 3101
- basic-server-vanillajs: 3102
- budget-allocator-server: 3103
- cohort-heatmap-server: 3104
- customer-segmentation-server: 3105
- scenario-modeler-server: 3106
- system-monitor-server: 3107
- threejs-server: 3108
- wiki-explorer-server: 3109

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

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

* fix(examples): expose mcp-session-id header for CORS requests

Without exposedHeaders in the CORS config, browsers block JavaScript
from reading the mcp-session-id response header. This caused the SDK's
StreamableHTTPClientTransport to never capture the session ID, breaking
all subsequent requests with "Bad request: not initialized" errors.

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

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

* pretty:fix

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-12 13:10:10 +00:00
Frédéric Barthelet
e99517d75c Implement BYO zod v3 or v4
Following recommendations from https://zod.dev/library-authors
2025-12-12 11:29:02 +01:00
Olivier Chafik
70b393a7e6
feat: implement ui/notifications/tool-cancelled + add missing App.onteardown (#120)
* feat: implement ui/notifications/tool-cancelled throughout SDK

Wire the tool-cancelled notification that hosts MUST send when tool
execution is cancelled (user action, timeout, classifier intervention, etc.):

- Add McpUiToolCancelledNotification type in spec.types.ts
- Generate Zod schema via ts-to-zod
- Add AppBridge.sendToolCancelled() method for hosts
- Add App.ontoolcancelled setter for guest UIs
- Export type and schema from types.ts
- Add tests for notification with/without reason

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

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

* feat: add App.onteardown handler for graceful shutdown

Wire the guest UI side of ui/resource-teardown request:

- Add onteardown setter in App class for guest UIs to handle teardown
- Allow ui/resource-teardown in assertRequestHandlerCapability
- Import McpUiResourceTeardownRequest/Result types
- Add tests for sync and async cleanup handlers

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

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

* feat(example): wire tool-cancelled and teardown in basic-host

Update basic-host example to properly use the new notifications:

- Send sendToolCancelled when tool call promise rejects
- Send sendResourceTeardown when React component unmounts
- Store appBridge ref for cleanup access

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

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

* fix(example): implement graceful teardown per spec recommendation

Address review feedback: the host now waits for guest's teardown
response before unmounting, following the spec: "Host SHOULD wait
for a response before tearing down the resource (to prevent data loss)."

Changes:
- Add close button to tool call panels
- Two-phase unmount: isDestroying state dims panel and disables events
- sendResourceTeardown() completes before component removal
- Non-app tool results close immediately

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

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

* feat(examples): add onteardown handlers to demo apps

Demonstrate graceful shutdown with simulated 500ms cleanup work.

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

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-11 20:31:17 +01:00
Olivier Chafik
8075bffec8
refactor(examples): use concurrently API for proper process cleanup (#128)
Replace custom spawn-based orchestration with concurrently's API.
This fixes zombie processes on Ctrl+C - concurrently uses tree-kill
internally to properly terminate entire process trees.

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

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-11 14:04:39 +01:00
Jonathan Hefner
366c5d5a6b
Add wiki-explorer-server example (#122)
Interactive Wikipedia link graph visualization using force-graph with:
- Force-directed graph layout for exploring page connections
- Node expansion to reveal first-degree Wikipedia links
- Visual state tracking (blue=default, green=expanded, red=error)
- Direct browser access to Wikipedia pages

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

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-11 13:58:05 +01:00
Anton Pidkuiko
6a8f5031be
Fix mimeType, CSP settings and QR code example (#111)
- Fix RESOURCE_MIME_TYPE to match spec: "text/html;profile=mcp-app"
- Add CSP field to McpUiSandboxResourceReadyNotification type and schema
- Update basic-host to extract and pass CSP metadata from resources
- Update sandbox.ts to dynamically inject CSP meta tag into inner iframe
- Remove static CSP from sandbox.html (now dynamic based on resource metadata)
- Update QR server to use custom read_resource handler for _meta injection
- Update requirements.txt to require mcp[cli]>=1.23.3

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

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-09 20:26:34 +01:00
Anton Pidkuiko
546f507e49
Add QR code Python MCP server example (#105)
* Add QR code Python MCP server example

A minimal Python MCP server that generates customizable QR codes with an
interactive widget UI. Features:

- Generate QR codes from any text or URL
- Customizable colors, size, border, and error correction
- Interactive widget using MCP Apps SDK protocol
- Supports both HTTP (for web clients) and stdio (for Claude Desktop)

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

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

* Potential fix for code scanning alert no. 10: Client-side cross-site scripting

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* Add semicolon

* Bind to 0.0.0.0 for Docker compatibility

* Use SDK from unpkg + add CSP resourceDomains for external scripts

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2025-12-09 19:20:08 +01:00
Olivier Chafik
3ac7c7935b
Add RESOURCE_MIME_TYPE constant (#108)
* Add RESOURCE_MIME_TYPE constant

* Update app-bridge.ts

* update syntax
2025-12-09 19:10:56 +01:00
Jonathan Hefner
4ca20f21c4
Smoothen the process of getting started (#103)
* Restructure threejs-server README to match marketing examples

- Update title format to "Example: Three.js App"
- Constrain screenshot width using table layout
- Add Features section with key capabilities
- Reorganize Running section with Tool Input subsection
- Add Architecture section describing server and app components
- Remove implementation-focused sections (WidgetProps, Creating a New Widget)

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

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

* Add bun as devDependency to example packages

npm install now automatically installs bun, eliminating the need for
separate installation instructions. Removed manual bun install step
from customer-segmentation-server README.

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

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

* Add start:http and start:stdio npm scripts to examples

For the 6 examples supporting --stdio transport, add explicit scripts:
- serve:http / serve:stdio for running the server
- start:http / start:stdio for build + serve
- start now aliases to start:http for backward compatibility

Update READMEs to document both transport options.

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

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

* Default basic-host SERVERS to localhost:3001/mcp

- Change threejs-server default port from 3109 to 3001 for consistency
- Add default SERVERS value in basic-host serve.ts
- Document SERVERS env var in basic-host README

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

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

* Improve Examples section in README

Frame the three basic examples as foundational starting points and
add a link to the examples directory for additional demo apps.

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

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

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-09 16:15:32 +01:00
Anton Pidkuiko
fd29038351
Merge pull request #100 from modelcontextprotocol/docs/add-bun-install-step
docs: add Bun installation step to customer-segmentation-server README
2025-12-08 23:48:31 +00:00
Anton Pidkuiko MacBook
2194acea5f
docs: add Bun installation step to customer-segmentation-server README
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-08 23:39:01 +00:00
Jonathan Hefner
d11b656d8e Refactor basic-host to use ServerSelect component
Extract server dropdown into ServerSelect component and simplify
ToolCallInfoPanel to read server name from toolCallInfo.serverInfo.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-08 16:34:52 -06:00
Jonathan Hefner
8bff1dff68 Add dynamic example orchestration script
Replace hardcoded port assignments and npm scripts with run-all.ts that:
- Auto-discovers example directories and assigns ports
- Passes server URLs to basic-host via SERVERS env var
- Supports start, dev, and build commands

Update basic-host to fetch server list from /api/servers endpoint
and display server names from MCP server metadata.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-08 16:34:52 -06:00
Anton Pidkuiko MacBook
2755438dba
Add Three.js marketing example server
New example demonstrating interactive 3D scene rendering with:
- show_threejs_scene tool with streaming code preview
- learn_threejs documentation tool
- Full WidgetProps interface for MCP App integration
- Reusable mcp-app-wrapper.tsx pattern

Also adds bun.lockb to .gitignore.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-08 21:19:42 +00:00
Olivier Chafik
f6ebefe238
Add server selector to basic-host example (#95)
* Add server selector to basic-host example

- Add ServerSelector component to switch between MCP servers
- Run all example servers concurrently on ports 3101-3107
- Update examples:start to launch all servers with assigned ports

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

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

* Move server selector into tool call panel

- Server selector now in same component as tool selector
- Tool call results persist across server switches
- Connection caching avoids reconnects when switching servers
- Display server name with tool name in results (ServerName:ToolName)

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

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-08 18:45:50 +01:00
Olivier Chafik
3dde360dc9
handle server errors (#91) 2025-12-08 18:45:31 +01:00
Jonathan Hefner
5e96fcc87f Enable responsive width growing in basic-host
Change onsizechange handler to use min-width instead of width,
treating the app's reported size as a floor rather than exact.
Use min(Xpx, 100%) to allow shrinking with container.

Also remove outmost max-width constraint and simplify iframe CSS to
allow apps to demonstrate responsive growing.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-08 10:33:37 -06:00
Anton Pidkuiko MacBook
8ef9142f00
Fix widget layout to use full available width
- Change marketing widget containers from fixed 600px to width: 100%
- Update basic-host iframe to use flex: 1 for proper expansion
- Widgets now fill their parent container instead of fixed size

Files changed:
- examples/budget-allocator-server/src/mcp-app.css
- examples/customer-segmentation-server/src/mcp-app.css
- examples/scenario-modeler-server/src/mcp-app.css
- examples/system-monitor-server/src/mcp-app.css
- examples/basic-host/src/index.module.css

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-08 14:01:28 +00:00
Anton Pidkuiko MacBook
d6ff3d9271
fix: format cohort-heatmap-server console.log line
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-08 13:37:17 +00:00
Anton Pidkuiko MacBook
e516b28d2e
Add optional stdio transport to marketing example servers
When launched with --stdio flag, servers use StdioServerTransport
instead of starting an HTTP server. This enables direct integration
with Claude Desktop and other MCP clients that use stdio transport.

Usage:
  bun examples/budget-allocator-server/server.ts --stdio

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-08 13:20:07 +00:00
Jonathan Hefner
437b9185cc
Merge pull request #81 from jonathanhefner/examples-use-content-for-now
Use `content` instead of `structuredContent` in examples
2025-12-05 16:36:32 -06:00
Jonathan Hefner
61cd4ed219 Use content instead of structuredContent in examples
Not all MCP clients support structuredContent in MCP tool results, so
examples now return data as JSON in content and parse it client-side.

Pattern used:
- Server: content: [{ type: "text", text: JSON.stringify(data) }]
- Client: JSON.parse(result.content!.filter(...).map(...).join(""))

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 16:35:20 -06:00
Jonathan Hefner
6b9f6327a6 Add screenshots to marketing example READMEs
Insert thumbnail galleries linking to full-size images hosted on
GitHub Pages for budget-allocator, cohort-heatmap, customer-segmentation,
scenario-modeler, and system-monitor server examples.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 15:37:25 -06:00
Jonathan Hefner
8bb58f332a Update MIME type to text/html;profile=mcp-app
Apply MIME type change from commit 0af1532 to all examples and docs.
The profile parameter follows RFC 6838 recommendations for custom
media types, as MCP Apps is a profile of HTML rather than a new syntax.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 14:50:30 -06:00
Jonathan Hefner
79fa10097b Add scenario-modeler-server example
Demo MCP App for SaaS financial planning with:
- Interactive sliders for MRR, growth, churn, margin, and costs
- 12-month projection charts (MRR, Gross Profit, Net Profit)
- 5 pre-built scenario templates (Bootstrapped, VC Rocketship, etc.)
- Template comparison overlay for strategy analysis
- Light/dark theme support

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 14:33:07 -06:00
Jonathan Hefner
f81d17f385 Add budget-allocator-server example
Demo MCP App for interactive budget allocation with:
- Slider controls for 5 categories (Marketing, Engineering, etc.)
- Real-time donut chart visualization via Chart.js
- 24-month sparkline trends per category
- Industry benchmark percentile badges
- Company stage selector (Seed through Growth)
- Budget preset buttons ($50K-$500K)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 14:33:01 -06:00
Jonathan Hefner
c711b1aac4 Add cohort-heatmap-server example
Demo MCP App visualizing cohort retention data with:
- Interactive heatmap with HSL color interpolation
- Multiple metrics: Retention %, Revenue Retention, Active Users
- Monthly/weekly period views
- Cell hover tooltips and row/column highlighting
- Light/dark theme support

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 14:32:53 -06:00
Jonathan Hefner
98d8fcddff Add customer-segmentation-server example
Demo MCP App for customer data visualization featuring:
- Interactive bubble chart (Chart.js) with configurable X/Y axes
- 250 customers across 4 segments (Enterprise, Mid-Market, SMB, Startup)
- 6 metrics: Revenue, Employees, Account Age, Engagement, Tickets, NPS
- Optional bubble sizing by a third metric
- Clickable legend for segment filtering
- Detail panel on hover/click
- Light/dark theme support

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 14:32:47 -06:00
Jonathan Hefner
fa2d413f1d Add system-monitor-server example
Demo MCP App showcasing real-time OS metrics visualization with:
- Per-core CPU usage via stacked area chart (Chart.js)
- Memory usage bar gauge with color-coded thresholds
- Auto-polling at 2-second intervals
- Light/dark theme support

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 14:32:41 -06:00
Jonathan Hefner
308537daac Remove simple-host and simple-server examples
These legacy examples have been replaced by basic-host,
basic-server-react, and basic-server-vanillajs.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 14:28:55 -06:00
Jonathan Hefner
4b5b0c7d79 Add basic-server-vanillajs example
Demonstrates MCP App SDK usage with vanilla JavaScript (no framework),
providing parity with the existing basic-server-react example.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 14:28:27 -06:00
Jonathan Hefner
97310d50c5 Add basic-host and basic-server-react examples
Introduce new example implementations to replace simple-host and
simple-server:

- basic-host: Reference host implementation with double-iframe sandbox
  pattern for secure UI isolation (outer iframe validates and relays
  messages, inner iframe renders untrusted tool UI via srcdoc)

- basic-server-react: MCP server example demonstrating tool registration
  with linked UI resources and React UI using the useApp() hook

Build infrastructure updates:
- Add build:all script and simplify CI/pre-commit to use it
- Add examples:dev for watch-mode development workflow

Also change PostMessageTransport logging from info to debug level.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 14:28:27 -06:00
Anton Pidkuiko
0af15322af
fix: use profile parameter for MIME type instead of suffix (#75)
Change MIME type from `text/html+mcp` to `text/html;profile=mcp-app`
to follow RFC 6838 recommendations for custom media types.

The `+suffix` format (like `text/html+mcp`) is intended for structured
syntax suffixes (e.g., `+json`, `+xml`) that describe the underlying
format. Since MCP Apps doesn't define a new syntax but rather a profile
of HTML, using a profile parameter is more semantically correct.

Fixes #59

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

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-04 20:28:58 +02:00
Jan Olaf Martin
a7d73c72e0
Make vite work out-of-the-box for simple-host (#33) 2025-12-01 21:57:46 +00:00
Jonathan Hefner
484768c3d1
Fix sandbox proxy ready detection in simple-host example (#47)
Replace Zod schema's internal _def.value access with a direct string
literal. The previous approach failed due to multiple Zod instances
being bundled, causing schema.shape.method._def.value to return
undefined.

The fix uses a typed string constant that provides compile-time safety
via McpUiSandboxProxyReadyNotification["method"] while avoiding runtime
dependency on Zod internals.

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

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-01 20:07:40 +00:00
Matthew Wang
40e0fdf685
docs: fix React UI tool call example 2025-12-01 02:04:40 +02:00
Olivier Chafik
3e5ec1ae0b
build: use workspaces for example subfolders (#23)
* use npm workspaces

* Update package.json
2025-11-25 03:14:14 +00:00
Olivier Chafik
b4c6019d47
example-host: fix sandboxing setup (#21)
* example-host: prevent accidental non-iframing of sandbox (or iframing in prod)

* fix sandbox isolation + "test in prod"

* Update package.json

* Update sandbox.ts
2025-11-25 02:45:55 +00:00