From 67273903dbe6f33e46330b854f45e2d8a3a3c1a5 Mon Sep 17 00:00:00 2001 From: Ido Salomon Date: Wed, 10 Dec 2025 19:41:39 +0200 Subject: [PATCH 01/13] feat: add ui/update-context --- specification/draft/apps.mdx | 48 ++++- src/app-bridge.test.ts | 46 +++++ src/app-bridge.ts | 39 ++++ src/app.ts | 36 ++++ src/generated/schema.json | 360 +++++++++++++++++++++++++++++++++++ src/generated/schema.test.ts | 20 ++ src/generated/schema.ts | 44 +++++ src/spec.types.ts | 35 ++++ src/types.ts | 4 + 9 files changed, 629 insertions(+), 3 deletions(-) diff --git a/specification/draft/apps.mdx b/specification/draft/apps.mdx index 8ceae01d..7aeed253 100644 --- a/specification/draft/apps.mdx +++ b/specification/draft/apps.mdx @@ -379,7 +379,7 @@ UI iframes can use the following subset of standard MCP protocol messages: **Notifications:** -- `notifications/message` - Log messages to host +- `notifications/message` - Log messages to host (for logging) **Lifecycle:** @@ -533,6 +533,45 @@ Host SHOULD open the URL in the user's default browser or a new tab. Host SHOULD add the message to the conversation thread, preserving the specified role. +`ui/update-context` - Update the agent's conversation context + +```typescript +// Request +{ + jsonrpc: "2.0", + id: 3, + method: "ui/update-context", + params: { + role: "user", + content: ContentBlock[] + } +} + +// Success Response +{ + jsonrpc: "2.0", + id: 3, + result: {} // Empty result on success +} + +// Error Response (if denied or failed) +{ + jsonrpc: "2.0", + id: 3, + error: { + code: -32000, // Implementation-defined error + message: "Context update denied" | "Invalid content format" + } +} +``` + +Guest UI MAY send this request to inform the agent about app state changes that should be stored in the conversation context for future reasoning. This event serves a different use case from `notifications/message` (logging) and `ui/message` (which also trigger followups). + +Host behavior: +- SHOULD store the context update in the conversation context +- MAY display context updates to the user +- MAY filter or aggregate context updates + #### Notifications (Host → UI) `ui/notifications/tool-input` - Host MUST send this notification with the complete tool arguments after the Guest UI's initialize request completes. @@ -765,9 +804,12 @@ sequenceDiagram else Message UI ->> H: ui/message H -->> H: Process message and follow up - else Notify + else Context update + UI ->> H: ui/update-context + H ->> H: Process context update and store in conversation context + else Log UI ->> H: notifications/message - H ->> H: Process notification and store in context + H ->> H: Record log for debugging/telemetry else Resource read UI ->> H: resources/read H ->> S: resources/read diff --git a/src/app-bridge.test.ts b/src/app-bridge.test.ts index 0d9e9e5b..82e3b179 100644 --- a/src/app-bridge.test.ts +++ b/src/app-bridge.test.ts @@ -212,6 +212,52 @@ describe("App <-> AppBridge integration", () => { logger: "TestApp", }); }); + + it("app.sendContext triggers bridge.oncontext and returns result", async () => { + const receivedContexts: unknown[] = []; + bridge.oncontext = (params) => { + receivedContexts.push(params); + }; + + await app.connect(appTransport); + const result = await app.sendContext({ + role: "user", + content: [{ type: "text", text: "User selected 3 items" }], + }); + + expect(receivedContexts).toHaveLength(1); + expect(receivedContexts[0]).toMatchObject({ + role: "user", + content: [{ type: "text", text: "User selected 3 items" }], + }); + expect(result).toEqual({}); + }); + + it("app.sendContext works with multiple content blocks", async () => { + const receivedContexts: unknown[] = []; + bridge.oncontext = (params) => { + receivedContexts.push(params); + }; + + await app.connect(appTransport); + const result = await app.sendContext({ + role: "user", + content: [ + { type: "text", text: "Filter applied" }, + { type: "text", text: "Category: electronics" }, + ], + }); + + expect(receivedContexts).toHaveLength(1); + expect(receivedContexts[0]).toMatchObject({ + role: "user", + content: [ + { type: "text", text: "Filter applied" }, + { type: "text", text: "Category: electronics" }, + ], + }); + expect(result).toEqual({}); + }); }); describe("App -> Host requests", () => { diff --git a/src/app-bridge.ts b/src/app-bridge.ts index c4b2bdbd..6676e470 100644 --- a/src/app-bridge.ts +++ b/src/app-bridge.ts @@ -39,6 +39,8 @@ import { type McpUiToolResultNotification, LATEST_PROTOCOL_VERSION, McpUiAppCapabilities, + McpUiUpdateContextRequest, + McpUiUpdateContextRequestSchema, McpUiHostCapabilities, McpUiHostContext, McpUiHostContextChangedNotification, @@ -502,6 +504,43 @@ export class AppBridge extends Protocol { ); } + /** + * Register a handler for context updates from the Guest UI. + * + * The Guest UI sends `ui/update-context` requests to inform the agent + * about app state changes that should be stored in the conversation context for + * future reasoning. Unlike logging messages, context updates are intended to be + * available to the agent for decision making. + * + * @param callback - Handler that receives context update params + * - params.role - Message role (currently only "user") + * - params.content - Content blocks (text, image, etc.) + * + * @example + * ```typescript + * bridge.oncontext = ({ role, content }) => { + * // Store context update for agent reasoning + * conversationContext.push({ + * type: "app_context", + * role, + * content, + * timestamp: Date.now() + * }); + * }; + * ``` + */ + set oncontext( + callback: (params: McpUiUpdateContextRequest["params"]) => void, + ) { + this.setRequestHandler( + McpUiUpdateContextRequestSchema, + async (request) => { + callback(request.params); + return {}; + }, + ); + } + /** * Verify that the guest supports the capability required for the given request method. * @internal diff --git a/src/app.ts b/src/app.ts index 6813becb..dab840c9 100644 --- a/src/app.ts +++ b/src/app.ts @@ -21,6 +21,8 @@ import { import { LATEST_PROTOCOL_VERSION, McpUiAppCapabilities, + McpUiUpdateContextRequest, + McpUiUpdateContextResultSchema, McpUiHostCapabilities, McpUiHostContextChangedNotification, McpUiHostContextChangedNotificationSchema, @@ -673,6 +675,40 @@ export class App extends Protocol { }); } + /** + * Send context updates to the host for storage in the agent's conversation context. + * + * Unlike `sendLog` which is for debugging/telemetry, context updates are intended + * to inform the agent about app state changes that should be available for future + * reasoning without requiring a follow-up action (i.e., a prompt). + * + * @param params - Context role and content (same structure as ui/message) + * @param options - Request options (timeout, etc.) + * + * @example Notify agent of significant state change + * ```typescript + * await app.sendContext({ + * role: "user", + * content: [{ type: "text", text: "User selected 3 items totaling $150.00" }] + * }); + * ``` + * + * @returns Promise that resolves when the context update is acknowledged + */ + sendContext( + params: McpUiUpdateContextRequest["params"], + options?: RequestOptions + ) { + return this.request( + { + method: "ui/update-context", + params, + }, + McpUiUpdateContextResultSchema, + options + ); + } + /** * Request the host to open an external URL in the default browser. * diff --git a/src/generated/schema.json b/src/generated/schema.json index b51e23bc..935b8c30 100644 --- a/src/generated/schema.json +++ b/src/generated/schema.json @@ -89,6 +89,12 @@ "type": "object", "properties": {}, "additionalProperties": false + }, + "context": { + "description": "Host accepts context updates to be stored in the agent's conversation context.", + "type": "object", + "properties": {}, + "additionalProperties": false } }, "additionalProperties": false @@ -851,6 +857,12 @@ "type": "object", "properties": {}, "additionalProperties": false + }, + "context": { + "description": "Host accepts context updates to be stored in the agent's conversation context.", + "type": "object", + "properties": {}, + "additionalProperties": false } }, "additionalProperties": false @@ -2146,6 +2158,354 @@ }, "required": ["method", "params"], "additionalProperties": false + }, + "McpUiUpdateContextRequest": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "method": { + "type": "string", + "const": "ui/update-context" + }, + "params": { + "type": "object", + "properties": { + "role": { + "description": "Message role, currently only \"user\" is supported.", + "type": "string", + "const": "user" + }, + "content": { + "description": "Context content blocks (text, image, etc.).", + "type": "array", + "items": { + "anyOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "text" + }, + "text": { + "type": "string" + }, + "annotations": { + "type": "object", + "properties": { + "audience": { + "type": "array", + "items": { + "type": "string", + "enum": ["user", "assistant"] + } + }, + "priority": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "lastModified": { + "type": "string", + "format": "date-time", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-]\\d{2}:\\d{2})))$" + } + }, + "additionalProperties": false + }, + "_meta": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + } + }, + "required": ["type", "text"], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "image" + }, + "data": { + "type": "string" + }, + "mimeType": { + "type": "string" + }, + "annotations": { + "type": "object", + "properties": { + "audience": { + "type": "array", + "items": { + "type": "string", + "enum": ["user", "assistant"] + } + }, + "priority": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "lastModified": { + "type": "string", + "format": "date-time", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-]\\d{2}:\\d{2})))$" + } + }, + "additionalProperties": false + }, + "_meta": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + } + }, + "required": ["type", "data", "mimeType"], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "audio" + }, + "data": { + "type": "string" + }, + "mimeType": { + "type": "string" + }, + "annotations": { + "type": "object", + "properties": { + "audience": { + "type": "array", + "items": { + "type": "string", + "enum": ["user", "assistant"] + } + }, + "priority": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "lastModified": { + "type": "string", + "format": "date-time", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-]\\d{2}:\\d{2})))$" + } + }, + "additionalProperties": false + }, + "_meta": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + } + }, + "required": ["type", "data", "mimeType"], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "title": { + "type": "string" + }, + "icons": { + "type": "array", + "items": { + "type": "object", + "properties": { + "src": { + "type": "string" + }, + "mimeType": { + "type": "string" + }, + "sizes": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": ["src"], + "additionalProperties": false + } + }, + "uri": { + "type": "string" + }, + "description": { + "type": "string" + }, + "mimeType": { + "type": "string" + }, + "annotations": { + "type": "object", + "properties": { + "audience": { + "type": "array", + "items": { + "type": "string", + "enum": ["user", "assistant"] + } + }, + "priority": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "lastModified": { + "type": "string", + "format": "date-time", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-]\\d{2}:\\d{2})))$" + } + }, + "additionalProperties": false + }, + "_meta": { + "type": "object", + "properties": {}, + "additionalProperties": {} + }, + "type": { + "type": "string", + "const": "resource_link" + } + }, + "required": ["name", "uri", "type"], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "resource" + }, + "resource": { + "anyOf": [ + { + "type": "object", + "properties": { + "uri": { + "type": "string" + }, + "mimeType": { + "type": "string" + }, + "_meta": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + }, + "text": { + "type": "string" + } + }, + "required": ["uri", "text"], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "uri": { + "type": "string" + }, + "mimeType": { + "type": "string" + }, + "_meta": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + }, + "blob": { + "type": "string" + } + }, + "required": ["uri", "blob"], + "additionalProperties": false + } + ] + }, + "annotations": { + "type": "object", + "properties": { + "audience": { + "type": "array", + "items": { + "type": "string", + "enum": ["user", "assistant"] + } + }, + "priority": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "lastModified": { + "type": "string", + "format": "date-time", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-]\\d{2}:\\d{2})))$" + } + }, + "additionalProperties": false + }, + "_meta": { + "type": "object", + "propertyNames": { + "type": "string" + }, + "additionalProperties": {} + } + }, + "required": ["type", "resource"], + "additionalProperties": false + } + ] + } + } + }, + "required": ["role", "content"], + "additionalProperties": false + } + }, + "required": ["method", "params"], + "additionalProperties": false + }, + "McpUiUpdateContextResult": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "isError": { + "description": "True if the host rejected or failed to store the context update.", + "type": "boolean" + } + }, + "additionalProperties": {} } } } diff --git a/src/generated/schema.test.ts b/src/generated/schema.test.ts index 5a2e3a60..1cb66756 100644 --- a/src/generated/schema.test.ts +++ b/src/generated/schema.test.ts @@ -51,6 +51,10 @@ export type McpUiToolInputPartialNotificationSchemaInferredType = z.infer< typeof generated.McpUiToolInputPartialNotificationSchema >; +export type McpUiUpdateContextResultSchemaInferredType = z.infer< + typeof generated.McpUiUpdateContextResultSchema +>; + export type McpUiResourceTeardownRequestSchemaInferredType = z.infer< typeof generated.McpUiResourceTeardownRequestSchema >; @@ -95,6 +99,10 @@ export type McpUiHostContextChangedNotificationSchemaInferredType = z.infer< typeof generated.McpUiHostContextChangedNotificationSchema >; +export type McpUiUpdateContextRequestSchemaInferredType = z.infer< + typeof generated.McpUiUpdateContextRequestSchema +>; + export type McpUiInitializeRequestSchemaInferredType = z.infer< typeof generated.McpUiInitializeRequestSchema >; @@ -151,6 +159,12 @@ expectType( expectType( {} as spec.McpUiToolInputPartialNotification, ); +expectType( + {} as McpUiUpdateContextResultSchemaInferredType, +); +expectType( + {} as spec.McpUiUpdateContextResult, +); expectType( {} as McpUiResourceTeardownRequestSchemaInferredType, ); @@ -205,6 +219,12 @@ expectType( expectType( {} as spec.McpUiHostContextChangedNotification, ); +expectType( + {} as McpUiUpdateContextRequestSchemaInferredType, +); +expectType( + {} as spec.McpUiUpdateContextRequest, +); expectType( {} as McpUiInitializeRequestSchemaInferredType, ); diff --git a/src/generated/schema.ts b/src/generated/schema.ts index 1b181afa..8c4baddf 100644 --- a/src/generated/schema.ts +++ b/src/generated/schema.ts @@ -160,6 +160,20 @@ export const McpUiToolInputPartialNotificationSchema = z.object({ }), }); +/** + * @description Result from updating the agent's context. + * @see {@link McpUiUpdateContextRequest} + */ +export const McpUiUpdateContextResultSchema = z.looseObject({ + /** @description True if the host rejected or failed to store the context update. */ + isError: z + .boolean() + .optional() + .describe( + "True if the host rejected or failed to store the context update.", + ), +}); + /** * @description Request for graceful shutdown of the Guest UI (Host -> Guest UI). * @see {@link app-bridge.AppBridge.sendResourceTeardown} for the host method that sends this @@ -217,6 +231,13 @@ export const McpUiHostCapabilitiesSchema = z.object({ .describe("Host can proxy resource reads to the MCP server."), /** @description Host accepts log messages. */ logging: z.object({}).optional().describe("Host accepts log messages."), + /** @description Host accepts context updates to be stored in the agent's conversation context. */ + context: z + .object({}) + .optional() + .describe( + "Host accepts context updates to be stored in the agent's conversation context.", + ), }); /** @@ -423,6 +444,29 @@ export const McpUiHostContextChangedNotificationSchema = z.object({ ), }); +/** + * @description Request to update the agent's context without requiring a follow-up action (Guest UI -> Host). + * + * Unlike `notifications/message` which is for debugging/logging, this request is intended + * to inform the agent about app-driven updates that should be stored in the conversation context + * for future reasoning. + * + * @see {@link app.App.sendUpdateContext} for the method that sends this request + */ +export const McpUiUpdateContextRequestSchema = z.object({ + method: z.literal("ui/update-context"), + params: z.object({ + /** @description Message role, currently only "user" is supported. */ + role: z + .literal("user") + .describe('Message role, currently only "user" is supported.'), + /** @description Context content blocks (text, image, etc.). */ + content: z + .array(ContentBlockSchema) + .describe("Context content blocks (text, image, etc.)."), + }), +}); + /** * @description Initialization request sent from Guest UI to Host. * @see {@link app.App.connect} for the method that sends this request diff --git a/src/spec.types.ts b/src/spec.types.ts index 2596bff5..5fa57308 100644 --- a/src/spec.types.ts +++ b/src/spec.types.ts @@ -233,6 +233,39 @@ export interface McpUiHostContextChangedNotification { params: McpUiHostContext; } +/** + * @description Request to update the agent's context without requiring a follow-up action (Guest UI -> Host). + * + * Unlike `notifications/message` which is for debugging/logging, this request is intended + * to inform the agent about app-driven updates that should be stored in the conversation context + * for future reasoning. + * + * @see {@link app.App.sendUpdateContext} for the method that sends this request + */ +export interface McpUiUpdateContextRequest { + method: "ui/update-context"; + params: { + /** @description Message role, currently only "user" is supported. */ + role: "user"; + /** @description Context content blocks (text, image, etc.). */ + content: ContentBlock[]; + }; +} + +/** + * @description Result from updating the agent's context. + * @see {@link McpUiUpdateContextRequest} + */ +export interface McpUiUpdateContextResult { + /** @description True if the host rejected or failed to store the context update. */ + isError?: boolean; + /** + * Index signature required for MCP SDK `Protocol` class compatibility. + * Note: The schema intentionally omits this to enforce strict validation. + */ + [key: string]: unknown; +} + /** * @description Request for graceful shutdown of the Guest UI (Host -> Guest UI). * @see {@link app-bridge.AppBridge.sendResourceTeardown} for the host method that sends this @@ -274,6 +307,8 @@ export interface McpUiHostCapabilities { }; /** @description Host accepts log messages. */ logging?: {}; + /** @description Host accepts context updates to be stored in the agent's conversation context. */ + context?: {}; } /** diff --git a/src/types.ts b/src/types.ts index 92bb8cf8..e5555509 100644 --- a/src/types.ts +++ b/src/types.ts @@ -18,6 +18,8 @@ export { type McpUiOpenLinkResult, type McpUiMessageRequest, type McpUiMessageResult, + type McpUiUpdateContextRequest, + type McpUiUpdateContextResult, type McpUiSandboxProxyReadyNotification, type McpUiSandboxResourceReadyNotification, type McpUiSizeChangedNotification, @@ -45,6 +47,8 @@ export { McpUiOpenLinkResultSchema, McpUiMessageRequestSchema, McpUiMessageResultSchema, + McpUiUpdateContextRequestSchema, + McpUiUpdateContextResultSchema, McpUiSandboxProxyReadyNotificationSchema, McpUiSandboxResourceReadyNotificationSchema, McpUiSizeChangedNotificationSchema, From 69b757013cc2381a1dd829bb54bbe88cdbf6b3fb Mon Sep 17 00:00:00 2001 From: Ido Salomon Date: Wed, 10 Dec 2025 19:42:09 +0200 Subject: [PATCH 02/13] lint --- src/app-bridge.ts | 11 ++++------- src/app.ts | 4 ++-- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/app-bridge.ts b/src/app-bridge.ts index 6676e470..04ca61c4 100644 --- a/src/app-bridge.ts +++ b/src/app-bridge.ts @@ -532,13 +532,10 @@ export class AppBridge extends Protocol { set oncontext( callback: (params: McpUiUpdateContextRequest["params"]) => void, ) { - this.setRequestHandler( - McpUiUpdateContextRequestSchema, - async (request) => { - callback(request.params); - return {}; - }, - ); + this.setRequestHandler(McpUiUpdateContextRequestSchema, async (request) => { + callback(request.params); + return {}; + }); } /** diff --git a/src/app.ts b/src/app.ts index dab840c9..2eb9baf9 100644 --- a/src/app.ts +++ b/src/app.ts @@ -697,7 +697,7 @@ export class App extends Protocol { */ sendContext( params: McpUiUpdateContextRequest["params"], - options?: RequestOptions + options?: RequestOptions, ) { return this.request( { @@ -705,7 +705,7 @@ export class App extends Protocol { params, }, McpUiUpdateContextResultSchema, - options + options, ); } From 0085768688cb43b58c41884e061832fe7e0c6f0c Mon Sep 17 00:00:00 2001 From: Ido Salomon Date: Wed, 10 Dec 2025 19:53:14 +0200 Subject: [PATCH 03/13] sequence diagram --- specification/draft/apps.mdx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/specification/draft/apps.mdx b/specification/draft/apps.mdx index 7aeed253..d816b7e6 100644 --- a/specification/draft/apps.mdx +++ b/specification/draft/apps.mdx @@ -803,10 +803,12 @@ sequenceDiagram H-->>UI: ui/notifications/tool-result else Message UI ->> H: ui/message + H -->> UI: ui/message response H -->> H: Process message and follow up else Context update UI ->> H: ui/update-context - H ->> H: Process context update and store in conversation context + H ->> H: Store in conversation context + H -->> UI: ui/update-context response else Log UI ->> H: notifications/message H ->> H: Record log for debugging/telemetry From b84864210d8bb9d312fd9bb7e58047048dea8da8 Mon Sep 17 00:00:00 2001 From: Ido Salomon Date: Wed, 10 Dec 2025 20:01:18 +0200 Subject: [PATCH 04/13] cr --- src/app-bridge.test.ts | 20 +++++++++++++++++-- src/app-bridge.ts | 45 +++++++++++++++++++++++++++++------------- 2 files changed, 49 insertions(+), 16 deletions(-) diff --git a/src/app-bridge.test.ts b/src/app-bridge.test.ts index 82e3b179..1ba07ffd 100644 --- a/src/app-bridge.test.ts +++ b/src/app-bridge.test.ts @@ -215,8 +215,9 @@ describe("App <-> AppBridge integration", () => { it("app.sendContext triggers bridge.oncontext and returns result", async () => { const receivedContexts: unknown[] = []; - bridge.oncontext = (params) => { + bridge.oncontext = async (params) => { receivedContexts.push(params); + return {}; }; await app.connect(appTransport); @@ -235,8 +236,9 @@ describe("App <-> AppBridge integration", () => { it("app.sendContext works with multiple content blocks", async () => { const receivedContexts: unknown[] = []; - bridge.oncontext = (params) => { + bridge.oncontext = async (params) => { receivedContexts.push(params); + return {}; }; await app.connect(appTransport); @@ -258,6 +260,20 @@ describe("App <-> AppBridge integration", () => { }); expect(result).toEqual({}); }); + + it("app.sendContext returns error result when handler indicates error", async () => { + bridge.oncontext = async () => { + return { isError: true }; + }; + + await app.connect(appTransport); + const result = await app.sendContext({ + role: "user", + content: [{ type: "text", text: "Test" }], + }); + + expect(result.isError).toBe(true); + }); }); describe("App -> Host requests", () => { diff --git a/src/app-bridge.ts b/src/app-bridge.ts index 04ca61c4..1deea433 100644 --- a/src/app-bridge.ts +++ b/src/app-bridge.ts @@ -41,6 +41,7 @@ import { McpUiAppCapabilities, McpUiUpdateContextRequest, McpUiUpdateContextRequestSchema, + McpUiUpdateContextResult, McpUiHostCapabilities, McpUiHostContext, McpUiHostContextChangedNotification, @@ -512,30 +513,46 @@ export class AppBridge extends Protocol { * future reasoning. Unlike logging messages, context updates are intended to be * available to the agent for decision making. * - * @param callback - Handler that receives context update params + * @param callback - Handler that receives context update params and returns a result * - params.role - Message role (currently only "user") * - params.content - Content blocks (text, image, etc.) + * - extra - Request metadata (abort signal, session info) + * - Returns: Promise with optional isError flag * * @example * ```typescript - * bridge.oncontext = ({ role, content }) => { - * // Store context update for agent reasoning - * conversationContext.push({ - * type: "app_context", - * role, - * content, - * timestamp: Date.now() - * }); + * bridge.oncontext = async ({ role, content }, extra) => { + * try { + * // Store context update for agent reasoning + * conversationContext.push({ + * type: "app_context", + * role, + * content, + * timestamp: Date.now() + * }); + * return {}; + * } catch (err) { + * // Handle error and signal failure to the app + * return { isError: true }; + * } * }; * ``` + * + * @see {@link McpUiUpdateContextRequest} for the request type + * @see {@link McpUiUpdateContextResult} for the result type */ set oncontext( - callback: (params: McpUiUpdateContextRequest["params"]) => void, + callback: ( + params: McpUiUpdateContextRequest["params"], + extra: RequestHandlerExtra, + ) => Promise, ) { - this.setRequestHandler(McpUiUpdateContextRequestSchema, async (request) => { - callback(request.params); - return {}; - }); + this.setRequestHandler( + McpUiUpdateContextRequestSchema, + async (request, extra) => { + return callback(request.params, extra); + }, + ); } /** From 5369d3346b60b37b3d5ff75793766924e2a43238 Mon Sep 17 00:00:00 2001 From: Ido Salomon Date: Wed, 10 Dec 2025 20:24:59 +0200 Subject: [PATCH 05/13] CR --- specification/draft/apps.mdx | 2 +- src/app-bridge.test.ts | 18 +++++++++--------- src/app-bridge.ts | 4 ++-- src/app.ts | 6 +++--- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/specification/draft/apps.mdx b/specification/draft/apps.mdx index d816b7e6..0601cc16 100644 --- a/specification/draft/apps.mdx +++ b/specification/draft/apps.mdx @@ -565,7 +565,7 @@ Host SHOULD add the message to the conversation thread, preserving the specified } ``` -Guest UI MAY send this request to inform the agent about app state changes that should be stored in the conversation context for future reasoning. This event serves a different use case from `notifications/message` (logging) and `ui/message` (which also trigger followups). +Guest UI MAY send this request to inform the agent about app state changes that should be stored in the conversation context for future reasoning. This event serves a different use case from `notifications/message` (logging) and `ui/message` (which also trigger follow-ups). Host behavior: - SHOULD store the context update in the conversation context diff --git a/src/app-bridge.test.ts b/src/app-bridge.test.ts index 1ba07ffd..96fc1566 100644 --- a/src/app-bridge.test.ts +++ b/src/app-bridge.test.ts @@ -213,15 +213,15 @@ describe("App <-> AppBridge integration", () => { }); }); - it("app.sendContext triggers bridge.oncontext and returns result", async () => { + it("app.sendUpdateContext triggers bridge.onupdatecontext and returns result", async () => { const receivedContexts: unknown[] = []; - bridge.oncontext = async (params) => { + bridge.onupdatecontext = async (params) => { receivedContexts.push(params); return {}; }; await app.connect(appTransport); - const result = await app.sendContext({ + const result = await app.sendUpdateContext({ role: "user", content: [{ type: "text", text: "User selected 3 items" }], }); @@ -234,15 +234,15 @@ describe("App <-> AppBridge integration", () => { expect(result).toEqual({}); }); - it("app.sendContext works with multiple content blocks", async () => { + it("app.sendUpdateContext works with multiple content blocks", async () => { const receivedContexts: unknown[] = []; - bridge.oncontext = async (params) => { + bridge.onupdatecontext = async (params) => { receivedContexts.push(params); return {}; }; await app.connect(appTransport); - const result = await app.sendContext({ + const result = await app.sendUpdateContext({ role: "user", content: [ { type: "text", text: "Filter applied" }, @@ -261,13 +261,13 @@ describe("App <-> AppBridge integration", () => { expect(result).toEqual({}); }); - it("app.sendContext returns error result when handler indicates error", async () => { - bridge.oncontext = async () => { + it("app.sendUpdateContext returns error result when handler indicates error", async () => { + bridge.onupdatecontext = async () => { return { isError: true }; }; await app.connect(appTransport); - const result = await app.sendContext({ + const result = await app.sendUpdateContext({ role: "user", content: [{ type: "text", text: "Test" }], }); diff --git a/src/app-bridge.ts b/src/app-bridge.ts index 1deea433..65e7b2ad 100644 --- a/src/app-bridge.ts +++ b/src/app-bridge.ts @@ -521,7 +521,7 @@ export class AppBridge extends Protocol { * * @example * ```typescript - * bridge.oncontext = async ({ role, content }, extra) => { + * bridge.onupdatecontext = async ({ role, content }, extra) => { * try { * // Store context update for agent reasoning * conversationContext.push({ @@ -541,7 +541,7 @@ export class AppBridge extends Protocol { * @see {@link McpUiUpdateContextRequest} for the request type * @see {@link McpUiUpdateContextResult} for the result type */ - set oncontext( + set onupdatecontext( callback: ( params: McpUiUpdateContextRequest["params"], extra: RequestHandlerExtra, diff --git a/src/app.ts b/src/app.ts index 2eb9baf9..92e4d668 100644 --- a/src/app.ts +++ b/src/app.ts @@ -680,14 +680,14 @@ export class App extends Protocol { * * Unlike `sendLog` which is for debugging/telemetry, context updates are intended * to inform the agent about app state changes that should be available for future - * reasoning without requiring a follow-up action (i.e., a prompt). + * reasoning without requiring a follow-up action (like `sendMessage`). * * @param params - Context role and content (same structure as ui/message) * @param options - Request options (timeout, etc.) * * @example Notify agent of significant state change * ```typescript - * await app.sendContext({ + * await app.sendUpdateContext({ * role: "user", * content: [{ type: "text", text: "User selected 3 items totaling $150.00" }] * }); @@ -695,7 +695,7 @@ export class App extends Protocol { * * @returns Promise that resolves when the context update is acknowledged */ - sendContext( + sendUpdateContext( params: McpUiUpdateContextRequest["params"], options?: RequestOptions, ) { From 0447af5d37f6dea57f13396a7bf9e2dff265298a Mon Sep 17 00:00:00 2001 From: Ido Salomon Date: Wed, 10 Dec 2025 22:21:17 +0200 Subject: [PATCH 06/13] comment --- specification/draft/apps.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/draft/apps.mdx b/specification/draft/apps.mdx index 0601cc16..1d9ca150 100644 --- a/specification/draft/apps.mdx +++ b/specification/draft/apps.mdx @@ -379,7 +379,7 @@ UI iframes can use the following subset of standard MCP protocol messages: **Notifications:** -- `notifications/message` - Log messages to host (for logging) +- `notifications/message` - Log messages to host **Lifecycle:** From 7392629f4c8f14724a812f4c5950cf149c4f008b Mon Sep 17 00:00:00 2001 From: Ido Salomon Date: Wed, 10 Dec 2025 22:26:42 +0200 Subject: [PATCH 07/13] rename capability --- src/generated/schema.json | 4 ++-- src/generated/schema.ts | 2 +- src/spec.types.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/generated/schema.json b/src/generated/schema.json index 935b8c30..dab2b073 100644 --- a/src/generated/schema.json +++ b/src/generated/schema.json @@ -90,7 +90,7 @@ "properties": {}, "additionalProperties": false }, - "context": { + "updateContext": { "description": "Host accepts context updates to be stored in the agent's conversation context.", "type": "object", "properties": {}, @@ -858,7 +858,7 @@ "properties": {}, "additionalProperties": false }, - "context": { + "updateContext": { "description": "Host accepts context updates to be stored in the agent's conversation context.", "type": "object", "properties": {}, diff --git a/src/generated/schema.ts b/src/generated/schema.ts index 8c4baddf..db242182 100644 --- a/src/generated/schema.ts +++ b/src/generated/schema.ts @@ -232,7 +232,7 @@ export const McpUiHostCapabilitiesSchema = z.object({ /** @description Host accepts log messages. */ logging: z.object({}).optional().describe("Host accepts log messages."), /** @description Host accepts context updates to be stored in the agent's conversation context. */ - context: z + updateContext: z .object({}) .optional() .describe( diff --git a/src/spec.types.ts b/src/spec.types.ts index 5fa57308..71757e1e 100644 --- a/src/spec.types.ts +++ b/src/spec.types.ts @@ -308,7 +308,7 @@ export interface McpUiHostCapabilities { /** @description Host accepts log messages. */ logging?: {}; /** @description Host accepts context updates to be stored in the agent's conversation context. */ - context?: {}; + updateContext?: {}; } /** From 9e920c926b087d78ef5b7b2dd3c0748a0932fcb2 Mon Sep 17 00:00:00 2001 From: Ido Salomon Date: Fri, 19 Dec 2025 00:30:57 +0200 Subject: [PATCH 08/13] Update to `update-model-context` --- specification/draft/apps.mdx | 17 +++++++------- src/app-bridge.test.ts | 18 +++++++-------- src/app-bridge.ts | 42 +++++++++++++++------------------- src/app.ts | 26 ++++++++++----------- src/generated/schema.json | 44 ++++++++++++++++++------------------ src/generated/schema.test.ts | 24 ++++++++++---------- src/generated/schema.ts | 22 +++++++++--------- src/spec.types.ts | 22 +++++++++--------- src/types.ts | 8 +++---- 9 files changed, 109 insertions(+), 114 deletions(-) diff --git a/specification/draft/apps.mdx b/specification/draft/apps.mdx index 1d9ca150..5193f18c 100644 --- a/specification/draft/apps.mdx +++ b/specification/draft/apps.mdx @@ -533,14 +533,14 @@ Host SHOULD open the URL in the user's default browser or a new tab. Host SHOULD add the message to the conversation thread, preserving the specified role. -`ui/update-context` - Update the agent's conversation context +`ui/update-model-context` - Update the model context ```typescript // Request { jsonrpc: "2.0", id: 3, - method: "ui/update-context", + method: "ui/update-model-context", params: { role: "user", content: ContentBlock[] @@ -565,12 +565,13 @@ Host SHOULD add the message to the conversation thread, preserving the specified } ``` -Guest UI MAY send this request to inform the agent about app state changes that should be stored in the conversation context for future reasoning. This event serves a different use case from `notifications/message` (logging) and `ui/message` (which also trigger follow-ups). +Guest UI MAY send this request to update the Host's model context. This context will be used in future turns. Each request overwrites the previous context sent by the Guest UI. +This event serves a different use case from `notifications/message` (logging) and `ui/message` (which also trigger follow-ups). Host behavior: -- SHOULD store the context update in the conversation context +- SHOULD store the context snapshot in the conversation context +- SHOULD overwrite the previous model context with the new update - MAY display context updates to the user -- MAY filter or aggregate context updates #### Notifications (Host → UI) @@ -806,9 +807,9 @@ sequenceDiagram H -->> UI: ui/message response H -->> H: Process message and follow up else Context update - UI ->> H: ui/update-context - H ->> H: Store in conversation context - H -->> UI: ui/update-context response + UI ->> H: ui/update-model-context + H ->> H: Store model context (overwrite existing) + H -->> UI: ui/update-model-context response else Log UI ->> H: notifications/message H ->> H: Record log for debugging/telemetry diff --git a/src/app-bridge.test.ts b/src/app-bridge.test.ts index 96fc1566..d1551d84 100644 --- a/src/app-bridge.test.ts +++ b/src/app-bridge.test.ts @@ -213,15 +213,15 @@ describe("App <-> AppBridge integration", () => { }); }); - it("app.sendUpdateContext triggers bridge.onupdatecontext and returns result", async () => { + it("app.sendUpdateModelContext triggers bridge.onupdatemodelcontext and returns result", async () => { const receivedContexts: unknown[] = []; - bridge.onupdatecontext = async (params) => { + bridge.onupdatemodelcontext = async (params) => { receivedContexts.push(params); return {}; }; await app.connect(appTransport); - const result = await app.sendUpdateContext({ + const result = await app.sendUpdateModelContext({ role: "user", content: [{ type: "text", text: "User selected 3 items" }], }); @@ -234,15 +234,15 @@ describe("App <-> AppBridge integration", () => { expect(result).toEqual({}); }); - it("app.sendUpdateContext works with multiple content blocks", async () => { + it("app.sendUpdateModelContext works with multiple content blocks", async () => { const receivedContexts: unknown[] = []; - bridge.onupdatecontext = async (params) => { + bridge.onupdatemodelcontext = async (params) => { receivedContexts.push(params); return {}; }; await app.connect(appTransport); - const result = await app.sendUpdateContext({ + const result = await app.sendUpdateModelContext({ role: "user", content: [ { type: "text", text: "Filter applied" }, @@ -261,13 +261,13 @@ describe("App <-> AppBridge integration", () => { expect(result).toEqual({}); }); - it("app.sendUpdateContext returns error result when handler indicates error", async () => { - bridge.onupdatecontext = async () => { + it("app.sendUpdateModelContext returns error result when handler indicates error", async () => { + bridge.onupdatemodelcontext = async () => { return { isError: true }; }; await app.connect(appTransport); - const result = await app.sendUpdateContext({ + const result = await app.sendUpdateModelContext({ role: "user", content: [{ type: "text", text: "Test" }], }); diff --git a/src/app-bridge.ts b/src/app-bridge.ts index 65e7b2ad..db0c1b85 100644 --- a/src/app-bridge.ts +++ b/src/app-bridge.ts @@ -39,9 +39,9 @@ import { type McpUiToolResultNotification, LATEST_PROTOCOL_VERSION, McpUiAppCapabilities, - McpUiUpdateContextRequest, - McpUiUpdateContextRequestSchema, - McpUiUpdateContextResult, + McpUiUpdateModelContextRequest, + McpUiUpdateModelContextRequestSchema, + McpUiUpdateModelContextResult, McpUiHostCapabilities, McpUiHostContext, McpUiHostContextChangedNotification, @@ -506,30 +506,24 @@ export class AppBridge extends Protocol { } /** - * Register a handler for context updates from the Guest UI. + * Register a handler for model context updates from the Guest UI. * - * The Guest UI sends `ui/update-context` requests to inform the agent - * about app state changes that should be stored in the conversation context for - * future reasoning. Unlike logging messages, context updates are intended to be - * available to the agent for decision making. - * - * @param callback - Handler that receives context update params and returns a result - * - params.role - Message role (currently only "user") - * - params.content - Content blocks (text, image, etc.) - * - extra - Request metadata (abort signal, session info) - * - Returns: Promise with optional isError flag + * The Guest UI sends `ui/update-model-context` requests to update the Host's + * model context. Each request overwrites the previous context stored by the Guest UI. + * Unlike logging messages, context updates are intended to be available to + * the model in future turns. Unlike messages, context updates do not trigger follow-ups * * @example * ```typescript - * bridge.onupdatecontext = async ({ role, content }, extra) => { + * bridge.onupdatemodelcontext = async ({ role, content }, extra) => { * try { - * // Store context update for agent reasoning - * conversationContext.push({ + * // Update the model context with the new snapshot + * modelContext = { * type: "app_context", * role, * content, * timestamp: Date.now() - * }); + * }; * return {}; * } catch (err) { * // Handle error and signal failure to the app @@ -538,17 +532,17 @@ export class AppBridge extends Protocol { * }; * ``` * - * @see {@link McpUiUpdateContextRequest} for the request type - * @see {@link McpUiUpdateContextResult} for the result type + * @see {@link McpUiUpdateModelContextRequest} for the request type + * @see {@link McpUiUpdateModelContextResult} for the result type */ - set onupdatecontext( + set onupdatemodelcontext( callback: ( - params: McpUiUpdateContextRequest["params"], + params: McpUiUpdateModelContextRequest["params"], extra: RequestHandlerExtra, - ) => Promise, + ) => Promise, ) { this.setRequestHandler( - McpUiUpdateContextRequestSchema, + McpUiUpdateModelContextRequestSchema, async (request, extra) => { return callback(request.params, extra); }, diff --git a/src/app.ts b/src/app.ts index 92e4d668..20007c02 100644 --- a/src/app.ts +++ b/src/app.ts @@ -21,8 +21,8 @@ import { import { LATEST_PROTOCOL_VERSION, McpUiAppCapabilities, - McpUiUpdateContextRequest, - McpUiUpdateContextResultSchema, + McpUiUpdateModelContextRequest, + McpUiUpdateModelContextResultSchema, McpUiHostCapabilities, McpUiHostContextChangedNotification, McpUiHostContextChangedNotificationSchema, @@ -676,18 +676,18 @@ export class App extends Protocol { } /** - * Send context updates to the host for storage in the agent's conversation context. + * Send context updates to the host to be included in the agent's context. * - * Unlike `sendLog` which is for debugging/telemetry, context updates are intended - * to inform the agent about app state changes that should be available for future - * reasoning without requiring a follow-up action (like `sendMessage`). + * Unlike `sendLog`, which is for debugging/telemetry, context updates + * are inteded to be available to the model in future reasoning, + * without requiring a follow-up action (like `sendMessage`). * * @param params - Context role and content (same structure as ui/message) * @param options - Request options (timeout, etc.) * - * @example Notify agent of significant state change + * @example Update model context with current app state * ```typescript - * await app.sendUpdateContext({ + * await app.sendUpdateModelContext({ * role: "user", * content: [{ type: "text", text: "User selected 3 items totaling $150.00" }] * }); @@ -695,16 +695,16 @@ export class App extends Protocol { * * @returns Promise that resolves when the context update is acknowledged */ - sendUpdateContext( - params: McpUiUpdateContextRequest["params"], + sendUpdateModelContext( + params: McpUiUpdateModelContextRequest["params"], options?: RequestOptions, ) { return this.request( - { - method: "ui/update-context", + { + method: "ui/update-model-context", params, }, - McpUiUpdateContextResultSchema, + McpUiUpdateModelContextResultSchema, options, ); } diff --git a/src/generated/schema.json b/src/generated/schema.json index dab2b073..24576374 100644 --- a/src/generated/schema.json +++ b/src/generated/schema.json @@ -90,8 +90,8 @@ "properties": {}, "additionalProperties": false }, - "updateContext": { - "description": "Host accepts context updates to be stored in the agent's conversation context.", + "updateModelContext": { + "description": "Host accepts context updates to be included in the model's context for future turns.", "type": "object", "properties": {}, "additionalProperties": false @@ -858,8 +858,8 @@ "properties": {}, "additionalProperties": false }, - "updateContext": { - "description": "Host accepts context updates to be stored in the agent's conversation context.", + "updateModelContext": { + "description": "Host accepts context updates to be included in the model's context for future turns.", "type": "object", "properties": {}, "additionalProperties": false @@ -1224,7 +1224,7 @@ "lastModified": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-]\\d{2}:\\d{2})))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" } }, "additionalProperties": false @@ -1271,7 +1271,7 @@ "lastModified": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-]\\d{2}:\\d{2})))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" } }, "additionalProperties": false @@ -1318,7 +1318,7 @@ "lastModified": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-]\\d{2}:\\d{2})))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" } }, "additionalProperties": false @@ -1392,7 +1392,7 @@ "lastModified": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-]\\d{2}:\\d{2})))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" } }, "additionalProperties": false @@ -1485,7 +1485,7 @@ "lastModified": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-]\\d{2}:\\d{2})))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" } }, "additionalProperties": false @@ -1861,7 +1861,7 @@ "lastModified": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-]\\d{2}:\\d{2})))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" } }, "additionalProperties": false @@ -1908,7 +1908,7 @@ "lastModified": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-]\\d{2}:\\d{2})))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" } }, "additionalProperties": false @@ -1955,7 +1955,7 @@ "lastModified": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-]\\d{2}:\\d{2})))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" } }, "additionalProperties": false @@ -2029,7 +2029,7 @@ "lastModified": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-]\\d{2}:\\d{2})))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" } }, "additionalProperties": false @@ -2122,7 +2122,7 @@ "lastModified": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-]\\d{2}:\\d{2})))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" } }, "additionalProperties": false @@ -2159,13 +2159,13 @@ "required": ["method", "params"], "additionalProperties": false }, - "McpUiUpdateContextRequest": { + "McpUiUpdateModelContextRequest": { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "method": { "type": "string", - "const": "ui/update-context" + "const": "ui/update-model-context" }, "params": { "type": "object", @@ -2208,7 +2208,7 @@ "lastModified": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-]\\d{2}:\\d{2})))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" } }, "additionalProperties": false @@ -2255,7 +2255,7 @@ "lastModified": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-]\\d{2}:\\d{2})))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" } }, "additionalProperties": false @@ -2302,7 +2302,7 @@ "lastModified": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-]\\d{2}:\\d{2})))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" } }, "additionalProperties": false @@ -2376,7 +2376,7 @@ "lastModified": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-]\\d{2}:\\d{2})))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" } }, "additionalProperties": false @@ -2469,7 +2469,7 @@ "lastModified": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-]\\d{2}:\\d{2})))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" } }, "additionalProperties": false @@ -2496,7 +2496,7 @@ "required": ["method", "params"], "additionalProperties": false }, - "McpUiUpdateContextResult": { + "McpUiUpdateModelContextResult": { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { diff --git a/src/generated/schema.test.ts b/src/generated/schema.test.ts index 1cb66756..3704764f 100644 --- a/src/generated/schema.test.ts +++ b/src/generated/schema.test.ts @@ -51,8 +51,8 @@ export type McpUiToolInputPartialNotificationSchemaInferredType = z.infer< typeof generated.McpUiToolInputPartialNotificationSchema >; -export type McpUiUpdateContextResultSchemaInferredType = z.infer< - typeof generated.McpUiUpdateContextResultSchema +export type McpUiUpdateModelContextResultSchemaInferredType = z.infer< + typeof generated.McpUiUpdateModelContextResultSchema >; export type McpUiResourceTeardownRequestSchemaInferredType = z.infer< @@ -99,8 +99,8 @@ export type McpUiHostContextChangedNotificationSchemaInferredType = z.infer< typeof generated.McpUiHostContextChangedNotificationSchema >; -export type McpUiUpdateContextRequestSchemaInferredType = z.infer< - typeof generated.McpUiUpdateContextRequestSchema +export type McpUiUpdateModelContextRequestSchemaInferredType = z.infer< + typeof generated.McpUiUpdateModelContextRequestSchema >; export type McpUiInitializeRequestSchemaInferredType = z.infer< @@ -159,11 +159,11 @@ expectType( expectType( {} as spec.McpUiToolInputPartialNotification, ); -expectType( - {} as McpUiUpdateContextResultSchemaInferredType, +expectType( + {} as McpUiUpdateModelContextResultSchemaInferredType, ); -expectType( - {} as spec.McpUiUpdateContextResult, +expectType( + {} as spec.McpUiUpdateModelContextResult, ); expectType( {} as McpUiResourceTeardownRequestSchemaInferredType, @@ -219,11 +219,11 @@ expectType( expectType( {} as spec.McpUiHostContextChangedNotification, ); -expectType( - {} as McpUiUpdateContextRequestSchemaInferredType, +expectType( + {} as McpUiUpdateModelContextRequestSchemaInferredType, ); -expectType( - {} as spec.McpUiUpdateContextRequest, +expectType( + {} as spec.McpUiUpdateModelContextRequest, ); expectType( {} as McpUiInitializeRequestSchemaInferredType, diff --git a/src/generated/schema.ts b/src/generated/schema.ts index db242182..f5341bc3 100644 --- a/src/generated/schema.ts +++ b/src/generated/schema.ts @@ -161,10 +161,10 @@ export const McpUiToolInputPartialNotificationSchema = z.object({ }); /** - * @description Result from updating the agent's context. - * @see {@link McpUiUpdateContextRequest} + * @description Result from setting the agent's model context. + * @see {@link McpUiUpdateModelContextRequest} */ -export const McpUiUpdateContextResultSchema = z.looseObject({ +export const McpUiUpdateModelContextResultSchema = z.looseObject({ /** @description True if the host rejected or failed to store the context update. */ isError: z .boolean() @@ -231,12 +231,12 @@ export const McpUiHostCapabilitiesSchema = z.object({ .describe("Host can proxy resource reads to the MCP server."), /** @description Host accepts log messages. */ logging: z.object({}).optional().describe("Host accepts log messages."), - /** @description Host accepts context updates to be stored in the agent's conversation context. */ - updateContext: z + /** @description Host accepts context updates to be included in the model's context for future turns. */ + updateModelContext: z .object({}) .optional() .describe( - "Host accepts context updates to be stored in the agent's conversation context.", + "Host accepts context updates to be included in the model's context for future turns.", ), }); @@ -448,13 +448,13 @@ export const McpUiHostContextChangedNotificationSchema = z.object({ * @description Request to update the agent's context without requiring a follow-up action (Guest UI -> Host). * * Unlike `notifications/message` which is for debugging/logging, this request is intended - * to inform the agent about app-driven updates that should be stored in the conversation context - * for future reasoning. * - * @see {@link app.App.sendUpdateContext} for the method that sends this request + * to update the Host's model context. Each request overwrites the previous context sent by the Guest UI. + * Unlike messages, context updates do not trigger follow-ups. + * @see {@link app.App.sendUpdateModelContext} for the method that sends this request */ -export const McpUiUpdateContextRequestSchema = z.object({ - method: z.literal("ui/update-context"), +export const McpUiUpdateModelContextRequestSchema = z.object({ + method: z.literal("ui/update-model-context"), params: z.object({ /** @description Message role, currently only "user" is supported. */ role: z diff --git a/src/spec.types.ts b/src/spec.types.ts index 71757e1e..6c193bc9 100644 --- a/src/spec.types.ts +++ b/src/spec.types.ts @@ -237,13 +237,13 @@ export interface McpUiHostContextChangedNotification { * @description Request to update the agent's context without requiring a follow-up action (Guest UI -> Host). * * Unlike `notifications/message` which is for debugging/logging, this request is intended - * to inform the agent about app-driven updates that should be stored in the conversation context - * for future reasoning. - * - * @see {@link app.App.sendUpdateContext} for the method that sends this request + * + * to update the Host's model context. Each request overwrites the previous context sent by the Guest UI. + * Unlike messages, context updates do not trigger follow-ups. + * @see {@link app.App.sendUpdateModelContext} for the method that sends this request */ -export interface McpUiUpdateContextRequest { - method: "ui/update-context"; +export interface McpUiUpdateModelContextRequest { + method: "ui/update-model-context"; params: { /** @description Message role, currently only "user" is supported. */ role: "user"; @@ -253,10 +253,10 @@ export interface McpUiUpdateContextRequest { } /** - * @description Result from updating the agent's context. - * @see {@link McpUiUpdateContextRequest} + * @description Result from setting the agent's model context. + * @see {@link McpUiUpdateModelContextRequest} */ -export interface McpUiUpdateContextResult { +export interface McpUiUpdateModelContextResult { /** @description True if the host rejected or failed to store the context update. */ isError?: boolean; /** @@ -307,8 +307,8 @@ export interface McpUiHostCapabilities { }; /** @description Host accepts log messages. */ logging?: {}; - /** @description Host accepts context updates to be stored in the agent's conversation context. */ - updateContext?: {}; + /** @description Host accepts context updates to be included in the model's context for future turns. */ + updateModelContext?: {}; } /** diff --git a/src/types.ts b/src/types.ts index e5555509..f4ea6723 100644 --- a/src/types.ts +++ b/src/types.ts @@ -18,8 +18,8 @@ export { type McpUiOpenLinkResult, type McpUiMessageRequest, type McpUiMessageResult, - type McpUiUpdateContextRequest, - type McpUiUpdateContextResult, + type McpUiUpdateModelContextRequest, + type McpUiUpdateModelContextResult, type McpUiSandboxProxyReadyNotification, type McpUiSandboxResourceReadyNotification, type McpUiSizeChangedNotification, @@ -47,8 +47,8 @@ export { McpUiOpenLinkResultSchema, McpUiMessageRequestSchema, McpUiMessageResultSchema, - McpUiUpdateContextRequestSchema, - McpUiUpdateContextResultSchema, + McpUiUpdateModelContextRequestSchema, + McpUiUpdateModelContextResultSchema, McpUiSandboxProxyReadyNotificationSchema, McpUiSandboxResourceReadyNotificationSchema, McpUiSizeChangedNotificationSchema, From 27f950a24ba5af16e37bc886aa67758798a7db23 Mon Sep 17 00:00:00 2001 From: Ido Salomon Date: Fri, 19 Dec 2025 00:31:56 +0200 Subject: [PATCH 09/13] clean up comment --- src/generated/schema.ts | 1 - src/spec.types.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/src/generated/schema.ts b/src/generated/schema.ts index f5341bc3..e7d3b843 100644 --- a/src/generated/schema.ts +++ b/src/generated/schema.ts @@ -448,7 +448,6 @@ export const McpUiHostContextChangedNotificationSchema = z.object({ * @description Request to update the agent's context without requiring a follow-up action (Guest UI -> Host). * * Unlike `notifications/message` which is for debugging/logging, this request is intended - * * to update the Host's model context. Each request overwrites the previous context sent by the Guest UI. * Unlike messages, context updates do not trigger follow-ups. * @see {@link app.App.sendUpdateModelContext} for the method that sends this request diff --git a/src/spec.types.ts b/src/spec.types.ts index 6c193bc9..106c7e3d 100644 --- a/src/spec.types.ts +++ b/src/spec.types.ts @@ -237,7 +237,6 @@ export interface McpUiHostContextChangedNotification { * @description Request to update the agent's context without requiring a follow-up action (Guest UI -> Host). * * Unlike `notifications/message` which is for debugging/logging, this request is intended - * * to update the Host's model context. Each request overwrites the previous context sent by the Guest UI. * Unlike messages, context updates do not trigger follow-ups. * @see {@link app.App.sendUpdateModelContext} for the method that sends this request From 782d780fdec0d7af89fd705405b8f0ce07c0fe8f Mon Sep 17 00:00:00 2001 From: Olivier Chafik Date: Mon, 12 Jan 2026 13:11:31 +0000 Subject: [PATCH 10/13] refactor: improve ui/update-model-context API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Rename sendUpdateModelContext → updateModelContext (avoid double verbs) - Remove role field from params (always user, adds no value) - Add structuredContent support for machine-readable context data - Use EmptyResult instead of {isError?: boolean} for result type - Errors now signaled via JSON-RPC error responses - Update capability to specify supported content types: text, image, audio, resource, resourceLink, structuredContent - Add spec guidance for deferred delivery semantics: - Host MAY defer until next user message - Host MAY dedupe identical updates - Only last update before user message is sent to model --- specification/draft/apps.mdx | 9 +- src/app-bridge.test.ts | 44 ++- src/app-bridge.ts | 34 +- src/app.ts | 28 +- src/generated/schema.json | 96 ++++- src/generated/schema.test.ts | 418 +++++++--------------- src/generated/schema.ts | 672 +++++++++++------------------------ src/spec.types.ts | 30 +- 8 files changed, 506 insertions(+), 825 deletions(-) diff --git a/specification/draft/apps.mdx b/specification/draft/apps.mdx index 2b98540c..e8c429e4 100644 --- a/specification/draft/apps.mdx +++ b/specification/draft/apps.mdx @@ -809,8 +809,8 @@ Guest UI behavior: id: 3, method: "ui/update-model-context", params: { - role: "user", - content: ContentBlock[] + content?: ContentBlock[], + structuredContent?: Record } } @@ -836,8 +836,11 @@ Guest UI MAY send this request to update the Host's model context. This context This event serves a different use case from `notifications/message` (logging) and `ui/message` (which also trigger follow-ups). Host behavior: -- SHOULD store the context snapshot in the conversation context +- SHOULD provide the context to the model in future turns - SHOULD overwrite the previous model context with the new update +- MAY defer sending the context to the model until the next user message (including `ui/message`) +- MAY dedupe identical `ui/update-model-context` calls +- If multiple updates are received before the next user message, Host SHOULD only send the last update to the model - MAY display context updates to the user #### Notifications (Host → UI) diff --git a/src/app-bridge.test.ts b/src/app-bridge.test.ts index 510e3142..cb7ec0a1 100644 --- a/src/app-bridge.test.ts +++ b/src/app-bridge.test.ts @@ -440,7 +440,7 @@ describe("App <-> AppBridge integration", () => { }); }); - it("app.sendUpdateModelContext triggers bridge.onupdatemodelcontext and returns result", async () => { + it("app.updateModelContext triggers bridge.onupdatemodelcontext and returns result", async () => { const receivedContexts: unknown[] = []; bridge.onupdatemodelcontext = async (params) => { receivedContexts.push(params); @@ -448,20 +448,18 @@ describe("App <-> AppBridge integration", () => { }; await app.connect(appTransport); - const result = await app.sendUpdateModelContext({ - role: "user", + const result = await app.updateModelContext({ content: [{ type: "text", text: "User selected 3 items" }], }); expect(receivedContexts).toHaveLength(1); expect(receivedContexts[0]).toMatchObject({ - role: "user", content: [{ type: "text", text: "User selected 3 items" }], }); expect(result).toEqual({}); }); - it("app.sendUpdateModelContext works with multiple content blocks", async () => { + it("app.updateModelContext works with multiple content blocks", async () => { const receivedContexts: unknown[] = []; bridge.onupdatemodelcontext = async (params) => { receivedContexts.push(params); @@ -469,8 +467,7 @@ describe("App <-> AppBridge integration", () => { }; await app.connect(appTransport); - const result = await app.sendUpdateModelContext({ - role: "user", + const result = await app.updateModelContext({ content: [ { type: "text", text: "Filter applied" }, { type: "text", text: "Category: electronics" }, @@ -479,7 +476,6 @@ describe("App <-> AppBridge integration", () => { expect(receivedContexts).toHaveLength(1); expect(receivedContexts[0]).toMatchObject({ - role: "user", content: [ { type: "text", text: "Filter applied" }, { type: "text", text: "Category: electronics" }, @@ -488,18 +484,36 @@ describe("App <-> AppBridge integration", () => { expect(result).toEqual({}); }); - it("app.sendUpdateModelContext returns error result when handler indicates error", async () => { - bridge.onupdatemodelcontext = async () => { - return { isError: true }; + it("app.updateModelContext works with structuredContent", async () => { + const receivedContexts: unknown[] = []; + bridge.onupdatemodelcontext = async (params) => { + receivedContexts.push(params); + return {}; }; await app.connect(appTransport); - const result = await app.sendUpdateModelContext({ - role: "user", - content: [{ type: "text", text: "Test" }], + const result = await app.updateModelContext({ + structuredContent: { selectedItems: 3, total: 150.0, currency: "USD" }, }); - expect(result.isError).toBe(true); + expect(receivedContexts).toHaveLength(1); + expect(receivedContexts[0]).toMatchObject({ + structuredContent: { selectedItems: 3, total: 150.0, currency: "USD" }, + }); + expect(result).toEqual({}); + }); + + it("app.updateModelContext throws when handler throws", async () => { + bridge.onupdatemodelcontext = async () => { + throw new Error("Context update failed"); + }; + + await app.connect(appTransport); + await expect( + app.updateModelContext({ + content: [{ type: "text", text: "Test" }], + }), + ).rejects.toThrow("Context update failed"); }); }); diff --git a/src/app-bridge.ts b/src/app-bridge.ts index e9f3603f..b329220f 100644 --- a/src/app-bridge.ts +++ b/src/app-bridge.ts @@ -5,6 +5,7 @@ import { CallToolRequestSchema, CallToolResult, CallToolResultSchema, + EmptyResult, Implementation, ListPromptsRequest, ListPromptsRequestSchema, @@ -53,7 +54,6 @@ import { McpUiAppCapabilities, McpUiUpdateModelContextRequest, McpUiUpdateModelContextRequestSchema, - McpUiUpdateModelContextResult, McpUiHostCapabilities, McpUiHostContext, McpUiHostContextChangedNotification, @@ -641,35 +641,33 @@ export class AppBridge extends Protocol< * The Guest UI sends `ui/update-model-context` requests to update the Host's * model context. Each request overwrites the previous context stored by the Guest UI. * Unlike logging messages, context updates are intended to be available to - * the model in future turns. Unlike messages, context updates do not trigger follow-ups + * the model in future turns. Unlike messages, context updates do not trigger follow-ups. + * + * The host will typically defer sending the context to the model until the + * next user message (including `ui/message`), and will only send the last + * update received. * * @example * ```typescript - * bridge.onupdatemodelcontext = async ({ role, content }, extra) => { - * try { - * // Update the model context with the new snapshot - * modelContext = { - * type: "app_context", - * role, - * content, - * timestamp: Date.now() - * }; - * return {}; - * } catch (err) { - * // Handle error and signal failure to the app - * return { isError: true }; - * } + * bridge.onupdatemodelcontext = async ({ content, structuredContent }, extra) => { + * // Update the model context with the new snapshot + * modelContext = { + * type: "app_context", + * content, + * structuredContent, + * timestamp: Date.now() + * }; + * return {}; * }; * ``` * * @see {@link McpUiUpdateModelContextRequest} for the request type - * @see {@link McpUiUpdateModelContextResult} for the result type */ set onupdatemodelcontext( callback: ( params: McpUiUpdateModelContextRequest["params"], extra: RequestHandlerExtra, - ) => Promise, + ) => Promise, ) { this.setRequestHandler( McpUiUpdateModelContextRequestSchema, diff --git a/src/app.ts b/src/app.ts index 8281ea8a..526a4876 100644 --- a/src/app.ts +++ b/src/app.ts @@ -9,6 +9,7 @@ import { CallToolRequestSchema, CallToolResult, CallToolResultSchema, + EmptyResultSchema, Implementation, ListToolsRequest, ListToolsRequestSchema, @@ -21,7 +22,6 @@ import { LATEST_PROTOCOL_VERSION, McpUiAppCapabilities, McpUiUpdateModelContextRequest, - McpUiUpdateModelContextResultSchema, McpUiHostCapabilities, McpUiHostContext, McpUiHostContextChangedNotification, @@ -812,26 +812,38 @@ export class App extends Protocol { } /** - * Send context updates to the host to be included in the agent's context. + * Update the host's model context with app state. * * Unlike `sendLog`, which is for debugging/telemetry, context updates - * are inteded to be available to the model in future reasoning, + * are intended to be available to the model in future reasoning, * without requiring a follow-up action (like `sendMessage`). * - * @param params - Context role and content (same structure as ui/message) + * The host will typically defer sending the context to the model until the + * next user message (including `ui/message`), and will only send the last + * update received. Each call overwrites any previous context update. + * + * @param params - Context content and/or structured content * @param options - Request options (timeout, etc.) * + * @throws {Error} If the host rejects the context update (e.g., unsupported content type) + * * @example Update model context with current app state * ```typescript - * await app.sendUpdateModelContext({ - * role: "user", + * await app.updateModelContext({ * content: [{ type: "text", text: "User selected 3 items totaling $150.00" }] * }); * ``` * + * @example Update with structured content + * ```typescript + * await app.updateModelContext({ + * structuredContent: { selectedItems: 3, total: 150.00, currency: "USD" } + * }); + * ``` + * * @returns Promise that resolves when the context update is acknowledged */ - sendUpdateModelContext( + updateModelContext( params: McpUiUpdateModelContextRequest["params"], options?: RequestOptions, ) { @@ -840,7 +852,7 @@ export class App extends Protocol { method: "ui/update-model-context", params, }, - McpUiUpdateModelContextResultSchema, + EmptyResultSchema, options, ); } diff --git a/src/generated/schema.json b/src/generated/schema.json index 85e65e43..3146e536 100644 --- a/src/generated/schema.json +++ b/src/generated/schema.json @@ -93,7 +93,44 @@ "updateModelContext": { "description": "Host accepts context updates to be included in the model's context for future turns.", "type": "object", - "properties": {}, + "properties": { + "text": { + "description": "Host supports text content blocks.", + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "image": { + "description": "Host supports image content blocks.", + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "audio": { + "description": "Host supports audio content blocks.", + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "resource": { + "description": "Host supports resource content blocks.", + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "resourceLink": { + "description": "Host supports resource link content blocks.", + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "structuredContent": { + "description": "Host supports structured content.", + "type": "object", + "properties": {}, + "additionalProperties": false + } + }, "additionalProperties": false } }, @@ -1892,7 +1929,44 @@ "updateModelContext": { "description": "Host accepts context updates to be included in the model's context for future turns.", "type": "object", - "properties": {}, + "properties": { + "text": { + "description": "Host supports text content blocks.", + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "image": { + "description": "Host supports image content blocks.", + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "audio": { + "description": "Host supports audio content blocks.", + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "resource": { + "description": "Host supports resource content blocks.", + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "resourceLink": { + "description": "Host supports resource link content blocks.", + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "structuredContent": { + "description": "Host supports structured content.", + "type": "object", + "properties": {}, + "additionalProperties": false + } + }, "additionalProperties": false } }, @@ -4299,11 +4373,6 @@ "params": { "type": "object", "properties": { - "role": { - "description": "Message role, currently only \"user\" is supported.", - "type": "string", - "const": "user" - }, "content": { "description": "Context content blocks (text, image, etc.).", "type": "array", @@ -4616,9 +4685,13 @@ } ] } + }, + "structuredContent": { + "description": "Structured content for machine-readable context data.", + "type": "object", + "additionalProperties": {} } }, - "required": ["role", "content"], "additionalProperties": false } }, @@ -4628,12 +4701,7 @@ "McpUiUpdateModelContextResult": { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", - "properties": { - "isError": { - "description": "True if the host rejected or failed to store the context update.", - "type": "boolean" - } - }, + "properties": {}, "additionalProperties": {} } } diff --git a/src/generated/schema.test.ts b/src/generated/schema.test.ts index 98e52e75..b9b837e0 100644 --- a/src/generated/schema.test.ts +++ b/src/generated/schema.test.ts @@ -11,303 +11,139 @@ function expectType(_: T) { /* noop */ } -export type McpUiThemeSchemaInferredType = z.infer< - typeof generated.McpUiThemeSchema ->; +export type McpUiThemeSchemaInferredType = z.infer; -export type McpUiDisplayModeSchemaInferredType = z.infer< - typeof generated.McpUiDisplayModeSchema ->; +export type McpUiDisplayModeSchemaInferredType = z.infer; -export type McpUiStyleVariableKeySchemaInferredType = z.infer< - typeof generated.McpUiStyleVariableKeySchema ->; +export type McpUiStyleVariableKeySchemaInferredType = z.infer; -export type McpUiStylesSchemaInferredType = z.infer< - typeof generated.McpUiStylesSchema ->; +export type McpUiStylesSchemaInferredType = z.infer; -export type McpUiOpenLinkRequestSchemaInferredType = z.infer< - typeof generated.McpUiOpenLinkRequestSchema ->; +export type McpUiOpenLinkRequestSchemaInferredType = z.infer; -export type McpUiOpenLinkResultSchemaInferredType = z.infer< - typeof generated.McpUiOpenLinkResultSchema ->; +export type McpUiOpenLinkResultSchemaInferredType = z.infer; -export type McpUiMessageResultSchemaInferredType = z.infer< - typeof generated.McpUiMessageResultSchema ->; +export type McpUiMessageResultSchemaInferredType = z.infer; -export type McpUiSandboxProxyReadyNotificationSchemaInferredType = z.infer< - typeof generated.McpUiSandboxProxyReadyNotificationSchema ->; +export type McpUiSandboxProxyReadyNotificationSchemaInferredType = z.infer; -export type McpUiSandboxResourceReadyNotificationSchemaInferredType = z.infer< - typeof generated.McpUiSandboxResourceReadyNotificationSchema ->; +export type McpUiSandboxResourceReadyNotificationSchemaInferredType = z.infer; -export type McpUiSizeChangedNotificationSchemaInferredType = z.infer< - typeof generated.McpUiSizeChangedNotificationSchema ->; - -export type McpUiToolInputNotificationSchemaInferredType = z.infer< - typeof generated.McpUiToolInputNotificationSchema ->; - -export type McpUiToolInputPartialNotificationSchemaInferredType = z.infer< - typeof generated.McpUiToolInputPartialNotificationSchema ->; - -export type McpUiToolCancelledNotificationSchemaInferredType = z.infer< - typeof generated.McpUiToolCancelledNotificationSchema ->; - -export type McpUiHostCssSchemaInferredType = z.infer< - typeof generated.McpUiHostCssSchema ->; - -export type McpUiHostStylesSchemaInferredType = z.infer< - typeof generated.McpUiHostStylesSchema ->; - -export type McpUiUpdateModelContextResultSchemaInferredType = z.infer< - typeof generated.McpUiUpdateModelContextResultSchema ->; - -export type McpUiResourceTeardownRequestSchemaInferredType = z.infer< - typeof generated.McpUiResourceTeardownRequestSchema ->; - -export type McpUiResourceTeardownResultSchemaInferredType = z.infer< - typeof generated.McpUiResourceTeardownResultSchema ->; - -export type McpUiHostCapabilitiesSchemaInferredType = z.infer< - typeof generated.McpUiHostCapabilitiesSchema ->; - -export type McpUiAppCapabilitiesSchemaInferredType = z.infer< - typeof generated.McpUiAppCapabilitiesSchema ->; - -export type McpUiInitializedNotificationSchemaInferredType = z.infer< - typeof generated.McpUiInitializedNotificationSchema ->; - -export type McpUiResourceCspSchemaInferredType = z.infer< - typeof generated.McpUiResourceCspSchema ->; - -export type McpUiResourceMetaSchemaInferredType = z.infer< - typeof generated.McpUiResourceMetaSchema ->; - -export type McpUiRequestDisplayModeRequestSchemaInferredType = z.infer< - typeof generated.McpUiRequestDisplayModeRequestSchema ->; - -export type McpUiRequestDisplayModeResultSchemaInferredType = z.infer< - typeof generated.McpUiRequestDisplayModeResultSchema ->; - -export type McpUiToolVisibilitySchemaInferredType = z.infer< - typeof generated.McpUiToolVisibilitySchema ->; - -export type McpUiToolMetaSchemaInferredType = z.infer< - typeof generated.McpUiToolMetaSchema ->; - -export type McpUiMessageRequestSchemaInferredType = z.infer< - typeof generated.McpUiMessageRequestSchema ->; - -export type McpUiToolResultNotificationSchemaInferredType = z.infer< - typeof generated.McpUiToolResultNotificationSchema ->; - -export type McpUiHostContextSchemaInferredType = z.infer< - typeof generated.McpUiHostContextSchema ->; - -export type McpUiHostContextChangedNotificationSchemaInferredType = z.infer< - typeof generated.McpUiHostContextChangedNotificationSchema ->; - -export type McpUiUpdateModelContextRequestSchemaInferredType = z.infer< - typeof generated.McpUiUpdateModelContextRequestSchema ->; - -export type McpUiInitializeRequestSchemaInferredType = z.infer< - typeof generated.McpUiInitializeRequestSchema ->; - -export type McpUiInitializeResultSchemaInferredType = z.infer< - typeof generated.McpUiInitializeResultSchema ->; - -expectType({} as McpUiThemeSchemaInferredType); -expectType({} as spec.McpUiTheme); -expectType({} as McpUiDisplayModeSchemaInferredType); -expectType({} as spec.McpUiDisplayMode); -expectType( - {} as McpUiStyleVariableKeySchemaInferredType, -); -expectType( - {} as spec.McpUiStyleVariableKey, -); -expectType({} as McpUiStylesSchemaInferredType); -expectType({} as spec.McpUiStyles); -expectType( - {} as McpUiOpenLinkRequestSchemaInferredType, -); -expectType( - {} as spec.McpUiOpenLinkRequest, -); -expectType( - {} as McpUiOpenLinkResultSchemaInferredType, -); -expectType( - {} as spec.McpUiOpenLinkResult, -); -expectType({} as McpUiMessageResultSchemaInferredType); -expectType({} as spec.McpUiMessageResult); -expectType( - {} as McpUiSandboxProxyReadyNotificationSchemaInferredType, -); -expectType( - {} as spec.McpUiSandboxProxyReadyNotification, -); -expectType( - {} as McpUiSandboxResourceReadyNotificationSchemaInferredType, -); -expectType( - {} as spec.McpUiSandboxResourceReadyNotification, -); -expectType( - {} as McpUiSizeChangedNotificationSchemaInferredType, -); -expectType( - {} as spec.McpUiSizeChangedNotification, -); -expectType( - {} as McpUiToolInputNotificationSchemaInferredType, -); -expectType( - {} as spec.McpUiToolInputNotification, -); -expectType( - {} as McpUiToolInputPartialNotificationSchemaInferredType, -); -expectType( - {} as spec.McpUiToolInputPartialNotification, -); -expectType( - {} as McpUiToolCancelledNotificationSchemaInferredType, -); -expectType( - {} as spec.McpUiToolCancelledNotification, -); -expectType({} as McpUiHostCssSchemaInferredType); -expectType({} as spec.McpUiHostCss); -expectType({} as McpUiHostStylesSchemaInferredType); -expectType({} as spec.McpUiHostStyles); -expectType( - {} as McpUiUpdateModelContextResultSchemaInferredType, -); -expectType( - {} as spec.McpUiUpdateModelContextResult, -); -expectType( - {} as McpUiResourceTeardownRequestSchemaInferredType, -); -expectType( - {} as spec.McpUiResourceTeardownRequest, -); -expectType( - {} as McpUiResourceTeardownResultSchemaInferredType, -); -expectType( - {} as spec.McpUiResourceTeardownResult, -); -expectType( - {} as McpUiHostCapabilitiesSchemaInferredType, -); -expectType( - {} as spec.McpUiHostCapabilities, -); -expectType( - {} as McpUiAppCapabilitiesSchemaInferredType, -); -expectType( - {} as spec.McpUiAppCapabilities, -); -expectType( - {} as McpUiInitializedNotificationSchemaInferredType, -); -expectType( - {} as spec.McpUiInitializedNotification, -); -expectType({} as McpUiResourceCspSchemaInferredType); -expectType({} as spec.McpUiResourceCsp); -expectType({} as McpUiResourceMetaSchemaInferredType); -expectType({} as spec.McpUiResourceMeta); -expectType( - {} as McpUiRequestDisplayModeRequestSchemaInferredType, -); -expectType( - {} as spec.McpUiRequestDisplayModeRequest, -); -expectType( - {} as McpUiRequestDisplayModeResultSchemaInferredType, -); -expectType( - {} as spec.McpUiRequestDisplayModeResult, -); -expectType( - {} as McpUiToolVisibilitySchemaInferredType, -); -expectType( - {} as spec.McpUiToolVisibility, -); -expectType({} as McpUiToolMetaSchemaInferredType); -expectType({} as spec.McpUiToolMeta); -expectType( - {} as McpUiMessageRequestSchemaInferredType, -); -expectType( - {} as spec.McpUiMessageRequest, -); -expectType( - {} as McpUiToolResultNotificationSchemaInferredType, -); -expectType( - {} as spec.McpUiToolResultNotification, -); -expectType({} as McpUiHostContextSchemaInferredType); -expectType({} as spec.McpUiHostContext); -expectType( - {} as McpUiHostContextChangedNotificationSchemaInferredType, -); -expectType( - {} as spec.McpUiHostContextChangedNotification, -); -expectType( - {} as McpUiUpdateModelContextRequestSchemaInferredType, -); -expectType( - {} as spec.McpUiUpdateModelContextRequest, -); -expectType( - {} as McpUiInitializeRequestSchemaInferredType, -); -expectType( - {} as spec.McpUiInitializeRequest, -); -expectType( - {} as McpUiInitializeResultSchemaInferredType, -); -expectType( - {} as spec.McpUiInitializeResult, -); +export type McpUiSizeChangedNotificationSchemaInferredType = z.infer; + +export type McpUiToolInputNotificationSchemaInferredType = z.infer; + +export type McpUiToolInputPartialNotificationSchemaInferredType = z.infer; + +export type McpUiToolCancelledNotificationSchemaInferredType = z.infer; + +export type McpUiHostCssSchemaInferredType = z.infer; + +export type McpUiHostStylesSchemaInferredType = z.infer; + +export type McpUiUpdateModelContextResultSchemaInferredType = z.infer; + +export type McpUiResourceTeardownRequestSchemaInferredType = z.infer; + +export type McpUiResourceTeardownResultSchemaInferredType = z.infer; + +export type McpUiHostCapabilitiesSchemaInferredType = z.infer; + +export type McpUiAppCapabilitiesSchemaInferredType = z.infer; + +export type McpUiInitializedNotificationSchemaInferredType = z.infer; + +export type McpUiResourceCspSchemaInferredType = z.infer; + +export type McpUiResourceMetaSchemaInferredType = z.infer; + +export type McpUiRequestDisplayModeRequestSchemaInferredType = z.infer; + +export type McpUiRequestDisplayModeResultSchemaInferredType = z.infer; + +export type McpUiToolVisibilitySchemaInferredType = z.infer; + +export type McpUiToolMetaSchemaInferredType = z.infer; + +export type McpUiMessageRequestSchemaInferredType = z.infer; + +export type McpUiToolResultNotificationSchemaInferredType = z.infer; + +export type McpUiHostContextSchemaInferredType = z.infer; + +export type McpUiHostContextChangedNotificationSchemaInferredType = z.infer; + +export type McpUiUpdateModelContextRequestSchemaInferredType = z.infer; + +export type McpUiInitializeRequestSchemaInferredType = z.infer; + +export type McpUiInitializeResultSchemaInferredType = z.infer; + +expectType({} as McpUiThemeSchemaInferredType) +expectType({} as spec.McpUiTheme) +expectType({} as McpUiDisplayModeSchemaInferredType) +expectType({} as spec.McpUiDisplayMode) +expectType({} as McpUiStyleVariableKeySchemaInferredType) +expectType({} as spec.McpUiStyleVariableKey) +expectType({} as McpUiStylesSchemaInferredType) +expectType({} as spec.McpUiStyles) +expectType({} as McpUiOpenLinkRequestSchemaInferredType) +expectType({} as spec.McpUiOpenLinkRequest) +expectType({} as McpUiOpenLinkResultSchemaInferredType) +expectType({} as spec.McpUiOpenLinkResult) +expectType({} as McpUiMessageResultSchemaInferredType) +expectType({} as spec.McpUiMessageResult) +expectType({} as McpUiSandboxProxyReadyNotificationSchemaInferredType) +expectType({} as spec.McpUiSandboxProxyReadyNotification) +expectType({} as McpUiSandboxResourceReadyNotificationSchemaInferredType) +expectType({} as spec.McpUiSandboxResourceReadyNotification) +expectType({} as McpUiSizeChangedNotificationSchemaInferredType) +expectType({} as spec.McpUiSizeChangedNotification) +expectType({} as McpUiToolInputNotificationSchemaInferredType) +expectType({} as spec.McpUiToolInputNotification) +expectType({} as McpUiToolInputPartialNotificationSchemaInferredType) +expectType({} as spec.McpUiToolInputPartialNotification) +expectType({} as McpUiToolCancelledNotificationSchemaInferredType) +expectType({} as spec.McpUiToolCancelledNotification) +expectType({} as McpUiHostCssSchemaInferredType) +expectType({} as spec.McpUiHostCss) +expectType({} as McpUiHostStylesSchemaInferredType) +expectType({} as spec.McpUiHostStyles) +expectType({} as McpUiUpdateModelContextResultSchemaInferredType) +expectType({} as spec.McpUiUpdateModelContextResult) +expectType({} as McpUiResourceTeardownRequestSchemaInferredType) +expectType({} as spec.McpUiResourceTeardownRequest) +expectType({} as McpUiResourceTeardownResultSchemaInferredType) +expectType({} as spec.McpUiResourceTeardownResult) +expectType({} as McpUiHostCapabilitiesSchemaInferredType) +expectType({} as spec.McpUiHostCapabilities) +expectType({} as McpUiAppCapabilitiesSchemaInferredType) +expectType({} as spec.McpUiAppCapabilities) +expectType({} as McpUiInitializedNotificationSchemaInferredType) +expectType({} as spec.McpUiInitializedNotification) +expectType({} as McpUiResourceCspSchemaInferredType) +expectType({} as spec.McpUiResourceCsp) +expectType({} as McpUiResourceMetaSchemaInferredType) +expectType({} as spec.McpUiResourceMeta) +expectType({} as McpUiRequestDisplayModeRequestSchemaInferredType) +expectType({} as spec.McpUiRequestDisplayModeRequest) +expectType({} as McpUiRequestDisplayModeResultSchemaInferredType) +expectType({} as spec.McpUiRequestDisplayModeResult) +expectType({} as McpUiToolVisibilitySchemaInferredType) +expectType({} as spec.McpUiToolVisibility) +expectType({} as McpUiToolMetaSchemaInferredType) +expectType({} as spec.McpUiToolMeta) +expectType({} as McpUiMessageRequestSchemaInferredType) +expectType({} as spec.McpUiMessageRequest) +expectType({} as McpUiToolResultNotificationSchemaInferredType) +expectType({} as spec.McpUiToolResultNotification) +expectType({} as McpUiHostContextSchemaInferredType) +expectType({} as spec.McpUiHostContext) +expectType({} as McpUiHostContextChangedNotificationSchemaInferredType) +expectType({} as spec.McpUiHostContextChangedNotification) +expectType({} as McpUiUpdateModelContextRequestSchemaInferredType) +expectType({} as spec.McpUiUpdateModelContextRequest) +expectType({} as McpUiInitializeRequestSchemaInferredType) +expectType({} as spec.McpUiInitializeRequest) +expectType({} as McpUiInitializeResultSchemaInferredType) +expectType({} as spec.McpUiInitializeResult) diff --git a/src/generated/schema.ts b/src/generated/schema.ts index e01184db..62defe18 100644 --- a/src/generated/schema.ts +++ b/src/generated/schema.ts @@ -13,100 +13,17 @@ import { /** * @description Color theme preference for the host environment. */ -export const McpUiThemeSchema = z - .union([z.literal("light"), z.literal("dark")]) - .describe("Color theme preference for the host environment."); +export const McpUiThemeSchema = z.union([z.literal("light"), z.literal("dark")]).describe("Color theme preference for the host environment."); /** * @description Display mode for UI presentation. */ -export const McpUiDisplayModeSchema = z - .union([z.literal("inline"), z.literal("fullscreen"), z.literal("pip")]) - .describe("Display mode for UI presentation."); +export const McpUiDisplayModeSchema = z.union([z.literal("inline"), z.literal("fullscreen"), z.literal("pip")]).describe("Display mode for UI presentation."); /** * @description CSS variable keys available to MCP apps for theming. */ -export const McpUiStyleVariableKeySchema = z - .union([ - z.literal("--color-background-primary"), - z.literal("--color-background-secondary"), - z.literal("--color-background-tertiary"), - z.literal("--color-background-inverse"), - z.literal("--color-background-ghost"), - z.literal("--color-background-info"), - z.literal("--color-background-danger"), - z.literal("--color-background-success"), - z.literal("--color-background-warning"), - z.literal("--color-background-disabled"), - z.literal("--color-text-primary"), - z.literal("--color-text-secondary"), - z.literal("--color-text-tertiary"), - z.literal("--color-text-inverse"), - z.literal("--color-text-info"), - z.literal("--color-text-danger"), - z.literal("--color-text-success"), - z.literal("--color-text-warning"), - z.literal("--color-text-disabled"), - z.literal("--color-text-ghost"), - z.literal("--color-border-primary"), - z.literal("--color-border-secondary"), - z.literal("--color-border-tertiary"), - z.literal("--color-border-inverse"), - z.literal("--color-border-ghost"), - z.literal("--color-border-info"), - z.literal("--color-border-danger"), - z.literal("--color-border-success"), - z.literal("--color-border-warning"), - z.literal("--color-border-disabled"), - z.literal("--color-ring-primary"), - z.literal("--color-ring-secondary"), - z.literal("--color-ring-inverse"), - z.literal("--color-ring-info"), - z.literal("--color-ring-danger"), - z.literal("--color-ring-success"), - z.literal("--color-ring-warning"), - z.literal("--font-sans"), - z.literal("--font-mono"), - z.literal("--font-weight-normal"), - z.literal("--font-weight-medium"), - z.literal("--font-weight-semibold"), - z.literal("--font-weight-bold"), - z.literal("--font-text-xs-size"), - z.literal("--font-text-sm-size"), - z.literal("--font-text-md-size"), - z.literal("--font-text-lg-size"), - z.literal("--font-heading-xs-size"), - z.literal("--font-heading-sm-size"), - z.literal("--font-heading-md-size"), - z.literal("--font-heading-lg-size"), - z.literal("--font-heading-xl-size"), - z.literal("--font-heading-2xl-size"), - z.literal("--font-heading-3xl-size"), - z.literal("--font-text-xs-line-height"), - z.literal("--font-text-sm-line-height"), - z.literal("--font-text-md-line-height"), - z.literal("--font-text-lg-line-height"), - z.literal("--font-heading-xs-line-height"), - z.literal("--font-heading-sm-line-height"), - z.literal("--font-heading-md-line-height"), - z.literal("--font-heading-lg-line-height"), - z.literal("--font-heading-xl-line-height"), - z.literal("--font-heading-2xl-line-height"), - z.literal("--font-heading-3xl-line-height"), - z.literal("--border-radius-xs"), - z.literal("--border-radius-sm"), - z.literal("--border-radius-md"), - z.literal("--border-radius-lg"), - z.literal("--border-radius-xl"), - z.literal("--border-radius-full"), - z.literal("--border-width-regular"), - z.literal("--shadow-hairline"), - z.literal("--shadow-sm"), - z.literal("--shadow-md"), - z.literal("--shadow-lg"), - ]) - .describe("CSS variable keys available to MCP apps for theming."); +export const McpUiStyleVariableKeySchema = z.union([z.literal("--color-background-primary"), z.literal("--color-background-secondary"), z.literal("--color-background-tertiary"), z.literal("--color-background-inverse"), z.literal("--color-background-ghost"), z.literal("--color-background-info"), z.literal("--color-background-danger"), z.literal("--color-background-success"), z.literal("--color-background-warning"), z.literal("--color-background-disabled"), z.literal("--color-text-primary"), z.literal("--color-text-secondary"), z.literal("--color-text-tertiary"), z.literal("--color-text-inverse"), z.literal("--color-text-info"), z.literal("--color-text-danger"), z.literal("--color-text-success"), z.literal("--color-text-warning"), z.literal("--color-text-disabled"), z.literal("--color-text-ghost"), z.literal("--color-border-primary"), z.literal("--color-border-secondary"), z.literal("--color-border-tertiary"), z.literal("--color-border-inverse"), z.literal("--color-border-ghost"), z.literal("--color-border-info"), z.literal("--color-border-danger"), z.literal("--color-border-success"), z.literal("--color-border-warning"), z.literal("--color-border-disabled"), z.literal("--color-ring-primary"), z.literal("--color-ring-secondary"), z.literal("--color-ring-inverse"), z.literal("--color-ring-info"), z.literal("--color-ring-danger"), z.literal("--color-ring-success"), z.literal("--color-ring-warning"), z.literal("--font-sans"), z.literal("--font-mono"), z.literal("--font-weight-normal"), z.literal("--font-weight-medium"), z.literal("--font-weight-semibold"), z.literal("--font-weight-bold"), z.literal("--font-text-xs-size"), z.literal("--font-text-sm-size"), z.literal("--font-text-md-size"), z.literal("--font-text-lg-size"), z.literal("--font-heading-xs-size"), z.literal("--font-heading-sm-size"), z.literal("--font-heading-md-size"), z.literal("--font-heading-lg-size"), z.literal("--font-heading-xl-size"), z.literal("--font-heading-2xl-size"), z.literal("--font-heading-3xl-size"), z.literal("--font-text-xs-line-height"), z.literal("--font-text-sm-line-height"), z.literal("--font-text-md-line-height"), z.literal("--font-text-lg-line-height"), z.literal("--font-heading-xs-line-height"), z.literal("--font-heading-sm-line-height"), z.literal("--font-heading-md-line-height"), z.literal("--font-heading-lg-line-height"), z.literal("--font-heading-xl-line-height"), z.literal("--font-heading-2xl-line-height"), z.literal("--font-heading-3xl-line-height"), z.literal("--border-radius-xs"), z.literal("--border-radius-sm"), z.literal("--border-radius-md"), z.literal("--border-radius-lg"), z.literal("--border-radius-xl"), z.literal("--border-radius-full"), z.literal("--border-width-regular"), z.literal("--shadow-hairline"), z.literal("--shadow-sm"), z.literal("--shadow-md"), z.literal("--shadow-lg")]).describe("CSS variable keys available to MCP apps for theming."); /** * @description Style variables for theming MCP apps. @@ -117,62 +34,37 @@ export const McpUiStyleVariableKeySchema = z * Note: This type uses `Record` rather than `Partial>` * for compatibility with Zod schema generation. Both are functionally equivalent for validation. */ -export const McpUiStylesSchema = z - .record( - McpUiStyleVariableKeySchema.describe( - "Style variables for theming MCP apps.\n\nIndividual style keys are optional - hosts may provide any subset of these values.\nValues are strings containing CSS values (colors, sizes, font stacks, etc.).\n\nNote: This type uses `Record` rather than `Partial>`\nfor compatibility with Zod schema generation. Both are functionally equivalent for validation.", - ), - z - .union([z.string(), z.undefined()]) - .describe( - "Style variables for theming MCP apps.\n\nIndividual style keys are optional - hosts may provide any subset of these values.\nValues are strings containing CSS values (colors, sizes, font stacks, etc.).\n\nNote: This type uses `Record` rather than `Partial>`\nfor compatibility with Zod schema generation. Both are functionally equivalent for validation.", - ), - ) - .describe( - "Style variables for theming MCP apps.\n\nIndividual style keys are optional - hosts may provide any subset of these values.\nValues are strings containing CSS values (colors, sizes, font stacks, etc.).\n\nNote: This type uses `Record` rather than `Partial>`\nfor compatibility with Zod schema generation. Both are functionally equivalent for validation.", - ); +export const McpUiStylesSchema = z.record(McpUiStyleVariableKeySchema.describe("Style variables for theming MCP apps.\n\nIndividual style keys are optional - hosts may provide any subset of these values.\nValues are strings containing CSS values (colors, sizes, font stacks, etc.).\n\nNote: This type uses `Record` rather than `Partial>`\nfor compatibility with Zod schema generation. Both are functionally equivalent for validation."), z.union([z.string(), z.undefined()]).describe("Style variables for theming MCP apps.\n\nIndividual style keys are optional - hosts may provide any subset of these values.\nValues are strings containing CSS values (colors, sizes, font stacks, etc.).\n\nNote: This type uses `Record` rather than `Partial>`\nfor compatibility with Zod schema generation. Both are functionally equivalent for validation.")).describe("Style variables for theming MCP apps.\n\nIndividual style keys are optional - hosts may provide any subset of these values.\nValues are strings containing CSS values (colors, sizes, font stacks, etc.).\n\nNote: This type uses `Record` rather than `Partial>`\nfor compatibility with Zod schema generation. Both are functionally equivalent for validation."); /** * @description Request to open an external URL in the host's default browser. * @see {@link app.App.sendOpenLink} for the method that sends this request */ export const McpUiOpenLinkRequestSchema = z.object({ - method: z.literal("ui/open-link"), - params: z.object({ - /** @description URL to open in the host's browser */ - url: z.string().describe("URL to open in the host's browser"), - }), + method: z.literal("ui/open-link"), + params: z.object({ + /** @description URL to open in the host's browser */ + url: z.string().describe("URL to open in the host's browser") + }) }); /** * @description Result from opening a URL. * @see {@link McpUiOpenLinkRequest} */ -export const McpUiOpenLinkResultSchema = z - .object({ +export const McpUiOpenLinkResultSchema = z.object({ /** @description True if the host failed to open the URL (e.g., due to security policy). */ - isError: z - .boolean() - .optional() - .describe( - "True if the host failed to open the URL (e.g., due to security policy).", - ), - }) - .passthrough(); + isError: z.boolean().optional().describe("True if the host failed to open the URL (e.g., due to security policy).") +}).passthrough(); /** * @description Result from sending a message. * @see {@link McpUiMessageRequest} */ -export const McpUiMessageResultSchema = z - .object({ +export const McpUiMessageResultSchema = z.object({ /** @description True if the host rejected or failed to deliver the message. */ - isError: z - .boolean() - .optional() - .describe("True if the host rejected or failed to deliver the message."), - }) - .passthrough(); + isError: z.boolean().optional().describe("True if the host rejected or failed to deliver the message.") +}).passthrough(); /** * @description Notification that the sandbox proxy iframe is ready to receive content. @@ -180,8 +72,8 @@ export const McpUiMessageResultSchema = z * @see https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/draft/apps.mdx#sandbox-proxy */ export const McpUiSandboxProxyReadyNotificationSchema = z.object({ - method: z.literal("ui/notifications/sandbox-proxy-ready"), - params: z.object({}), + method: z.literal("ui/notifications/sandbox-proxy-ready"), + params: z.object({}) }); /** @@ -190,34 +82,20 @@ export const McpUiSandboxProxyReadyNotificationSchema = z.object({ * @see https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/draft/apps.mdx#sandbox-proxy */ export const McpUiSandboxResourceReadyNotificationSchema = z.object({ - method: z.literal("ui/notifications/sandbox-resource-ready"), - params: z.object({ - /** @description HTML content to load into the inner iframe. */ - html: z.string().describe("HTML content to load into the inner iframe."), - /** @description Optional override for the inner iframe's sandbox attribute. */ - sandbox: z - .string() - .optional() - .describe("Optional override for the inner iframe's sandbox attribute."), - /** @description CSP configuration from resource metadata. */ - csp: z - .object({ - /** @description Origins for network requests (fetch/XHR/WebSocket). */ - connectDomains: z - .array(z.string()) - .optional() - .describe("Origins for network requests (fetch/XHR/WebSocket)."), - /** @description Origins for static resources (scripts, images, styles, fonts). */ - resourceDomains: z - .array(z.string()) - .optional() - .describe( - "Origins for static resources (scripts, images, styles, fonts).", - ), - }) - .optional() - .describe("CSP configuration from resource metadata."), - }), + method: z.literal("ui/notifications/sandbox-resource-ready"), + params: z.object({ + /** @description HTML content to load into the inner iframe. */ + html: z.string().describe("HTML content to load into the inner iframe."), + /** @description Optional override for the inner iframe's sandbox attribute. */ + sandbox: z.string().optional().describe("Optional override for the inner iframe's sandbox attribute."), + /** @description CSP configuration from resource metadata. */ + csp: z.object({ + /** @description Origins for network requests (fetch/XHR/WebSocket). */ + connectDomains: z.array(z.string()).optional().describe("Origins for network requests (fetch/XHR/WebSocket)."), + /** @description Origins for static resources (scripts, images, styles, fonts). */ + resourceDomains: z.array(z.string()).optional().describe("Origins for static resources (scripts, images, styles, fonts).") + }).optional().describe("CSP configuration from resource metadata.") + }) }); /** @@ -225,51 +103,35 @@ export const McpUiSandboxResourceReadyNotificationSchema = z.object({ * @see {@link app.App.sendSizeChanged} for the method to send this from Guest UI */ export const McpUiSizeChangedNotificationSchema = z.object({ - method: z.literal("ui/notifications/size-changed"), - params: z.object({ - /** @description New width in pixels. */ - width: z.number().optional().describe("New width in pixels."), - /** @description New height in pixels. */ - height: z.number().optional().describe("New height in pixels."), - }), + method: z.literal("ui/notifications/size-changed"), + params: z.object({ + /** @description New width in pixels. */ + width: z.number().optional().describe("New width in pixels."), + /** @description New height in pixels. */ + height: z.number().optional().describe("New height in pixels.") + }) }); /** * @description Notification containing complete tool arguments (Host -> Guest UI). */ export const McpUiToolInputNotificationSchema = z.object({ - method: z.literal("ui/notifications/tool-input"), - params: z.object({ - /** @description Complete tool call arguments as key-value pairs. */ - arguments: z - .record( - z.string(), - z - .unknown() - .describe("Complete tool call arguments as key-value pairs."), - ) - .optional() - .describe("Complete tool call arguments as key-value pairs."), - }), + method: z.literal("ui/notifications/tool-input"), + params: z.object({ + /** @description Complete tool call arguments as key-value pairs. */ + arguments: z.record(z.string(), z.unknown().describe("Complete tool call arguments as key-value pairs.")).optional().describe("Complete tool call arguments as key-value pairs.") + }) }); /** * @description Notification containing partial/streaming tool arguments (Host -> Guest UI). */ export const McpUiToolInputPartialNotificationSchema = z.object({ - method: z.literal("ui/notifications/tool-input-partial"), - params: z.object({ - /** @description Partial tool call arguments (incomplete, may change). */ - arguments: z - .record( - z.string(), - z - .unknown() - .describe("Partial tool call arguments (incomplete, may change)."), - ) - .optional() - .describe("Partial tool call arguments (incomplete, may change)."), - }), + method: z.literal("ui/notifications/tool-input-partial"), + params: z.object({ + /** @description Partial tool call arguments (incomplete, may change). */ + arguments: z.record(z.string(), z.unknown().describe("Partial tool call arguments (incomplete, may change).")).optional().describe("Partial tool call arguments (incomplete, may change).") + }) }); /** @@ -278,123 +140,89 @@ export const McpUiToolInputPartialNotificationSchema = z.object({ * sampling error, classifier intervention, etc.). */ export const McpUiToolCancelledNotificationSchema = z.object({ - method: z.literal("ui/notifications/tool-cancelled"), - params: z.object({ - /** @description Optional reason for the cancellation (e.g., "user action", "timeout"). */ - reason: z - .string() - .optional() - .describe( - 'Optional reason for the cancellation (e.g., "user action", "timeout").', - ), - }), + method: z.literal("ui/notifications/tool-cancelled"), + params: z.object({ + /** @description Optional reason for the cancellation (e.g., "user action", "timeout"). */ + reason: z.string().optional().describe("Optional reason for the cancellation (e.g., \"user action\", \"timeout\").") + }) }); /** * @description CSS blocks that can be injected by apps. */ export const McpUiHostCssSchema = z.object({ - /** @description CSS for font loading (@font-face rules or @import statements). Apps must apply using applyHostFonts(). */ - fonts: z - .string() - .optional() - .describe("CSS for font loading (@font-face rules or"), + /** @description CSS for font loading (@font-face rules or @import statements). Apps must apply using applyHostFonts(). */ + fonts: z.string().optional().describe("CSS for font loading (@font-face rules or") }); /** * @description Style configuration for theming MCP apps. */ export const McpUiHostStylesSchema = z.object({ - /** @description CSS variables for theming the app. */ - variables: McpUiStylesSchema.optional().describe( - "CSS variables for theming the app.", - ), - /** @description CSS blocks that apps can inject. */ - css: McpUiHostCssSchema.optional().describe( - "CSS blocks that apps can inject.", - ), + /** @description CSS variables for theming the app. */ + variables: McpUiStylesSchema.optional().describe("CSS variables for theming the app."), + /** @description CSS blocks that apps can inject. */ + css: McpUiHostCssSchema.optional().describe("CSS blocks that apps can inject.") }); /** * @description Result from setting the agent's model context. + * Empty on success; errors are signaled via JSON-RPC error responses. * @see {@link McpUiUpdateModelContextRequest} */ -export const McpUiUpdateModelContextResultSchema = z - .object({ - /** @description True if the host rejected or failed to store the context update. */ - isError: z - .boolean() - .optional() - .describe( - "True if the host rejected or failed to store the context update.", - ), - }) - .passthrough(); +export const McpUiUpdateModelContextResultSchema = z.record(z.string(), z.unknown()); /** * @description Request for graceful shutdown of the Guest UI (Host -> Guest UI). * @see {@link app-bridge.AppBridge.teardownResource} for the host method that sends this */ export const McpUiResourceTeardownRequestSchema = z.object({ - method: z.literal("ui/resource-teardown"), - params: z.object({}), + method: z.literal("ui/resource-teardown"), + params: z.object({}) }); /** * @description Result from graceful shutdown request. * @see {@link McpUiResourceTeardownRequest} */ -export const McpUiResourceTeardownResultSchema = z.record( - z.string(), - z.unknown(), -); +export const McpUiResourceTeardownResultSchema = z.record(z.string(), z.unknown()); /** * @description Capabilities supported by the host application. * @see {@link McpUiInitializeResult} for the initialization result that includes these capabilities */ export const McpUiHostCapabilitiesSchema = z.object({ - /** @description Experimental features (structure TBD). */ - experimental: z - .object({}) - .optional() - .describe("Experimental features (structure TBD)."), - /** @description Host supports opening external URLs. */ - openLinks: z - .object({}) - .optional() - .describe("Host supports opening external URLs."), - /** @description Host can proxy tool calls to the MCP server. */ - serverTools: z - .object({ - /** @description Host supports tools/list_changed notifications. */ - listChanged: z - .boolean() - .optional() - .describe("Host supports tools/list_changed notifications."), - }) - .optional() - .describe("Host can proxy tool calls to the MCP server."), - /** @description Host can proxy resource reads to the MCP server. */ - serverResources: z - .object({ - /** @description Host supports resources/list_changed notifications. */ - listChanged: z - .boolean() - .optional() - .describe("Host supports resources/list_changed notifications."), - }) - .optional() - .describe("Host can proxy resource reads to the MCP server."), - /** @description Host accepts log messages. */ - logging: z.object({}).optional().describe("Host accepts log messages."), - /** @description Host accepts context updates to be included in the model's context for future turns. */ - updateModelContext: z - .object({}) - .optional() - .describe( - "Host accepts context updates to be included in the model's context for future turns.", - ), + /** @description Experimental features (structure TBD). */ + experimental: z.object({}).optional().describe("Experimental features (structure TBD)."), + /** @description Host supports opening external URLs. */ + openLinks: z.object({}).optional().describe("Host supports opening external URLs."), + /** @description Host can proxy tool calls to the MCP server. */ + serverTools: z.object({ + /** @description Host supports tools/list_changed notifications. */ + listChanged: z.boolean().optional().describe("Host supports tools/list_changed notifications.") + }).optional().describe("Host can proxy tool calls to the MCP server."), + /** @description Host can proxy resource reads to the MCP server. */ + serverResources: z.object({ + /** @description Host supports resources/list_changed notifications. */ + listChanged: z.boolean().optional().describe("Host supports resources/list_changed notifications.") + }).optional().describe("Host can proxy resource reads to the MCP server."), + /** @description Host accepts log messages. */ + logging: z.object({}).optional().describe("Host accepts log messages."), + /** @description Host accepts context updates to be included in the model's context for future turns. */ + updateModelContext: z.object({ + /** @description Host supports text content blocks. */ + text: z.object({}).optional().describe("Host supports text content blocks."), + /** @description Host supports image content blocks. */ + image: z.object({}).optional().describe("Host supports image content blocks."), + /** @description Host supports audio content blocks. */ + audio: z.object({}).optional().describe("Host supports audio content blocks."), + /** @description Host supports resource content blocks. */ + resource: z.object({}).optional().describe("Host supports resource content blocks."), + /** @description Host supports resource link content blocks. */ + resourceLink: z.object({}).optional().describe("Host supports resource link content blocks."), + /** @description Host supports structured content. */ + structuredContent: z.object({}).optional().describe("Host supports structured content.") + }).optional().describe("Host accepts context updates to be included in the model's context for future turns.") }); /** @@ -402,22 +230,13 @@ export const McpUiHostCapabilitiesSchema = z.object({ * @see {@link McpUiInitializeRequest} for the initialization request that includes these capabilities */ export const McpUiAppCapabilitiesSchema = z.object({ - /** @description Experimental features (structure TBD). */ - experimental: z - .object({}) - .optional() - .describe("Experimental features (structure TBD)."), - /** @description App exposes MCP-style tools that the host can call. */ - tools: z - .object({ - /** @description App supports tools/list_changed notifications. */ - listChanged: z - .boolean() - .optional() - .describe("App supports tools/list_changed notifications."), - }) - .optional() - .describe("App exposes MCP-style tools that the host can call."), + /** @description Experimental features (structure TBD). */ + experimental: z.object({}).optional().describe("Experimental features (structure TBD)."), + /** @description App exposes MCP-style tools that the host can call. */ + tools: z.object({ + /** @description App supports tools/list_changed notifications. */ + listChanged: z.boolean().optional().describe("App supports tools/list_changed notifications.") + }).optional().describe("App exposes MCP-style tools that the host can call.") }); /** @@ -425,46 +244,30 @@ export const McpUiAppCapabilitiesSchema = z.object({ * @see {@link app.App.connect} for the method that sends this notification */ export const McpUiInitializedNotificationSchema = z.object({ - method: z.literal("ui/notifications/initialized"), - params: z.object({}).optional(), + method: z.literal("ui/notifications/initialized"), + params: z.object({}).optional() }); /** * @description Content Security Policy configuration for UI resources. */ export const McpUiResourceCspSchema = z.object({ - /** @description Origins for network requests (fetch/XHR/WebSocket). */ - connectDomains: z - .array(z.string()) - .optional() - .describe("Origins for network requests (fetch/XHR/WebSocket)."), - /** @description Origins for static resources (scripts, images, styles, fonts). */ - resourceDomains: z - .array(z.string()) - .optional() - .describe("Origins for static resources (scripts, images, styles, fonts)."), + /** @description Origins for network requests (fetch/XHR/WebSocket). */ + connectDomains: z.array(z.string()).optional().describe("Origins for network requests (fetch/XHR/WebSocket)."), + /** @description Origins for static resources (scripts, images, styles, fonts). */ + resourceDomains: z.array(z.string()).optional().describe("Origins for static resources (scripts, images, styles, fonts).") }); /** * @description UI Resource metadata for security and rendering configuration. */ export const McpUiResourceMetaSchema = z.object({ - /** @description Content Security Policy configuration. */ - csp: McpUiResourceCspSchema.optional().describe( - "Content Security Policy configuration.", - ), - /** @description Dedicated origin for widget sandbox. */ - domain: z - .string() - .optional() - .describe("Dedicated origin for widget sandbox."), - /** @description Visual boundary preference - true if UI prefers a visible border. */ - prefersBorder: z - .boolean() - .optional() - .describe( - "Visual boundary preference - true if UI prefers a visible border.", - ), + /** @description Content Security Policy configuration. */ + csp: McpUiResourceCspSchema.optional().describe("Content Security Policy configuration."), + /** @description Dedicated origin for widget sandbox. */ + domain: z.string().optional().describe("Dedicated origin for widget sandbox."), + /** @description Visual boundary preference - true if UI prefers a visible border. */ + prefersBorder: z.boolean().optional().describe("Visual boundary preference - true if UI prefers a visible border.") }); /** @@ -474,171 +277,121 @@ export const McpUiResourceMetaSchema = z.object({ * @see {@link app.App.requestDisplayMode} for the method that sends this request */ export const McpUiRequestDisplayModeRequestSchema = z.object({ - method: z.literal("ui/request-display-mode"), - params: z.object({ - /** @description The display mode being requested. */ - mode: McpUiDisplayModeSchema.describe("The display mode being requested."), - }), + method: z.literal("ui/request-display-mode"), + params: z.object({ + /** @description The display mode being requested. */ + mode: McpUiDisplayModeSchema.describe("The display mode being requested.") + }) }); /** * @description Result from requesting a display mode change. * @see {@link McpUiRequestDisplayModeRequest} */ -export const McpUiRequestDisplayModeResultSchema = z - .object({ +export const McpUiRequestDisplayModeResultSchema = z.object({ /** @description The display mode that was actually set. May differ from requested if not supported. */ - mode: McpUiDisplayModeSchema.describe( - "The display mode that was actually set. May differ from requested if not supported.", - ), - }) - .passthrough(); + mode: McpUiDisplayModeSchema.describe("The display mode that was actually set. May differ from requested if not supported.") +}).passthrough(); /** * @description Tool visibility scope - who can access the tool. */ -export const McpUiToolVisibilitySchema = z - .union([z.literal("model"), z.literal("app")]) - .describe("Tool visibility scope - who can access the tool."); +export const McpUiToolVisibilitySchema = z.union([z.literal("model"), z.literal("app")]).describe("Tool visibility scope - who can access the tool."); /** * @description UI-related metadata for tools. */ export const McpUiToolMetaSchema = z.object({ - /** - * URI of the UI resource to display for this tool. - * This is converted to `_meta["ui/resourceUri"]`. - * - * @example "ui://weather/widget.html" - */ - resourceUri: z.string(), - /** - * @description Who can access this tool. Default: ["model", "app"] - * - "model": Tool visible to and callable by the agent - * - "app": Tool callable by the app from this server only - */ - visibility: z - .array(McpUiToolVisibilitySchema) - .optional() - .describe( - 'Who can access this tool. Default: ["model", "app"]\n- "model": Tool visible to and callable by the agent\n- "app": Tool callable by the app from this server only', - ), + /** + * URI of the UI resource to display for this tool. + * This is converted to `_meta["ui/resourceUri"]`. + * + * @example "ui://weather/widget.html" + */ + resourceUri: z.string(), + /** + * @description Who can access this tool. Default: ["model", "app"] + * - "model": Tool visible to and callable by the agent + * - "app": Tool callable by the app from this server only + */ + visibility: z.array(McpUiToolVisibilitySchema).optional().describe("Who can access this tool. Default: [\"model\", \"app\"]\n- \"model\": Tool visible to and callable by the agent\n- \"app\": Tool callable by the app from this server only") }); + + + + + /** * @description Request to send a message to the host's chat interface. * @see {@link app.App.sendMessage} for the method that sends this request */ export const McpUiMessageRequestSchema = z.object({ - method: z.literal("ui/message"), - params: z.object({ - /** @description Message role, currently only "user" is supported. */ - role: z - .literal("user") - .describe('Message role, currently only "user" is supported.'), - /** @description Message content blocks (text, image, etc.). */ - content: z - .array(ContentBlockSchema) - .describe("Message content blocks (text, image, etc.)."), - }), + method: z.literal("ui/message"), + params: z.object({ + /** @description Message role, currently only "user" is supported. */ + role: z.literal("user").describe("Message role, currently only \"user\" is supported."), + /** @description Message content blocks (text, image, etc.). */ + content: z.array(ContentBlockSchema).describe("Message content blocks (text, image, etc.).") + }) }); /** * @description Notification containing tool execution result (Host -> Guest UI). */ export const McpUiToolResultNotificationSchema = z.object({ - method: z.literal("ui/notifications/tool-result"), - /** @description Standard MCP tool execution result. */ - params: CallToolResultSchema.describe("Standard MCP tool execution result."), + method: z.literal("ui/notifications/tool-result"), + /** @description Standard MCP tool execution result. */ + params: CallToolResultSchema.describe("Standard MCP tool execution result.") }); /** * @description Rich context about the host environment provided to Guest UIs. */ -export const McpUiHostContextSchema = z - .object({ +export const McpUiHostContextSchema = z.object({ /** @description Metadata of the tool call that instantiated this App. */ - toolInfo: z - .object({ + toolInfo: z.object({ /** @description 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. */ - tool: ToolSchema.describe( - "Tool definition including name, inputSchema, etc.", - ), - }) - .optional() - .describe("Metadata of the tool call that instantiated this App."), + tool: ToolSchema.describe("Tool definition including name, inputSchema, etc.") + }).optional().describe("Metadata of the tool call that instantiated this App."), /** @description Current color theme preference. */ - theme: McpUiThemeSchema.optional().describe( - "Current color theme preference.", - ), + theme: McpUiThemeSchema.optional().describe("Current color theme preference."), /** @description Style configuration for theming the app. */ - styles: McpUiHostStylesSchema.optional().describe( - "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.", - ), + 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."), + availableDisplayModes: z.array(z.string()).optional().describe("Display modes the host supports."), /** @description Current and maximum dimensions available to the UI. */ - viewport: z - .object({ + viewport: z.object({ /** @description Current viewport width in pixels. */ width: z.number().describe("Current viewport width in pixels."), /** @description Current viewport height in pixels. */ height: z.number().describe("Current viewport height in pixels."), /** @description Maximum available height in pixels (if constrained). */ - maxHeight: z - .number() - .optional() - .describe("Maximum available height in pixels (if constrained)."), + maxHeight: z.number().optional().describe("Maximum available height in pixels (if constrained)."), /** @description Maximum available width in pixels (if constrained). */ - maxWidth: z - .number() - .optional() - .describe("Maximum available width in pixels (if constrained)."), - }) - .optional() - .describe("Current and maximum dimensions available to the UI."), + maxWidth: z.number().optional().describe("Maximum available width in pixels (if constrained).") + }).optional().describe("Current and maximum dimensions available to the UI."), /** @description User's language and region preference in BCP 47 format. */ - locale: z - .string() - .optional() - .describe("User's language and region preference in BCP 47 format."), + locale: z.string().optional().describe("User's language and region preference in BCP 47 format."), /** @description User's timezone in IANA format. */ timeZone: z.string().optional().describe("User's timezone in IANA format."), /** @description Host application identifier. */ userAgent: z.string().optional().describe("Host application identifier."), /** @description Platform type for responsive design decisions. */ - platform: z - .union([z.literal("web"), z.literal("desktop"), z.literal("mobile")]) - .optional() - .describe("Platform type for responsive design decisions."), + platform: z.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({ + deviceCapabilities: z.object({ /** @description Whether the device supports touch input. */ - touch: z - .boolean() - .optional() - .describe("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."), + 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({ + 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. */ @@ -646,23 +399,18 @@ export const McpUiHostContextSchema = z /** @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(); + 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). * @see {@link McpUiHostContext} for the full context structure */ export const McpUiHostContextChangedNotificationSchema = z.object({ - method: z.literal("ui/notifications/host-context-changed"), - /** @description Partial context update containing only changed fields. */ - params: McpUiHostContextSchema.describe( - "Partial context update containing only changed fields.", - ), + method: z.literal("ui/notifications/host-context-changed"), + /** @description Partial context update containing only changed fields. */ + params: McpUiHostContextSchema.describe("Partial context update containing only changed fields.") }); /** @@ -671,20 +419,20 @@ export const McpUiHostContextChangedNotificationSchema = z.object({ * Unlike `notifications/message` which is for debugging/logging, this request is intended * to update the Host's model context. Each request overwrites the previous context sent by the Guest UI. * Unlike messages, context updates do not trigger follow-ups. - * @see {@link app.App.sendUpdateModelContext} for the method that sends this request + * + * The host will typically defer sending the context to the model until the next user message + * (including `ui/message`), and will only send the last update received. + * + * @see {@link app.App.updateModelContext} for the method that sends this request */ export const McpUiUpdateModelContextRequestSchema = z.object({ - method: z.literal("ui/update-model-context"), - params: z.object({ - /** @description Message role, currently only "user" is supported. */ - role: z - .literal("user") - .describe('Message role, currently only "user" is supported.'), - /** @description Context content blocks (text, image, etc.). */ - content: z - .array(ContentBlockSchema) - .describe("Context content blocks (text, image, etc.)."), - }), + method: z.literal("ui/update-model-context"), + params: z.object({ + /** @description Context content blocks (text, image, etc.). */ + content: z.array(ContentBlockSchema).optional().describe("Context content blocks (text, image, etc.)."), + /** @description Structured content for machine-readable context data. */ + structuredContent: z.record(z.string(), z.unknown().describe("Structured content for machine-readable context data.")).optional().describe("Structured content for machine-readable context data.") + }) }); /** @@ -692,42 +440,28 @@ export const McpUiUpdateModelContextRequestSchema = z.object({ * @see {@link app.App.connect} for the method that sends this request */ export const McpUiInitializeRequestSchema = z.object({ - method: z.literal("ui/initialize"), - params: z.object({ - /** @description App identification (name and version). */ - appInfo: ImplementationSchema.describe( - "App identification (name and version).", - ), - /** @description Features and capabilities this app provides. */ - appCapabilities: McpUiAppCapabilitiesSchema.describe( - "Features and capabilities this app provides.", - ), - /** @description Protocol version this app supports. */ - protocolVersion: z.string().describe("Protocol version this app supports."), - }), + method: z.literal("ui/initialize"), + params: z.object({ + /** @description App identification (name and version). */ + appInfo: ImplementationSchema.describe("App identification (name and version)."), + /** @description Features and capabilities this app provides. */ + appCapabilities: McpUiAppCapabilitiesSchema.describe("Features and capabilities this app provides."), + /** @description Protocol version this app supports. */ + protocolVersion: z.string().describe("Protocol version this app supports.") + }) }); /** * @description Initialization result returned from Host to Guest UI. * @see {@link McpUiInitializeRequest} */ -export const McpUiInitializeResultSchema = z - .object({ +export const McpUiInitializeResultSchema = z.object({ /** @description Negotiated protocol version string (e.g., "2025-11-21"). */ - protocolVersion: z - .string() - .describe('Negotiated protocol version string (e.g., "2025-11-21").'), + protocolVersion: z.string().describe("Negotiated protocol version string (e.g., \"2025-11-21\")."), /** @description Host application identification and version. */ - hostInfo: ImplementationSchema.describe( - "Host application identification and version.", - ), + hostInfo: ImplementationSchema.describe("Host application identification and version."), /** @description Features and capabilities provided by the host. */ - hostCapabilities: McpUiHostCapabilitiesSchema.describe( - "Features and capabilities provided by the host.", - ), + hostCapabilities: McpUiHostCapabilitiesSchema.describe("Features and capabilities provided by the host."), /** @description Rich context about the host environment. */ - hostContext: McpUiHostContextSchema.describe( - "Rich context about the host environment.", - ), - }) - .passthrough(); + hostContext: McpUiHostContextSchema.describe("Rich context about the host environment.") +}).passthrough(); diff --git a/src/spec.types.ts b/src/spec.types.ts index 3ae6bbd5..eee6c578 100644 --- a/src/spec.types.ts +++ b/src/spec.types.ts @@ -379,25 +379,28 @@ export interface McpUiHostContextChangedNotification { * Unlike `notifications/message` which is for debugging/logging, this request is intended * to update the Host's model context. Each request overwrites the previous context sent by the Guest UI. * Unlike messages, context updates do not trigger follow-ups. - * @see {@link app.App.sendUpdateModelContext} for the method that sends this request + * + * The host will typically defer sending the context to the model until the next user message + * (including `ui/message`), and will only send the last update received. + * + * @see {@link app.App.updateModelContext} for the method that sends this request */ export interface McpUiUpdateModelContextRequest { method: "ui/update-model-context"; params: { - /** @description Message role, currently only "user" is supported. */ - role: "user"; /** @description Context content blocks (text, image, etc.). */ - content: ContentBlock[]; + content?: ContentBlock[]; + /** @description Structured content for machine-readable context data. */ + structuredContent?: Record; }; } /** * @description Result from setting the agent's model context. + * Empty on success; errors are signaled via JSON-RPC error responses. * @see {@link McpUiUpdateModelContextRequest} */ export interface McpUiUpdateModelContextResult { - /** @description True if the host rejected or failed to store the context update. */ - isError?: boolean; /** * Index signature required for MCP SDK `Protocol` class compatibility. * Note: The schema intentionally omits this to enforce strict validation. @@ -447,7 +450,20 @@ export interface McpUiHostCapabilities { /** @description Host accepts log messages. */ logging?: {}; /** @description Host accepts context updates to be included in the model's context for future turns. */ - updateModelContext?: {}; + updateModelContext?: { + /** @description Host supports text content blocks. */ + text?: {}; + /** @description Host supports image content blocks. */ + image?: {}; + /** @description Host supports audio content blocks. */ + audio?: {}; + /** @description Host supports resource content blocks. */ + resource?: {}; + /** @description Host supports resource link content blocks. */ + resourceLink?: {}; + /** @description Host supports structured content. */ + structuredContent?: {}; + }; } /** From 0e2ad4bbdbde395f2902ef290c58b1df35a88f7f Mon Sep 17 00:00:00 2001 From: Olivier Chafik Date: Mon, 12 Jan 2026 13:31:33 +0000 Subject: [PATCH 11/13] refactor: extract McpUiSupportedContentBlockModalities type - Create reusable McpUiSupportedContentBlockModalities interface - Use it for both updateModelContext and message capabilities - Add message capability to advertise ui/message content type support --- src/generated/schema.json | 1290 ++++++++++++++++++++++++++++------ src/generated/schema.test.ts | 4 + src/generated/schema.ts | 34 +- src/spec.types.ts | 34 +- src/types.ts | 2 + 5 files changed, 1124 insertions(+), 240 deletions(-) diff --git a/src/generated/schema.json b/src/generated/schema.json index 3146e536..4d430921 100644 --- a/src/generated/schema.json +++ b/src/generated/schema.json @@ -30,7 +30,6 @@ }, "McpUiDisplayMode": { "$schema": "https://json-schema.org/draft/2020-12/schema", - "description": "Display mode for UI presentation.", "anyOf": [ { "type": "string", @@ -44,7 +43,8 @@ "type": "string", "const": "pip" } - ] + ], + "description": "Display mode for UI presentation." }, "McpUiHostCapabilities": { "$schema": "https://json-schema.org/draft/2020-12/schema", @@ -91,7 +91,50 @@ "additionalProperties": false }, "updateModelContext": { - "description": "Host accepts context updates to be included in the model's context for future turns.", + "description": "Host accepts context updates (ui/update-model-context) to be included in the model's context for future turns.", + "type": "object", + "properties": { + "text": { + "description": "Host supports text content blocks.", + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "image": { + "description": "Host supports image content blocks.", + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "audio": { + "description": "Host supports audio content blocks.", + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "resource": { + "description": "Host supports resource content blocks.", + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "resourceLink": { + "description": "Host supports resource link content blocks.", + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "structuredContent": { + "description": "Host supports structured content.", + "type": "object", + "properties": {}, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + "message": { + "description": "Host supports receiving content messages (ui/message) from the Guest UI.", "type": "object", "properties": { "text": { @@ -145,7 +188,6 @@ "const": "ui/notifications/host-context-changed" }, "params": { - "description": "Partial context update containing only changed fields.", "type": "object", "properties": { "toolInfo": { @@ -153,7 +195,6 @@ "type": "object", "properties": { "id": { - "description": "JSON-RPC id of the tools/call request.", "anyOf": [ { "type": "string" @@ -163,10 +204,10 @@ "minimum": -9007199254740991, "maximum": 9007199254740991 } - ] + ], + "description": "JSON-RPC id of the tools/call request." }, "tool": { - "description": "Tool definition including name, inputSchema, etc.", "type": "object", "properties": { "name": { @@ -191,9 +232,18 @@ "items": { "type": "string" } + }, + "theme": { + "type": "string", + "enum": [ + "light", + "dark" + ] } }, - "required": ["src"], + "required": [ + "src" + ], "additionalProperties": false } }, @@ -221,7 +271,9 @@ } } }, - "required": ["type"], + "required": [ + "type" + ], "additionalProperties": {} }, "outputSchema": { @@ -245,7 +297,9 @@ } } }, - "required": ["type"], + "required": [ + "type" + ], "additionalProperties": {} }, "annotations": { @@ -274,7 +328,11 @@ "properties": { "taskSupport": { "type": "string", - "enum": ["required", "optional", "forbidden"] + "enum": [ + "required", + "optional", + "forbidden" + ] } }, "additionalProperties": false @@ -287,11 +345,18 @@ "additionalProperties": {} } }, - "required": ["name", "inputSchema"], - "additionalProperties": false + "required": [ + "name", + "inputSchema" + ], + "additionalProperties": false, + "description": "Tool definition including name, inputSchema, etc." } }, - "required": ["id", "tool"], + "required": [ + "id", + "tool" + ], "additionalProperties": false }, "theme": { @@ -315,7 +380,6 @@ "description": "CSS variables for theming the app.", "type": "object", "propertyNames": { - "description": "Style variables for theming MCP apps.\n\nIndividual style keys are optional - hosts may provide any subset of these values.\nValues are strings containing CSS values (colors, sizes, font stacks, etc.).\n\nNote: This type uses `Record` rather than `Partial>`\nfor compatibility with Zod schema generation. Both are functionally equivalent for validation.", "anyOf": [ { "type": "string", @@ -621,17 +685,96 @@ "type": "string", "const": "--shadow-lg" } - ] + ], + "description": "Style variables for theming MCP apps.\n\nIndividual style keys are optional - hosts may provide any subset of these values.\nValues are strings containing CSS values (colors, sizes, font stacks, etc.).\n\nNote: This type uses `Record` rather than `Partial>`\nfor compatibility with Zod schema generation. Both are functionally equivalent for validation." }, "additionalProperties": { - "description": "Style variables for theming MCP apps.\n\nIndividual style keys are optional - hosts may provide any subset of these values.\nValues are strings containing CSS values (colors, sizes, font stacks, etc.).\n\nNote: This type uses `Record` rather than `Partial>`\nfor compatibility with Zod schema generation. Both are functionally equivalent for validation.", "anyOf": [ { "type": "string" }, {} - ] - } + ], + "description": "Style variables for theming MCP apps.\n\nIndividual style keys are optional - hosts may provide any subset of these values.\nValues are strings containing CSS values (colors, sizes, font stacks, etc.).\n\nNote: This type uses `Record` rather than `Partial>`\nfor compatibility with Zod schema generation. Both are functionally equivalent for validation." + }, + "required": [ + "--color-background-primary", + "--color-background-secondary", + "--color-background-tertiary", + "--color-background-inverse", + "--color-background-ghost", + "--color-background-info", + "--color-background-danger", + "--color-background-success", + "--color-background-warning", + "--color-background-disabled", + "--color-text-primary", + "--color-text-secondary", + "--color-text-tertiary", + "--color-text-inverse", + "--color-text-info", + "--color-text-danger", + "--color-text-success", + "--color-text-warning", + "--color-text-disabled", + "--color-text-ghost", + "--color-border-primary", + "--color-border-secondary", + "--color-border-tertiary", + "--color-border-inverse", + "--color-border-ghost", + "--color-border-info", + "--color-border-danger", + "--color-border-success", + "--color-border-warning", + "--color-border-disabled", + "--color-ring-primary", + "--color-ring-secondary", + "--color-ring-inverse", + "--color-ring-info", + "--color-ring-danger", + "--color-ring-success", + "--color-ring-warning", + "--font-sans", + "--font-mono", + "--font-weight-normal", + "--font-weight-medium", + "--font-weight-semibold", + "--font-weight-bold", + "--font-text-xs-size", + "--font-text-sm-size", + "--font-text-md-size", + "--font-text-lg-size", + "--font-heading-xs-size", + "--font-heading-sm-size", + "--font-heading-md-size", + "--font-heading-lg-size", + "--font-heading-xl-size", + "--font-heading-2xl-size", + "--font-heading-3xl-size", + "--font-text-xs-line-height", + "--font-text-sm-line-height", + "--font-text-md-line-height", + "--font-text-lg-line-height", + "--font-heading-xs-line-height", + "--font-heading-sm-line-height", + "--font-heading-md-line-height", + "--font-heading-lg-line-height", + "--font-heading-xl-line-height", + "--font-heading-2xl-line-height", + "--font-heading-3xl-line-height", + "--border-radius-xs", + "--border-radius-sm", + "--border-radius-md", + "--border-radius-lg", + "--border-radius-xl", + "--border-radius-full", + "--border-width-regular", + "--shadow-hairline", + "--shadow-sm", + "--shadow-md", + "--shadow-lg" + ] }, "css": { "description": "CSS blocks that apps can inject.", @@ -676,12 +819,12 @@ "type": "object", "properties": { "width": { - "description": "Current viewport width in pixels.", - "type": "number" + "type": "number", + "description": "Current viewport width in pixels." }, "height": { - "description": "Current viewport height in pixels.", - "type": "number" + "type": "number", + "description": "Current viewport height in pixels." }, "maxHeight": { "description": "Maximum available height in pixels (if constrained).", @@ -692,7 +835,10 @@ "type": "number" } }, - "required": ["width", "height"], + "required": [ + "width", + "height" + ], "additionalProperties": false }, "locale": { @@ -744,30 +890,39 @@ "type": "object", "properties": { "top": { - "description": "Top safe area inset in pixels.", - "type": "number" + "type": "number", + "description": "Top safe area inset in pixels." }, "right": { - "description": "Right safe area inset in pixels.", - "type": "number" + "type": "number", + "description": "Right safe area inset in pixels." }, "bottom": { - "description": "Bottom safe area inset in pixels.", - "type": "number" + "type": "number", + "description": "Bottom safe area inset in pixels." }, "left": { - "description": "Left safe area inset in pixels.", - "type": "number" + "type": "number", + "description": "Left safe area inset in pixels." } }, - "required": ["top", "right", "bottom", "left"], + "required": [ + "top", + "right", + "bottom", + "left" + ], "additionalProperties": false } }, - "additionalProperties": {} + "additionalProperties": {}, + "description": "Partial context update containing only changed fields." } }, - "required": ["method", "params"], + "required": [ + "method", + "params" + ], "additionalProperties": false }, "McpUiHostContext": { @@ -779,7 +934,6 @@ "type": "object", "properties": { "id": { - "description": "JSON-RPC id of the tools/call request.", "anyOf": [ { "type": "string" @@ -789,10 +943,10 @@ "minimum": -9007199254740991, "maximum": 9007199254740991 } - ] + ], + "description": "JSON-RPC id of the tools/call request." }, "tool": { - "description": "Tool definition including name, inputSchema, etc.", "type": "object", "properties": { "name": { @@ -817,9 +971,18 @@ "items": { "type": "string" } + }, + "theme": { + "type": "string", + "enum": [ + "light", + "dark" + ] } }, - "required": ["src"], + "required": [ + "src" + ], "additionalProperties": false } }, @@ -847,7 +1010,9 @@ } } }, - "required": ["type"], + "required": [ + "type" + ], "additionalProperties": {} }, "outputSchema": { @@ -871,7 +1036,9 @@ } } }, - "required": ["type"], + "required": [ + "type" + ], "additionalProperties": {} }, "annotations": { @@ -900,7 +1067,11 @@ "properties": { "taskSupport": { "type": "string", - "enum": ["required", "optional", "forbidden"] + "enum": [ + "required", + "optional", + "forbidden" + ] } }, "additionalProperties": false @@ -913,11 +1084,18 @@ "additionalProperties": {} } }, - "required": ["name", "inputSchema"], - "additionalProperties": false + "required": [ + "name", + "inputSchema" + ], + "additionalProperties": false, + "description": "Tool definition including name, inputSchema, etc." } }, - "required": ["id", "tool"], + "required": [ + "id", + "tool" + ], "additionalProperties": false }, "theme": { @@ -941,7 +1119,6 @@ "description": "CSS variables for theming the app.", "type": "object", "propertyNames": { - "description": "Style variables for theming MCP apps.\n\nIndividual style keys are optional - hosts may provide any subset of these values.\nValues are strings containing CSS values (colors, sizes, font stacks, etc.).\n\nNote: This type uses `Record` rather than `Partial>`\nfor compatibility with Zod schema generation. Both are functionally equivalent for validation.", "anyOf": [ { "type": "string", @@ -1247,17 +1424,96 @@ "type": "string", "const": "--shadow-lg" } - ] + ], + "description": "Style variables for theming MCP apps.\n\nIndividual style keys are optional - hosts may provide any subset of these values.\nValues are strings containing CSS values (colors, sizes, font stacks, etc.).\n\nNote: This type uses `Record` rather than `Partial>`\nfor compatibility with Zod schema generation. Both are functionally equivalent for validation." }, "additionalProperties": { - "description": "Style variables for theming MCP apps.\n\nIndividual style keys are optional - hosts may provide any subset of these values.\nValues are strings containing CSS values (colors, sizes, font stacks, etc.).\n\nNote: This type uses `Record` rather than `Partial>`\nfor compatibility with Zod schema generation. Both are functionally equivalent for validation.", "anyOf": [ { "type": "string" }, {} - ] - } + ], + "description": "Style variables for theming MCP apps.\n\nIndividual style keys are optional - hosts may provide any subset of these values.\nValues are strings containing CSS values (colors, sizes, font stacks, etc.).\n\nNote: This type uses `Record` rather than `Partial>`\nfor compatibility with Zod schema generation. Both are functionally equivalent for validation." + }, + "required": [ + "--color-background-primary", + "--color-background-secondary", + "--color-background-tertiary", + "--color-background-inverse", + "--color-background-ghost", + "--color-background-info", + "--color-background-danger", + "--color-background-success", + "--color-background-warning", + "--color-background-disabled", + "--color-text-primary", + "--color-text-secondary", + "--color-text-tertiary", + "--color-text-inverse", + "--color-text-info", + "--color-text-danger", + "--color-text-success", + "--color-text-warning", + "--color-text-disabled", + "--color-text-ghost", + "--color-border-primary", + "--color-border-secondary", + "--color-border-tertiary", + "--color-border-inverse", + "--color-border-ghost", + "--color-border-info", + "--color-border-danger", + "--color-border-success", + "--color-border-warning", + "--color-border-disabled", + "--color-ring-primary", + "--color-ring-secondary", + "--color-ring-inverse", + "--color-ring-info", + "--color-ring-danger", + "--color-ring-success", + "--color-ring-warning", + "--font-sans", + "--font-mono", + "--font-weight-normal", + "--font-weight-medium", + "--font-weight-semibold", + "--font-weight-bold", + "--font-text-xs-size", + "--font-text-sm-size", + "--font-text-md-size", + "--font-text-lg-size", + "--font-heading-xs-size", + "--font-heading-sm-size", + "--font-heading-md-size", + "--font-heading-lg-size", + "--font-heading-xl-size", + "--font-heading-2xl-size", + "--font-heading-3xl-size", + "--font-text-xs-line-height", + "--font-text-sm-line-height", + "--font-text-md-line-height", + "--font-text-lg-line-height", + "--font-heading-xs-line-height", + "--font-heading-sm-line-height", + "--font-heading-md-line-height", + "--font-heading-lg-line-height", + "--font-heading-xl-line-height", + "--font-heading-2xl-line-height", + "--font-heading-3xl-line-height", + "--border-radius-xs", + "--border-radius-sm", + "--border-radius-md", + "--border-radius-lg", + "--border-radius-xl", + "--border-radius-full", + "--border-width-regular", + "--shadow-hairline", + "--shadow-sm", + "--shadow-md", + "--shadow-lg" + ] }, "css": { "description": "CSS blocks that apps can inject.", @@ -1302,12 +1558,12 @@ "type": "object", "properties": { "width": { - "description": "Current viewport width in pixels.", - "type": "number" + "type": "number", + "description": "Current viewport width in pixels." }, "height": { - "description": "Current viewport height in pixels.", - "type": "number" + "type": "number", + "description": "Current viewport height in pixels." }, "maxHeight": { "description": "Maximum available height in pixels (if constrained).", @@ -1318,7 +1574,10 @@ "type": "number" } }, - "required": ["width", "height"], + "required": [ + "width", + "height" + ], "additionalProperties": false }, "locale": { @@ -1370,23 +1629,28 @@ "type": "object", "properties": { "top": { - "description": "Top safe area inset in pixels.", - "type": "number" + "type": "number", + "description": "Top safe area inset in pixels." }, "right": { - "description": "Right safe area inset in pixels.", - "type": "number" + "type": "number", + "description": "Right safe area inset in pixels." }, "bottom": { - "description": "Bottom safe area inset in pixels.", - "type": "number" + "type": "number", + "description": "Bottom safe area inset in pixels." }, "left": { - "description": "Left safe area inset in pixels.", - "type": "number" + "type": "number", + "description": "Left safe area inset in pixels." } }, - "required": ["top", "right", "bottom", "left"], + "required": [ + "top", + "right", + "bottom", + "left" + ], "additionalProperties": false } }, @@ -1411,7 +1675,6 @@ "description": "CSS variables for theming the app.", "type": "object", "propertyNames": { - "description": "Style variables for theming MCP apps.\n\nIndividual style keys are optional - hosts may provide any subset of these values.\nValues are strings containing CSS values (colors, sizes, font stacks, etc.).\n\nNote: This type uses `Record` rather than `Partial>`\nfor compatibility with Zod schema generation. Both are functionally equivalent for validation.", "anyOf": [ { "type": "string", @@ -1717,17 +1980,96 @@ "type": "string", "const": "--shadow-lg" } - ] + ], + "description": "Style variables for theming MCP apps.\n\nIndividual style keys are optional - hosts may provide any subset of these values.\nValues are strings containing CSS values (colors, sizes, font stacks, etc.).\n\nNote: This type uses `Record` rather than `Partial>`\nfor compatibility with Zod schema generation. Both are functionally equivalent for validation." }, "additionalProperties": { - "description": "Style variables for theming MCP apps.\n\nIndividual style keys are optional - hosts may provide any subset of these values.\nValues are strings containing CSS values (colors, sizes, font stacks, etc.).\n\nNote: This type uses `Record` rather than `Partial>`\nfor compatibility with Zod schema generation. Both are functionally equivalent for validation.", "anyOf": [ { "type": "string" }, {} - ] - } + ], + "description": "Style variables for theming MCP apps.\n\nIndividual style keys are optional - hosts may provide any subset of these values.\nValues are strings containing CSS values (colors, sizes, font stacks, etc.).\n\nNote: This type uses `Record` rather than `Partial>`\nfor compatibility with Zod schema generation. Both are functionally equivalent for validation." + }, + "required": [ + "--color-background-primary", + "--color-background-secondary", + "--color-background-tertiary", + "--color-background-inverse", + "--color-background-ghost", + "--color-background-info", + "--color-background-danger", + "--color-background-success", + "--color-background-warning", + "--color-background-disabled", + "--color-text-primary", + "--color-text-secondary", + "--color-text-tertiary", + "--color-text-inverse", + "--color-text-info", + "--color-text-danger", + "--color-text-success", + "--color-text-warning", + "--color-text-disabled", + "--color-text-ghost", + "--color-border-primary", + "--color-border-secondary", + "--color-border-tertiary", + "--color-border-inverse", + "--color-border-ghost", + "--color-border-info", + "--color-border-danger", + "--color-border-success", + "--color-border-warning", + "--color-border-disabled", + "--color-ring-primary", + "--color-ring-secondary", + "--color-ring-inverse", + "--color-ring-info", + "--color-ring-danger", + "--color-ring-success", + "--color-ring-warning", + "--font-sans", + "--font-mono", + "--font-weight-normal", + "--font-weight-medium", + "--font-weight-semibold", + "--font-weight-bold", + "--font-text-xs-size", + "--font-text-sm-size", + "--font-text-md-size", + "--font-text-lg-size", + "--font-heading-xs-size", + "--font-heading-sm-size", + "--font-heading-md-size", + "--font-heading-lg-size", + "--font-heading-xl-size", + "--font-heading-2xl-size", + "--font-heading-3xl-size", + "--font-text-xs-line-height", + "--font-text-sm-line-height", + "--font-text-md-line-height", + "--font-text-lg-line-height", + "--font-heading-xs-line-height", + "--font-heading-sm-line-height", + "--font-heading-md-line-height", + "--font-heading-lg-line-height", + "--font-heading-xl-line-height", + "--font-heading-2xl-line-height", + "--font-heading-3xl-line-height", + "--border-radius-xs", + "--border-radius-sm", + "--border-radius-md", + "--border-radius-lg", + "--border-radius-xl", + "--border-radius-full", + "--border-width-regular", + "--shadow-hairline", + "--shadow-sm", + "--shadow-md", + "--shadow-lg" + ] }, "css": { "description": "CSS blocks that apps can inject.", @@ -1755,7 +2097,6 @@ "type": "object", "properties": { "appInfo": { - "description": "App identification (name and version).", "type": "object", "properties": { "name": { @@ -1780,9 +2121,18 @@ "items": { "type": "string" } + }, + "theme": { + "type": "string", + "enum": [ + "light", + "dark" + ] } }, - "required": ["src"], + "required": [ + "src" + ], "additionalProperties": false } }, @@ -1791,13 +2141,19 @@ }, "websiteUrl": { "type": "string" + }, + "description": { + "type": "string" } }, - "required": ["name", "version"], - "additionalProperties": false + "required": [ + "name", + "version" + ], + "additionalProperties": false, + "description": "App identification (name and version)." }, "appCapabilities": { - "description": "Features and capabilities this app provides.", "type": "object", "properties": { "experimental": { @@ -1818,18 +2174,26 @@ "additionalProperties": false } }, - "additionalProperties": false + "additionalProperties": false, + "description": "Features and capabilities this app provides." }, "protocolVersion": { - "description": "Protocol version this app supports.", - "type": "string" + "type": "string", + "description": "Protocol version this app supports." } }, - "required": ["appInfo", "appCapabilities", "protocolVersion"], + "required": [ + "appInfo", + "appCapabilities", + "protocolVersion" + ], "additionalProperties": false } }, - "required": ["method", "params"], + "required": [ + "method", + "params" + ], "additionalProperties": false }, "McpUiInitializeResult": { @@ -1837,11 +2201,10 @@ "type": "object", "properties": { "protocolVersion": { - "description": "Negotiated protocol version string (e.g., \"2025-11-21\").", - "type": "string" + "type": "string", + "description": "Negotiated protocol version string (e.g., \"2025-11-21\")." }, "hostInfo": { - "description": "Host application identification and version.", "type": "object", "properties": { "name": { @@ -1866,9 +2229,18 @@ "items": { "type": "string" } + }, + "theme": { + "type": "string", + "enum": [ + "light", + "dark" + ] } }, - "required": ["src"], + "required": [ + "src" + ], "additionalProperties": false } }, @@ -1877,13 +2249,19 @@ }, "websiteUrl": { "type": "string" + }, + "description": { + "type": "string" } }, - "required": ["name", "version"], - "additionalProperties": false + "required": [ + "name", + "version" + ], + "additionalProperties": false, + "description": "Host application identification and version." }, "hostCapabilities": { - "description": "Features and capabilities provided by the host.", "type": "object", "properties": { "experimental": { @@ -1927,7 +2305,50 @@ "additionalProperties": false }, "updateModelContext": { - "description": "Host accepts context updates to be included in the model's context for future turns.", + "description": "Host accepts context updates (ui/update-model-context) to be included in the model's context for future turns.", + "type": "object", + "properties": { + "text": { + "description": "Host supports text content blocks.", + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "image": { + "description": "Host supports image content blocks.", + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "audio": { + "description": "Host supports audio content blocks.", + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "resource": { + "description": "Host supports resource content blocks.", + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "resourceLink": { + "description": "Host supports resource link content blocks.", + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "structuredContent": { + "description": "Host supports structured content.", + "type": "object", + "properties": {}, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + "message": { + "description": "Host supports receiving content messages (ui/message) from the Guest UI.", "type": "object", "properties": { "text": { @@ -1970,10 +2391,10 @@ "additionalProperties": false } }, - "additionalProperties": false + "additionalProperties": false, + "description": "Features and capabilities provided by the host." }, "hostContext": { - "description": "Rich context about the host environment.", "type": "object", "properties": { "toolInfo": { @@ -1981,7 +2402,6 @@ "type": "object", "properties": { "id": { - "description": "JSON-RPC id of the tools/call request.", "anyOf": [ { "type": "string" @@ -1991,10 +2411,10 @@ "minimum": -9007199254740991, "maximum": 9007199254740991 } - ] + ], + "description": "JSON-RPC id of the tools/call request." }, "tool": { - "description": "Tool definition including name, inputSchema, etc.", "type": "object", "properties": { "name": { @@ -2019,9 +2439,18 @@ "items": { "type": "string" } + }, + "theme": { + "type": "string", + "enum": [ + "light", + "dark" + ] } }, - "required": ["src"], + "required": [ + "src" + ], "additionalProperties": false } }, @@ -2049,7 +2478,9 @@ } } }, - "required": ["type"], + "required": [ + "type" + ], "additionalProperties": {} }, "outputSchema": { @@ -2073,7 +2504,9 @@ } } }, - "required": ["type"], + "required": [ + "type" + ], "additionalProperties": {} }, "annotations": { @@ -2102,7 +2535,11 @@ "properties": { "taskSupport": { "type": "string", - "enum": ["required", "optional", "forbidden"] + "enum": [ + "required", + "optional", + "forbidden" + ] } }, "additionalProperties": false @@ -2115,11 +2552,18 @@ "additionalProperties": {} } }, - "required": ["name", "inputSchema"], - "additionalProperties": false + "required": [ + "name", + "inputSchema" + ], + "additionalProperties": false, + "description": "Tool definition including name, inputSchema, etc." } }, - "required": ["id", "tool"], + "required": [ + "id", + "tool" + ], "additionalProperties": false }, "theme": { @@ -2143,7 +2587,6 @@ "description": "CSS variables for theming the app.", "type": "object", "propertyNames": { - "description": "Style variables for theming MCP apps.\n\nIndividual style keys are optional - hosts may provide any subset of these values.\nValues are strings containing CSS values (colors, sizes, font stacks, etc.).\n\nNote: This type uses `Record` rather than `Partial>`\nfor compatibility with Zod schema generation. Both are functionally equivalent for validation.", "anyOf": [ { "type": "string", @@ -2449,17 +2892,96 @@ "type": "string", "const": "--shadow-lg" } - ] + ], + "description": "Style variables for theming MCP apps.\n\nIndividual style keys are optional - hosts may provide any subset of these values.\nValues are strings containing CSS values (colors, sizes, font stacks, etc.).\n\nNote: This type uses `Record` rather than `Partial>`\nfor compatibility with Zod schema generation. Both are functionally equivalent for validation." }, "additionalProperties": { - "description": "Style variables for theming MCP apps.\n\nIndividual style keys are optional - hosts may provide any subset of these values.\nValues are strings containing CSS values (colors, sizes, font stacks, etc.).\n\nNote: This type uses `Record` rather than `Partial>`\nfor compatibility with Zod schema generation. Both are functionally equivalent for validation.", "anyOf": [ { "type": "string" }, {} - ] - } + ], + "description": "Style variables for theming MCP apps.\n\nIndividual style keys are optional - hosts may provide any subset of these values.\nValues are strings containing CSS values (colors, sizes, font stacks, etc.).\n\nNote: This type uses `Record` rather than `Partial>`\nfor compatibility with Zod schema generation. Both are functionally equivalent for validation." + }, + "required": [ + "--color-background-primary", + "--color-background-secondary", + "--color-background-tertiary", + "--color-background-inverse", + "--color-background-ghost", + "--color-background-info", + "--color-background-danger", + "--color-background-success", + "--color-background-warning", + "--color-background-disabled", + "--color-text-primary", + "--color-text-secondary", + "--color-text-tertiary", + "--color-text-inverse", + "--color-text-info", + "--color-text-danger", + "--color-text-success", + "--color-text-warning", + "--color-text-disabled", + "--color-text-ghost", + "--color-border-primary", + "--color-border-secondary", + "--color-border-tertiary", + "--color-border-inverse", + "--color-border-ghost", + "--color-border-info", + "--color-border-danger", + "--color-border-success", + "--color-border-warning", + "--color-border-disabled", + "--color-ring-primary", + "--color-ring-secondary", + "--color-ring-inverse", + "--color-ring-info", + "--color-ring-danger", + "--color-ring-success", + "--color-ring-warning", + "--font-sans", + "--font-mono", + "--font-weight-normal", + "--font-weight-medium", + "--font-weight-semibold", + "--font-weight-bold", + "--font-text-xs-size", + "--font-text-sm-size", + "--font-text-md-size", + "--font-text-lg-size", + "--font-heading-xs-size", + "--font-heading-sm-size", + "--font-heading-md-size", + "--font-heading-lg-size", + "--font-heading-xl-size", + "--font-heading-2xl-size", + "--font-heading-3xl-size", + "--font-text-xs-line-height", + "--font-text-sm-line-height", + "--font-text-md-line-height", + "--font-text-lg-line-height", + "--font-heading-xs-line-height", + "--font-heading-sm-line-height", + "--font-heading-md-line-height", + "--font-heading-lg-line-height", + "--font-heading-xl-line-height", + "--font-heading-2xl-line-height", + "--font-heading-3xl-line-height", + "--border-radius-xs", + "--border-radius-sm", + "--border-radius-md", + "--border-radius-lg", + "--border-radius-xl", + "--border-radius-full", + "--border-width-regular", + "--shadow-hairline", + "--shadow-sm", + "--shadow-md", + "--shadow-lg" + ] }, "css": { "description": "CSS blocks that apps can inject.", @@ -2504,12 +3026,12 @@ "type": "object", "properties": { "width": { - "description": "Current viewport width in pixels.", - "type": "number" + "type": "number", + "description": "Current viewport width in pixels." }, "height": { - "description": "Current viewport height in pixels.", - "type": "number" + "type": "number", + "description": "Current viewport height in pixels." }, "maxHeight": { "description": "Maximum available height in pixels (if constrained).", @@ -2520,7 +3042,10 @@ "type": "number" } }, - "required": ["width", "height"], + "required": [ + "width", + "height" + ], "additionalProperties": false }, "locale": { @@ -2572,27 +3097,33 @@ "type": "object", "properties": { "top": { - "description": "Top safe area inset in pixels.", - "type": "number" + "type": "number", + "description": "Top safe area inset in pixels." }, "right": { - "description": "Right safe area inset in pixels.", - "type": "number" + "type": "number", + "description": "Right safe area inset in pixels." }, "bottom": { - "description": "Bottom safe area inset in pixels.", - "type": "number" + "type": "number", + "description": "Bottom safe area inset in pixels." }, "left": { - "description": "Left safe area inset in pixels.", - "type": "number" + "type": "number", + "description": "Left safe area inset in pixels." } }, - "required": ["top", "right", "bottom", "left"], + "required": [ + "top", + "right", + "bottom", + "left" + ], "additionalProperties": false } }, - "additionalProperties": {} + "additionalProperties": {}, + "description": "Rich context about the host environment." } }, "required": [ @@ -2617,7 +3148,9 @@ "additionalProperties": false } }, - "required": ["method"], + "required": [ + "method" + ], "additionalProperties": false }, "McpUiMessageRequest": { @@ -2632,12 +3165,11 @@ "type": "object", "properties": { "role": { - "description": "Message role, currently only \"user\" is supported.", "type": "string", - "const": "user" + "const": "user", + "description": "Message role, currently only \"user\" is supported." }, "content": { - "description": "Message content blocks (text, image, etc.).", "type": "array", "items": { "anyOf": [ @@ -2658,7 +3190,10 @@ "type": "array", "items": { "type": "string", - "enum": ["user", "assistant"] + "enum": [ + "user", + "assistant" + ] } }, "priority": { @@ -2682,7 +3217,10 @@ "additionalProperties": {} } }, - "required": ["type", "text"], + "required": [ + "type", + "text" + ], "additionalProperties": false }, { @@ -2705,7 +3243,10 @@ "type": "array", "items": { "type": "string", - "enum": ["user", "assistant"] + "enum": [ + "user", + "assistant" + ] } }, "priority": { @@ -2729,7 +3270,11 @@ "additionalProperties": {} } }, - "required": ["type", "data", "mimeType"], + "required": [ + "type", + "data", + "mimeType" + ], "additionalProperties": false }, { @@ -2752,7 +3297,10 @@ "type": "array", "items": { "type": "string", - "enum": ["user", "assistant"] + "enum": [ + "user", + "assistant" + ] } }, "priority": { @@ -2776,7 +3324,11 @@ "additionalProperties": {} } }, - "required": ["type", "data", "mimeType"], + "required": [ + "type", + "data", + "mimeType" + ], "additionalProperties": false }, { @@ -2804,9 +3356,18 @@ "items": { "type": "string" } + }, + "theme": { + "type": "string", + "enum": [ + "light", + "dark" + ] } }, - "required": ["src"], + "required": [ + "src" + ], "additionalProperties": false } }, @@ -2826,7 +3387,10 @@ "type": "array", "items": { "type": "string", - "enum": ["user", "assistant"] + "enum": [ + "user", + "assistant" + ] } }, "priority": { @@ -2852,7 +3416,11 @@ "const": "resource_link" } }, - "required": ["name", "uri", "type"], + "required": [ + "name", + "uri", + "type" + ], "additionalProperties": false }, { @@ -2884,7 +3452,10 @@ "type": "string" } }, - "required": ["uri", "text"], + "required": [ + "uri", + "text" + ], "additionalProperties": false }, { @@ -2907,7 +3478,10 @@ "type": "string" } }, - "required": ["uri", "blob"], + "required": [ + "uri", + "blob" + ], "additionalProperties": false } ] @@ -2919,7 +3493,10 @@ "type": "array", "items": { "type": "string", - "enum": ["user", "assistant"] + "enum": [ + "user", + "assistant" + ] } }, "priority": { @@ -2943,18 +3520,28 @@ "additionalProperties": {} } }, - "required": ["type", "resource"], + "required": [ + "type", + "resource" + ], "additionalProperties": false } ] - } + }, + "description": "Message content blocks (text, image, etc.)." } }, - "required": ["role", "content"], + "required": [ + "role", + "content" + ], "additionalProperties": false } }, - "required": ["method", "params"], + "required": [ + "method", + "params" + ], "additionalProperties": false }, "McpUiMessageResult": { @@ -2980,15 +3567,20 @@ "type": "object", "properties": { "url": { - "description": "URL to open in the host's browser", - "type": "string" + "type": "string", + "description": "URL to open in the host's browser" } }, - "required": ["url"], + "required": [ + "url" + ], "additionalProperties": false } }, - "required": ["method", "params"], + "required": [ + "method", + "params" + ], "additionalProperties": false }, "McpUiOpenLinkResult": { @@ -3014,7 +3606,6 @@ "type": "object", "properties": { "mode": { - "description": "The display mode being requested.", "anyOf": [ { "type": "string", @@ -3028,14 +3619,20 @@ "type": "string", "const": "pip" } - ] + ], + "description": "The display mode being requested." } }, - "required": ["mode"], + "required": [ + "mode" + ], "additionalProperties": false } }, - "required": ["method", "params"], + "required": [ + "method", + "params" + ], "additionalProperties": false }, "McpUiRequestDisplayModeResult": { @@ -3043,7 +3640,6 @@ "type": "object", "properties": { "mode": { - "description": "The display mode that was actually set. May differ from requested if not supported.", "anyOf": [ { "type": "string", @@ -3057,10 +3653,13 @@ "type": "string", "const": "pip" } - ] + ], + "description": "The display mode that was actually set. May differ from requested if not supported." } }, - "required": ["mode"], + "required": [ + "mode" + ], "additionalProperties": {} }, "McpUiResourceCsp": { @@ -3134,7 +3733,10 @@ "additionalProperties": false } }, - "required": ["method", "params"], + "required": [ + "method", + "params" + ], "additionalProperties": false }, "McpUiResourceTeardownResult": { @@ -3159,7 +3761,10 @@ "additionalProperties": false } }, - "required": ["method", "params"], + "required": [ + "method", + "params" + ], "additionalProperties": false }, "McpUiSandboxResourceReadyNotification": { @@ -3174,8 +3779,8 @@ "type": "object", "properties": { "html": { - "description": "HTML content to load into the inner iframe.", - "type": "string" + "type": "string", + "description": "HTML content to load into the inner iframe." }, "sandbox": { "description": "Optional override for the inner iframe's sandbox attribute.", @@ -3203,11 +3808,16 @@ "additionalProperties": false } }, - "required": ["html"], + "required": [ + "html" + ], "additionalProperties": false } }, - "required": ["method", "params"], + "required": [ + "method", + "params" + ], "additionalProperties": false }, "McpUiSizeChangedNotification": { @@ -3233,12 +3843,14 @@ "additionalProperties": false } }, - "required": ["method", "params"], + "required": [ + "method", + "params" + ], "additionalProperties": false }, "McpUiStyleVariableKey": { "$schema": "https://json-schema.org/draft/2020-12/schema", - "description": "CSS variable keys available to MCP apps for theming.", "anyOf": [ { "type": "string", @@ -3544,14 +4156,13 @@ "type": "string", "const": "--shadow-lg" } - ] + ], + "description": "CSS variable keys available to MCP apps for theming." }, "McpUiStyles": { "$schema": "https://json-schema.org/draft/2020-12/schema", - "description": "Style variables for theming MCP apps.\n\nIndividual style keys are optional - hosts may provide any subset of these values.\nValues are strings containing CSS values (colors, sizes, font stacks, etc.).\n\nNote: This type uses `Record` rather than `Partial>`\nfor compatibility with Zod schema generation. Both are functionally equivalent for validation.", "type": "object", "propertyNames": { - "description": "Style variables for theming MCP apps.\n\nIndividual style keys are optional - hosts may provide any subset of these values.\nValues are strings containing CSS values (colors, sizes, font stacks, etc.).\n\nNote: This type uses `Record` rather than `Partial>`\nfor compatibility with Zod schema generation. Both are functionally equivalent for validation.", "anyOf": [ { "type": "string", @@ -3857,21 +4468,143 @@ "type": "string", "const": "--shadow-lg" } - ] + ], + "description": "Style variables for theming MCP apps.\n\nIndividual style keys are optional - hosts may provide any subset of these values.\nValues are strings containing CSS values (colors, sizes, font stacks, etc.).\n\nNote: This type uses `Record` rather than `Partial>`\nfor compatibility with Zod schema generation. Both are functionally equivalent for validation." }, "additionalProperties": { - "description": "Style variables for theming MCP apps.\n\nIndividual style keys are optional - hosts may provide any subset of these values.\nValues are strings containing CSS values (colors, sizes, font stacks, etc.).\n\nNote: This type uses `Record` rather than `Partial>`\nfor compatibility with Zod schema generation. Both are functionally equivalent for validation.", "anyOf": [ { "type": "string" }, {} - ] - } + ], + "description": "Style variables for theming MCP apps.\n\nIndividual style keys are optional - hosts may provide any subset of these values.\nValues are strings containing CSS values (colors, sizes, font stacks, etc.).\n\nNote: This type uses `Record` rather than `Partial>`\nfor compatibility with Zod schema generation. Both are functionally equivalent for validation." + }, + "required": [ + "--color-background-primary", + "--color-background-secondary", + "--color-background-tertiary", + "--color-background-inverse", + "--color-background-ghost", + "--color-background-info", + "--color-background-danger", + "--color-background-success", + "--color-background-warning", + "--color-background-disabled", + "--color-text-primary", + "--color-text-secondary", + "--color-text-tertiary", + "--color-text-inverse", + "--color-text-info", + "--color-text-danger", + "--color-text-success", + "--color-text-warning", + "--color-text-disabled", + "--color-text-ghost", + "--color-border-primary", + "--color-border-secondary", + "--color-border-tertiary", + "--color-border-inverse", + "--color-border-ghost", + "--color-border-info", + "--color-border-danger", + "--color-border-success", + "--color-border-warning", + "--color-border-disabled", + "--color-ring-primary", + "--color-ring-secondary", + "--color-ring-inverse", + "--color-ring-info", + "--color-ring-danger", + "--color-ring-success", + "--color-ring-warning", + "--font-sans", + "--font-mono", + "--font-weight-normal", + "--font-weight-medium", + "--font-weight-semibold", + "--font-weight-bold", + "--font-text-xs-size", + "--font-text-sm-size", + "--font-text-md-size", + "--font-text-lg-size", + "--font-heading-xs-size", + "--font-heading-sm-size", + "--font-heading-md-size", + "--font-heading-lg-size", + "--font-heading-xl-size", + "--font-heading-2xl-size", + "--font-heading-3xl-size", + "--font-text-xs-line-height", + "--font-text-sm-line-height", + "--font-text-md-line-height", + "--font-text-lg-line-height", + "--font-heading-xs-line-height", + "--font-heading-sm-line-height", + "--font-heading-md-line-height", + "--font-heading-lg-line-height", + "--font-heading-xl-line-height", + "--font-heading-2xl-line-height", + "--font-heading-3xl-line-height", + "--border-radius-xs", + "--border-radius-sm", + "--border-radius-md", + "--border-radius-lg", + "--border-radius-xl", + "--border-radius-full", + "--border-width-regular", + "--shadow-hairline", + "--shadow-sm", + "--shadow-md", + "--shadow-lg" + ], + "description": "Style variables for theming MCP apps.\n\nIndividual style keys are optional - hosts may provide any subset of these values.\nValues are strings containing CSS values (colors, sizes, font stacks, etc.).\n\nNote: This type uses `Record` rather than `Partial>`\nfor compatibility with Zod schema generation. Both are functionally equivalent for validation." + }, + "McpUiSupportedContentBlockModalities": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "text": { + "description": "Host supports text content blocks.", + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "image": { + "description": "Host supports image content blocks.", + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "audio": { + "description": "Host supports audio content blocks.", + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "resource": { + "description": "Host supports resource content blocks.", + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "resourceLink": { + "description": "Host supports resource link content blocks.", + "type": "object", + "properties": {}, + "additionalProperties": false + }, + "structuredContent": { + "description": "Host supports structured content.", + "type": "object", + "properties": {}, + "additionalProperties": false + } + }, + "additionalProperties": false }, "McpUiTheme": { "$schema": "https://json-schema.org/draft/2020-12/schema", - "description": "Color theme preference for the host environment.", "anyOf": [ { "type": "string", @@ -3881,7 +4614,8 @@ "type": "string", "const": "dark" } - ] + ], + "description": "Color theme preference for the host environment." }, "McpUiToolCancelledNotification": { "$schema": "https://json-schema.org/draft/2020-12/schema", @@ -3902,7 +4636,10 @@ "additionalProperties": false } }, - "required": ["method", "params"], + "required": [ + "method", + "params" + ], "additionalProperties": false }, "McpUiToolInputNotification": { @@ -3930,7 +4667,10 @@ "additionalProperties": false } }, - "required": ["method", "params"], + "required": [ + "method", + "params" + ], "additionalProperties": false }, "McpUiToolInputPartialNotification": { @@ -3958,7 +4698,10 @@ "additionalProperties": false } }, - "required": ["method", "params"], + "required": [ + "method", + "params" + ], "additionalProperties": false }, "McpUiToolMeta": { @@ -3972,7 +4715,6 @@ "description": "Who can access this tool. Default: [\"model\", \"app\"]\n- \"model\": Tool visible to and callable by the agent\n- \"app\": Tool callable by the app from this server only", "type": "array", "items": { - "description": "Tool visibility scope - who can access the tool.", "anyOf": [ { "type": "string", @@ -3982,11 +4724,14 @@ "type": "string", "const": "app" } - ] + ], + "description": "Tool visibility scope - who can access the tool." } } }, - "required": ["resourceUri"], + "required": [ + "resourceUri" + ], "additionalProperties": false }, "McpUiToolResultNotification": { @@ -3998,12 +4743,23 @@ "const": "ui/notifications/tool-result" }, "params": { - "description": "Standard MCP tool execution result.", "type": "object", "properties": { "_meta": { "type": "object", "properties": { + "progressToken": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "integer", + "minimum": -9007199254740991, + "maximum": 9007199254740991 + } + ] + }, "io.modelcontextprotocol/related-task": { "type": "object", "properties": { @@ -4011,8 +4767,10 @@ "type": "string" } }, - "required": ["taskId"], - "additionalProperties": {} + "required": [ + "taskId" + ], + "additionalProperties": false } }, "additionalProperties": {} @@ -4039,7 +4797,10 @@ "type": "array", "items": { "type": "string", - "enum": ["user", "assistant"] + "enum": [ + "user", + "assistant" + ] } }, "priority": { @@ -4063,7 +4824,10 @@ "additionalProperties": {} } }, - "required": ["type", "text"], + "required": [ + "type", + "text" + ], "additionalProperties": false }, { @@ -4086,7 +4850,10 @@ "type": "array", "items": { "type": "string", - "enum": ["user", "assistant"] + "enum": [ + "user", + "assistant" + ] } }, "priority": { @@ -4110,7 +4877,11 @@ "additionalProperties": {} } }, - "required": ["type", "data", "mimeType"], + "required": [ + "type", + "data", + "mimeType" + ], "additionalProperties": false }, { @@ -4133,7 +4904,10 @@ "type": "array", "items": { "type": "string", - "enum": ["user", "assistant"] + "enum": [ + "user", + "assistant" + ] } }, "priority": { @@ -4157,7 +4931,11 @@ "additionalProperties": {} } }, - "required": ["type", "data", "mimeType"], + "required": [ + "type", + "data", + "mimeType" + ], "additionalProperties": false }, { @@ -4185,9 +4963,18 @@ "items": { "type": "string" } + }, + "theme": { + "type": "string", + "enum": [ + "light", + "dark" + ] } }, - "required": ["src"], + "required": [ + "src" + ], "additionalProperties": false } }, @@ -4207,7 +4994,10 @@ "type": "array", "items": { "type": "string", - "enum": ["user", "assistant"] + "enum": [ + "user", + "assistant" + ] } }, "priority": { @@ -4233,7 +5023,11 @@ "const": "resource_link" } }, - "required": ["name", "uri", "type"], + "required": [ + "name", + "uri", + "type" + ], "additionalProperties": false }, { @@ -4265,7 +5059,10 @@ "type": "string" } }, - "required": ["uri", "text"], + "required": [ + "uri", + "text" + ], "additionalProperties": false }, { @@ -4288,7 +5085,10 @@ "type": "string" } }, - "required": ["uri", "blob"], + "required": [ + "uri", + "blob" + ], "additionalProperties": false } ] @@ -4300,7 +5100,10 @@ "type": "array", "items": { "type": "string", - "enum": ["user", "assistant"] + "enum": [ + "user", + "assistant" + ] } }, "priority": { @@ -4324,7 +5127,10 @@ "additionalProperties": {} } }, - "required": ["type", "resource"], + "required": [ + "type", + "resource" + ], "additionalProperties": false } ] @@ -4341,16 +5147,21 @@ "type": "boolean" } }, - "required": ["content"], - "additionalProperties": {} + "required": [ + "content" + ], + "additionalProperties": {}, + "description": "Standard MCP tool execution result." } }, - "required": ["method", "params"], + "required": [ + "method", + "params" + ], "additionalProperties": false }, "McpUiToolVisibility": { "$schema": "https://json-schema.org/draft/2020-12/schema", - "description": "Tool visibility scope - who can access the tool.", "anyOf": [ { "type": "string", @@ -4360,7 +5171,8 @@ "type": "string", "const": "app" } - ] + ], + "description": "Tool visibility scope - who can access the tool." }, "McpUiUpdateModelContextRequest": { "$schema": "https://json-schema.org/draft/2020-12/schema", @@ -4395,7 +5207,10 @@ "type": "array", "items": { "type": "string", - "enum": ["user", "assistant"] + "enum": [ + "user", + "assistant" + ] } }, "priority": { @@ -4419,7 +5234,10 @@ "additionalProperties": {} } }, - "required": ["type", "text"], + "required": [ + "type", + "text" + ], "additionalProperties": false }, { @@ -4442,7 +5260,10 @@ "type": "array", "items": { "type": "string", - "enum": ["user", "assistant"] + "enum": [ + "user", + "assistant" + ] } }, "priority": { @@ -4466,7 +5287,11 @@ "additionalProperties": {} } }, - "required": ["type", "data", "mimeType"], + "required": [ + "type", + "data", + "mimeType" + ], "additionalProperties": false }, { @@ -4489,7 +5314,10 @@ "type": "array", "items": { "type": "string", - "enum": ["user", "assistant"] + "enum": [ + "user", + "assistant" + ] } }, "priority": { @@ -4513,7 +5341,11 @@ "additionalProperties": {} } }, - "required": ["type", "data", "mimeType"], + "required": [ + "type", + "data", + "mimeType" + ], "additionalProperties": false }, { @@ -4541,9 +5373,18 @@ "items": { "type": "string" } + }, + "theme": { + "type": "string", + "enum": [ + "light", + "dark" + ] } }, - "required": ["src"], + "required": [ + "src" + ], "additionalProperties": false } }, @@ -4563,7 +5404,10 @@ "type": "array", "items": { "type": "string", - "enum": ["user", "assistant"] + "enum": [ + "user", + "assistant" + ] } }, "priority": { @@ -4589,7 +5433,11 @@ "const": "resource_link" } }, - "required": ["name", "uri", "type"], + "required": [ + "name", + "uri", + "type" + ], "additionalProperties": false }, { @@ -4621,7 +5469,10 @@ "type": "string" } }, - "required": ["uri", "text"], + "required": [ + "uri", + "text" + ], "additionalProperties": false }, { @@ -4644,7 +5495,10 @@ "type": "string" } }, - "required": ["uri", "blob"], + "required": [ + "uri", + "blob" + ], "additionalProperties": false } ] @@ -4656,7 +5510,10 @@ "type": "array", "items": { "type": "string", - "enum": ["user", "assistant"] + "enum": [ + "user", + "assistant" + ] } }, "priority": { @@ -4680,7 +5537,10 @@ "additionalProperties": {} } }, - "required": ["type", "resource"], + "required": [ + "type", + "resource" + ], "additionalProperties": false } ] @@ -4689,19 +5549,29 @@ "structuredContent": { "description": "Structured content for machine-readable context data.", "type": "object", - "additionalProperties": {} + "propertyNames": { + "type": "string" + }, + "additionalProperties": { + "description": "Structured content for machine-readable context data." + } } }, "additionalProperties": false } }, - "required": ["method", "params"], + "required": [ + "method", + "params" + ], "additionalProperties": false }, "McpUiUpdateModelContextResult": { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", - "properties": {}, + "propertyNames": { + "type": "string" + }, "additionalProperties": {} } } diff --git a/src/generated/schema.test.ts b/src/generated/schema.test.ts index b9b837e0..2ef7d39a 100644 --- a/src/generated/schema.test.ts +++ b/src/generated/schema.test.ts @@ -47,6 +47,8 @@ export type McpUiResourceTeardownRequestSchemaInferredType = z.infer; +export type McpUiSupportedContentBlockModalitiesSchemaInferredType = z.infer; + export type McpUiHostCapabilitiesSchemaInferredType = z.infer; export type McpUiAppCapabilitiesSchemaInferredType = z.infer; @@ -115,6 +117,8 @@ expectType({} as McpUiResourceTeardownRequest expectType({} as spec.McpUiResourceTeardownRequest) expectType({} as McpUiResourceTeardownResultSchemaInferredType) expectType({} as spec.McpUiResourceTeardownResult) +expectType({} as McpUiSupportedContentBlockModalitiesSchemaInferredType) +expectType({} as spec.McpUiSupportedContentBlockModalities) expectType({} as McpUiHostCapabilitiesSchemaInferredType) expectType({} as spec.McpUiHostCapabilities) expectType({} as McpUiAppCapabilitiesSchemaInferredType) diff --git a/src/generated/schema.ts b/src/generated/schema.ts index 62defe18..40f7e8c7 100644 --- a/src/generated/schema.ts +++ b/src/generated/schema.ts @@ -187,6 +187,21 @@ export const McpUiResourceTeardownRequestSchema = z.object({ */ export const McpUiResourceTeardownResultSchema = z.record(z.string(), z.unknown()); +export const McpUiSupportedContentBlockModalitiesSchema = z.object({ + /** @description Host supports text content blocks. */ + text: z.object({}).optional().describe("Host supports text content blocks."), + /** @description Host supports image content blocks. */ + image: z.object({}).optional().describe("Host supports image content blocks."), + /** @description Host supports audio content blocks. */ + audio: z.object({}).optional().describe("Host supports audio content blocks."), + /** @description Host supports resource content blocks. */ + resource: z.object({}).optional().describe("Host supports resource content blocks."), + /** @description Host supports resource link content blocks. */ + resourceLink: z.object({}).optional().describe("Host supports resource link content blocks."), + /** @description Host supports structured content. */ + structuredContent: z.object({}).optional().describe("Host supports structured content.") +}); + /** * @description Capabilities supported by the host application. * @see {@link McpUiInitializeResult} for the initialization result that includes these capabilities @@ -208,21 +223,10 @@ export const McpUiHostCapabilitiesSchema = z.object({ }).optional().describe("Host can proxy resource reads to the MCP server."), /** @description Host accepts log messages. */ logging: z.object({}).optional().describe("Host accepts log messages."), - /** @description Host accepts context updates to be included in the model's context for future turns. */ - updateModelContext: z.object({ - /** @description Host supports text content blocks. */ - text: z.object({}).optional().describe("Host supports text content blocks."), - /** @description Host supports image content blocks. */ - image: z.object({}).optional().describe("Host supports image content blocks."), - /** @description Host supports audio content blocks. */ - audio: z.object({}).optional().describe("Host supports audio content blocks."), - /** @description Host supports resource content blocks. */ - resource: z.object({}).optional().describe("Host supports resource content blocks."), - /** @description Host supports resource link content blocks. */ - resourceLink: z.object({}).optional().describe("Host supports resource link content blocks."), - /** @description Host supports structured content. */ - structuredContent: z.object({}).optional().describe("Host supports structured content.") - }).optional().describe("Host accepts context updates to be included in the model's context for future turns.") + /** @description Host accepts context updates (ui/update-model-context) to be included in the model's context for future turns. */ + updateModelContext: McpUiSupportedContentBlockModalitiesSchema.optional().describe("Host accepts context updates (ui/update-model-context) to be included in the model's context for future turns."), + /** @description Host supports receiving content messages (ui/message) from the Guest UI. */ + message: McpUiSupportedContentBlockModalitiesSchema.optional().describe("Host supports receiving content messages (ui/message) from the Guest UI.") }); /** diff --git a/src/spec.types.ts b/src/spec.types.ts index eee6c578..b73d64bc 100644 --- a/src/spec.types.ts +++ b/src/spec.types.ts @@ -428,6 +428,21 @@ export interface McpUiResourceTeardownResult { [key: string]: unknown; } +export interface McpUiSupportedContentBlockModalities { + /** @description Host supports text content blocks. */ + text?: {}; + /** @description Host supports image content blocks. */ + image?: {}; + /** @description Host supports audio content blocks. */ + audio?: {}; + /** @description Host supports resource content blocks. */ + resource?: {}; + /** @description Host supports resource link content blocks. */ + resourceLink?: {}; + /** @description Host supports structured content. */ + structuredContent?: {}; +} + /** * @description Capabilities supported by the host application. * @see {@link McpUiInitializeResult} for the initialization result that includes these capabilities @@ -449,21 +464,10 @@ export interface McpUiHostCapabilities { }; /** @description Host accepts log messages. */ logging?: {}; - /** @description Host accepts context updates to be included in the model's context for future turns. */ - updateModelContext?: { - /** @description Host supports text content blocks. */ - text?: {}; - /** @description Host supports image content blocks. */ - image?: {}; - /** @description Host supports audio content blocks. */ - audio?: {}; - /** @description Host supports resource content blocks. */ - resource?: {}; - /** @description Host supports resource link content blocks. */ - resourceLink?: {}; - /** @description Host supports structured content. */ - structuredContent?: {}; - }; + /** @description Host accepts context updates (ui/update-model-context) to be included in the model's context for future turns. */ + updateModelContext?: McpUiSupportedContentBlockModalities; + /** @description Host supports receiving content messages (ui/message) from the Guest UI. */ + message?: McpUiSupportedContentBlockModalities; } /** diff --git a/src/types.ts b/src/types.ts index e0fc255b..d99ff341 100644 --- a/src/types.ts +++ b/src/types.ts @@ -24,6 +24,7 @@ export { type McpUiMessageResult, type McpUiUpdateModelContextRequest, type McpUiUpdateModelContextResult, + type McpUiSupportedContentBlockModalities, type McpUiSandboxProxyReadyNotification, type McpUiSandboxResourceReadyNotification, type McpUiSizeChangedNotification, @@ -85,6 +86,7 @@ export { McpUiMessageResultSchema, McpUiUpdateModelContextRequestSchema, McpUiUpdateModelContextResultSchema, + McpUiSupportedContentBlockModalitiesSchema, McpUiSandboxProxyReadyNotificationSchema, McpUiSandboxResourceReadyNotificationSchema, McpUiSizeChangedNotificationSchema, From 2b0869d483c058da10706d57829f6f11b8d28653 Mon Sep 17 00:00:00 2001 From: Olivier Chafik Date: Mon, 12 Jan 2026 13:36:31 +0000 Subject: [PATCH 12/13] spec: change overwrite behavior from SHOULD to MAY Gives hosts flexibility to accumulate context history if desired, rather than mandating replacement semantics. --- specification/draft/apps.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/draft/apps.mdx b/specification/draft/apps.mdx index e8c429e4..21ed4833 100644 --- a/specification/draft/apps.mdx +++ b/specification/draft/apps.mdx @@ -837,7 +837,7 @@ This event serves a different use case from `notifications/message` (logging) an Host behavior: - SHOULD provide the context to the model in future turns -- SHOULD overwrite the previous model context with the new update +- MAY overwrite the previous model context with the new update - MAY defer sending the context to the model until the next user message (including `ui/message`) - MAY dedupe identical `ui/update-model-context` calls - If multiple updates are received before the next user message, Host SHOULD only send the last update to the model From 0d65356d5344b19e176184c613f0d146300e99a6 Mon Sep 17 00:00:00 2001 From: Olivier Chafik Date: Mon, 12 Jan 2026 15:18:32 +0000 Subject: [PATCH 13/13] refactor: remove redundant McpUiUpdateModelContextResult (use EmptyResult) --- src/generated/schema.json | 8 -------- src/generated/schema.test.ts | 10 ---------- src/generated/schema.ts | 10 ---------- src/spec.types.ts | 13 ------------- src/types.ts | 4 ---- 5 files changed, 45 deletions(-) diff --git a/src/generated/schema.json b/src/generated/schema.json index 3b775747..1d87d9c8 100644 --- a/src/generated/schema.json +++ b/src/generated/schema.json @@ -5698,14 +5698,6 @@ }, "required": ["method", "params"], "additionalProperties": false - }, - "McpUiUpdateModelContextResult": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": {} } } } diff --git a/src/generated/schema.test.ts b/src/generated/schema.test.ts index acf07f60..727c28d2 100644 --- a/src/generated/schema.test.ts +++ b/src/generated/schema.test.ts @@ -75,10 +75,6 @@ export type McpUiHostStylesSchemaInferredType = z.infer< typeof generated.McpUiHostStylesSchema >; -export type McpUiUpdateModelContextResultSchemaInferredType = z.infer< - typeof generated.McpUiUpdateModelContextResultSchema ->; - export type McpUiResourceTeardownRequestSchemaInferredType = z.infer< typeof generated.McpUiResourceTeardownRequestSchema >; @@ -223,12 +219,6 @@ expectType({} as McpUiHostCssSchemaInferredType); expectType({} as spec.McpUiHostCss); expectType({} as McpUiHostStylesSchemaInferredType); expectType({} as spec.McpUiHostStyles); -expectType( - {} as McpUiUpdateModelContextResultSchemaInferredType, -); -expectType( - {} as spec.McpUiUpdateModelContextResult, -); expectType( {} as McpUiResourceTeardownRequestSchemaInferredType, ); diff --git a/src/generated/schema.ts b/src/generated/schema.ts index 472083ec..69abe496 100644 --- a/src/generated/schema.ts +++ b/src/generated/schema.ts @@ -340,16 +340,6 @@ export const McpUiHostStylesSchema = z.object({ ), }); -/** - * @description Result from setting the agent's model context. - * Empty on success; errors are signaled via JSON-RPC error responses. - * @see {@link McpUiUpdateModelContextRequest} - */ -export const McpUiUpdateModelContextResultSchema = z.record( - z.string(), - z.unknown(), -); - /** * @description Request for graceful shutdown of the Guest UI (Host -> Guest UI). * @see {@link app-bridge.AppBridge.teardownResource} for the host method that sends this diff --git a/src/spec.types.ts b/src/spec.types.ts index 553bad13..998e4d26 100644 --- a/src/spec.types.ts +++ b/src/spec.types.ts @@ -406,19 +406,6 @@ export interface McpUiUpdateModelContextRequest { }; } -/** - * @description Result from setting the agent's model context. - * Empty on success; errors are signaled via JSON-RPC error responses. - * @see {@link McpUiUpdateModelContextRequest} - */ -export interface McpUiUpdateModelContextResult { - /** - * Index signature required for MCP SDK `Protocol` class compatibility. - * Note: The schema intentionally omits this to enforce strict validation. - */ - [key: string]: unknown; -} - /** * @description Request for graceful shutdown of the Guest UI (Host -> Guest UI). * @see {@link app-bridge.AppBridge.teardownResource} for the host method that sends this diff --git a/src/types.ts b/src/types.ts index 052de113..5cbc0b48 100644 --- a/src/types.ts +++ b/src/types.ts @@ -37,7 +37,6 @@ export { type McpUiMessageRequest, type McpUiMessageResult, type McpUiUpdateModelContextRequest, - type McpUiUpdateModelContextResult, type McpUiSupportedContentBlockModalities, type McpUiSandboxProxyReadyNotification, type McpUiSandboxResourceReadyNotification, @@ -84,7 +83,6 @@ import type { McpUiInitializeResult, McpUiOpenLinkResult, McpUiMessageResult, - McpUiUpdateModelContextResult, McpUiResourceTeardownResult, McpUiRequestDisplayModeResult, } from "./spec.types.js"; @@ -100,7 +98,6 @@ export { McpUiMessageRequestSchema, McpUiMessageResultSchema, McpUiUpdateModelContextRequestSchema, - McpUiUpdateModelContextResultSchema, McpUiSupportedContentBlockModalitiesSchema, McpUiSandboxProxyReadyNotificationSchema, McpUiSandboxResourceReadyNotificationSchema, @@ -209,7 +206,6 @@ export type AppResult = | McpUiInitializeResult | McpUiOpenLinkResult | McpUiMessageResult - | McpUiUpdateModelContextResult | McpUiResourceTeardownResult | McpUiRequestDisplayModeResult | CallToolResult