feat(basic-host): improve host UI with collapsible panels and SDK types (#244)

* refactor(basic-host): use SDK types for ModelContext and AppMessage

- Import McpUiUpdateModelContextRequest and McpUiMessageRequest from SDK
- Replace custom ModelContext with McpUiUpdateModelContextRequest['params']
- Replace custom AppMessage with McpUiMessageRequest['params']
- Pass full message params instead of extracting text
- Format messages by extracting text from content blocks in display

* feat(basic-host): handle non-text content blocks in display

- Add formatContentBlock helper for text, image, audio, resource types
- Show placeholders like <image: image/png> for non-text content
- Apply to both messages and model context display

* test: update shadertoy screenshot

* test: update screenshots from CI (linux x64)
This commit is contained in:
Olivier Chafik 2026-01-12 19:42:11 +00:00 • committed by GitHub
commit 741b1d3925
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -76,6 +76,7 @@ import {
McpUiRequestDisplayModeRequest,
McpUiRequestDisplayModeRequestSchema,
McpUiRequestDisplayModeResult,
McpUiResourcePermissions,
} from "./types";
export * from "./types";
export { RESOURCE_URI_META_KEY, RESOURCE_MIME_TYPE } from "./app";
@ -126,6 +127,36 @@ export function getToolUiResourceUri(tool: {
return undefined;
}
/**
* Build iframe `allow` attribute string from permissions.
*
* Maps McpUiResourcePermissions to the Permission Policy allow attribute
* format used by iframes (e.g., "microphone; clipboard-write").
*
* @param permissions - Permissions requested by the UI resource
* @returns Space-separated permission directives, or empty string if none
*
* @example
* ```typescript
* const allow = buildAllowAttribute({ microphone: {}, clipboardWrite: {} });
* // Returns: "microphone; clipboard-write"
* iframe.setAttribute("allow", allow);
* ```
*/
export function buildAllowAttribute(
permissions: McpUiResourcePermissions | undefined,
): string {
if (!permissions) return "";
const allowList: string[] = [];
if (permissions.camera) allowList.push("camera");
if (permissions.microphone) allowList.push("microphone");
if (permissions.geolocation) allowList.push("geolocation");
if (permissions.clipboardWrite) allowList.push("clipboard-write");
return allowList.join("; ");
}
/**
* Options for configuring AppBridge behavior.
*