Updating viewport type and documentation
This commit is contained in:
parent
e514e6c745
commit
93b9da9e7a
6 changed files with 342 additions and 180 deletions
|
|
@ -461,13 +461,18 @@ interface HostContext {
|
||||||
displayMode?: "inline" | "fullscreen" | "pip";
|
displayMode?: "inline" | "fullscreen" | "pip";
|
||||||
/** Display modes the host supports */
|
/** Display modes the host supports */
|
||||||
availableDisplayModes?: string[];
|
availableDisplayModes?: string[];
|
||||||
/** Current and maximum dimensions available to the UI */
|
/**
|
||||||
viewport?: {
|
* Viewport dimensions available to the UI.
|
||||||
width: number;
|
*
|
||||||
height: number;
|
* The viewport has two independent dimension pairs:
|
||||||
maxHeight?: number;
|
* - Height: Either `height` (fixed) or `maxHeight` (flexible), never both
|
||||||
maxWidth?: number;
|
* - Width: Either `width` (fixed) or `maxWidth` (flexible), never both
|
||||||
};
|
*
|
||||||
|
* Fixed dimensions (height/width): The host controls the size. Set height: 100% (recommended) or use the pixel value directly.
|
||||||
|
* Flexible dimensions (maxHeight/maxWidth or undefined): The app controls the size, up to the max if specified.
|
||||||
|
*/
|
||||||
|
viewport?: ({ height: number } | { maxHeight?: number }) &
|
||||||
|
({ width: number } | { maxWidth?: number });
|
||||||
/** User's language/region preference (BCP 47, e.g., "en-US") */
|
/** User's language/region preference (BCP 47, e.g., "en-US") */
|
||||||
locale?: string;
|
locale?: string;
|
||||||
/** User's timezone (IANA, e.g., "America/New_York") */
|
/** User's timezone (IANA, e.g., "America/New_York") */
|
||||||
|
|
@ -516,12 +521,76 @@ Example:
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"displayMode": "inline",
|
"displayMode": "inline",
|
||||||
"viewport": { "width": 400, "height": 300 }
|
"viewport": { "width": 400, "maxHeight": 600 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Viewport and Sizing
|
||||||
|
|
||||||
|
The `viewport` field in `HostContext` communicates sizing constraints between host and app. Each dimension (height and width) operates independently and can be either **fixed** or **flexible**.
|
||||||
|
|
||||||
|
#### Viewport Modes
|
||||||
|
|
||||||
|
| Mode | Viewport Field | Meaning |
|
||||||
|
|------|---------------|---------|
|
||||||
|
| Fixed | `height` or `width` | Host controls the size. App should fill the available space. |
|
||||||
|
| Flexible | `maxHeight` or `maxWidth` | App controls the size, up to the specified maximum. |
|
||||||
|
| Unbounded | Field omitted | App controls the size with no limit. |
|
||||||
|
|
||||||
|
These modes can be combined independently. For example, a host might specify a fixed width but flexible height, allowing the app to grow vertically based on content.
|
||||||
|
|
||||||
|
#### App Behavior
|
||||||
|
|
||||||
|
Apps should check the viewport configuration and apply appropriate CSS:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// In the app's initialization
|
||||||
|
const viewport = hostContext.viewport;
|
||||||
|
|
||||||
|
if (viewport) {
|
||||||
|
// Handle height
|
||||||
|
if ("height" in viewport) {
|
||||||
|
// Fixed height: fill the container
|
||||||
|
document.body.style.height = "100%";
|
||||||
|
} else if (viewport.maxHeight) {
|
||||||
|
// Flexible with max: let content determine size, up to max
|
||||||
|
document.body.style.maxHeight = `${viewport.maxHeight}px`;
|
||||||
|
}
|
||||||
|
// If neither, height is unbounded
|
||||||
|
|
||||||
|
// Handle width
|
||||||
|
if ("width" in viewport) {
|
||||||
|
// Fixed width: fill the container
|
||||||
|
document.body.style.width = "100%";
|
||||||
|
} else if (viewport.maxWidth) {
|
||||||
|
// Flexible with max: let content determine size, up to max
|
||||||
|
document.body.style.maxWidth = `${viewport.maxWidth}px`;
|
||||||
|
}
|
||||||
|
// If neither, width is unbounded
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Host Behavior
|
||||||
|
|
||||||
|
When using flexible dimensions (no fixed `height` or `width`), hosts MUST listen for `ui/notifications/size-changed` notifications from the app and update the iframe dimensions accordingly:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Host listens for size changes from the app
|
||||||
|
bridge.onsizechange = ({ width, height }) => {
|
||||||
|
// Update iframe to match app's content size
|
||||||
|
if (width != null) {
|
||||||
|
iframe.style.width = `${width}px`;
|
||||||
|
}
|
||||||
|
if (height != null) {
|
||||||
|
iframe.style.height = `${height}px`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
### Theming
|
### Theming
|
||||||
|
|
||||||
Hosts can optionally pass CSS custom properties via `HostContext.styles.variables` for visual cohesion with the host environment.
|
Hosts can optionally pass CSS custom properties via `HostContext.styles.variables` for visual cohesion with the host environment.
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,7 @@ describe("App <-> AppBridge integration", () => {
|
||||||
const testHostContext = {
|
const testHostContext = {
|
||||||
theme: "dark" as const,
|
theme: "dark" as const,
|
||||||
locale: "en-US",
|
locale: "en-US",
|
||||||
viewport: { width: 800, height: 600 },
|
viewport: { width: 800, maxHeight: 600 },
|
||||||
};
|
};
|
||||||
const newBridge = new AppBridge(
|
const newBridge = new AppBridge(
|
||||||
createMockClient() as Client,
|
createMockClient() as Client,
|
||||||
|
|
@ -337,7 +337,7 @@ describe("App <-> AppBridge integration", () => {
|
||||||
const initialContext = {
|
const initialContext = {
|
||||||
theme: "light" as const,
|
theme: "light" as const,
|
||||||
locale: "en-US",
|
locale: "en-US",
|
||||||
viewport: { width: 800, height: 600 },
|
viewport: { width: 800, maxHeight: 600 },
|
||||||
};
|
};
|
||||||
const newBridge = new AppBridge(
|
const newBridge = new AppBridge(
|
||||||
createMockClient() as Client,
|
createMockClient() as Client,
|
||||||
|
|
@ -356,7 +356,7 @@ describe("App <-> AppBridge integration", () => {
|
||||||
|
|
||||||
// Send another partial update: only viewport changes
|
// Send another partial update: only viewport changes
|
||||||
newBridge.sendHostContextChange({
|
newBridge.sendHostContextChange({
|
||||||
viewport: { width: 1024, height: 768 },
|
viewport: { width: 1024, maxHeight: 768 },
|
||||||
});
|
});
|
||||||
await flush();
|
await flush();
|
||||||
|
|
||||||
|
|
@ -367,7 +367,7 @@ describe("App <-> AppBridge integration", () => {
|
||||||
const context = newApp.getHostContext();
|
const context = newApp.getHostContext();
|
||||||
expect(context?.theme).toBe("dark");
|
expect(context?.theme).toBe("dark");
|
||||||
expect(context?.locale).toBe("en-US");
|
expect(context?.locale).toBe("en-US");
|
||||||
expect(context?.viewport).toEqual({ width: 1024, height: 768 });
|
expect(context?.viewport).toEqual({ width: 1024, maxHeight: 768 });
|
||||||
|
|
||||||
await newAppTransport.close();
|
await newAppTransport.close();
|
||||||
await newBridgeTransport.close();
|
await newBridgeTransport.close();
|
||||||
|
|
|
||||||
|
|
@ -1008,7 +1008,7 @@ export class AppBridge extends Protocol<
|
||||||
* ```typescript
|
* ```typescript
|
||||||
* bridge.setHostContext({
|
* bridge.setHostContext({
|
||||||
* theme: "dark",
|
* theme: "dark",
|
||||||
* viewport: { width: 800, height: 600 }
|
* viewport: { width: 800, maxHeight: 600 }
|
||||||
* });
|
* });
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
|
|
|
||||||
201
src/generated/schema.json
generated
201
src/generated/schema.json
generated
|
|
@ -629,28 +629,55 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"description": "Current and maximum dimensions available to the UI.",
|
"description": "Viewport dimensions available to the UI.\n\nThe viewport has two independent dimension pairs:\n- Height: Either `height` (fixed) or `maxHeight` (flexible), never both\n- Width: Either `width` (fixed) or `maxWidth` (flexible), never both\n\nFixed dimensions (height/width): The host controls the size. Set height: 100% (recommended) or use the pixel value directly.\nFlexible dimensions (maxHeight/maxWidth or undefined): The app controls the size, up to the max if specified. If undefined, there is no limit.",
|
||||||
"type": "object",
|
"allOf": [
|
||||||
"properties": {
|
{
|
||||||
"width": {
|
"anyOf": [
|
||||||
"description": "Current viewport width in pixels.",
|
{
|
||||||
"type": "number"
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"height": {
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["height"],
|
||||||
|
"additionalProperties": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"maxHeight": {
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"height": {
|
{
|
||||||
"description": "Current viewport height in pixels.",
|
"anyOf": [
|
||||||
"type": "number"
|
{
|
||||||
},
|
"type": "object",
|
||||||
"maxHeight": {
|
"properties": {
|
||||||
"description": "Maximum available height in pixels (if constrained).",
|
"width": {
|
||||||
"type": "number"
|
"type": "number"
|
||||||
},
|
}
|
||||||
"maxWidth": {
|
},
|
||||||
"description": "Maximum available width in pixels (if constrained).",
|
"required": ["width"],
|
||||||
"type": "number"
|
"additionalProperties": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"maxWidth": {
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
]
|
||||||
"required": ["width", "height"],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
},
|
||||||
"locale": {
|
"locale": {
|
||||||
"description": "User's language and region preference in BCP 47 format.",
|
"description": "User's language and region preference in BCP 47 format.",
|
||||||
|
|
@ -1255,28 +1282,55 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"description": "Current and maximum dimensions available to the UI.",
|
"description": "Viewport dimensions available to the UI.\n\nThe viewport has two independent dimension pairs:\n- Height: Either `height` (fixed) or `maxHeight` (flexible), never both\n- Width: Either `width` (fixed) or `maxWidth` (flexible), never both\n\nFixed dimensions (height/width): The host controls the size. Set height: 100% (recommended) or use the pixel value directly.\nFlexible dimensions (maxHeight/maxWidth or undefined): The app controls the size, up to the max if specified. If undefined, there is no limit.",
|
||||||
"type": "object",
|
"allOf": [
|
||||||
"properties": {
|
{
|
||||||
"width": {
|
"anyOf": [
|
||||||
"description": "Current viewport width in pixels.",
|
{
|
||||||
"type": "number"
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"height": {
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["height"],
|
||||||
|
"additionalProperties": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"maxHeight": {
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"height": {
|
{
|
||||||
"description": "Current viewport height in pixels.",
|
"anyOf": [
|
||||||
"type": "number"
|
{
|
||||||
},
|
"type": "object",
|
||||||
"maxHeight": {
|
"properties": {
|
||||||
"description": "Maximum available height in pixels (if constrained).",
|
"width": {
|
||||||
"type": "number"
|
"type": "number"
|
||||||
},
|
}
|
||||||
"maxWidth": {
|
},
|
||||||
"description": "Maximum available width in pixels (if constrained).",
|
"required": ["width"],
|
||||||
"type": "number"
|
"additionalProperties": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"maxWidth": {
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
]
|
||||||
"required": ["width", "height"],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
},
|
||||||
"locale": {
|
"locale": {
|
||||||
"description": "User's language and region preference in BCP 47 format.",
|
"description": "User's language and region preference in BCP 47 format.",
|
||||||
|
|
@ -2414,28 +2468,55 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"description": "Current and maximum dimensions available to the UI.",
|
"description": "Viewport dimensions available to the UI.\n\nThe viewport has two independent dimension pairs:\n- Height: Either `height` (fixed) or `maxHeight` (flexible), never both\n- Width: Either `width` (fixed) or `maxWidth` (flexible), never both\n\nFixed dimensions (height/width): The host controls the size. Set height: 100% (recommended) or use the pixel value directly.\nFlexible dimensions (maxHeight/maxWidth or undefined): The app controls the size, up to the max if specified. If undefined, there is no limit.",
|
||||||
"type": "object",
|
"allOf": [
|
||||||
"properties": {
|
{
|
||||||
"width": {
|
"anyOf": [
|
||||||
"description": "Current viewport width in pixels.",
|
{
|
||||||
"type": "number"
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"height": {
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["height"],
|
||||||
|
"additionalProperties": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"maxHeight": {
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"height": {
|
{
|
||||||
"description": "Current viewport height in pixels.",
|
"anyOf": [
|
||||||
"type": "number"
|
{
|
||||||
},
|
"type": "object",
|
||||||
"maxHeight": {
|
"properties": {
|
||||||
"description": "Maximum available height in pixels (if constrained).",
|
"width": {
|
||||||
"type": "number"
|
"type": "number"
|
||||||
},
|
}
|
||||||
"maxWidth": {
|
},
|
||||||
"description": "Maximum available width in pixels (if constrained).",
|
"required": ["width"],
|
||||||
"type": "number"
|
"additionalProperties": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"maxWidth": {
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
]
|
||||||
"required": ["width", "height"],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
},
|
||||||
"locale": {
|
"locale": {
|
||||||
"description": "User's language and region preference in BCP 47 format.",
|
"description": "User's language and region preference in BCP 47 format.",
|
||||||
|
|
|
||||||
203
src/generated/schema.ts
generated
203
src/generated/schema.ts
generated
|
|
@ -532,103 +532,114 @@ export const McpUiToolResultNotificationSchema = z.object({
|
||||||
/**
|
/**
|
||||||
* @description Rich context about the host environment provided to Guest UIs.
|
* @description Rich context about the host environment provided to Guest UIs.
|
||||||
*/
|
*/
|
||||||
export const McpUiHostContextSchema = z
|
export const McpUiHostContextSchema = z.looseObject({
|
||||||
.object({
|
/** @description Metadata of the tool call that instantiated this App. */
|
||||||
/** @description Metadata of the tool call that instantiated this App. */
|
toolInfo: z
|
||||||
toolInfo: z
|
.object({
|
||||||
.object({
|
/** @description JSON-RPC id of the tools/call request. */
|
||||||
/** @description JSON-RPC id of the tools/call request. */
|
id: RequestIdSchema.describe("JSON-RPC id of the tools/call request."),
|
||||||
id: RequestIdSchema.describe("JSON-RPC id of the tools/call request."),
|
/** @description Tool definition including name, inputSchema, etc. */
|
||||||
/** @description Tool definition including name, inputSchema, etc. */
|
tool: ToolSchema.describe(
|
||||||
tool: ToolSchema.describe(
|
"Tool definition including name, inputSchema, etc.",
|
||||||
"Tool definition including name, inputSchema, etc.",
|
),
|
||||||
),
|
})
|
||||||
})
|
.optional()
|
||||||
.optional()
|
.describe("Metadata of the tool call that instantiated this App."),
|
||||||
.describe("Metadata of the tool call that instantiated this App."),
|
/** @description Current color theme preference. */
|
||||||
/** @description Current color theme preference. */
|
theme: McpUiThemeSchema.optional().describe(
|
||||||
theme: McpUiThemeSchema.optional().describe(
|
"Current color theme preference.",
|
||||||
"Current color theme preference.",
|
),
|
||||||
|
/** @description Style configuration for theming the app. */
|
||||||
|
styles: McpUiHostStylesSchema.optional().describe(
|
||||||
|
"Style configuration for theming the app.",
|
||||||
|
),
|
||||||
|
/** @description How the UI is currently displayed. */
|
||||||
|
displayMode: McpUiDisplayModeSchema.optional().describe(
|
||||||
|
"How the UI is currently displayed.",
|
||||||
|
),
|
||||||
|
/** @description Display modes the host supports. */
|
||||||
|
availableDisplayModes: z
|
||||||
|
.array(z.string())
|
||||||
|
.optional()
|
||||||
|
.describe("Display modes the host supports."),
|
||||||
|
/**
|
||||||
|
* @description Viewport dimensions available to the UI.
|
||||||
|
*
|
||||||
|
* The viewport has two independent dimension pairs:
|
||||||
|
* - Height: Either `height` (fixed) or `maxHeight` (flexible), never both
|
||||||
|
* - Width: Either `width` (fixed) or `maxWidth` (flexible), never both
|
||||||
|
*
|
||||||
|
* Fixed dimensions (height/width): The host controls the size. Set height: 100% (recommended) or use the pixel value directly.
|
||||||
|
* Flexible dimensions (maxHeight/maxWidth or undefined): The app controls the size, up to the max if specified. If undefined, there is no limit.
|
||||||
|
*/
|
||||||
|
viewport: z
|
||||||
|
.union([
|
||||||
|
z.object({
|
||||||
|
height: z.number(),
|
||||||
|
}),
|
||||||
|
z.object({
|
||||||
|
maxHeight: z.number().optional(),
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
.and(
|
||||||
|
z.union([
|
||||||
|
z.object({
|
||||||
|
width: z.number(),
|
||||||
|
}),
|
||||||
|
z.object({
|
||||||
|
maxWidth: z.number().optional(),
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
.optional()
|
||||||
|
.describe(
|
||||||
|
"Viewport dimensions available to the UI.\n\nThe viewport has two independent dimension pairs:\n- Height: Either `height` (fixed) or `maxHeight` (flexible), never both\n- Width: Either `width` (fixed) or `maxWidth` (flexible), never both\n\nFixed dimensions (height/width): The host controls the size. Set height: 100% (recommended) or use the pixel value directly.\nFlexible dimensions (maxHeight/maxWidth or undefined): The app controls the size, up to the max if specified. If undefined, there is no limit.",
|
||||||
),
|
),
|
||||||
/** @description Style configuration for theming the app. */
|
/** @description User's language and region preference in BCP 47 format. */
|
||||||
styles: McpUiHostStylesSchema.optional().describe(
|
locale: z
|
||||||
"Style configuration for theming the app.",
|
.string()
|
||||||
),
|
.optional()
|
||||||
/** @description How the UI is currently displayed. */
|
.describe("User's language and region preference in BCP 47 format."),
|
||||||
displayMode: McpUiDisplayModeSchema.optional().describe(
|
/** @description User's timezone in IANA format. */
|
||||||
"How the UI is currently displayed.",
|
timeZone: z.string().optional().describe("User's timezone in IANA format."),
|
||||||
),
|
/** @description Host application identifier. */
|
||||||
/** @description Display modes the host supports. */
|
userAgent: z.string().optional().describe("Host application identifier."),
|
||||||
availableDisplayModes: z
|
/** @description Platform type for responsive design decisions. */
|
||||||
.array(z.string())
|
platform: z
|
||||||
.optional()
|
.union([z.literal("web"), z.literal("desktop"), z.literal("mobile")])
|
||||||
.describe("Display modes the host supports."),
|
.optional()
|
||||||
/** @description Current and maximum dimensions available to the UI. */
|
.describe("Platform type for responsive design decisions."),
|
||||||
viewport: z
|
/** @description Device input capabilities. */
|
||||||
.object({
|
deviceCapabilities: z
|
||||||
/** @description Current viewport width in pixels. */
|
.object({
|
||||||
width: z.number().describe("Current viewport width in pixels."),
|
/** @description Whether the device supports touch input. */
|
||||||
/** @description Current viewport height in pixels. */
|
touch: z
|
||||||
height: z.number().describe("Current viewport height in pixels."),
|
.boolean()
|
||||||
/** @description Maximum available height in pixels (if constrained). */
|
.optional()
|
||||||
maxHeight: z
|
.describe("Whether the device supports touch input."),
|
||||||
.number()
|
/** @description Whether the device supports hover interactions. */
|
||||||
.optional()
|
hover: z
|
||||||
.describe("Maximum available height in pixels (if constrained)."),
|
.boolean()
|
||||||
/** @description Maximum available width in pixels (if constrained). */
|
.optional()
|
||||||
maxWidth: z
|
.describe("Whether the device supports hover interactions."),
|
||||||
.number()
|
})
|
||||||
.optional()
|
.optional()
|
||||||
.describe("Maximum available width in pixels (if constrained)."),
|
.describe("Device input capabilities."),
|
||||||
})
|
/** @description Mobile safe area boundaries in pixels. */
|
||||||
.optional()
|
safeAreaInsets: z
|
||||||
.describe("Current and maximum dimensions available to the UI."),
|
.object({
|
||||||
/** @description User's language and region preference in BCP 47 format. */
|
/** @description Top safe area inset in pixels. */
|
||||||
locale: z
|
top: z.number().describe("Top safe area inset in pixels."),
|
||||||
.string()
|
/** @description Right safe area inset in pixels. */
|
||||||
.optional()
|
right: z.number().describe("Right safe area inset in pixels."),
|
||||||
.describe("User's language and region preference in BCP 47 format."),
|
/** @description Bottom safe area inset in pixels. */
|
||||||
/** @description User's timezone in IANA format. */
|
bottom: z.number().describe("Bottom safe area inset in pixels."),
|
||||||
timeZone: z.string().optional().describe("User's timezone in IANA format."),
|
/** @description Left safe area inset in pixels. */
|
||||||
/** @description Host application identifier. */
|
left: z.number().describe("Left safe area inset in pixels."),
|
||||||
userAgent: z.string().optional().describe("Host application identifier."),
|
})
|
||||||
/** @description Platform type for responsive design decisions. */
|
.optional()
|
||||||
platform: z
|
.describe("Mobile safe area boundaries in pixels."),
|
||||||
.union([z.literal("web"), z.literal("desktop"), z.literal("mobile")])
|
});
|
||||||
.optional()
|
|
||||||
.describe("Platform type for responsive design decisions."),
|
|
||||||
/** @description Device input capabilities. */
|
|
||||||
deviceCapabilities: z
|
|
||||||
.object({
|
|
||||||
/** @description Whether the device supports touch input. */
|
|
||||||
touch: z
|
|
||||||
.boolean()
|
|
||||||
.optional()
|
|
||||||
.describe("Whether the device supports touch input."),
|
|
||||||
/** @description Whether the device supports hover interactions. */
|
|
||||||
hover: z
|
|
||||||
.boolean()
|
|
||||||
.optional()
|
|
||||||
.describe("Whether the device supports hover interactions."),
|
|
||||||
})
|
|
||||||
.optional()
|
|
||||||
.describe("Device input capabilities."),
|
|
||||||
/** @description Mobile safe area boundaries in pixels. */
|
|
||||||
safeAreaInsets: z
|
|
||||||
.object({
|
|
||||||
/** @description Top safe area inset in pixels. */
|
|
||||||
top: z.number().describe("Top safe area inset in pixels."),
|
|
||||||
/** @description Right safe area inset in pixels. */
|
|
||||||
right: z.number().describe("Right safe area inset in pixels."),
|
|
||||||
/** @description Bottom safe area inset in pixels. */
|
|
||||||
bottom: z.number().describe("Bottom safe area inset in pixels."),
|
|
||||||
/** @description Left safe area inset in pixels. */
|
|
||||||
left: z.number().describe("Left safe area inset in pixels."),
|
|
||||||
})
|
|
||||||
.optional()
|
|
||||||
.describe("Mobile safe area boundaries in pixels."),
|
|
||||||
})
|
|
||||||
.passthrough();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Notification that host context has changed (Host -> Guest UI).
|
* @description Notification that host context has changed (Host -> Guest UI).
|
||||||
|
|
|
||||||
|
|
@ -324,17 +324,18 @@ export interface McpUiHostContext {
|
||||||
displayMode?: McpUiDisplayMode;
|
displayMode?: McpUiDisplayMode;
|
||||||
/** @description Display modes the host supports. */
|
/** @description Display modes the host supports. */
|
||||||
availableDisplayModes?: string[];
|
availableDisplayModes?: string[];
|
||||||
/** @description Current and maximum dimensions available to the UI. */
|
/**
|
||||||
viewport?: {
|
* @description Viewport dimensions available to the UI.
|
||||||
/** @description Current viewport width in pixels. */
|
*
|
||||||
width: number;
|
* The viewport has two independent dimension pairs:
|
||||||
/** @description Current viewport height in pixels. */
|
* - Height: Either `height` (fixed) or `maxHeight` (flexible), never both
|
||||||
height: number;
|
* - Width: Either `width` (fixed) or `maxWidth` (flexible), never both
|
||||||
/** @description Maximum available height in pixels (if constrained). */
|
*
|
||||||
maxHeight?: number;
|
* Fixed dimensions (height/width): The host controls the size. Set height: 100% (recommended) or use the pixel value directly.
|
||||||
/** @description Maximum available width in pixels (if constrained). */
|
* Flexible dimensions (maxHeight/maxWidth or undefined): The app controls the size, up to the max if specified. If undefined, there is no limit.
|
||||||
maxWidth?: number;
|
*/
|
||||||
};
|
viewport?: ({ height: number } | { maxHeight?: number }) &
|
||||||
|
({ width: number } | { maxWidth?: number });
|
||||||
/** @description User's language and region preference in BCP 47 format. */
|
/** @description User's language and region preference in BCP 47 format. */
|
||||||
locale?: string;
|
locale?: string;
|
||||||
/** @description User's timezone in IANA format. */
|
/** @description User's timezone in IANA format. */
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue