Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 121 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

42 changes: 42 additions & 0 deletions specification/draft/apps.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,48 @@ MCP Apps introduces additional JSON-RPC methods for UI-specific functionality:

Host SHOULD open the URL in the user's default browser or a new tab.

`ui/request-display-mode` - Request display mode change

```typescript
// Request
{
jsonrpc: "2.0",
id: 2,
method: "ui/request-display-mode",
params: {
displayMode: "inline" | "fullscreen" | "pip"
}
}

// Success Response
{
jsonrpc: "2.0",
id: 2,
result: {
success: boolean, // Whether the request was honored
currentDisplayMode: string // The actual display mode after the request
}
}

// Error Response (if denied or failed)
{
jsonrpc: "2.0",
id: 2,
error: {
code: -32000, // Implementation-defined error
message: "Display mode change denied" | "Unsupported display mode"
}
}
```

Guest UI can request a display mode change from the Host. The Host maintains full control and MAY deny the request based on:
- User preferences or policies
- Platform constraints (e.g., mobile platforms may not support fullscreen)
- Current application state
- Security considerations

The Host MUST return `success: true` if the request was honored. If denied, the Host MUST return `success: false`. The Host SHOULD return the updated `currentDisplayMode`. The Host MAY send a `ui/notifications/host-context-changed` notification after honoring the request to update all context fields.

`ui/message` - Send message content to the host's chat interface

```typescript
Expand Down
45 changes: 45 additions & 0 deletions src/app-bridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ import {
McpUiOpenLinkRequest,
McpUiOpenLinkRequestSchema,
McpUiOpenLinkResult,
McpUiRequestDisplayModeRequest,
McpUiRequestDisplayModeRequestSchema,
McpUiRequestDisplayModeResult,
McpUiResourceTeardownRequest,
McpUiResourceTeardownResult,
McpUiResourceTeardownResultSchema,
Expand Down Expand Up @@ -494,6 +497,48 @@ export class AppBridge extends Protocol<
);
}

/**
* Register a handler for display mode requests from the Guest UI.
*
* The Guest UI sends `ui/request-display-mode` requests when it wants to change
* its display mode (e.g., fullscreen, picture-in-picture). The handler should
* evaluate the request based on the host's capabilities and user preferences,
* then return the result indicating success or denial.
*
* @param callback - Handler that receives display mode params and returns a result
* - params.displayMode - Requested display mode ("inline", "fullscreen", "pip")
* - extra - Request metadata (abort signal, session info)
* - Returns: Promise<McpUiRequestDisplayModeResult> with success flag and current mode
*
* @example
* ```typescript
* bridge.onrequestdisplaymode = async ({ displayMode }, extra) => {
* if (displayMode === "fullscreen" && !hostSupportsFullscreen()) {
* return { success: false, currentDisplayMode: "inline" };
* }
*
* await setAppDisplayMode(displayMode);
* return { success: true, currentDisplayMode: displayMode };
* };
* ```
*
* @see {@link McpUiRequestDisplayModeRequest} for the request type
* @see {@link McpUiRequestDisplayModeResult} for the result type
*/
set onrequestdisplaymode(
callback: (
params: McpUiRequestDisplayModeRequest["params"],
extra: RequestHandlerExtra,
) => Promise<McpUiRequestDisplayModeResult>,
) {
this.setRequestHandler(
McpUiRequestDisplayModeRequestSchema,
async (request, extra) => {
return callback(request.params, extra);
},
);
}

/**
* Register a handler for logging messages from the Guest UI.
*
Expand Down
44 changes: 44 additions & 0 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ import {
McpUiMessageResultSchema,
McpUiOpenLinkRequest,
McpUiOpenLinkResultSchema,
McpUiRequestDisplayModeRequest,
McpUiRequestDisplayModeResultSchema,
McpUiResourceTeardownRequest,
McpUiResourceTeardownRequestSchema,
McpUiResourceTeardownResult,
Expand Down Expand Up @@ -839,6 +841,48 @@ export class App extends Protocol<AppRequest, AppNotification, AppResult> {
);
}

/**
* Request the host to change the app's display mode.
*
* Apps can request different display modes (inline, fullscreen, pip) to optimize
* their UI for various contexts. The host may accept or reject the request based
* on user preferences or platform capabilities.
*
* @param params - Desired display mode
* @param options - Request options (timeout, etc.)
* @returns Result indicating success and the current display mode
*
* @throws {Error} If the host denies the request (e.g., unsupported mode)
* @throws {Error} If the request times out or the connection is lost
*
* @example Request fullscreen mode
* ```typescript
* try {
* const result = await app.requestDisplayMode({ displayMode: "fullscreen" });
* if (result.success) {
* console.log("Now in", result.currentDisplayMode, "mode");
* }
* } catch (error) {
* console.error("Failed to change display mode:", error);
* }
* ```
*
* @see {@link McpUiRequestDisplayModeRequest} for request structure
*/
requestDisplayMode(
params: McpUiRequestDisplayModeRequest["params"],
options?: RequestOptions,
) {
return this.request(
<McpUiRequestDisplayModeRequest>{
method: "ui/request-display-mode",
params,
},
McpUiRequestDisplayModeResultSchema,
options,
);
}

/**
* Notify the host of UI size changes.
*
Expand Down
52 changes: 52 additions & 0 deletions src/generated/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1545,6 +1545,58 @@
},
"additionalProperties": {}
},
"McpUiRequestDisplayModeRequest": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"method": {
"type": "string",
"const": "ui/request-display-mode"
},
"params": {
"type": "object",
"properties": {
"displayMode": {
"description": "Requested display mode.",
"anyOf": [
{
"type": "string",
"const": "inline"
},
{
"type": "string",
"const": "fullscreen"
},
{
"type": "string",
"const": "pip"
}
]
}
},
"required": ["displayMode"],
"additionalProperties": false
}
},
"required": ["method", "params"],
"additionalProperties": false
},
"McpUiRequestDisplayModeResult": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"success": {
"description": "Whether the display mode change was successful.",
"type": "boolean"
},
"currentDisplayMode": {
"description": "The current display mode after the request.",
"type": "string"
}
},
"required": ["success", "currentDisplayMode"],
"additionalProperties": {}
},
"McpUiResourceCsp": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
Expand Down
20 changes: 20 additions & 0 deletions src/generated/schema.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ export type McpUiOpenLinkResultSchemaInferredType = z.infer<
typeof generated.McpUiOpenLinkResultSchema
>;

export type McpUiRequestDisplayModeRequestSchemaInferredType = z.infer<
typeof generated.McpUiRequestDisplayModeRequestSchema
>;

export type McpUiRequestDisplayModeResultSchemaInferredType = z.infer<
typeof generated.McpUiRequestDisplayModeResultSchema
>;

export type McpUiMessageResultSchemaInferredType = z.infer<
typeof generated.McpUiMessageResultSchema
>;
Expand Down Expand Up @@ -123,6 +131,18 @@ expectType<spec.McpUiOpenLinkResult>(
expectType<McpUiOpenLinkResultSchemaInferredType>(
{} as spec.McpUiOpenLinkResult,
);
expectType<spec.McpUiRequestDisplayModeRequest>(
{} as McpUiRequestDisplayModeRequestSchemaInferredType,
);
expectType<McpUiRequestDisplayModeRequestSchemaInferredType>(
{} as spec.McpUiRequestDisplayModeRequest,
);
expectType<spec.McpUiRequestDisplayModeResult>(
{} as McpUiRequestDisplayModeResultSchemaInferredType,
);
expectType<McpUiRequestDisplayModeResultSchemaInferredType>(
{} as spec.McpUiRequestDisplayModeResult,
);
expectType<spec.McpUiMessageResult>({} as McpUiMessageResultSchemaInferredType);
expectType<McpUiMessageResultSchemaInferredType>({} as spec.McpUiMessageResult);
expectType<spec.McpUiSandboxProxyReadyNotification>(
Expand Down
Loading
Loading