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>
The host implementation has been fixed to return the correct result
format, so this workaround is no longer needed.
Reverts the hack added in #82.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude <noreply@anthropic.com>
- 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>
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>
* Fix compatibility with @modelcontextprotocol/sdk 1.23+
Implement required abstract methods `assertTaskCapability` and
`assertTaskHandlerCapability` in App and AppBridge classes. These
were added to the Protocol base class in SDK 1.23+.
Also regenerates package-lock.json with valid npm registry versions
(previously had non-existent vite@6.4.1).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Add pkg-pr-new workflow for PR/commit publishing
Enables automatic publishing of any commit or PR to pkg.pr.new,
allowing consumers to install directly from git commits:
npm install https://pkg.pr.new/modelcontextprotocol/ext-apps/@modelcontextprotocol/ext-apps@<commit-or-pr>
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
Remove 'system' option from theme, leaving only 'light' | 'dark'.
This aligns the SDK with:
- The spec (which already only has light/dark)
- OpenAI Apps SDK compatibility
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude <noreply@anthropic.com>
Update `ui/host-context-change` to `ui/notifications/host-context-changed`
to match the SDK implementation and follow the notifications naming convention.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude <noreply@anthropic.com>
Some host implementations incorrectly return the full JSON-RPC envelope
(with result, jsonrpc, id fields) instead of just the unwrapped result.
This causes apps using callServerTool() to fail when accessing result.content.
This fix detects wrapped responses and unwraps them automatically.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
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>
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>
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>
Replace hardcoded workspace list with find + xargs to automatically
build all examples in parallel. New examples are picked up without
manual script updates.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
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>
Introduces a step-by-step tutorial covering:
- Project setup with Vite and TypeScript
- Server creation with tool + resource registration
- UI development using the App SDK
- Testing with basic-host
Also updates README to link to the guide and configures
typedoc to include it in generated documentation.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
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>
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>
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>
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>
Safe area insets apply on web as well, not just mobile devices.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add @types/bun which was missing from the lockfile.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude <noreply@anthropic.com>
Add types for parsing `_meta.ui` field from resources/read responses:
- McpUiResourceCspSchema: CSP domain declarations (connectDomains for
fetch/XHR/WebSocket, resourceDomains for scripts/images/fonts)
- McpUiResourceMetaSchema: Full metadata including CSP, dedicated domain
for widget sandbox, and border preference
Hosts need these to construct CSP headers and configure iframe sandboxing.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude <noreply@anthropic.com>
The previous approach measured html/body elements which expand to fill
the viewport, causing the iframe to be larger than necessary.
Fix by using CSS fit-content to measure the true minimum content size:
- Temporarily set html to fit-content to shrink it to content
- This automatically includes body margins
- Cache last sent size to prevent feedback loops from style changes
- Simplify scrollbar compensation (already 0 when no scrollbar)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude <noreply@anthropic.com>
* Add App <-> AppBridge integration tests
- Add minimalistic tests validating communication between App (guest) and AppBridge (host)
- Test initialization handshake flow
- Test Host -> App notifications (toolInput, toolInputPartial, toolResult, hostContext)
- Test App -> Host notifications (sizeChange, log)
- Test App -> Host requests (sendMessage, sendOpenLink)
- Test ping functionality
- Add setHostContext and sendToolInputPartial to AppBridge
- Add test script to package.json
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* docs: add JSDoc for setHostContext and sendToolInputPartial
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: add @types/bun for test type checking
- Add @types/bun devDependency for bun:test types
- Fix mock client request return type
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
The host should resolve "system" to either "light" or "dark" before
passing the theme to the app. Apps only need to know the actual
resolved theme value.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Olivier Chafik <ochafik@anthropic.com>
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>
* Track package-lock.json for deterministic builds
- Remove package-lock.json from .gitignore
- Add CI check to verify no private registry URLs in package-lock.json
- Add fresh package-lock.json from registry.npmjs.org
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Mark package-lock.json as generated in .gitattributes
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>