[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 <noreply@anthropic.com> * 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 <noreply@anthropic.com> * 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 <noreply@anthropic.com> * 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 <noreply@anthropic.com> * 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 <noreply@anthropic.com> * 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 <noreply@anthropic.com> * Remove mode coercion clause from display modes 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * Regenerate schemas with correct version 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
parent
7bbf2bb250
commit
89f58bf555
4 changed files with 174 additions and 14 deletions
|
|
@ -505,6 +505,27 @@ UI iframes can use the following subset of standard MCP protocol messages:
|
|||
- `ui/initialize` → `ui/notifications/initialized` - MCP-like handshake (replaces custom iframe-ready pattern in MCP-UI)
|
||||
- `ping` - Connection health check
|
||||
|
||||
### App Capabilities in `ui/initialize`
|
||||
|
||||
When the View sends an `ui/initialize` request to the Host, it MUST include its capabilities in the `appCapabilities` field:
|
||||
|
||||
```typescript
|
||||
interface McpUiAppCapabilities {
|
||||
/** Experimental features (structure TBD). */
|
||||
experimental?: {};
|
||||
/** App exposes MCP-style tools that the host can call. */
|
||||
tools?: {
|
||||
/** App supports tools/list_changed notifications. */
|
||||
listChanged?: boolean;
|
||||
};
|
||||
/**
|
||||
* Display modes the app supports. See Display Modes section for details.
|
||||
* @example ["inline", "fullscreen"]
|
||||
*/
|
||||
availableDisplayModes?: Array<"inline" | "fullscreen" | "pip">;
|
||||
}
|
||||
```
|
||||
|
||||
### Host Context in `McpUiInitializeResult`
|
||||
|
||||
When the View sends an `ui/initialize` request to the Host, the Host SHOULD include UI-specific context in the `McpUiInitializeResult`'s `hostContext` field:
|
||||
|
|
@ -709,6 +730,62 @@ bridge.onsizechange = ({ width, height }) => {
|
|||
|
||||
Apps using the SDK automatically send size-changed notifications via ResizeObserver when `autoResize` is enabled (the default). The notifications are debounced and only sent when dimensions actually change.
|
||||
|
||||
### Display Modes
|
||||
|
||||
Views can be displayed in different modes depending on the host's capabilities and the view's declared support.
|
||||
|
||||
```typescript
|
||||
type McpUiDisplayMode = "inline" | "fullscreen" | "pip";
|
||||
```
|
||||
|
||||
- **inline**: Default mode, embedded within the host's content flow
|
||||
- **fullscreen**: View takes over the full screen/window
|
||||
- **pip**: Picture-in-picture, floating overlay
|
||||
|
||||
#### Declaring Support
|
||||
|
||||
**View (`appCapabilities.availableDisplayModes`):**
|
||||
|
||||
Views declare which display modes they support in the `ui/initialize` request via `appCapabilities.availableDisplayModes`. This allows hosts to only offer display mode options that the view can handle.
|
||||
|
||||
```typescript
|
||||
// Example: View declares support for inline and fullscreen
|
||||
{
|
||||
method: "ui/initialize",
|
||||
params: {
|
||||
appCapabilities: {
|
||||
availableDisplayModes: ["inline", "fullscreen"]
|
||||
},
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Host (`HostContext.availableDisplayModes`):**
|
||||
|
||||
Hosts declare which display modes they support in `HostContext.availableDisplayModes`. Views should check this before requesting a mode change.
|
||||
|
||||
#### Requesting Changes
|
||||
|
||||
Views request display mode changes via `ui/request-display-mode`. See the Requests section for message format.
|
||||
|
||||
#### Notifying Changes
|
||||
|
||||
Hosts notify views of display mode changes via `ui/notifications/host-context-changed` with the `displayMode` field.
|
||||
|
||||
#### Requirements
|
||||
|
||||
**View behavior:**
|
||||
- View MUST declare all display modes it supports in `appCapabilities.availableDisplayModes` during initialization.
|
||||
- View MUST check if the requested mode is in `availableDisplayModes` from host context before requesting a mode change.
|
||||
- View MUST handle the response mode differing from the requested mode.
|
||||
|
||||
**Host behavior:**
|
||||
- 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 decline display mode requests from Views that did not declare said modes in their capabilities.
|
||||
|
||||
### Theming
|
||||
|
||||
Hosts can optionally pass CSS custom properties via `HostContext.styles.variables` for visual cohesion with the host environment.
|
||||
|
|
@ -977,15 +1054,7 @@ Host behavior:
|
|||
}
|
||||
```
|
||||
|
||||
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.
|
||||
See the Display Modes section for detailed behavior requirements.
|
||||
|
||||
`ui/update-model-context` - Update the model context
|
||||
|
||||
|
|
|
|||
90
src/generated/schema.json
generated
90
src/generated/schema.json
generated
|
|
@ -24,6 +24,27 @@
|
|||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"availableDisplayModes": {
|
||||
"description": "Display modes the app supports.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"const": "inline"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"const": "fullscreen"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"const": "pip"
|
||||
}
|
||||
],
|
||||
"description": "Display mode for UI presentation."
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
|
|
@ -882,7 +903,21 @@
|
|||
"description": "Display modes the host supports.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"const": "inline"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"const": "fullscreen"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"const": "pip"
|
||||
}
|
||||
],
|
||||
"description": "Display mode for UI presentation."
|
||||
}
|
||||
},
|
||||
"containerDimensions": {
|
||||
|
|
@ -1635,7 +1670,21 @@
|
|||
"description": "Display modes the host supports.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"const": "inline"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"const": "fullscreen"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"const": "pip"
|
||||
}
|
||||
],
|
||||
"description": "Display mode for UI presentation."
|
||||
}
|
||||
},
|
||||
"containerDimensions": {
|
||||
|
|
@ -2284,6 +2333,27 @@
|
|||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"availableDisplayModes": {
|
||||
"description": "Display modes the app supports.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"const": "inline"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"const": "fullscreen"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"const": "pip"
|
||||
}
|
||||
],
|
||||
"description": "Display mode for UI presentation."
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
|
|
@ -3172,7 +3242,21 @@
|
|||
"description": "Display modes the host supports.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"const": "inline"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"const": "fullscreen"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"const": "pip"
|
||||
}
|
||||
],
|
||||
"description": "Display mode for UI presentation."
|
||||
}
|
||||
},
|
||||
"containerDimensions": {
|
||||
|
|
|
|||
7
src/generated/schema.ts
generated
7
src/generated/schema.ts
generated
|
|
@ -470,6 +470,11 @@ export const McpUiAppCapabilitiesSchema = z.object({
|
|||
})
|
||||
.optional()
|
||||
.describe("App exposes MCP-style tools that the host can call."),
|
||||
/** @description Display modes the app supports. */
|
||||
availableDisplayModes: z
|
||||
.array(McpUiDisplayModeSchema)
|
||||
.optional()
|
||||
.describe("Display modes the app supports."),
|
||||
});
|
||||
|
||||
/**
|
||||
|
|
@ -668,7 +673,7 @@ export const McpUiHostContextSchema = z
|
|||
),
|
||||
/** @description Display modes the host supports. */
|
||||
availableDisplayModes: z
|
||||
.array(z.string())
|
||||
.array(McpUiDisplayModeSchema)
|
||||
.optional()
|
||||
.describe("Display modes the host supports."),
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -321,7 +321,7 @@ export interface McpUiHostContext {
|
|||
/** @description How the UI is currently displayed. */
|
||||
displayMode?: McpUiDisplayMode;
|
||||
/** @description Display modes the host supports. */
|
||||
availableDisplayModes?: string[];
|
||||
availableDisplayModes?: McpUiDisplayMode[];
|
||||
/**
|
||||
* @description Container dimensions. Represents the dimensions of the iframe or other
|
||||
* container holding the app. Specify either width or maxWidth, and either height or maxHeight.
|
||||
|
|
@ -487,6 +487,8 @@ export interface McpUiAppCapabilities {
|
|||
/** @description App supports tools/list_changed notifications. */
|
||||
listChanged?: boolean;
|
||||
};
|
||||
/** @description Display modes the app supports. */
|
||||
availableDisplayModes?: McpUiDisplayMode[];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in a new issue