* feat: add transcript-server example with live speech transcription
- New example: transcript-server with Web Speech API transcription
- Start/stop recording with timer display
- Live transcript with interim results
- Send button to send transcript as ui/message to host
- Copy button to copy full transcript
- Sent messages marked with divider, greyed out
- Experimental ui/update-model-context for live context updates
- Transparent background, respects host theme
- Enable microphone and clipboard in basic-host sandbox iframes
- Add allow="microphone; clipboard-write" to both outer and inner iframes
- Required for Web Speech API, audio capture, and clipboard access
- Add alert popup in basic-host for ui/message from apps
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* style: format transcript-server files
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* test: add e2e test and golden for transcript-server
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: use @types/dom-speech-recognition instead of hand-rolled types
Removes ~50 lines of manually defined Web Speech API types in favor of
the community-maintained type package.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: add newlines between transcript chunks when copying to clipboard
* refactor: unify transcript formatting with timestamps
- Add formatEntry() helper that includes [timestamp] prefix
- Add formatEntries() helper that joins entries with newlines
- Use same format for clipboard copy, send message, and model context
- DRY up duplicate code in send button handler
* fix: log model context update failures instead of silently swallowing
* fix: log model context updates for debugging
* refactor: pass permissions through loadSandboxProxy like csp
- Add permissions parameter to loadSandboxProxy in implementation.ts
- Build iframe allow attribute from permissions instead of hardcoding
- Update sandbox.ts to not hardcode allow attribute (set via notification)
- Add microphone + clipboardWrite permissions to transcript-server resource
- Update README to reflect permission configuration via resource _meta.ui
* fix(transcript-server): auto-expand instead of scroll
- Remove min-height: 100vh and overflow-y: auto
- Let content grow naturally with autoResize (default)
- Remove unnecessary scrollTop calls
* test: remove transcript timer mask (no longer dynamic)
* refactor: pass permissions through loadSandboxProxy like csp
* docs: document updateModelContext for transitional speech
* test: update e2e screenshots
* refactor: use app.updateModelContext() instead of raw request
* package-lock.json
* src/generated/schema.json
* test: update e2e screenshots from CI
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* refactor(basic-host): use SDK types for ModelContext and AppMessage
- Import McpUiUpdateModelContextRequest and McpUiMessageRequest from SDK
- Replace custom ModelContext with McpUiUpdateModelContextRequest['params']
- Replace custom AppMessage with McpUiMessageRequest['params']
- Pass full message params instead of extracting text
- Format messages by extracting text from content blocks in display
* feat(basic-host): handle non-text content blocks in display
- Add formatContentBlock helper for text, image, audio, resource types
- Show placeholders like <image: image/png> for non-text content
- Apply to both messages and model context display
* test: update shadertoy screenshot
* test: update screenshots from CI (linux x64)
Introduces a new MCP App example that renders ShaderToy-compatible GLSL
fragment shaders in real-time using WebGL 2.0 and ShaderToyLite.js.
Features:
- Standard ShaderToy uniforms (`iTime`, `iResolution`, `iMouse`, etc.)
- Multi-pass rendering with buffers A-D for feedback effects
- Shader compilation error overlay
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* fix: Move CSP to HTTP headers + add worker-src, frameDomains, baseUriDomains, permissions
Security improvements:
- CSP is now set via HTTP headers in serve.ts instead of meta tags
(meta tag CSP can be tampered with by same-origin content)
- CSP passed as query param to sandbox.html for header-based enforcement
New CSP/permissions features (borrowed from PR #158):
- frameDomains: control frame-src directive for nested iframes
- baseUriDomains: control base-uri directive
- permissions: camera, microphone, geolocation via iframe allow attribute
WebGL fix:
- Use document.write() instead of srcdoc for inner iframe content
(srcdoc creates opaque origin that breaks WebGL canvas updates)
- Add worker-src directive with blob: support (critical for WebGL apps
like CesiumJS/Three.js that use workers for tile decoding, terrain
processing, image processing)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: Remove permissions support (defer to PR #158)
Keep this PR focused on CSP security fixes only.
Permissions (camera, microphone, geolocation) will be
handled in #158.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* cleanup McpUiResourceCsp type usage / duplicate defs
* fix: guard against CSP injection in domain parameters
Validate CSP domain entries to reject characters that could:
- Break out of CSP directives (semicolons, newlines)
- Inject CSP keywords like 'unsafe-eval' (quotes)
- Inject multiple sources in one entry (spaces)
This prevents injection attacks where malicious domains could
override the security policy.
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* feat: publish example servers to npm
Make example MCP App servers publishable to npm under the
@modelcontextprotocol scope:
- server-basic-react
- server-basic-vanillajs
- server-budget-allocator
- server-cohort-heatmap
- server-customer-segmentation
- server-scenario-modeler
- server-system-monitor
- server-threejs
- server-wiki-explorer
Changes:
- Remove `private: true` from example package.json files
- Add proper npm metadata (description, repository, license, files)
- Update ext-apps dependency from relative to ^0.2.2
- Copy server-utils.ts into each package for standalone use
- Add publish-examples job to npm-publish.yml workflow
The examples will be published automatically when a GitHub release
is created, after the main SDK package is published.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* feat: publish examples with pkg-pr-new for PR testing
* feat: export createServer from example servers
* style: format integration-server/server.ts
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: update e2e snapshots for basic-server examples
Update golden screenshots for basic-react and basic-vanillajs after
the tool output was simplified from JSON to plain text in #182.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* merge
* refactor: update sheet-music-server and video-resource-server to new publishing pattern
- Move server-utils.ts from src/ to root level
- Add npm publishing metadata (scoped name, repository, license, files)
- Change ext-apps dependency from local to versioned ^0.2.2
- Update server.ts to handle stdio mode inline
* update package-lock
* fix: update package-lock.json for renamed server packages
* feat: add NASA public domain video to video-resource-server
Added 'nasa-earth' option - NASA ISS Earth observations (6.4MB).
Source: archive.org/details/NASA-Ultra-High-Definition (public domain)
* fix: add default videoId for video-resource-server
* fix: use existing bunny-1mb as default video, remove nasa-earth
* refactor: update new framework examples to publishing pattern
Add publishing metadata for:
- @modelcontextprotocol/server-basic-preact
- @modelcontextprotocol/server-basic-solid
- @modelcontextprotocol/server-basic-svelte
- @modelcontextprotocol/server-basic-vue
Changes:
- Move server-utils.ts from src/ to root
- Add npm publishing metadata
- Update ext-apps dep to versioned ^0.2.2
- Add stdio mode support in main()
* fix: add missing @rollup/rollup-win32-arm64-msvc to optionalDependencies
This fixes the Windows ARM64 CI build failure caused by npm's optional
dependency bug. The package.json was missing this platform-specific
rollup binding.
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Olivier Chafik <ochafik@anthropic.com>
The spec (apps.mdx) defines toolInfo.id as optional (id?: RequestId),
but the TypeScript types and generated schemas had it as required.
This allows hosts to pass just the tool definition without needing
a request ID, which is useful when the tool name is the primary
information needed by the widget.
* fix(app): add source validation to default PostMessageTransport
App.connect() now passes window.parent as both eventTarget and eventSource,
enabling source validation by default. This ensures apps only accept
messages from their parent window, preventing potential cross-app
message spoofing attacks.
Previously, the default transport only specified the target but not the
source for validation, meaning apps would accept messages from ANY window.
* fix(sandbox): add origin validation for host messages
The sandbox proxy now validates that messages from the parent window
come from the expected host origin (derived from document.referrer).
This prevents malicious pages from sending spoofed messages to the sandbox.
Changes:
- Extract EXPECTED_HOST_ORIGIN from document.referrer
- Validate event.origin against expected origin for parent messages
- Use specific origin instead of '*' when sending to parent
- Reject and log messages from unexpected origins
This addresses the TODO comment that was previously in the code.
* validate messages from app come from same origin as sandbox proxy
* fix(basic-host): be resilient to individual server connection failures
Use Promise.allSettled instead of Promise.all when connecting to
servers, so that a single server failure doesn't crash the entire UI.
Failed connections are logged as warnings but the UI continues with
the servers that connected successfully.
Also fixes video-resource-server missing server-utils.ts.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
* Update `package.json`
* Add TypeScript type checking to example build scripts
Add `tsc --noEmit &&` before `vite build` in all example `package.json`
files to catch type errors during builds. Previously, type errors
in `server.ts` files were not detected because Vite/Bun transpile
without type checking.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Make `_meta` optional in `McpUiAppResourceConfig`
The `_meta` and `ui` properties were required, causing TypeScript errors
when calling `registerAppResource()` without providing metadata.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix Zod type compatibility in `registerAppTool()`
Use `ZodRawShapeCompat | AnySchema` from SDK's `zod-compat` module
instead of raw `ZodRawShape` to resolve type errors when examples
pass `ZodObject` schemas to `registerAppTool()`.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Remove unused imports in example apps
- `basic-server-react`: Remove unused `McpUiResourceTeardownResult`
- `customer-segmentation-server`: Remove unused `PostMessageTransport`
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix CI git install test for fork PRs
Use `github.event.pull_request.head.repo.full_name` to correctly
reference the fork repository when testing git installs from PRs.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* feat: make generated Zod schemas version-agnostic (v3.25+/v4)
- Change generated schema imports from `zod/v4` to standard `zod`
- Replace v4-only `z.looseObject()` with `z.object().passthrough()`
- Works with both Zod v3.25+ and v4, matching MCP TS SDK approach
- Bump version to 0.2.2
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* chore: regenerate package-lock.json in Docker
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
* refactor: rename request methods to remove send prefix
Following the MCP TS SDK convention where request methods don't have
the "send" prefix (reserved for notifications):
- App.sendMessage() → App.message()
- App.sendOpenLink() → App.openLink()
- AppBridge.sendResourceTeardown() → AppBridge.resourceTeardown()
The old method names are kept as deprecated aliases for backwards
compatibility.
Updated all examples to use the new method names.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* test: add tests for deprecated method aliases
- Update existing tests to use new method names (message, openLink)
- Add tests verifying deprecated aliases are same reference as new methods
- Add tests verifying deprecated aliases still work functionally
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* refactor: rename message→sendMessage, resourceTeardown→teardownResource
- App.message() → App.sendMessage() (with deprecated message alias)
- AppBridge.resourceTeardown() → AppBridge.teardownResource() (with deprecated aliases)
This better follows the pattern where methods that send data have 'send' or action verb prefix.
* fix: update examples to use sendMessage instead of message
* fix: update basic-host to use teardownResource
* fix: update threejs-server to use sendMessage
* refactor: remove deprecated app.message alias
The app.message alias was removed since sendMessage is the correct name.
sendResourceTeardown already exists in AppBridge.
* refactor: remove resourceTeardown alias, keep only sendResourceTeardown
---------
Co-authored-by: Claude <noreply@anthropic.com>
* docs: add tool visibility and restructure _meta.ui
- Restructure tool metadata: `_meta["ui/resourceUri"]` → `_meta.ui.resourceUri`
- Add `visibility` array field: ["model"], ["apps"], or ["model", "apps"]
- Default ["model"] preserves standard MCP behavior
- ["apps"] enables widget-only tools hidden from agent
- Add McpUiToolMeta interface for type safety
- Add Design Decision #4 explaining approach vs OpenAI's two-field model
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* address PR review comments
- Change default visibility to ["model", "apps"]
- Add deprecation notice for flat ui/resourceUri format
- Add McpUiToolMeta and McpUiToolVisibility to spec.types.ts
- Improve tools/list and tools/call behavior wording
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* chore: regenerate schemas for McpUiToolMeta types
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* feat: tool visibility and nested _meta.ui format
- Rename visibility "apps" → "app" in McpUiToolVisibility type
- Add _meta.ui.resourceUri nested format (deprecate flat format)
- Add getToolUiResourceUri() utility with backward compatibility
- Add visibility demo to system-monitor-server:
- get-system-stats: visibility ["model"] with resourceUri
- refresh-stats: visibility ["app"] (app-only polling)
- Update all example servers to use new _meta.ui format
- Add 11 unit tests for getToolUiResourceUri()
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* chore: regenerate schemas with updated dependencies
* feat: export McpUiToolMeta type and add type annotations
- Export McpUiToolMeta and McpUiToolVisibility types from types.ts
- Export corresponding Zod schemas (McpUiToolMetaSchema, McpUiToolVisibilitySchema)
- Add `as McpUiToolMeta` type annotations to all example servers
- Update docs/quickstart.md with proper typing
Ensures type safety for `_meta.ui` tool metadata across the codebase.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* 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>
* feat: update McpUiAppToolConfig to support both _meta.ui and flat formats
* refactor: simplify server helper imports
* docs: add deprecation notice and improve resourceUri documentation
* feat: add backward compat normalization in registerAppTool
- If _meta.ui.resourceUri is set, also set legacy flat key
- If legacy flat key is set, also set _meta.ui.resourceUri
- Preserves existing visibility when merging
- Does not overwrite if both formats already set
* refactor: avoid mutating config arg in registerAppTool
* style: format with prettier
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Olivier Chafik <ochafik@anthropic.com>
Co-authored-by: Jonathan Hefner <jonathan@hefner.pro>
* 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>
Updated screenshots to reflect UI changes from styles addition.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Add setter-based handlers for MCP request/notification forwarding
- Add oncalltool, onlistresources, onlistresourcetemplates, onreadresource, onlistprompts setters for Guest UI → Host requests
- Add sendToolListChanged, sendResourceListChanged, sendPromptListChanged methods for Host → Guest UI notifications
- Refactor connect() to use new setters with inlined callbacks
- Update documentation to clarify optional client parameter behavior
- Remove unused forwardRequest/forwardNotification helper methods
- Add comprehensive tests for AppBridge without MCP client (manual handlers)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Potential fix for pull request finding 'Unused variable, import, function or class'
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
* fix: move prettier to dependencies for git-based installs
* fix: add explicit prettierrc to prevent inheriting parent configs during git-based installs
* Apply suggestions from code review
Co-authored-by: Jonathan Hefner <jonathan@hefner.pro>
* refactor(tests): factor out test values and add missing assertions
Address PR review feedback:
- Factor out test value objects (toolCall, resultContent, etc.) for clearer tests
- Add missing assertions on receivedRequests[0] for list handlers
- Improve test readability by defining expected values at the top of each test
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* docs: improve TypeDoc formatting and use `as const` for notification methods
- Use proper TypeDoc syntax with `@param callback.params` and `@param callback.extra`
- Add {@link ResultType} references for return types
- Replace `as Notification` with `as const` on method literals where possible
(sendResourceListChanged, sendPromptListChanged)
- Simplify sendHostContextChange cast syntax
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* refactor(types): use explicit type unions for AppBridge protocol types
- Add AppBridgeRequest, AppBridgeNotification, AppBridgeResult type unions
that explicitly list all valid types for the protocol
- Replace generic SDK Request/Notification/Result with our specific types
- Remove all type casts by using `as const` on method literals
- Add index signature to McpUiHostContext for forward compatibility
This improves type safety and documents exactly what the AppBridge supports.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* refactor: move AppRequest/AppNotification/AppResult to types.ts
Move protocol type unions from app-bridge.ts to types.ts where they
belong with other type definitions.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* chore: regenerate schemas with clean npm install
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
Co-authored-by: Jonathan Hefner <jonathan@hefner.pro>
* fix: prettify generated files on the fly
- Add prettier --write to generate:schemas script to format generated
files immediately after generation
- Remove redundant prettier:fix from CI schema verification step
(now that generation includes formatting)
This fixes the release CI failure where generated files weren't
formatted. Previously, PR CI masked this by running prettier:fix
before the final prettier check, while release CI ran the check
directly on freshly-generated (unformatted) files.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* format
---------
Co-authored-by: Claude <noreply@anthropic.com>
* feat: store and expose hostContext in App class
Fixes#129 - The App class now stores the initial hostContext received
during initialization and exposes it via getHostContext().
Changes:
- Add _hostContext private property to App class
- Store result.hostContext in connect() method
- Add getHostContext() getter method (parallel to getHostCapabilities())
- Update onhostcontextchanged setter to merge partial updates into
stored context
- Add default notification handler to update context even when
user hasn't set onhostcontextchanged
This enables apps to:
- Access toolInfo immediately after connection (only in initial context)
- Render with correct theme/locale without waiting for first notification
- Synchronously access viewport, timezone, and other initial state
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: use sendHostContextChange for partial update accumulation test
Address PR review feedback: The test was using setHostContext with full
context spreads which didn't clearly demonstrate partial update
accumulation. Now uses sendHostContextChange directly to send truly
partial updates (only theme, then only viewport), making it clear
the App correctly merges multiple partial notifications.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
* 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>