Improve JSDoc comments with cross-references and clarifications (#254)
Key improvements:
- Add `{@link}` cross-references throughout the codebase to make API
documentation navigable and help AI models understand relationships
- Use `{@link module!Export}` syntax for cross-module references
- Add backticks for inline code formatting (`ResizeObserver`, `App`, etc)
- Fix `PostMessageTransport` examples to show required two-argument form
- Clarify `onteardown` callback return type requirement
- Document React hooks cleanup behavior and Strict Mode considerations
- Add tool visibility example for `registerAppTool`
- Add CSP example for `registerAppResource`
- Fix notification direction documentation in `spec.types.ts`
TypeDoc config migrated from `typedoc.json` to `typedoc.config.mjs` to:
- Support custom `@description` block tag
- Add `intentionallyNotExported` for internal types
- Include `src/server/index.ts` entry point
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
978d8e6fff
commit
d48e35d88a
15 changed files with 359 additions and 231 deletions
|
|
@ -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<McpUiMessageResult> 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<McpUiMessageResult>` 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<McpUiOpenLinkResult> with optional isError flag
|
||||
* - `params.url` - URL to open in the host's browser
|
||||
* - `extra` - Request metadata (abort signal, session info)
|
||||
* - Returns: `Promise<McpUiOpenLinkResult>` 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<McpUiRequestDisplayModeResult> with the actual mode set
|
||||
* - `params.mode` - The display mode being requested ("inline" | "fullscreen" | "pip")
|
||||
* - `extra` - Request metadata (abort signal, session info)
|
||||
* - Returns: `Promise<McpUiRequestDisplayModeResult>` 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.
|
||||
|
|
|
|||
56
src/app.ts
56
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<AppRequest, AppNotification, AppResult> {
|
|||
*
|
||||
* @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<AppRequest, AppNotification, AppResult> {
|
|||
*
|
||||
* 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<AppRequest, AppNotification, AppResult> {
|
|||
*
|
||||
* 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<AppRequest, AppNotification, AppResult> {
|
|||
*
|
||||
* 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<AppRequest, AppNotification, AppResult> {
|
|||
*
|
||||
* 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<AppRequest, AppNotification, AppResult> {
|
|||
* 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<AppRequest, AppNotification, AppResult> {
|
|||
* 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<AppRequest, AppNotification, AppResult> {
|
|||
* await saveState();
|
||||
* closeConnections();
|
||||
* console.log("App ready for teardown");
|
||||
* return {};
|
||||
* };
|
||||
* ```
|
||||
*
|
||||
|
|
@ -620,9 +630,9 @@ export class App extends Protocol<AppRequest, AppNotification, AppResult> {
|
|||
*
|
||||
* 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<AppRequest, AppNotification, AppResult> {
|
|||
* 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<AppRequest, AppNotification, AppResult> {
|
|||
* );
|
||||
*
|
||||
* 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);
|
||||
|
|
|
|||
5
src/generated/schema.json
generated
5
src/generated/schema.json
generated
|
|
@ -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"
|
||||
}
|
||||
},
|
||||
|
|
|
|||
25
src/generated/schema.ts
generated
25
src/generated/schema.ts
generated
|
|
@ -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"),
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
* <div style={{ background: 'var(--color-background-primary)' }}>
|
||||
|
|
@ -47,15 +46,6 @@ import { McpUiHostContext } from "../types";
|
|||
* }
|
||||
* ```
|
||||
*
|
||||
* @example With initial context
|
||||
* ```tsx
|
||||
* const [hostContext, setHostContext] = useState<McpUiHostContext | null>(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 <div style={{ background: 'var(--color-background-primary)' }}>...</div>;
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @see {@link useHostStyleVariables} for style variables and theme only
|
||||
* @see {@link useHostFonts} for fonts only
|
||||
|
|
|
|||
|
|
@ -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<McpServer, "registerResource">,
|
||||
|
|
|
|||
|
|
@ -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<McpUiStyleVariableKey, string | undefined>;
|
|||
|
||||
/**
|
||||
* @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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
13
src/types.ts
13
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 =
|
||||
|
|
|
|||
30
typedoc.config.mjs
Normal file
30
typedoc.config.mjs
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
import { OptionDefaults } from "typedoc";
|
||||
|
||||
/** @type {Partial<import('typedoc').TypeDocOptions>} */
|
||||
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;
|
||||
22
typedoc.json
22
typedoc.json
|
|
@ -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
|
||||
}
|
||||
Loading…
Reference in a new issue