diff --git a/src/app-bridge.ts b/src/app-bridge.ts index 2b6704b5..079dc705 100644 --- a/src/app-bridge.ts +++ b/src/app-bridge.ts @@ -92,7 +92,7 @@ export { PostMessageTransport } from "./message-transport"; * * @param tool - A tool object with optional `_meta` property * @returns The UI resource URI if valid, undefined if not present - * @throws Error if resourceUri is present but invalid (not starting with "ui://") + * @throws Error if resourceUri is present but invalid (does not start with "ui://") * * @example * ```typescript @@ -158,9 +158,12 @@ export function buildAllowAttribute( } /** - * Options for configuring AppBridge behavior. + * Options for configuring {@link AppBridge} behavior. * - * @see ProtocolOptions from @modelcontextprotocol/sdk for available options + * @property hostContext - Optional initial host context to provide to the Guest UI + * + * @see `ProtocolOptions` from @modelcontextprotocol/sdk for available options + * @see {@link McpUiHostContext} for the hostContext structure */ export type HostOptions = ProtocolOptions & { hostContext?: McpUiHostContext; @@ -177,7 +180,7 @@ export const SUPPORTED_PROTOCOL_VERSIONS = [LATEST_PROTOCOL_VERSION]; /** * Extra metadata passed to request handlers. * - * This type represents the additional context provided by the Protocol class + * This type represents the additional context provided by the `Protocol` class * when handling requests, including abort signals and session information. * It is extracted from the MCP SDK's request handler signature. * @@ -188,12 +191,13 @@ type RequestHandlerExtra = Parameters< >[1]; /** - * Host-side bridge for communicating with a single Guest UI (App). + * Host-side bridge for communicating with a single Guest UI ({@link app!App}). * - * AppBridge extends the MCP SDK's Protocol class and acts as a proxy between - * the host application and a Guest UI running in an iframe. It automatically - * forwards MCP server capabilities (tools, resources, prompts) to the Guest UI - * and handles the initialization handshake. + * `AppBridge` extends the MCP SDK's `Protocol` class and acts as a proxy between + * the host application and a Guest UI running in an iframe. When an MCP client + * is provided to the constructor, it automatically forwards MCP server capabilities + * (tools, resources, prompts) to the Guest UI. It also handles the initialization + * handshake. * * ## Architecture * @@ -205,11 +209,11 @@ type RequestHandlerExtra = Parameters< * * ## Lifecycle * - * 1. **Create**: Instantiate AppBridge with MCP client and capabilities + * 1. **Create**: Instantiate `AppBridge` with MCP client and capabilities * 2. **Connect**: Call `connect()` with transport to establish communication * 3. **Wait for init**: Guest UI sends initialize request, bridge responds - * 4. **Send data**: Call `sendToolInput()`, `sendToolResult()`, etc. - * 5. **Teardown**: Call `teardownResource()` before unmounting iframe + * 4. **Send data**: Call {@link sendToolInput}, {@link sendToolResult}, etc. + * 5. **Teardown**: Call {@link teardownResource} before unmounting iframe * * @example Basic usage * ```typescript @@ -261,7 +265,7 @@ export class AppBridge extends Protocol< * @param _client - MCP client connected to the server, or `null`. When provided, * {@link connect} will automatically set up forwarding of MCP requests/notifications * between the Guest UI and the server. When `null`, you must register handlers - * manually using the `oncalltool`, `onlistresources`, etc. setters. + * manually using the {@link oncalltool}, {@link onlistresources}, etc. setters. * @param _hostInfo - Host application identification (name and version) * @param _capabilities - Features and capabilities the host supports * @param options - Configuration options (inherited from Protocol) @@ -363,7 +367,7 @@ export class AppBridge extends Protocol< * Optional handler for ping requests from the Guest UI. * * The Guest UI can send standard MCP `ping` requests to verify the connection - * is alive. The AppBridge automatically responds with an empty object, but this + * is alive. The {@link AppBridge} automatically responds with an empty object, but this * handler allows the host to observe or log ping activity. * * Unlike the other handlers which use setters, this is a direct property @@ -385,7 +389,7 @@ export class AppBridge extends Protocol< * Register a handler for size change notifications from the Guest UI. * * The Guest UI sends `ui/notifications/size-changed` when its rendered content - * size changes, typically via ResizeObserver. Set this callback to dynamically + * size changes, typically via `ResizeObserver`. Set this callback to dynamically * adjust the iframe container dimensions based on the Guest UI's content. * * Note: This is for Guest UI → Host communication. To notify the Guest UI of @@ -404,7 +408,7 @@ export class AppBridge extends Protocol< * ``` * * @see {@link McpUiSizeChangedNotification} for the notification type - * @see {@link app.App.sendSizeChanged} for Host → Guest UI size notifications + * @see {@link app!App.sendSizeChanged} - the Guest UI method that sends these notifications */ set onsizechange( callback: (params: McpUiSizeChangedNotification["params"]) => void, @@ -490,10 +494,10 @@ export class AppBridge extends Protocol< * leakage. * * @param callback - Handler that receives message params and returns a result - * - params.role - Message role (currently only "user" is supported) - * - params.content - Message content blocks (text, image, etc.) - * - extra - Request metadata (abort signal, session info) - * - Returns: Promise with optional isError flag + * - `params.role` - Message role (currently only "user" is supported) + * - `params.content` - Message content blocks (text, image, etc.) + * - `extra` - Request metadata (abort signal, session info) + * - Returns: `Promise` with optional `isError` flag * * @example * ```typescript @@ -539,9 +543,9 @@ export class AppBridge extends Protocol< * - Reject the request entirely * * @param callback - Handler that receives URL params and returns a result - * - params.url - URL to open in the host's browser - * - extra - Request metadata (abort signal, session info) - * - Returns: Promise with optional isError flag + * - `params.url` - URL to open in the host's browser + * - `extra` - Request metadata (abort signal, session info) + * - Returns: `Promise` with optional `isError` flag * * @example * ```typescript @@ -593,17 +597,22 @@ export class AppBridge extends Protocol< * If the requested mode is not available, the handler should return the current * display mode instead. * + * By default, `AppBridge` returns the current `displayMode` from host context (or "inline"). + * Setting this property replaces that default behavior. + * * @param callback - Handler that receives the requested mode and returns the actual mode set - * - params.mode - The display mode being requested ("inline" | "fullscreen" | "pip") - * - extra - Request metadata (abort signal, session info) - * - Returns: Promise with the actual mode set + * - `params.mode` - The display mode being requested ("inline" | "fullscreen" | "pip") + * - `extra` - Request metadata (abort signal, session info) + * - Returns: `Promise` with the actual mode set * * @example * ```typescript + * let currentDisplayMode: McpUiDisplayMode = "inline"; + * * bridge.onrequestdisplaymode = async ({ mode }, extra) => { * const availableModes = hostContext.availableDisplayModes ?? ["inline"]; * if (availableModes.includes(mode)) { - * setDisplayMode(mode); + * currentDisplayMode = mode; * return { mode }; * } * // Return current mode if requested mode not available @@ -640,9 +649,9 @@ export class AppBridge extends Protocol< * message type. * * @param callback - Handler that receives logging params - * - params.level - Log level: "debug" | "info" | "notice" | "warning" | "error" | "critical" | "alert" | "emergency" - * - params.logger - Optional logger name/identifier - * - params.data - Log message and optional structured data + * - `params.level` - Log level: "debug" | "info" | "notice" | "warning" | "error" | "critical" | "alert" | "emergency" + * - `params.logger` - Optional logger name/identifier + * - `params.data` - Log message and optional structured data * * @example * ```typescript @@ -716,9 +725,9 @@ export class AppBridge extends Protocol< * by forwarding them to the MCP server. * * @param callback - Handler that receives tool call params and returns a - * {@link CallToolResult} - * @param callback.params - Tool call parameters (name and arguments) - * @param callback.extra - Request metadata (abort signal, session info) + * `CallToolResult` + * - `params` - Tool call parameters (name and arguments) + * - `extra` - Request metadata (abort signal, session info) * * @example * ```typescript @@ -731,8 +740,8 @@ export class AppBridge extends Protocol< * }; * ``` * - * @see {@link CallToolRequest} for the request type - * @see {@link CallToolResult} for the result type + * @see `CallToolRequest` from @modelcontextprotocol/sdk for the request type + * @see `CallToolResult` from @modelcontextprotocol/sdk for the result type */ set oncalltool( callback: ( @@ -762,7 +771,7 @@ export class AppBridge extends Protocol< * }); * ``` * - * @see {@link ToolListChangedNotification} for the notification type + * @see `ToolListChangedNotification` from @modelcontextprotocol/sdk for the notification type */ sendToolListChanged(params: ToolListChangedNotification["params"] = {}) { return this.notification({ @@ -779,9 +788,9 @@ export class AppBridge extends Protocol< * requests, typically by forwarding them to the MCP server. * * @param callback - Handler that receives list params and returns a - * {@link ListResourcesResult} - * @param callback.params - Request params (may include cursor for pagination) - * @param callback.extra - Request metadata (abort signal, session info) + * `ListResourcesResult` + * - `params` - Request params (may include cursor for pagination) + * - `extra` - Request metadata (abort signal, session info) * * @example * ```typescript @@ -794,8 +803,8 @@ export class AppBridge extends Protocol< * }; * ``` * - * @see {@link ListResourcesRequest} for the request type - * @see {@link ListResourcesResult} for the result type + * @see `ListResourcesRequest` from @modelcontextprotocol/sdk for the request type + * @see `ListResourcesResult` from @modelcontextprotocol/sdk for the result type */ set onlistresources( callback: ( @@ -819,9 +828,9 @@ export class AppBridge extends Protocol< * these requests, typically by forwarding them to the MCP server. * * @param callback - Handler that receives list params and returns a - * {@link ListResourceTemplatesResult} - * @param callback.params - Request params (may include cursor for pagination) - * @param callback.extra - Request metadata (abort signal, session info) + * `ListResourceTemplatesResult` + * - `params` - Request params (may include cursor for pagination) + * - `extra` - Request metadata (abort signal, session info) * * @example * ```typescript @@ -834,8 +843,8 @@ export class AppBridge extends Protocol< * }; * ``` * - * @see {@link ListResourceTemplatesRequest} for the request type - * @see {@link ListResourceTemplatesResult} for the result type + * @see `ListResourceTemplatesRequest` from @modelcontextprotocol/sdk for the request type + * @see `ListResourceTemplatesResult` from @modelcontextprotocol/sdk for the result type */ set onlistresourcetemplates( callback: ( @@ -859,9 +868,9 @@ export class AppBridge extends Protocol< * requests, typically by forwarding them to the MCP server. * * @param callback - Handler that receives read params and returns a - * {@link ReadResourceResult} - * @param callback.params - Read parameters including the resource URI - * @param callback.extra - Request metadata (abort signal, session info) + * `ReadResourceResult` + * - `params` - Read parameters including the resource URI + * - `extra` - Request metadata (abort signal, session info) * * @example * ```typescript @@ -874,8 +883,8 @@ export class AppBridge extends Protocol< * }; * ``` * - * @see {@link ReadResourceRequest} for the request type - * @see {@link ReadResourceResult} for the result type + * @see `ReadResourceRequest` from @modelcontextprotocol/sdk for the request type + * @see `ReadResourceResult` from @modelcontextprotocol/sdk for the result type */ set onreadresource( callback: ( @@ -908,7 +917,7 @@ export class AppBridge extends Protocol< * }); * ``` * - * @see {@link ResourceListChangedNotification} for the notification type + * @see `ResourceListChangedNotification` from @modelcontextprotocol/sdk for the notification type */ sendResourceListChanged( params: ResourceListChangedNotification["params"] = {}, @@ -927,9 +936,9 @@ export class AppBridge extends Protocol< * requests, typically by forwarding them to the MCP server. * * @param callback - Handler that receives list params and returns a - * {@link ListPromptsResult} - * @param callback.params - Request params (may include cursor for pagination) - * @param callback.extra - Request metadata (abort signal, session info) + * `ListPromptsResult` + * - `params` - Request params (may include cursor for pagination) + * - `extra` - Request metadata (abort signal, session info) * * @example * ```typescript @@ -942,8 +951,8 @@ export class AppBridge extends Protocol< * }; * ``` * - * @see {@link ListPromptsRequest} for the request type - * @see {@link ListPromptsResult} for the result type + * @see `ListPromptsRequest` from @modelcontextprotocol/sdk for the request type + * @see `ListPromptsResult` from @modelcontextprotocol/sdk for the result type */ set onlistprompts( callback: ( @@ -973,7 +982,7 @@ export class AppBridge extends Protocol< * }); * ``` * - * @see {@link PromptListChangedNotification} for the notification type + * @see `PromptListChangedNotification` from @modelcontextprotocol/sdk for the notification type */ sendPromptListChanged(params: PromptListChangedNotification["params"] = {}) { return this.notification({ @@ -1062,9 +1071,10 @@ export class AppBridge extends Protocol< /** * Update the host context and notify the Guest UI of changes. * - * Compares the new context with the current context and sends a - * `ui/notifications/host-context-changed` notification containing only the - * fields that have changed. If no fields have changed, no notification is sent. + * Compares fields present in the new context with the current context and sends a + * `ui/notifications/host-context-changed` notification containing only fields + * that have been added or modified. If no fields have changed, no notification is sent. + * The new context fully replaces the internal state. * * Common use cases include notifying the Guest UI when: * - Theme changes (light/dark mode toggle) @@ -1111,8 +1121,13 @@ export class AppBridge extends Protocol< } /** - * Send a host context change notification to the app. - * Only sends the fields that have changed (partial update). + * Low-level method to notify the Guest UI of host context changes. + * + * Most hosts should use {@link setHostContext} instead, which automatically + * detects changes and calls this method with only the modified fields. + * Use this directly only when you need fine-grained control over change detection. + * + * @param params - The context fields that have changed (partial update) */ sendHostContextChange( params: McpUiHostContextChangedNotification["params"], @@ -1225,7 +1240,7 @@ export class AppBridge extends Protocol< * any other interruption. This allows the Guest UI to update its state and * display appropriate feedback to the user. * - * @param params - Optional cancellation details: + * @param params - Cancellation details object * - `reason`: Human-readable explanation for why the tool was cancelled * * @example User-initiated cancellation @@ -1330,13 +1345,13 @@ export class AppBridge extends Protocol< * - Prompts (prompts/list, notifications/prompts/list_changed) * * If no client was passed to the constructor, no automatic forwarding is set up - * and you must register handlers manually using the `oncalltool`, `onlistresources`, + * and you must register handlers manually using the {@link oncalltool}, {@link onlistresources}, * etc. setters. * - * After calling connect, wait for the `oninitialized` callback before sending + * After calling connect, wait for the {@link oninitialized} callback before sending * tool input and other data to the Guest UI. * - * @param transport - Transport layer (typically PostMessageTransport) + * @param transport - Transport layer (typically {@link PostMessageTransport}) * @returns Promise resolving when connection is established * * @throws {Error} If a client was passed but server capabilities are not available. diff --git a/src/app.ts b/src/app.ts index 2b43cd5e..e24913e3 100644 --- a/src/app.ts +++ b/src/app.ts @@ -64,7 +64,7 @@ export { * * MCP servers include this key in tool call result metadata to indicate which * UI resource should be displayed for the tool. When hosts receive a tool result - * containing this metadata, they resolve and render the corresponding App. + * containing this metadata, they resolve and render the corresponding {@link App}. * * **Note**: This constant is provided for reference. MCP servers set this metadata * in their tool handlers; App developers typically don't need to use it directly. @@ -93,21 +93,25 @@ export const RESOURCE_URI_META_KEY = "ui/resourceUri"; /** * MIME type for MCP UI resources. + * + * Identifies HTML content as an MCP App UI resource. + * + * Used by {@link server-helpers!registerAppResource} as the default MIME type for app resources. */ export const RESOURCE_MIME_TYPE = "text/html;profile=mcp-app"; /** - * Options for configuring App behavior. + * Options for configuring {@link App} behavior. * - * Extends ProtocolOptions from the MCP SDK with App-specific configuration. + * Extends `ProtocolOptions` from the MCP SDK with `App`-specific configuration. * - * @see ProtocolOptions from @modelcontextprotocol/sdk for inherited options + * @see `ProtocolOptions` from @modelcontextprotocol/sdk for inherited options */ type AppOptions = ProtocolOptions & { /** - * Automatically report size changes to the host using ResizeObserver. + * Automatically report size changes to the host using `ResizeObserver`. * - * When enabled, the App monitors `document.body` and `document.documentElement` + * When enabled, the {@link App} monitors `document.body` and `document.documentElement` * for size changes and automatically sends `ui/notifications/size-changed` * notifications to the host. * @@ -123,8 +127,8 @@ type RequestHandlerExtra = Parameters< /** * Main class for MCP Apps to communicate with their host. * - * The App class provides a framework-agnostic way to build interactive MCP Apps - * that run inside host applications. It extends the MCP SDK's Protocol class and + * The `App` class provides a framework-agnostic way to build interactive MCP Apps + * that run inside host applications. It extends the MCP SDK's `Protocol` class and * handles the connection lifecycle, initialization handshake, and bidirectional * communication with the host. * @@ -143,19 +147,20 @@ type RequestHandlerExtra = Parameters< * * ## Inherited Methods * - * As a subclass of Protocol, App inherits key methods for handling communication: + * As a subclass of `Protocol`, `App` inherits key methods for handling communication: * - `setRequestHandler()` - Register handlers for requests from host * - `setNotificationHandler()` - Register handlers for notifications from host * - * @see Protocol from @modelcontextprotocol/sdk for all inherited methods + * @see `Protocol` from @modelcontextprotocol/sdk for all inherited methods * * ## Notification Setters * - * For common notifications, the App class provides convenient setter properties + * For common notifications, the `App` class provides convenient setter properties * that simplify handler registration: * - `ontoolinput` - Complete tool arguments from host * - `ontoolinputpartial` - Streaming partial tool arguments * - `ontoolresult` - Tool execution results + * - `ontoolcancelled` - Tool execution was cancelled by user or host * - `onhostcontextchanged` - Host context changes (theme, locale, etc.) * * These setters are convenience wrappers around `setNotificationHandler()`. @@ -187,7 +192,7 @@ type RequestHandlerExtra = Parameters< * } * ); * - * await app.connect(new PostMessageTransport(window.parent)); + * await app.connect(new PostMessageTransport(window.parent, window.parent)); * ``` * * @example Sending a message to the host's chat @@ -208,7 +213,7 @@ export class App extends Protocol { * * @param _appInfo - App identification (name and version) * @param _capabilities - Features and capabilities this app provides - * @param options - Configuration options including autoResize behavior + * @param options - Configuration options including `autoResize` behavior * * @example * ```typescript @@ -339,7 +344,7 @@ export class App extends Protocol { * * Register handlers before calling {@link connect} to avoid missing notifications. * - * @param callback - Function called with the tool input params + * @param callback - Function called with the tool input params ({@link McpUiToolInputNotification.params}) * * @example Using the setter (simpler) * ```typescript @@ -384,7 +389,7 @@ export class App extends Protocol { * * Register handlers before calling {@link connect} to avoid missing notifications. * - * @param callback - Function called with each partial tool input update + * @param callback - Function called with each partial tool input update ({@link McpUiToolInputPartialNotification.params}) * * @example Progressive rendering of tool arguments * ```typescript @@ -418,7 +423,7 @@ export class App extends Protocol { * * Register handlers before calling {@link connect} to avoid missing notifications. * - * @param callback - Function called with the tool result + * @param callback - Function called with the tool result ({@link McpUiToolResultNotification.params}) * * @example Display tool execution results * ```typescript @@ -457,7 +462,7 @@ export class App extends Protocol { * * Register handlers before calling {@link connect} to avoid missing notifications. * - * @param callback - Function called when tool execution is cancelled + * @param callback - Function called when tool execution is cancelled. Receives optional cancellation reason — see {@link McpUiToolCancelledNotification.params}. * * @example Handle tool cancellation * ```typescript @@ -490,6 +495,10 @@ export class App extends Protocol { * This setter is a convenience wrapper around `setNotificationHandler()` that * automatically handles the notification schema and extracts the params for you. * + * Notification params are automatically merged into the internal host context + * before the callback is invoked. This means {@link getHostContext} will + * return the updated values even before your callback runs. + * * Register handlers before calling {@link connect} to avoid missing notifications. * * @param callback - Function called with the updated host context @@ -538,7 +547,7 @@ export class App extends Protocol { * Register handlers before calling {@link connect} to avoid missing requests. * * @param callback - Function called when teardown is requested. - * Can return void or a Promise that resolves when cleanup is complete. + * Must return `McpUiResourceTeardownResult` (can be an empty object `{}`) or a Promise resolving to it. * * @example Perform cleanup before teardown * ```typescript @@ -546,6 +555,7 @@ export class App extends Protocol { * await saveState(); * closeConnections(); * console.log("App ready for teardown"); + * return {}; * }; * ``` * @@ -620,9 +630,9 @@ export class App extends Protocol { * * Register handlers before calling {@link connect} to avoid missing requests. * - * @param callback - Async function that returns the list of available tools. - * The callback will only be invoked if the app declared tool capabilities - * in the constructor. + * @param callback - Async function that returns tool names as strings (simplified + * from full `ListToolsResult` with `Tool` objects). Registration is always + * allowed; capability validation occurs when handlers are invoked. * * @example Return available tools * ```typescript @@ -1050,7 +1060,7 @@ export class App extends Protocol { * If initialization fails, the connection is automatically closed and an error * is thrown. * - * @param transport - Transport layer (typically PostMessageTransport) + * @param transport - Transport layer (typically {@link PostMessageTransport}) * @param options - Request options for the initialize request * * @throws {Error} If initialization fails or connection is lost @@ -1063,7 +1073,7 @@ export class App extends Protocol { * ); * * try { - * await app.connect(new PostMessageTransport(window.parent)); + * await app.connect(new PostMessageTransport(window.parent, window.parent)); * console.log("Connected successfully!"); * } catch (error) { * console.error("Failed to connect:", error); diff --git a/src/generated/schema.json b/src/generated/schema.json index 1d87d9c8..e17767d9 100644 --- a/src/generated/schema.json +++ b/src/generated/schema.json @@ -839,7 +839,6 @@ "type": "object", "properties": { "fonts": { - "description": "CSS for font loading (@font-face rules or", "type": "string" } }, @@ -1593,7 +1592,6 @@ "type": "object", "properties": { "fonts": { - "description": "CSS for font loading (@font-face rules or", "type": "string" } }, @@ -1767,7 +1765,6 @@ "type": "object", "properties": { "fonts": { - "description": "CSS for font loading (@font-face rules or", "type": "string" } }, @@ -2186,7 +2183,6 @@ "type": "object", "properties": { "fonts": { - "description": "CSS for font loading (@font-face rules or", "type": "string" } }, @@ -3133,7 +3129,6 @@ "type": "object", "properties": { "fonts": { - "description": "CSS for font loading (@font-face rules or", "type": "string" } }, diff --git a/src/generated/schema.ts b/src/generated/schema.ts index 69abe496..32277d23 100644 --- a/src/generated/schema.ts +++ b/src/generated/schema.ts @@ -135,7 +135,7 @@ export const McpUiStylesSchema = z /** * @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 + * @see {@link app!App.openLink} for the method that sends this request */ export const McpUiOpenLinkRequestSchema = z.object({ method: z.literal("ui/open-link"), @@ -246,8 +246,8 @@ export const McpUiResourcePermissionsSchema = z.object({ }); /** - * @description Notification of UI size changes (bidirectional: Guest <-> Host). - * @see {@link app.App.sendSizeChanged} for the method to send this from Guest UI + * @description Notification of UI size changes (Guest UI -> Host). + * @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"), @@ -319,11 +319,8 @@ export const McpUiToolCancelledNotificationSchema = z.object({ * @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 {@link applyHostFonts}. */ + fonts: z.string().optional(), }); /** @@ -342,7 +339,7 @@ export const McpUiHostStylesSchema = z.object({ /** * @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 + * @see {@link app-bridge!AppBridge.teardownResource} for the host method that sends this */ export const McpUiResourceTeardownRequestSchema = z.object({ method: z.literal("ui/resource-teardown"), @@ -453,7 +450,7 @@ export const McpUiHostCapabilitiesSchema = z.object({ }); /** - * @description Capabilities provided by the Guest UI (App). + * @description Capabilities provided by the Guest UI ({@link app!App}). * @see {@link McpUiInitializeRequest} for the initialization request that includes these capabilities */ export const McpUiAppCapabilitiesSchema = z.object({ @@ -477,7 +474,7 @@ export const McpUiAppCapabilitiesSchema = z.object({ /** * @description Notification that Guest UI has completed initialization (Guest UI -> Host). - * @see {@link app.App.connect} for the method that sends this notification + * @see {@link app!App.connect} for the method that sends this notification */ export const McpUiInitializedNotificationSchema = z.object({ method: z.literal("ui/notifications/initialized"), @@ -514,7 +511,7 @@ export const McpUiResourceMetaSchema = z.object({ * @description Request to change the display mode of the UI. * The host will respond with the actual display mode that was set, * which may differ from the requested mode if not supported. - * @see {@link app.App.requestDisplayMode} for the method that sends this request + * @see {@link app!App.requestDisplayMode} for the method that sends this request */ export const McpUiRequestDisplayModeRequestSchema = z.object({ method: z.literal("ui/request-display-mode"), @@ -570,7 +567,7 @@ export const McpUiToolMetaSchema = z.object({ /** * @description Request to send a message to the host's chat interface. - * @see {@link app.App.sendMessage} for the method that sends this request + * @see {@link app!App.sendMessage} for the method that sends this request */ export const McpUiMessageRequestSchema = z.object({ method: z.literal("ui/message"), @@ -788,7 +785,7 @@ export const McpUiUpdateModelContextRequestSchema = z.object({ /** * @description Initialization request sent from Guest UI to Host. - * @see {@link app.App.connect} for the method that sends this request + * @see {@link app!App.connect} for the method that sends this request */ export const McpUiInitializeRequestSchema = z.object({ method: z.literal("ui/initialize"), diff --git a/src/message-transport.ts b/src/message-transport.ts index cd030d6f..9e4d49da 100644 --- a/src/message-transport.ts +++ b/src/message-transport.ts @@ -9,39 +9,38 @@ import { } from "@modelcontextprotocol/sdk/shared/transport.js"; /** - * JSON-RPC transport using window.postMessage for iframe↔parent communication. + * JSON-RPC transport using `window.postMessage` for iframe↔parent communication. * * This transport enables bidirectional communication between MCP Apps running in - * iframes and their host applications using the browser's postMessage API. It - * implements the MCP SDK's Transport interface. + * iframes and their host applications using the browser's `postMessage` API. It + * implements the MCP SDK's `Transport` interface. * * ## Security * - * The `eventSource` parameter provides origin validation by filtering messages - * from specific sources. Guest UIs typically don't need to specify this (they only - * communicate with their parent), but hosts should validate the iframe source for - * security. + * The `eventSource` parameter is required and validates the message source window + * by checking `event.source`. For guest UIs, pass `window.parent`. + * For hosts, pass `iframe.contentWindow` to validate the iframe source. * * ## Usage * - * **Guest UI (default)**: + * **Guest UI**: * ```typescript - * const transport = new PostMessageTransport(window.parent); + * const transport = new PostMessageTransport(window.parent, window.parent); * await app.connect(transport); * ``` * - * **Host (with source validation)**: + * **Host**: * ```typescript * const iframe = document.getElementById('app-iframe') as HTMLIFrameElement; * const transport = new PostMessageTransport( * iframe.contentWindow!, - * iframe.contentWindow // Validate messages from this iframe only + * iframe.contentWindow! * ); * await bridge.connect(transport); * ``` * - * @see {@link app.App.connect} for Guest UI usage - * @see {@link app-bridge.AppBridge.connect} for Host usage + * @see {@link app!App.connect} for Guest UI usage + * @see {@link app-bridge!AppBridge.connect} for Host usage */ export class PostMessageTransport implements Transport { private messageListener: ( @@ -52,22 +51,21 @@ export class PostMessageTransport implements Transport { /** * Create a new PostMessageTransport. * - * @param eventTarget - Target window to send messages to (default: window.parent) - * @param eventSource - Optional source validation. If specified, only messages from - * this source will be accepted. Guest UIs typically don't need this (they only - * receive from parent), but hosts should validate the iframe source. + * @param eventTarget - Target window to send messages to (default: `window.parent`) + * @param eventSource - Source window for message validation. For guests, pass + * `window.parent`. For hosts, pass `iframe.contentWindow`. * * @example Guest UI connecting to parent * ```typescript - * const transport = new PostMessageTransport(window.parent); + * const transport = new PostMessageTransport(window.parent, window.parent); * ``` * - * @example Host connecting to iframe with validation + * @example Host connecting to iframe * ```typescript * const iframe = document.getElementById('app') as HTMLIFrameElement; * const transport = new PostMessageTransport( * iframe.contentWindow!, - * iframe.contentWindow // Only accept messages from this iframe + * iframe.contentWindow! * ); * ``` */ @@ -108,7 +106,7 @@ export class PostMessageTransport implements Transport { /** * Send a JSON-RPC message to the target window. * - * Messages are sent using postMessage with "*" origin, meaning they are visible + * Messages are sent using `postMessage` with `"*"` origin, meaning they are visible * to all frames. The receiver should validate the message source for security. * * @param message - JSON-RPC message to send @@ -161,7 +159,7 @@ export class PostMessageTransport implements Transport { * Optional session identifier for this transport connection. * * Set by the MCP SDK to track the connection session. Not required for - * PostMessageTransport functionality. + * `PostMessageTransport` functionality. */ sessionId?: string; diff --git a/src/react/useApp.tsx b/src/react/useApp.tsx index 73f2812e..65b93daf 100644 --- a/src/react/useApp.tsx +++ b/src/react/useApp.tsx @@ -5,27 +5,29 @@ import { App, McpUiAppCapabilities, PostMessageTransport } from "../app"; export * from "../app"; /** - * Options for configuring the useApp hook. + * Options for configuring the {@link useApp} hook. * - * Note: This interface does NOT expose App options like `autoResize`. - * The hook creates the App with default options (autoResize: true). If you need - * custom App options, create the App manually instead of using this hook. + * Note: This interface does NOT expose {@link App} options like `autoResize`. + * The hook creates the `App` with default options (`autoResize: true`). If you + * need custom `App` options, create the `App` manually instead of using this hook. * * @see {@link useApp} for the hook that uses these options - * @see {@link useAutoResize} for manual auto-resize control with custom App options + * @see {@link useAutoResize} for manual auto-resize control with custom `App` options */ export interface UseAppOptions { /** App identification (name and version) */ appInfo: Implementation; - /** Features and capabilities this app provides */ + /** + * Declares what features this app supports. + */ capabilities: McpUiAppCapabilities; /** - * Called after App is created but before connection. + * Called after {@link App} is created but before connection. * * Use this to register request/notification handlers that need to be in place * before the initialization handshake completes. * - * @param app - The newly created App instance + * @param app - The newly created `App` instance * * @example Register a notification handler * ```typescript @@ -45,10 +47,10 @@ export interface UseAppOptions { } /** - * State returned by the useApp hook. + * State returned by the {@link useApp} hook. */ export interface AppState { - /** The connected App instance, null during initialization */ + /** The connected {@link App} instance, null during initialization */ app: App | null; /** Whether initialization completed successfully */ isConnected: boolean; @@ -59,16 +61,19 @@ export interface AppState { /** * React hook to create and connect an MCP App. * - * This hook manages the complete lifecycle of an {@link App}: creation, connection, - * and cleanup. It automatically creates a {@link PostMessageTransport} to window.parent - * and handles initialization. + * This hook manages {@link App} creation and connection. It automatically + * creates a {@link PostMessageTransport} to window.parent and handles + * initialization. + * + * This hook is part of the optional React integration. The core SDK (`App`, + * `PostMessageTransport`) is framework-agnostic and can be used with any UI + * framework or vanilla JavaScript. * * **Important**: The hook intentionally does NOT re-run when options change * to avoid reconnection loops. Options are only used during the initial mount. - * - * **Note**: This is part of the optional React integration. The core SDK - * (App, PostMessageTransport) is framework-agnostic and can be - * used with any UI framework or vanilla JavaScript. + * Furthermore, the `App` instance is NOT closed on unmount. This avoids cleanup + * issues during React Strict Mode's double-mount cycle. If you need to + * explicitly close the `App`, call {@link App.close} manually. * * @param options - Configuration for the app * @returns Current connection state and app instance. If connection fails during diff --git a/src/react/useAutoResize.ts b/src/react/useAutoResize.ts index 6b8779e6..4c83eff6 100644 --- a/src/react/useAutoResize.ts +++ b/src/react/useAutoResize.ts @@ -4,15 +4,17 @@ import { App } from "../app"; /** * React hook that automatically reports UI size changes to the host. * - * Uses ResizeObserver to watch `document.body` and `document.documentElement` for + * Uses `ResizeObserver` to watch `document.body` and `document.documentElement` for * size changes and sends `ui/notifications/size-changed` notifications. * + * The hook automatically cleans up the `ResizeObserver` when the component unmounts. + * * **Note**: This hook is rarely needed since the {@link useApp} hook automatically enables * auto-resize by default. This hook is provided for advanced cases where you * create the {@link App} manually with `autoResize: false` and want to add auto-resize * behavior later. * - * @param app - The connected App instance, or null during initialization + * @param app - The connected {@link App} instance, or null during initialization * @param elementRef - Currently unused. The hook always observes `document.body` * and `document.documentElement` regardless of this value. Passing a ref will * cause unnecessary effect re-runs; omit this parameter. @@ -31,7 +33,7 @@ import { App } from "../app"; * { autoResize: false } // Disable default auto-resize * ); * - * const transport = new PostMessageTransport(window.parent); + * const transport = new PostMessageTransport(window.parent, window.parent); * myApp.connect(transport) * .then(() => setApp(myApp)) * .catch((err) => setError(err)); diff --git a/src/react/useDocumentTheme.ts b/src/react/useDocumentTheme.ts index 2355c68f..a04c6e4b 100644 --- a/src/react/useDocumentTheme.ts +++ b/src/react/useDocumentTheme.ts @@ -5,11 +5,13 @@ import { McpUiTheme } from "../types"; /** * React hook that provides the current document theme reactively. * - * Uses a MutationObserver to watch for changes to the `data-theme` attribute + * Uses a `MutationObserver` to watch for changes to the `data-theme` attribute * or `class` on `document.documentElement`. When the theme changes (e.g., from * host context updates), the hook automatically re-renders your component with * the new theme value. * + * The `MutationObserver` is automatically disconnected when the component unmounts. + * * @returns The current theme ("light" or "dark") * * @example Conditionally render based on theme diff --git a/src/react/useHostStyles.ts b/src/react/useHostStyles.ts index 0e7fbf30..26006bc3 100644 --- a/src/react/useHostStyles.ts +++ b/src/react/useHostStyles.ts @@ -21,14 +21,13 @@ import { McpUiHostContext } from "../types"; * this hook ensures they work correctly by setting the `color-scheme` property * based on the host's theme preference. * - * @param app - The connected App instance, or null during initialization + * @param app - The connected {@link App} instance, or null during initialization * @param initialContext - Initial host context from the connection (optional). * If provided, styles and theme will be applied immediately on mount. * - * @example Basic usage with useApp + * @example * ```tsx - * import { useApp } from '@modelcontextprotocol/ext-apps/react'; - * import { useHostStyleVariables } from '@modelcontextprotocol/ext-apps/react'; + * import { useApp, useHostStyleVariables } from '@modelcontextprotocol/ext-apps/react'; * * function MyApp() { * const { app, isConnected } = useApp({ @@ -36,8 +35,8 @@ import { McpUiHostContext } from "../types"; * capabilities: {}, * }); * - * // Automatically apply host style variables and theme - * useHostStyleVariables(app); + * // Apply host styles - pass initial context to apply styles from connect() immediately + * useHostStyleVariables(app, app?.getHostContext()); * * return ( *
@@ -47,15 +46,6 @@ import { McpUiHostContext } from "../types"; * } * ``` * - * @example With initial context - * ```tsx - * const [hostContext, setHostContext] = useState(null); - * - * // ... get initial context from app.connect() result - * - * useHostStyleVariables(app, hostContext); - * ``` - * * @see {@link applyHostStyleVariables} for the underlying styles function * @see {@link applyDocumentTheme} for the underlying theme function * @see {@link useHostFonts} for applying host fonts @@ -112,7 +102,7 @@ export function useHostStyleVariables( * The hook also applies fonts from the initial host context when * the app first connects. * - * @param app - The connected App instance, or null during initialization + * @param app - The connected {@link App} instance, or null during initialization * @param initialContext - Initial host context from the connection (optional). * If provided, fonts will be applied immediately on mount. * @@ -182,13 +172,24 @@ export function useHostFonts( } /** - * React hook that applies host styles, fonts, and theme. + * Applies all host styling (CSS variables, theme, and fonts) to match the host application. * * This is a convenience hook that combines {@link useHostStyleVariables} and * {@link useHostFonts}. Use the individual hooks if you need more control. * - * @param app - The connected App instance, or null during initialization + * @param app - The connected {@link App} instance, or null during initialization * @param initialContext - Initial host context from the connection (optional). + * Pass `app?.getHostContext()` to apply styles immediately on mount. + * + * @example + * ```tsx + * function MyApp() { + * const { app } = useApp({ appInfo, capabilities: {} }); + * useHostStyles(app, app?.getHostContext()); + * + * return
...
; + * } + * ``` * * @see {@link useHostStyleVariables} for style variables and theme only * @see {@link useHostFonts} for fonts only diff --git a/src/server/index.ts b/src/server/index.ts index df7a36e5..f242e2a2 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -1,7 +1,25 @@ /** - * Server Helpers for MCP Apps. + * Utilities for MCP servers to register tools and resources that display interactive UIs. + * + * Use these helpers instead of the base SDK's `registerTool` and `registerResource` when + * your tool should render an {@link app!App} in the client. They handle UI metadata normalization + * and provide sensible defaults for the MCP Apps MIME type ({@link RESOURCE_MIME_TYPE}). * * @module server-helpers + * + * @example + * ```typescript + * import { registerAppTool, registerAppResource, RESOURCE_MIME_TYPE } from '@modelcontextprotocol/ext-apps/server'; + * + * // Register a tool that displays a widget + * registerAppTool(server, "weather", { + * description: "Get weather forecast", + * _meta: { ui: { resourceUri: "ui://weather/widget.html" } }, + * }, handler); + * + * // Register the HTML resource the tool references + * registerAppResource(server, "Weather Widget", "ui://weather/widget.html", {}, readCallback); + * ``` */ import { @@ -29,7 +47,8 @@ export { RESOURCE_URI_META_KEY, RESOURCE_MIME_TYPE }; export type { ResourceMetadata, ToolCallback, ReadResourceCallback }; /** - * Tool configuration (same as McpServer.registerTool). + * Base tool configuration matching the standard MCP server tool options. + * Extended by {@link McpUiAppToolConfig} to add UI metadata requirements. */ export interface ToolConfig { title?: string; @@ -41,7 +60,14 @@ export interface ToolConfig { } /** - * MCP App Tool configuration for `registerAppTool`. + * Configuration for tools that render an interactive UI. + * + * Extends {@link ToolConfig} with a required `_meta` field that specifies UI metadata. + * The UI resource can be specified in two ways: + * - `_meta.ui.resourceUri` (preferred) + * - `_meta["ui/resourceUri"]` (deprecated, for backward compatibility) + * + * @see {@link registerAppTool} for the recommended way to register app tools */ export interface McpUiAppToolConfig extends ToolConfig { _meta: { @@ -65,11 +91,24 @@ export interface McpUiAppToolConfig extends ToolConfig { } /** - * MCP App Resource configuration for `registerAppResource`. + * MCP App Resource configuration for {@link registerAppResource}. + * + * Extends the base MCP SDK `ResourceMetadata` with optional UI metadata + * for configuring security policies and rendering preferences. + * + * @see {@link registerAppResource} for usage */ export interface McpUiAppResourceConfig extends ResourceMetadata { + /** + * Optional UI metadata for the resource. + * Used to configure security policies (CSP) and rendering preferences. + */ _meta?: { + /** + * UI-specific metadata including CSP configuration and rendering preferences. + */ ui?: McpUiResourceMeta; + // Allow additional metadata properties for extensibility. [key: string]: unknown; }; } @@ -77,14 +116,16 @@ export interface McpUiAppResourceConfig extends ResourceMetadata { /** * Register an app tool with the MCP server. * - * This is a convenience wrapper around `server.registerTool` that will allow more backwards-compatibility. + * This is a convenience wrapper around `server.registerTool` that normalizes + * UI metadata: if `_meta.ui.resourceUri` is set, the legacy `_meta["ui/resourceUri"]` + * key is also populated (and vice versa) for compatibility with older hosts. * * @param server - The MCP server instance * @param name - Tool name/identifier - * @param config - Tool configuration with required `ui` field - * @param handler - Tool handler function + * @param config - Tool configuration with `_meta` field containing UI metadata + * @param cb - Tool handler function * - * @example + * @example Basic usage * ```typescript * import { registerAppTool } from '@modelcontextprotocol/ext-apps/server'; * import { z } from 'zod'; @@ -94,13 +135,50 @@ export interface McpUiAppResourceConfig extends ResourceMetadata { * description: "Get current weather for a location", * inputSchema: { location: z.string() }, * _meta: { - * [RESOURCE_URI_META_KEY]: "ui://weather/widget.html", + * ui: { resourceUri: "ui://weather/widget.html" }, * }, * }, async (args) => { * const weather = await fetchWeather(args.location); * return { content: [{ type: "text", text: JSON.stringify(weather) }] }; * }); * ``` + * + * @example Tool visibility - create app-only tools for UI actions + * ```typescript + * import { registerAppTool } from '@modelcontextprotocol/ext-apps/server'; + * import { z } from 'zod'; + * + * // Main tool - visible to both model and app (default) + * registerAppTool(server, "show-cart", { + * description: "Display the user's shopping cart", + * _meta: { + * ui: { + * resourceUri: "ui://shop/cart.html", + * visibility: ["model", "app"], + * }, + * }, + * }, async () => { + * const cart = await getCart(); + * return { content: [{ type: "text", text: JSON.stringify(cart) }] }; + * }); + * + * // App-only tool - hidden from the model, only callable by the UI + * registerAppTool(server, "update-quantity", { + * description: "Update item quantity in cart", + * inputSchema: { itemId: z.string(), quantity: z.number() }, + * _meta: { + * ui: { + * resourceUri: "ui://shop/cart.html", + * visibility: ["app"], + * }, + * }, + * }, async ({ itemId, quantity }) => { + * const cart = await updateCartItem(itemId, quantity); + * return { content: [{ type: "text", text: JSON.stringify(cart) }] }; + * }); + * ``` + * + * @see {@link registerAppResource} to register the HTML resource referenced by the tool */ export function registerAppTool< OutputArgs extends ZodRawShapeCompat | AnySchema, @@ -137,22 +215,21 @@ export function registerAppTool< * Register an app resource with the MCP server. * * This is a convenience wrapper around `server.registerResource` that: - * - Defaults the MIME type to "text/html;profile=mcp-app" + * - Defaults the MIME type to {@link RESOURCE_MIME_TYPE} (`"text/html;profile=mcp-app"`) * - Provides a cleaner API matching the SDK's callback signature * * @param server - The MCP server instance * @param name - Human-readable resource name - * @param uri - Resource URI (should match the `ui` field in tool config) + * @param uri - Resource URI (should match the `_meta.ui` field in tool config) * @param config - Resource configuration * @param readCallback - Callback that returns the resource contents * - * @example + * @example Basic usage * ```typescript * import { registerAppResource } from '@modelcontextprotocol/ext-apps/server'; * * registerAppResource(server, "Weather Widget", "ui://weather/widget.html", { * description: "Interactive weather display", - * mimeType: RESOURCE_MIME_TYPE, * }, async () => ({ * contents: [{ * uri: "ui://weather/widget.html", @@ -161,6 +238,23 @@ export function registerAppTool< * }], * })); * ``` + * + * @example With CSP configuration for external domains + * ```typescript + * registerAppResource(server, "Music Player", "ui://music/player.html", { + * description: "Audio player with external soundfonts", + * _meta: { + * ui: { + * csp: { + * connectDomains: ["https://api.example.com"], // For fetch/WebSocket + * resourceDomains: ["https://cdn.example.com"], // For scripts/styles/images + * }, + * }, + * }, + * }, readCallback); + * ``` + * + * @see {@link registerAppTool} to register tools that reference this resource */ export function registerAppResource( server: Pick, diff --git a/src/spec.types.ts b/src/spec.types.ts index 998e4d26..cb6af1f7 100644 --- a/src/spec.types.ts +++ b/src/spec.types.ts @@ -2,7 +2,7 @@ * MCP Apps Protocol Types (spec.types.ts) * * This file contains pure TypeScript interface definitions for the MCP Apps protocol. - * These types are the source of truth and are used to generate Zod schemas via ts-to-zod. + * These types are the source of truth and are used to generate Zod schemas via `ts-to-zod`. * * - Use `@description` JSDoc tags to generate `.describe()` calls on schemas * - Run `npm run generate:schemas` to regenerate schemas from these types @@ -144,7 +144,7 @@ export type McpUiStyles = Record; /** * @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 + * @see {@link app!App.openLink} for the method that sends this request */ export interface McpUiOpenLinkRequest { method: "ui/open-link"; @@ -163,14 +163,14 @@ export interface McpUiOpenLinkResult { isError?: boolean; /** * Index signature required for MCP SDK `Protocol` class compatibility. - * Note: The schema intentionally omits this to enforce strict validation. + * Note: The generated schema uses passthrough() to allow additional properties. */ [key: string]: unknown; } /** * @description Request to send a message to the host's chat interface. - * @see {@link app.App.sendMessage} for the method that sends this request + * @see {@link app!App.sendMessage} for the method that sends this request */ export interface McpUiMessageRequest { method: "ui/message"; @@ -191,7 +191,7 @@ export interface McpUiMessageResult { isError?: boolean; /** * Index signature required for MCP SDK `Protocol` class compatibility. - * Note: The schema intentionally omits this to enforce strict validation. + * Note: The generated schema uses passthrough() to allow additional properties. */ [key: string]: unknown; } @@ -226,8 +226,8 @@ export interface McpUiSandboxResourceReadyNotification { } /** - * @description Notification of UI size changes (bidirectional: Guest <-> Host). - * @see {@link app.App.sendSizeChanged} for the method to send this from Guest UI + * @description Notification of UI size changes (Guest UI -> Host). + * @see {@link app!App.sendSizeChanged} for the method to send this from Guest UI */ export interface McpUiSizeChangedNotification { method: "ui/notifications/size-changed"; @@ -287,7 +287,7 @@ export interface McpUiToolCancelledNotification { * @description CSS blocks that can be injected by apps. */ export interface McpUiHostCss { - /** @description CSS for font loading (@font-face rules or @import statements). Apps must apply using applyHostFonts(). */ + /** @description CSS for font loading (`@font-face` rules or `@import` statements). Apps must apply using {@link applyHostFonts}. */ fonts?: string; } @@ -408,7 +408,7 @@ export interface McpUiUpdateModelContextRequest { /** * @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 + * @see {@link app-bridge!AppBridge.teardownResource} for the host method that sends this */ export interface McpUiResourceTeardownRequest { method: "ui/resource-teardown"; @@ -476,7 +476,7 @@ export interface McpUiHostCapabilities { } /** - * @description Capabilities provided by the Guest UI (App). + * @description Capabilities provided by the Guest UI ({@link app!App}). * @see {@link McpUiInitializeRequest} for the initialization request that includes these capabilities */ export interface McpUiAppCapabilities { @@ -491,7 +491,7 @@ export interface McpUiAppCapabilities { /** * @description Initialization request sent from Guest UI to Host. - * @see {@link app.App.connect} for the method that sends this request + * @see {@link app!App.connect} for the method that sends this request */ export interface McpUiInitializeRequest { method: "ui/initialize"; @@ -520,14 +520,14 @@ export interface McpUiInitializeResult { hostContext: McpUiHostContext; /** * Index signature required for MCP SDK `Protocol` class compatibility. - * Note: The schema intentionally omits this to enforce strict validation. + * Note: The generated schema uses passthrough() to allow additional properties. */ [key: string]: unknown; } /** * @description Notification that Guest UI has completed initialization (Guest UI -> Host). - * @see {@link app.App.connect} for the method that sends this notification + * @see {@link app!App.connect} for the method that sends this notification */ export interface McpUiInitializedNotification { method: "ui/notifications/initialized"; @@ -582,7 +582,7 @@ export interface McpUiResourceMeta { * @description Request to change the display mode of the UI. * The host will respond with the actual display mode that was set, * which may differ from the requested mode if not supported. - * @see {@link app.App.requestDisplayMode} for the method that sends this request + * @see {@link app!App.requestDisplayMode} for the method that sends this request */ export interface McpUiRequestDisplayModeRequest { method: "ui/request-display-mode"; @@ -601,7 +601,7 @@ export interface McpUiRequestDisplayModeResult { mode: McpUiDisplayMode; /** * Index signature required for MCP SDK `Protocol` class compatibility. - * Note: The schema intentionally omits this to enforce strict validation. + * Note: The generated schema uses passthrough() to allow additional properties. */ [key: string]: unknown; } diff --git a/src/styles.ts b/src/styles.ts index f3d0e752..322c5e9f 100644 --- a/src/styles.ts +++ b/src/styles.ts @@ -76,12 +76,12 @@ export function applyDocumentTheme(theme: McpUiTheme): void { /** * Apply host style variables as CSS custom properties on an element. * - * This function takes the `variables` object from `McpUiHostContext.styles` and sets + * This function takes the `variables` object from {@link McpUiHostContext.styles} and sets * each CSS variable on the specified root element (defaults to `document.documentElement`). * This allows apps to use the host's theming values via CSS variables like * `var(--color-background-primary)`. * - * @param styles - The styles object from `McpUiHostContext.styles.variables` + * @param styles - The style variables object from `McpUiHostContext.styles.variables` * @param root - The element to apply styles to (defaults to `document.documentElement`) * * @example Apply style variables from host context @@ -123,10 +123,10 @@ export function applyHostStyleVariables( * self-hosted fonts, `@import` statements for Google Fonts or other font services, * or a combination of both. * - * The styles are only injected once. Subsequent calls will not create duplicate - * style tags. + * The styles are only injected once. Subsequent calls are no-ops and will not + * create duplicate style tags. * - * @param fontCss - CSS string containing @font-face rules and/or @import statements + * @param fontCss - CSS string containing `@font-face` rules and/or `@import` statements * * @example Apply fonts from host context * ```typescript diff --git a/src/types.ts b/src/types.ts index 5cbc0b48..77563dc8 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,12 +1,12 @@ /** * MCP Apps Protocol Types and Schemas * - * This file re-exports types from spec.types.ts and schemas from generated/schema.ts. - * Compile-time verification is handled by generated/schema.test.ts. + * This file re-exports types from `spec.types.ts` and schemas from `generated/schema.ts`. + * Compile-time verification is handled by `generated/schema.test.ts`. * - * @see spec.types.ts for the source of truth TypeScript interfaces - * @see generated/schema.ts for auto-generated Zod schemas - * @see generated/schema.test.ts for compile-time verification + * @see `spec.types.ts` for the source of truth TypeScript interfaces + * @see `generated/schema.ts` for auto-generated Zod schemas + * @see `generated/schema.test.ts` for compile-time verification */ // Re-export all types from spec.types.ts @@ -151,7 +151,8 @@ import { * * Includes: * - MCP UI requests (initialize, open-link, message, resource-teardown, request-display-mode) - * - MCP server requests forwarded from the app (tools/call, resources/*, prompts/list) + * - MCP server requests forwarded from the app (tools/call, tools/list, resources/list, + * resources/templates/list, resources/read, prompts/list) * - Protocol requests (ping) */ export type AppRequest = diff --git a/typedoc.config.mjs b/typedoc.config.mjs new file mode 100644 index 00000000..bda329ee --- /dev/null +++ b/typedoc.config.mjs @@ -0,0 +1,30 @@ +import { OptionDefaults } from "typedoc"; + +/** @type {Partial} */ +const config = { + blockTags: [...OptionDefaults.blockTags, "@description"], + intentionallyNotExported: ["AppOptions"], + projectDocuments: ["docs/quickstart.md"], + entryPoints: [ + "src/server/index.ts", + "src/app.ts", + "src/react/index.tsx", + "src/app-bridge.ts", + "src/message-transport.ts", + "src/types.ts", + ], + out: "docs/api", + gitRevision: "main", + excludePrivate: true, + excludeInternal: false, + categorizeByGroup: true, + navigationLinks: { + GitHub: "https://github.com/modelcontextprotocol/ext-apps", + Specification: + "https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/draft/apps.mdx", + }, + readme: "README.md", + includeVersion: true, +}; + +export default config; diff --git a/typedoc.json b/typedoc.json deleted file mode 100644 index 8ef1cb0e..00000000 --- a/typedoc.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "$schema": "https://typedoc.org/schema.json", - "projectDocuments": ["docs/quickstart.md"], - "entryPoints": [ - "src/app.ts", - "src/app-bridge.ts", - "src/types.ts", - "src/message-transport.ts", - "src/react/index.tsx" - ], - "out": "docs/api", - "gitRevision": "main", - "excludePrivate": true, - "excludeInternal": false, - "categorizeByGroup": true, - "navigationLinks": { - "GitHub": "https://github.com/modelcontextprotocol/ext-apps", - "Specification": "https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/draft/apps.mdx" - }, - "readme": "README.md", - "includeVersion": true -}