-
Notifications
You must be signed in to change notification settings - Fork 94
[MCP Apps] Add appCapabilities.availableDisplayModes documentation to spec #331
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@modelcontextprotocol/ext-apps
@modelcontextprotocol/server-basic-react
@modelcontextprotocol/server-basic-vanillajs
@modelcontextprotocol/server-budget-allocator
@modelcontextprotocol/server-cohort-heatmap
@modelcontextprotocol/server-customer-segmentation
@modelcontextprotocol/server-map
@modelcontextprotocol/server-pdf
@modelcontextprotocol/server-scenario-modeler
@modelcontextprotocol/server-shadertoy
@modelcontextprotocol/server-sheet-music
@modelcontextprotocol/server-system-monitor
@modelcontextprotocol/server-threejs
@modelcontextprotocol/server-transcript
@modelcontextprotocol/server-video-resource
@modelcontextprotocol/server-wiki-explorer
commit: |
ochafik
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks Martina!
specification/draft/apps.mdx
Outdated
|
|
||
| ### App Capabilities in `ui/initialize` | ||
|
|
||
| When the Guest UI sends an `ui/initialize` request to the Host, it MUST include its capabilities in the `appCapabilities` field: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
now just "view" (cf. #325)
| * | ||
| * @example ["inline", "fullscreen"] | ||
| */ | ||
| availableDisplayModes?: Array<"inline" | "fullscreen" | "pip">; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would clarify the purpose of this (which is to allow the host to change the view's display mode).
In the carousel app example you mentioned, the app might support fullscreen but only on its own terms (e.g. when user clicks somewhere specific in their UI), although not sure if that's a use-case worth the complexity.
@idosal wdyt?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If that's the intent, we should remove the requirement for the host to validate intersections, and instead suggest that it honors requests for its declared supported display modes (Host SHOULD honor requests for its declared supported display modes). We may enforce validation (e.g., Host MUST reject the request if the app's display mode isn't supported).
EDIT: I saw you've addressed this in your other comments. Completely agree :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
which is to allow the host to change the view's display mode
Yes, this part is not clear from this PR. Also the dynamic use case (availableDisplayModes changing as a result of user interaction like you mentioned) is not covered here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, didn't consider a dynamic value for this (this might be even more niche), more like the app doesn't want the host to initiate the fullscreen for it, it wants to be in control of when it wants to go fullscreen. But then again, maybe a bit niche, let's forget it for now ;-)
specification/draft/apps.mdx
Outdated
| **Host Behavior:** | ||
|
|
||
| - Host SHOULD intersect its own `availableDisplayModes` with the app's declared modes | ||
| - When responding to `ui/request-display-mode`, host SHOULD only allow modes both support |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for separation of concerns, host should only bother checking against its own supported modes. Would be good to spec out what happens when receiving an invalid mode, not sure it that's already covererd in the other availableDisplayModes section
specification/draft/apps.mdx
Outdated
| } | ||
| ``` | ||
|
|
||
| #### `availableDisplayModes` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| #### `availableDisplayModes` | |
| #### View `availableDisplayModes` |
(have clear local disambiguation w/ the other
#### Host `availableDisplayModes`
specification/draft/apps.mdx
Outdated
| - Host SHOULD intersect its own `availableDisplayModes` with the app's declared modes | ||
| - When responding to `ui/request-display-mode`, host SHOULD only allow modes both support | ||
| - Host MAY include the computed available modes in `HostContext.availableDisplayModes` | ||
| - Host MAY assume that all apps support `inline` display mode |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
host should only assume this if the spec says they MUST support inline above (which I'm not think if fair, e.g. some apps might wanna start in pip from the get go)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree. We shouldn't force inline
specification/draft/apps.mdx
Outdated
|
|
||
| ### App Capabilities in `ui/initialize` | ||
|
|
||
| When the Guest UI sends an `ui/initialize` request to the Host, it MUST include its capabilities in the `appCapabilities` field: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| When the Guest UI sends an `ui/initialize` request to the Host, it MUST include its capabilities in the `appCapabilities` field: | |
| When the View sends an `ui/initialize` request to the Host, it MUST include its capabilities in the `appCapabilities` field: |
|
Made those changes! |
|
Oop I realized that the reason this whole thing was missing in the first place was b/c my PR to add it to the app capabilities was merged into the wrong branch earlier. Added a commit that actually adds this field to app capabilities! |
ochafik
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @martinalong !
specification/draft/apps.mdx
Outdated
|
|
||
| **Host Behavior:** | ||
|
|
||
| - Host SHOULD honor requests for its declared supported display modes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds like this belongs to the Host availableDisplayModes / ui/request-display-mode sections no?
specification/draft/apps.mdx
Outdated
| - If omitted, hosts MAY assume the app supports all modes, or only `inline`. Apps that do not specify this field may not be able to take over fullscreen automatically. | ||
| - Apps MUST handle graceful degradation if placed in an unsupported mode | ||
|
|
||
| **Host Behavior:** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The host MUST NOT switch the view to a display mode that does not appear in its AppCapabilities.availableDisplayModes, if it is set.
specification/draft/apps.mdx
Outdated
| } | ||
| ``` | ||
|
|
||
| #### View `availableDisplayModes` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So there's already an untitled section:
Host behavior:
* App MUST check if the requested mode is in `availableDisplayModes` from host context.
* It is up to the host whether it switches to the requested mode, but the host MUST return the resulting mode (whether updated or not) in the response.
* If the requested mode is not available, Host SHOULD return the current display mode in the response.
* Host MAY coerce modes on certain platforms (e.g., "pip" to "fullscreen" on mobile).
View behavior:
* View SHOULD check `availableDisplayModes` in host context before requesting a mode change.
* View MUST handle the response mode differing from the requested mode.
Could we merge it and the new material to a #### Display Modes section?
Starts w/ the types
- Declaring support from View (
AppCapabilities.availableDisplayModes) - Declaring support from Host (
HostCapabilities.availableDisplayModes)
Then the methods: - Requesting change from View (
ui/request-display-mode) - Notifiying change from Host (
ui/notifications/host-context-changed)
Then the MUSTs and SHOULDs.
And this can be referenced from this and other sections.
| * | ||
| * @example ["inline", "fullscreen"] | ||
| */ | ||
| availableDisplayModes?: Array<"inline" | "fullscreen" | "pip">; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, didn't consider a dynamic value for this (this might be even more niche), more like the app doesn't want the host to initiate the fullscreen for it, it wants to be in control of when it wants to go fullscreen. But then again, maybe a bit niche, let's forget it for now ;-)
specification/draft/apps.mdx
Outdated
|
|
||
| - Apps SHOULD declare all display modes they are designed to support | ||
| - If omitted, hosts MAY assume the app supports all modes, or only `inline`. Apps that do not specify this field may not be able to take over fullscreen automatically. | ||
| - Apps MUST handle graceful degradation if placed in an unsupported mode |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that from inline to fullscreen, they just need to be reactive and respect insets (which they need to do anyway).
But anyway, why wouldn't we guarantee to an app we won't go against its express wishes?
specification/draft/apps.mdx
Outdated
|
|
||
| **App Behavior:** | ||
|
|
||
| - Apps SHOULD declare all display modes they are designed to support |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd even say MUST, and say that Hosts MAY decline display mode requests from apps that didn't declare said modes in the capabilities.
ochafik
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One last nit otherwise looks good, thanks @martinalong !
specification/draft/apps.mdx
Outdated
| - Host MUST NOT switch the View to a display mode that does not appear in its `appCapabilities.availableDisplayModes`, if set. | ||
| - Host MUST return the resulting mode (whether updated or not) in the response to `ui/request-display-mode`. | ||
| - If the requested mode is not available, Host SHOULD return the current display mode in the response. | ||
| - Host MAY coerce modes on certain platforms (e.g., "pip" to "fullscreen" on mobile). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this conflicts w/ host MUST NOT switch to unsupported display mode above, just drop?
Document the availableDisplayModes field in McpUiAppCapabilities that allows apps to declare which display modes they support. This enables hosts to compute the intersection of host and app capabilities and only offer appropriate display mode controls. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
- Change "Guest UI" to "View" terminology - Add "View" prefix to availableDisplayModes heading for disambiguation - Remove intersection logic - host only checks its own supported modes - Remove assumption that apps must support inline mode - Simplify host behavior to honor/reject based on its own capabilities 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
- Add `availableDisplayModes` field to `McpUiAppCapabilities` so apps can declare which display modes they support - Change `HostContext.availableDisplayModes` type from `string[]` to `McpUiDisplayMode[]` for type safety - Regenerate schemas 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
- Remove separate "App Capabilities" section for availableDisplayModes - Add display mode requirements to existing ui/request-display-mode section: - Host MUST NOT switch View to mode not in appCapabilities.availableDisplayModes - Host MAY decline requests from Views that didn't declare modes - View MUST declare supported modes during initialization 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
- Restore McpUiAppCapabilities interface documentation with availableDisplayModes - Restore "View MUST check if the requested mode is in availableDisplayModes from host context" clause that was accidentally removed 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Consolidate all display mode documentation into a single section: - Display mode types (inline, fullscreen, pip) - Declaring support from View (appCapabilities.availableDisplayModes) - Declaring support from Host (HostContext.availableDisplayModes) - Requesting changes (ui/request-display-mode) - Notifying changes (ui/notifications/host-context-changed) - All MUST/SHOULD requirements for View and Host behavior The ui/request-display-mode in Requests section now references the Display Modes section for behavior details. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
30c2c7c to
b4a9a5e
Compare
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
… spec (#331) * Add appCapabilities.availableDisplayModes documentation to spec Document the availableDisplayModes field in McpUiAppCapabilities that allows apps to declare which display modes they support. This enables hosts to compute the intersection of host and app capabilities and only offer appropriate display mode controls. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * Address PR review feedback - Change "Guest UI" to "View" terminology - Add "View" prefix to availableDisplayModes heading for disambiguation - Remove intersection logic - host only checks its own supported modes - Remove assumption that apps must support inline mode - Simplify host behavior to honor/reject based on its own capabilities 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * Add appCapabilities.availableDisplayModes to types - Add `availableDisplayModes` field to `McpUiAppCapabilities` so apps can declare which display modes they support - Change `HostContext.availableDisplayModes` type from `string[]` to `McpUiDisplayMode[]` for type safety - Regenerate schemas 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * Address Olivier's feedback - consolidate display mode docs - Remove separate "App Capabilities" section for availableDisplayModes - Add display mode requirements to existing ui/request-display-mode section: - Host MUST NOT switch View to mode not in appCapabilities.availableDisplayModes - Host MAY decline requests from Views that didn't declare modes - View MUST declare supported modes during initialization 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * Restore McpUiAppCapabilities docs and fix display mode clause - Restore McpUiAppCapabilities interface documentation with availableDisplayModes - Restore "View MUST check if the requested mode is in availableDisplayModes from host context" clause that was accidentally removed 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * Create unified Display Modes section Consolidate all display mode documentation into a single section: - Display mode types (inline, fullscreen, pip) - Declaring support from View (appCapabilities.availableDisplayModes) - Declaring support from Host (HostContext.availableDisplayModes) - Requesting changes (ui/request-display-mode) - Notifying changes (ui/notifications/host-context-changed) - All MUST/SHOULD requirements for View and Host behavior The ui/request-display-mode in Requests section now references the Display Modes section for behavior details. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * Remove mode coercion clause from display modes 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * Regenerate schemas with correct version 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> --------- Co-authored-by: Claude <[email protected]>
* Adding a simple (bad) pdf icon for directory (#330) * chore: bump version to 0.4.2 - Update package version from 0.4.1 to 0.4.2 - Pin @types/node to 22.10.0 for dev compatibility - Override seroval to ^1.4.1 to fix security vulnerabilities - Use '*' for workspace SDK dependency (works with unpublished versions) * fix(e2e): update Map Server display name to CesiumJS Map Server (#324) * fix(test): update map-server test to expect 'CesiumJS Map Server' The server name was renamed but the E2E test config was not updated. * fix: change in another file --------- Co-authored-by: Claude <[email protected]> Co-authored-by: Olivier Chafik <[email protected]> * feat(server): add getUiCapability helper for capability negotiation (#313) * feat(server): add hasUiSupport/getUiCapability for experimental+extensions Support double-tagging for MCP Apps capability negotiation: - Check both experimental and extensions fields in client capabilities - Add hasUiSupport() to easily check if client supports MCP Apps - Add getUiCapability() to retrieve the capability settings - Update spec to document both capability locations This enables forward compatibility as MCP transitions from experimental to the extensions field (SEP-1724). Claude-Generated-By: Claude Code (cli/claude-opus-4-5=100%) Claude-Steers: 0 Claude-Permission-Prompts: 0 Claude-Escapes: 0 * fix: update @types/node version in package-lock.json Replace invalid 22.19.5/22.19.6/22.19.7 versions with valid 22.19.3 * docs(spec): clarify hosts SHOULD double-tag, servers SHOULD check both - Hosts SHOULD advertise capabilities in both experimental and extensions - Servers SHOULD check both locations, preferring extensions when present - Updated example to show double-tagging pattern * chore: remove double-tagging recommendation, keep hasUiSupport helper Reverts the spec changes that recommended clients double-tag capabilities in both experimental and extensions fields. The helper functions remain as they're useful for checking capability in either location. * refactor(server): simplify to only getUiCapability, remove hasUiSupport - Remove hasUiSupport function (use getUiCapability directly) - Remove double-tagging logic (only check extensions field) - Add ClientCapabilitiesWithExtensions type using SDK's ClientCapabilities - Update spec to use getUiCapability - Simplify tests * fix: update @see link to getUiCapability * refactor(server): inline ClientCapabilitiesWithExtensions type in getUiCapability * refactor: move McpUiClientCapabilities to spec.types.ts * fix: update playwright docker image to v1.58.0 * fix: use -i instead of -it for docker commands (no TTY needed) * fix: Python server dependency resolution and Docker host validation (#333) * fix(say-server): add --index flag to uv run for PyPI resolution The pocket-tts dependency wasn't resolving without explicit --index flag when invoked via npm scripts. * fix(qr-server): allow Docker bridge IP in transport security Add 172.17.0.1:* to allowed_hosts to fix 421 Misdirected Request errors when the server is accessed from Docker containers. * feat(basic-host): Add theme toggle and MCP style variables (#336) * feat(basic-host): add theme toggle and MCP style variables Add theme support to basic-host example: - theme.ts: Global theme manager with light/dark toggle - host-styles.ts: Full set of MCP CSS variables using light-dark() - ThemeToggle component with sun/moon icons - Theme-aware CSS using CSS custom properties - Pass theme + styles to apps via hostContext - Notify apps when theme changes via sendHostContextChange Apps now receive: - hostContext.theme: 'light' | 'dark' - hostContext.styles.variables: All 60+ MCP CSS variables - onhostcontextchanged notifications when theme changes * test: update e2e goldens for theme changes * [MCP Apps] Add appCapabilities.availableDisplayModes documentation to spec (#331) * Add appCapabilities.availableDisplayModes documentation to spec Document the availableDisplayModes field in McpUiAppCapabilities that allows apps to declare which display modes they support. This enables hosts to compute the intersection of host and app capabilities and only offer appropriate display mode controls. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * Address PR review feedback - Change "Guest UI" to "View" terminology - Add "View" prefix to availableDisplayModes heading for disambiguation - Remove intersection logic - host only checks its own supported modes - Remove assumption that apps must support inline mode - Simplify host behavior to honor/reject based on its own capabilities 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * Add appCapabilities.availableDisplayModes to types - Add `availableDisplayModes` field to `McpUiAppCapabilities` so apps can declare which display modes they support - Change `HostContext.availableDisplayModes` type from `string[]` to `McpUiDisplayMode[]` for type safety - Regenerate schemas 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * Address Olivier's feedback - consolidate display mode docs - Remove separate "App Capabilities" section for availableDisplayModes - Add display mode requirements to existing ui/request-display-mode section: - Host MUST NOT switch View to mode not in appCapabilities.availableDisplayModes - Host MAY decline requests from Views that didn't declare modes - View MUST declare supported modes during initialization 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * Restore McpUiAppCapabilities docs and fix display mode clause - Restore McpUiAppCapabilities interface documentation with availableDisplayModes - Restore "View MUST check if the requested mode is in availableDisplayModes from host context" clause that was accidentally removed 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * Create unified Display Modes section Consolidate all display mode documentation into a single section: - Display mode types (inline, fullscreen, pip) - Declaring support from View (appCapabilities.availableDisplayModes) - Declaring support from Host (HostContext.availableDisplayModes) - Requesting changes (ui/request-display-mode) - Notifying changes (ui/notifications/host-context-changed) - All MUST/SHOULD requirements for View and Host behavior The ui/request-display-mode in Requests section now references the Display Modes section for behavior details. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * Remove mode coercion clause from display modes 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * Regenerate schemas with correct version 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> --------- Co-authored-by: Claude <[email protected]> * feat(say-server): add light/dark theme support (#338) - Add importmap entry for main SDK exports (applyDocumentTheme, etc.) - Import and apply host theme and styles on context changes - Apply initial host context theme/styles when app connects - Update CSS to use [data-theme="dark"] selector for host-provided themes - Keep @media prefers-color-scheme as fallback for standalone mode - Add color-scheme meta tag for native element theming * fix: followup app -> view terminology (#339) * chore: husky env fix, version pins, update-lock:docker script (#341) * fix(husky): load Node.js env for GUI apps + add update-lock:docker script Cherry-picked non-e2e changes from ochafik/fix-e2e-flaky-tests: - Load nvm/fnm/volta/homebrew paths in pre-commit for GitHub Desktop - Add update-lock:docker script to regenerate lockfile with public registry * pin package versions for dev compatibility - solid-js: 1.9.10 - caniuse-lite: 1.0.30001763 - cheerio: 1.1.2 - electron-to-chromium: 1.5.267 - @playwright/test: 1.57.0 - playwright: 1.57.0 - playwright-core: 1.57.0 * regen * fix: pin @types/node to existing version and regenerate lockfile - Fix @types/node 20.19.28 -> 20.19.27 (typo, version didn't exist) - Regenerate package-lock.json to resolve versions available on both public npm and Anthropic artifactory registries * fix(basic-server-solid): bump solid-js 1.9.10 -> 1.9.11 to fix seroval vulnerabilities * fix: pin seroval to 1.4.1 for dev compatibility * Refactor server startup functions Rename `startServer` to `startStreamableHTTPServer` and add a new `startStdioServer` helper to make the transport type explicit. Remove the `ServerOptions` interface in favor of reading `PORT` directly from the environment inside the function (defaulting to `3001`). Also update Python examples to default to port `3001` for consistency. Co-Authored-By: Claude Opus 4.5 <[email protected]> * Support full-file inclusion in synced code snippets Previously, the script only supported extracting regions from `.ts/.tsx` files using the `#regionName` syntax. Now it also supports including entire files without a region specifier, enabling sync of any file type (JSON, YAML, shell scripts, etc.) into documentation. Changes: - Make `#regionName` optional in the `source=""` attribute - Accept any fence language (not just `ts`/`tsx`) - Simplify cache to flat map with composite keys - Add validation error for region extraction on non-TypeScript files Co-Authored-By: Claude Opus 4.5 <[email protected]> * Rewrite Quickstart guide with type-checked code examples Rewrites the Quickstart tutorial to provide a more focused, step-by-step introduction to building MCP Apps. The guide now uses synced code fences that pull from `examples/quickstart/`, ensuring all code shown in the documentation is type-checked and tested. Key improvements: - Clearer project setup instructions with explicit commands - Streamlined explanations of the tool + resource registration pattern - Added screenshot showing the completed app - E2E test coverage validates the example works end-to-end Co-Authored-By: Claude Opus 4.5 <[email protected]> * Add MCP Apps Overview document Adds `docs/overview.md` covering the core concepts: architecture, lifecycle, UI resources, bidirectional communication, theming, display modes, and security. Includes mermaid flowchart and sequence diagrams. Also adds the `@boneskull/typedoc-plugin-mermaid` TypeDoc plugin for mermaid diagram support. However, the plugin handles HTML entities from TypeDoc incorrectly, so `scripts/typedoc-plugin-fix-mermaid-entities.mjs` decodes HTML entities before the plugin processes them. Co-Authored-By: Claude Opus 4.5 <[email protected]> * Add Agent Skills installation guide Add `docs/agent-skills.md` with installation instructions for multiple AI coding agents including Claude Code, VS Code/Copilot, Gemini CLI, Cline, and Goose. The guide provides three installation methods: Claude Code plugin, Vercel Skills CLI (`npx skills add`), and manual installation. Update `README.md` to link to the new guide and reframe the plugin section around the broader "Agent Skills" concept. Co-Authored-By: Claude Opus 4.5 <[email protected]> * Polish OpenAI migration reference for readability Add framing prose to the migration guide to improve navigation: - Expanded intro describing document purpose and how to use it - Added note about features marked "Not yet implemented" - Added brief transition sentences before Server-Side and Client-Side sections Co-Authored-By: Claude Opus 4.5 <[email protected]> * Fix mermaid diagram arrowheads not rendering The `@boneskull/typedoc-plugin-mermaid` creates both dark and light theme variants of each diagram, each with identical marker IDs (e.g., `#arrowhead`). When mermaid renders SVGs at runtime, lines reference `url(#arrowhead)`, but the browser resolves this to the first match in document order — the hidden dark-theme SVG — causing arrows to be invisible. The fix removes dark-theme `<div class="mermaid dark">` elements at build time, leaving only one SVG per diagram with unique marker IDs. A CSS filter (`filter: invert(1) hue-rotate(180deg)`) handles dark mode styling instead. Co-Authored-By: Claude Opus 4.5 <[email protected]> * fix(docs): improve OpenAI migration guide accuracy (#349) - Add missing setOpenInAppUrl API to 'Not Yet in MCP Apps' section - Clarify Event Handling table: specify exact OpenAI properties (toolInput/toolOutput) instead of vague 'window.openai.*' - Improve notes to distinguish sync property reads vs callbacks * Add Testing MCP Apps guide Document how to test MCP Apps using `basic-host` and MCP Apps-compatible hosts like Claude.ai and VS Code Copilot. Cover debugging features for `basic-host`, and using `cloudflared` to expose local servers for remote hosts. Co-Authored-By: Claude Opus 4.5 <[email protected]> * Fix `onhostcontextchanged` handler invocation in examples `App.onhostcontextchanged` is a setter-only property with no getter. TypeScript doesn't prevent reading from setter-only properties, so `app.onhostcontextchanged?.(ctx)` compiles but silently returns `undefined` at runtime. Extract the handler into a named `handleHostContextChanged()` function and call it directly after `connect()`, matching the pattern used in `basic-server-vanillajs` and other examples. Co-Authored-By: Claude Opus 4.5 <[email protected]> * Expand Agent Skills guide Add intro explaining what Agent Skills are and link to the two skill files (`create-mcp-app`, `migrate-oai-app`). Reorganize headings and add "Invoke a Skill" and "Test Your App" sections. Update `README.md` link text and add tip to quickstart suggesting agent skills as an alternative. Co-Authored-By: Claude Opus 4.5 <[email protected]> * fix(e2e): improve test stability and developer experience (#337) * fix(e2e): add masks for dynamic content and increase timeouts for slow servers - Add HOST_MASKS for Tool Input/Result panels with dynamic timestamps - Add say-server to SLOW_SERVERS (10s) for TTS model download - Add say-server to EXTRA_WAIT_MS (30s) in generate-grid-screenshots * feat: add update-lock:docker script to regenerate lockfile with public registry * pin package versions for dev compatibility * feat(basic-host): add ?theme=hide query param to hide theme toggle in screenshots - Add hideThemeToggle param to getQueryParams() - Conditionally render ThemeToggle based on ?theme=hide - Update e2e tests to use ?theme=hide for consistent screenshots * update screenshots * update screenshots * fix(husky): load Node.js environment for GUI apps like GitHub Desktop * fix(e2e): increase map-server wait time to 15s for tile loading * fix(e2e): increase waitForAppLoad timeout to 30s for nested iframe loading * ci: add workflow to update e2e snapshots * ci: trigger snapshot update on push to this branch * chore: update e2e snapshots [skip ci] * ci: trigger CI after snapshot update * style: fix prettier formatting in update-snapshots workflow * fix: pin seroval, seroval-plugins, and solid-js for dev compatibility --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * Improve README structure and clarity Add "Why MCP Apps?" section to explain the motivation upfront. Reorganize the "How It Works" section to lead with tool definition. Rename "Overview" to "Using the SDK" and add "For" prefix to audience headings. Restructure the Examples section with clearer subsections for running examples with `basic-host` vs MCP clients using stdio transport. Move the `qr` server note outside the collapsed details block. Co-Authored-By: Claude Opus 4.5 <[email protected]> * Add Codex and Goose to documentation Add Codex to the list of agents supporting skills in `agent-skills.md`. Add Goose to the list of supported clients in `testing-mcp-apps.md` and rename "VS Code Copilot" to "VS Code (Insiders)" for accuracy. Co-Authored-By: Claude Opus 4.5 <[email protected]> * chore: regenerate lockfile with public registry, use ^0.4.2 for ext-apps deps * fix: update quickstart example to use workspace reference * chore: remove internal registry references from lockfile * feat(ci): add /update-snapshots comment trigger for PRs - Comment '/update-snapshots' on any PR to update E2E snapshots - Adds rocket reaction to acknowledge the command - Comments back with result (updated or no changes needed) - Removes hardcoded branch trigger - Keeps workflow_dispatch for manual runs * docs: document /update-snapshots PR comment trigger * fix: pin @hono/node-server to 1.19.7 for dev compatibility SDK 1.25.3 requires @hono/node-server@^1.19.9 which doesn't exist on the public npm registry (latest is 1.19.7). * fix: pin @modelcontextprotocol/sdk to 1.25.2 SDK 1.25.3 has broken dependency on @hono/node-server@^1.19.9 which doesn't exist on public npm registry. * fix: restore flexible SDK peerDep range (^1.24.0) devDependencies stays pinned to 1.25.2 for our builds, but peerDependencies should allow users flexibility. * fix: pin @types/node to avoid unpublished versions - Pin quickstart @types/node to 22.19.5 (latest public 22.x) - Add @types/node override to root package.json - Regenerate lockfile with public registry only --------- Co-authored-by: Tobin South <[email protected]> Co-authored-by: Liad Yosef <[email protected]> Co-authored-by: Claude <[email protected]> Co-authored-by: martinalong <[email protected]> Co-authored-by: Ido Salomon <[email protected]> Co-authored-by: Jonathan Hefner <[email protected]> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Document the availableDisplayModes field in McpUiAppCapabilities that allows apps to declare which display modes they support. This enables hosts to compute the intersection of host and app capabilities and only offer appropriate display mode controls.