@modelcontextprotocol/ext-apps 0.4.0 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/LICENSE +196 -1
  2. package/README.md +274 -25
  3. package/dist/docs/patterns.d.ts +9 -0
  4. package/dist/src/app-bridge.d.ts +253 -247
  5. package/dist/src/app-bridge.examples.d.ts +9 -0
  6. package/dist/src/app-bridge.js +17 -17
  7. package/dist/src/app-with-deps.js +9 -9
  8. package/dist/src/app.d.ts +246 -209
  9. package/dist/src/app.examples.d.ts +9 -0
  10. package/dist/src/app.js +10 -10
  11. package/dist/src/generated/schema.d.ts +45 -33
  12. package/dist/src/generated/schema.test.d.ts +1 -0
  13. package/dist/src/message-transport.d.ts +30 -32
  14. package/dist/src/message-transport.examples.d.ts +9 -0
  15. package/dist/src/react/index.d.ts +8 -10
  16. package/dist/src/react/index.examples.d.ts +6 -0
  17. package/dist/src/react/index.js +8 -8
  18. package/dist/src/react/react-with-deps.js +8 -8
  19. package/dist/src/react/useApp.d.ts +58 -44
  20. package/dist/src/react/useApp.examples.d.ts +6 -0
  21. package/dist/src/react/useAutoResize.d.ts +14 -11
  22. package/dist/src/react/useAutoResize.examples.d.ts +6 -0
  23. package/dist/src/react/useDocumentTheme.d.ts +14 -16
  24. package/dist/src/react/useDocumentTheme.examples.d.ts +6 -0
  25. package/dist/src/react/useHostStyles.d.ts +45 -53
  26. package/dist/src/react/useHostStyles.examples.d.ts +6 -0
  27. package/dist/src/server/index.d.ts +215 -41
  28. package/dist/src/server/index.examples.d.ts +9 -0
  29. package/dist/src/server/index.js +10 -10
  30. package/dist/src/spec.types.d.ts +56 -40
  31. package/dist/src/styles.d.ts +75 -32
  32. package/dist/src/styles.examples.d.ts +9 -0
  33. package/dist/src/types.d.ts +8 -7
  34. package/package.json +26 -7
package/dist/src/app.d.ts CHANGED
@@ -7,52 +7,61 @@ export { PostMessageTransport } from "./message-transport";
7
7
  export * from "./types";
8
8
  export { applyHostStyleVariables, applyHostFonts, getDocumentTheme, applyDocumentTheme, } from "./styles";
9
9
  /**
10
- * Metadata key for associating a resource URI with a tool call.
10
+ * Metadata key for associating a UI resource URI with a tool.
11
11
  *
12
- * MCP servers include this key in tool call result metadata to indicate which
13
- * UI resource should be displayed for the tool. When hosts receive a tool result
14
- * containing this metadata, they resolve and render the corresponding App.
12
+ * MCP servers include this key in tool definition metadata (via `tools/list`)
13
+ * to indicate which UI resource should be displayed when the tool is called.
14
+ * When hosts see a tool with this metadata, they fetch and render the
15
+ * corresponding {@link App `App`}.
15
16
  *
16
- * **Note**: This constant is provided for reference. MCP servers set this metadata
17
- * in their tool handlers; App developers typically don't need to use it directly.
17
+ * **Note**: This constant is provided for reference. App developers typically
18
+ * don't need to use it directly. Prefer using {@link server-helpers!registerAppTool `registerAppTool`}
19
+ * with the `_meta.ui.resourceUri` format instead.
18
20
  *
19
21
  * @example How MCP servers use this key (server-side, not in Apps)
20
- * ```typescript
21
- * // In an MCP server's tool handler:
22
- * return {
23
- * content: [{ type: "text", text: "Result" }],
24
- * _meta: {
25
- * [RESOURCE_URI_META_KEY]: "ui://weather/forecast"
26
- * }
27
- * };
22
+ * ```ts source="./app.examples.ts#RESOURCE_URI_META_KEY_serverSide"
23
+ * server.registerTool(
24
+ * "weather",
25
+ * {
26
+ * description: "Get weather forecast",
27
+ * _meta: {
28
+ * [RESOURCE_URI_META_KEY]: "ui://weather/forecast",
29
+ * },
30
+ * },
31
+ * handler,
32
+ * );
28
33
  * ```
29
34
  *
30
35
  * @example How hosts check for this metadata (host-side)
31
- * ```typescript
32
- * const result = await mcpClient.callTool({ name: "weather", arguments: {} });
33
- * const uiUri = result._meta?.[RESOURCE_URI_META_KEY];
34
- * if (uiUri) {
35
- * // Load and display the UI resource
36
+ * ```ts source="./app.examples.ts#RESOURCE_URI_META_KEY_hostSide"
37
+ * // Check tool definition metadata (from tools/list response):
38
+ * const uiUri = tool._meta?.[RESOURCE_URI_META_KEY];
39
+ * if (typeof uiUri === "string" && uiUri.startsWith("ui://")) {
40
+ * // Fetch the resource and display the UI
36
41
  * }
37
42
  * ```
38
43
  */
39
44
  export declare const RESOURCE_URI_META_KEY = "ui/resourceUri";
40
45
  /**
41
46
  * MIME type for MCP UI resources.
47
+ *
48
+ * Identifies HTML content as an MCP App UI resource.
49
+ *
50
+ * Used by {@link server-helpers!registerAppResource `registerAppResource`} as the default MIME type for app resources.
42
51
  */
43
52
  export declare const RESOURCE_MIME_TYPE = "text/html;profile=mcp-app";
44
53
  /**
45
- * Options for configuring App behavior.
54
+ * Options for configuring {@link App `App`} behavior.
46
55
  *
47
- * Extends ProtocolOptions from the MCP SDK with App-specific configuration.
56
+ * Extends `ProtocolOptions` from the MCP SDK with `App`-specific configuration.
48
57
  *
49
- * @see ProtocolOptions from @modelcontextprotocol/sdk for inherited options
58
+ * @see `ProtocolOptions` from @modelcontextprotocol/sdk for inherited options
50
59
  */
51
60
  type AppOptions = ProtocolOptions & {
52
61
  /**
53
- * Automatically report size changes to the host using ResizeObserver.
62
+ * Automatically report size changes to the host using `ResizeObserver`.
54
63
  *
55
- * When enabled, the App monitors `document.body` and `document.documentElement`
64
+ * When enabled, the {@link App `App`} monitors `document.body` and `document.documentElement`
56
65
  * for size changes and automatically sends `ui/notifications/size-changed`
57
66
  * notifications to the host.
58
67
  *
@@ -64,14 +73,14 @@ type RequestHandlerExtra = Parameters<Parameters<App["setRequestHandler"]>[1]>[1
64
73
  /**
65
74
  * Main class for MCP Apps to communicate with their host.
66
75
  *
67
- * The App class provides a framework-agnostic way to build interactive MCP Apps
68
- * that run inside host applications. It extends the MCP SDK's Protocol class and
76
+ * The `App` class provides a framework-agnostic way to build interactive MCP Apps
77
+ * that run inside host applications. It extends the MCP SDK's `Protocol` class and
69
78
  * handles the connection lifecycle, initialization handshake, and bidirectional
70
79
  * communication with the host.
71
80
  *
72
81
  * ## Architecture
73
82
  *
74
- * Guest UIs (Apps) act as MCP clients connecting to the host via {@link PostMessageTransport}.
83
+ * Views (Apps) act as MCP clients connecting to the host via {@link PostMessageTransport `PostMessageTransport`}.
75
84
  * The host proxies requests to the actual MCP server and forwards
76
85
  * responses back to the App.
77
86
  *
@@ -84,59 +93,38 @@ type RequestHandlerExtra = Parameters<Parameters<App["setRequestHandler"]>[1]>[1
84
93
  *
85
94
  * ## Inherited Methods
86
95
  *
87
- * As a subclass of Protocol, App inherits key methods for handling communication:
96
+ * As a subclass of `Protocol`, `App` inherits key methods for handling communication:
88
97
  * - `setRequestHandler()` - Register handlers for requests from host
89
98
  * - `setNotificationHandler()` - Register handlers for notifications from host
90
99
  *
91
- * @see Protocol from @modelcontextprotocol/sdk for all inherited methods
100
+ * @see `Protocol` from @modelcontextprotocol/sdk for all inherited methods
92
101
  *
93
102
  * ## Notification Setters
94
103
  *
95
- * For common notifications, the App class provides convenient setter properties
104
+ * For common notifications, the `App` class provides convenient setter properties
96
105
  * that simplify handler registration:
97
106
  * - `ontoolinput` - Complete tool arguments from host
98
107
  * - `ontoolinputpartial` - Streaming partial tool arguments
99
108
  * - `ontoolresult` - Tool execution results
109
+ * - `ontoolcancelled` - Tool execution was cancelled by user or host
100
110
  * - `onhostcontextchanged` - Host context changes (theme, locale, etc.)
101
111
  *
102
112
  * These setters are convenience wrappers around `setNotificationHandler()`.
103
113
  * Both patterns work; use whichever fits your coding style better.
104
114
  *
105
115
  * @example Basic usage with PostMessageTransport
106
- * ```typescript
107
- * import {
108
- * App,
109
- * PostMessageTransport,
110
- * McpUiToolInputNotificationSchema
111
- * } from '@modelcontextprotocol/ext-apps';
112
- *
116
+ * ```ts source="./app.examples.ts#App_basicUsage"
113
117
  * const app = new App(
114
118
  * { name: "WeatherApp", version: "1.0.0" },
115
- * {} // capabilities
119
+ * {}, // capabilities
116
120
  * );
117
121
  *
118
- * // Register notification handler using setter (simpler)
122
+ * // Register handlers before connecting to ensure no notifications are missed
119
123
  * app.ontoolinput = (params) => {
120
124
  * console.log("Tool arguments:", params.arguments);
121
125
  * };
122
126
  *
123
- * // OR using inherited setNotificationHandler (more explicit)
124
- * app.setNotificationHandler(
125
- * McpUiToolInputNotificationSchema,
126
- * (notification) => {
127
- * console.log("Tool arguments:", notification.params.arguments);
128
- * }
129
- * );
130
- *
131
- * await app.connect(new PostMessageTransport(window.parent));
132
- * ```
133
- *
134
- * @example Sending a message to the host's chat
135
- * ```typescript
136
- * await app.sendMessage({
137
- * role: "user",
138
- * content: [{ type: "text", text: "Weather updated!" }]
139
- * });
127
+ * await app.connect();
140
128
  * ```
141
129
  */
142
130
  export declare class App extends Protocol<AppRequest, AppNotification, AppResult> {
@@ -151,14 +139,14 @@ export declare class App extends Protocol<AppRequest, AppNotification, AppResult
151
139
  *
152
140
  * @param _appInfo - App identification (name and version)
153
141
  * @param _capabilities - Features and capabilities this app provides
154
- * @param options - Configuration options including autoResize behavior
142
+ * @param options - Configuration options including `autoResize` behavior
155
143
  *
156
144
  * @example
157
- * ```typescript
145
+ * ```ts source="./app.examples.ts#App_constructor_basic"
158
146
  * const app = new App(
159
147
  * { name: "MyApp", version: "1.0.0" },
160
148
  * { tools: { listChanged: true } }, // capabilities
161
- * { autoResize: true } // options
149
+ * { autoResize: true }, // options
162
150
  * );
163
151
  * ```
164
152
  */
@@ -167,49 +155,40 @@ export declare class App extends Protocol<AppRequest, AppNotification, AppResult
167
155
  * Get the host's capabilities discovered during initialization.
168
156
  *
169
157
  * Returns the capabilities that the host advertised during the
170
- * {@link connect} handshake. Returns `undefined` if called before
158
+ * {@link connect `connect`} handshake. Returns `undefined` if called before
171
159
  * connection is established.
172
160
  *
173
161
  * @returns Host capabilities, or `undefined` if not yet connected
174
162
  *
175
163
  * @example Check host capabilities after connection
176
- * ```typescript
177
- * await app.connect(transport);
178
- * const caps = app.getHostCapabilities();
179
- * if (caps === undefined) {
180
- * console.error("Not connected");
181
- * return;
182
- * }
183
- * if (caps.serverTools) {
164
+ * ```ts source="./app.examples.ts#App_getHostCapabilities_checkAfterConnection"
165
+ * await app.connect();
166
+ * if (app.getHostCapabilities()?.serverTools) {
184
167
  * console.log("Host supports server tool calls");
185
168
  * }
186
169
  * ```
187
170
  *
188
- * @see {@link connect} for the initialization handshake
189
- * @see {@link McpUiHostCapabilities} for the capabilities structure
171
+ * @see {@link connect `connect`} for the initialization handshake
172
+ * @see {@link McpUiHostCapabilities `McpUiHostCapabilities`} for the capabilities structure
190
173
  */
191
174
  getHostCapabilities(): McpUiHostCapabilities | undefined;
192
175
  /**
193
176
  * Get the host's implementation info discovered during initialization.
194
177
  *
195
178
  * Returns the host's name and version as advertised during the
196
- * {@link connect} handshake. Returns `undefined` if called before
179
+ * {@link connect `connect`} handshake. Returns `undefined` if called before
197
180
  * connection is established.
198
181
  *
199
182
  * @returns Host implementation info, or `undefined` if not yet connected
200
183
  *
201
184
  * @example Log host information after connection
202
- * ```typescript
185
+ * ```ts source="./app.examples.ts#App_getHostVersion_logAfterConnection"
203
186
  * await app.connect(transport);
204
- * const host = app.getHostVersion();
205
- * if (host === undefined) {
206
- * console.error("Not connected");
207
- * return;
208
- * }
209
- * console.log(`Connected to ${host.name} v${host.version}`);
187
+ * const { name, version } = app.getHostVersion() ?? {};
188
+ * console.log(`Connected to ${name} v${version}`);
210
189
  * ```
211
190
  *
212
- * @see {@link connect} for the initialization handshake
191
+ * @see {@link connect `connect`} for the initialization handshake
213
192
  */
214
193
  getHostVersion(): Implementation | undefined;
215
194
  /**
@@ -225,24 +204,20 @@ export declare class App extends Protocol<AppRequest, AppNotification, AppResult
225
204
  * @returns Host context, or `undefined` if not yet connected
226
205
  *
227
206
  * @example Access host context after connection
228
- * ```typescript
207
+ * ```ts source="./app.examples.ts#App_getHostContext_accessAfterConnection"
229
208
  * await app.connect(transport);
230
209
  * const context = app.getHostContext();
231
- * if (context === undefined) {
232
- * console.error("Not connected");
233
- * return;
234
- * }
235
- * if (context.theme === "dark") {
210
+ * if (context?.theme === "dark") {
236
211
  * document.body.classList.add("dark-theme");
237
212
  * }
238
- * if (context.toolInfo) {
213
+ * if (context?.toolInfo) {
239
214
  * console.log("Tool:", context.toolInfo.tool.name);
240
215
  * }
241
216
  * ```
242
217
  *
243
- * @see {@link connect} for the initialization handshake
244
- * @see {@link onhostcontextchanged} for context change notifications
245
- * @see {@link McpUiHostContext} for the context structure
218
+ * @see {@link connect `connect`} for the initialization handshake
219
+ * @see {@link onhostcontextchanged `onhostcontextchanged`} for context change notifications
220
+ * @see {@link McpUiHostContext `McpUiHostContext`} for the context structure
246
221
  */
247
222
  getHostContext(): McpUiHostContext | undefined;
248
223
  /**
@@ -255,32 +230,22 @@ export declare class App extends Protocol<AppRequest, AppNotification, AppResult
255
230
  * This setter is a convenience wrapper around `setNotificationHandler()` that
256
231
  * automatically handles the notification schema and extracts the params for you.
257
232
  *
258
- * Register handlers before calling {@link connect} to avoid missing notifications.
233
+ * Register handlers before calling {@link connect `connect`} to avoid missing notifications.
259
234
  *
260
- * @param callback - Function called with the tool input params
235
+ * @param callback - Function called with the tool input params ({@link McpUiToolInputNotification.params `McpUiToolInputNotification.params`})
261
236
  *
262
- * @example Using the setter (simpler)
263
- * ```typescript
237
+ * @example
238
+ * ```ts source="./app.examples.ts#App_ontoolinput_setter"
264
239
  * // Register before connecting to ensure no notifications are missed
265
240
  * app.ontoolinput = (params) => {
266
241
  * console.log("Tool:", params.arguments);
267
242
  * // Update your UI with the tool arguments
268
243
  * };
269
- * await app.connect(transport);
244
+ * await app.connect();
270
245
  * ```
271
246
  *
272
- * @example Using setNotificationHandler (more explicit)
273
- * ```typescript
274
- * app.setNotificationHandler(
275
- * McpUiToolInputNotificationSchema,
276
- * (notification) => {
277
- * console.log("Tool:", notification.params.arguments);
278
- * }
279
- * );
280
- * ```
281
- *
282
- * @see {@link setNotificationHandler} for the underlying method
283
- * @see {@link McpUiToolInputNotification} for the notification structure
247
+ * @see {@link setNotificationHandler `setNotificationHandler`} for the underlying method
248
+ * @see {@link McpUiToolInputNotification `McpUiToolInputNotification`} for the notification structure
284
249
  */
285
250
  set ontoolinput(callback: (params: McpUiToolInputNotification["params"]) => void);
286
251
  /**
@@ -290,24 +255,46 @@ export declare class App extends Protocol<AppRequest, AppNotification, AppResult
290
255
  * streams partial tool arguments during tool call initialization. This enables
291
256
  * progressive rendering of tool arguments before they're complete.
292
257
  *
258
+ * **Important:** Partial arguments are "healed" JSON — the host closes unclosed
259
+ * brackets/braces to produce valid JSON. This means objects may be incomplete
260
+ * (e.g., the last item in an array may be truncated). Use partial data only
261
+ * for preview UI, not for critical operations.
262
+ *
293
263
  * This setter is a convenience wrapper around `setNotificationHandler()` that
294
264
  * automatically handles the notification schema and extracts the params for you.
295
265
  *
296
- * Register handlers before calling {@link connect} to avoid missing notifications.
266
+ * Register handlers before calling {@link connect `connect`} to avoid missing notifications.
297
267
  *
298
- * @param callback - Function called with each partial tool input update
268
+ * @param callback - Function called with each partial tool input update ({@link McpUiToolInputPartialNotification.params `McpUiToolInputPartialNotification.params`})
299
269
  *
300
270
  * @example Progressive rendering of tool arguments
301
- * ```typescript
271
+ * ```ts source="./app.examples.ts#App_ontoolinputpartial_progressiveRendering"
272
+ * let toolInputs: Record<string, unknown> | null = null;
273
+ * let toolInputsPartial: Record<string, unknown> | null = null;
274
+ *
302
275
  * app.ontoolinputpartial = (params) => {
303
- * console.log("Partial args:", params.arguments);
304
- * // Update your UI progressively as arguments stream in
276
+ * toolInputsPartial = params.arguments as Record<string, unknown>;
277
+ * render();
278
+ * };
279
+ *
280
+ * app.ontoolinput = (params) => {
281
+ * toolInputs = params.arguments as Record<string, unknown>;
282
+ * toolInputsPartial = null;
283
+ * render();
305
284
  * };
285
+ *
286
+ * function render() {
287
+ * if (toolInputs) {
288
+ * renderFinalUI(toolInputs);
289
+ * } else {
290
+ * renderLoadingUI(toolInputsPartial); // e.g., shimmer with partial preview
291
+ * }
292
+ * }
306
293
  * ```
307
294
  *
308
- * @see {@link setNotificationHandler} for the underlying method
309
- * @see {@link McpUiToolInputPartialNotification} for the notification structure
310
- * @see {@link ontoolinput} for the complete tool input handler
295
+ * @see {@link setNotificationHandler `setNotificationHandler`} for the underlying method
296
+ * @see {@link McpUiToolInputPartialNotification `McpUiToolInputPartialNotification`} for the notification structure
297
+ * @see {@link ontoolinput `ontoolinput`} for the complete tool input handler
311
298
  */
312
299
  set ontoolinputpartial(callback: (params: McpUiToolInputPartialNotification["params"]) => void);
313
300
  /**
@@ -320,25 +307,24 @@ export declare class App extends Protocol<AppRequest, AppNotification, AppResult
320
307
  * This setter is a convenience wrapper around `setNotificationHandler()` that
321
308
  * automatically handles the notification schema and extracts the params for you.
322
309
  *
323
- * Register handlers before calling {@link connect} to avoid missing notifications.
310
+ * Register handlers before calling {@link connect `connect`} to avoid missing notifications.
324
311
  *
325
- * @param callback - Function called with the tool result
312
+ * @param callback - Function called with the tool result ({@link McpUiToolResultNotification.params `McpUiToolResultNotification.params`})
326
313
  *
327
314
  * @example Display tool execution results
328
- * ```typescript
315
+ * ```ts source="./app.examples.ts#App_ontoolresult_displayResults"
329
316
  * app.ontoolresult = (params) => {
330
- * if (params.content) {
331
- * console.log("Tool output:", params.content);
332
- * }
333
317
  * if (params.isError) {
334
- * console.error("Tool execution failed");
318
+ * console.error("Tool execution failed:", params.content);
319
+ * } else if (params.content) {
320
+ * console.log("Tool output:", params.content);
335
321
  * }
336
322
  * };
337
323
  * ```
338
324
  *
339
- * @see {@link setNotificationHandler} for the underlying method
340
- * @see {@link McpUiToolResultNotification} for the notification structure
341
- * @see {@link ontoolinput} for the initial tool input handler
325
+ * @see {@link setNotificationHandler `setNotificationHandler`} for the underlying method
326
+ * @see {@link McpUiToolResultNotification `McpUiToolResultNotification`} for the notification structure
327
+ * @see {@link ontoolinput `ontoolinput`} for the initial tool input handler
342
328
  */
343
329
  set ontoolresult(callback: (params: McpUiToolResultNotification["params"]) => void);
344
330
  /**
@@ -352,21 +338,21 @@ export declare class App extends Protocol<AppRequest, AppNotification, AppResult
352
338
  * This setter is a convenience wrapper around `setNotificationHandler()` that
353
339
  * automatically handles the notification schema and extracts the params for you.
354
340
  *
355
- * Register handlers before calling {@link connect} to avoid missing notifications.
341
+ * Register handlers before calling {@link connect `connect`} to avoid missing notifications.
356
342
  *
357
- * @param callback - Function called when tool execution is cancelled
343
+ * @param callback - Function called when tool execution is cancelled. Receives optional cancellation reason — see {@link McpUiToolCancelledNotification.params `McpUiToolCancelledNotification.params`}.
358
344
  *
359
345
  * @example Handle tool cancellation
360
- * ```typescript
346
+ * ```ts source="./app.examples.ts#App_ontoolcancelled_handleCancellation"
361
347
  * app.ontoolcancelled = (params) => {
362
348
  * console.log("Tool cancelled:", params.reason);
363
- * showCancelledMessage(params.reason ?? "Operation was cancelled");
349
+ * // Update your UI to show cancellation state
364
350
  * };
365
351
  * ```
366
352
  *
367
- * @see {@link setNotificationHandler} for the underlying method
368
- * @see {@link McpUiToolCancelledNotification} for the notification structure
369
- * @see {@link ontoolresult} for successful tool completion
353
+ * @see {@link setNotificationHandler `setNotificationHandler`} for the underlying method
354
+ * @see {@link McpUiToolCancelledNotification `McpUiToolCancelledNotification`} for the notification structure
355
+ * @see {@link ontoolresult `ontoolresult`} for successful tool completion
370
356
  */
371
357
  set ontoolcancelled(callback: (params: McpUiToolCancelledNotification["params"]) => void);
372
358
  /**
@@ -380,12 +366,16 @@ export declare class App extends Protocol<AppRequest, AppNotification, AppResult
380
366
  * This setter is a convenience wrapper around `setNotificationHandler()` that
381
367
  * automatically handles the notification schema and extracts the params for you.
382
368
  *
383
- * Register handlers before calling {@link connect} to avoid missing notifications.
369
+ * Notification params are automatically merged into the internal host context
370
+ * before the callback is invoked. This means {@link getHostContext `getHostContext`} will
371
+ * return the updated values even before your callback runs.
372
+ *
373
+ * Register handlers before calling {@link connect `connect`} to avoid missing notifications.
384
374
  *
385
375
  * @param callback - Function called with the updated host context
386
376
  *
387
377
  * @example Respond to theme changes
388
- * ```typescript
378
+ * ```ts source="./app.examples.ts#App_onhostcontextchanged_respondToTheme"
389
379
  * app.onhostcontextchanged = (params) => {
390
380
  * if (params.theme === "dark") {
391
381
  * document.body.classList.add("dark-theme");
@@ -395,9 +385,9 @@ export declare class App extends Protocol<AppRequest, AppNotification, AppResult
395
385
  * };
396
386
  * ```
397
387
  *
398
- * @see {@link setNotificationHandler} for the underlying method
399
- * @see {@link McpUiHostContextChangedNotification} for the notification structure
400
- * @see {@link McpUiHostContext} for the full context structure
388
+ * @see {@link setNotificationHandler `setNotificationHandler`} for the underlying method
389
+ * @see {@link McpUiHostContextChangedNotification `McpUiHostContextChangedNotification`} for the notification structure
390
+ * @see {@link McpUiHostContext `McpUiHostContext`} for the full context structure
401
391
  */
402
392
  set onhostcontextchanged(callback: (params: McpUiHostContextChangedNotification["params"]) => void);
403
393
  /**
@@ -413,22 +403,23 @@ export declare class App extends Protocol<AppRequest, AppNotification, AppResult
413
403
  * This setter is a convenience wrapper around `setRequestHandler()` that
414
404
  * automatically handles the request schema.
415
405
  *
416
- * Register handlers before calling {@link connect} to avoid missing requests.
406
+ * Register handlers before calling {@link connect `connect`} to avoid missing requests.
417
407
  *
418
408
  * @param callback - Function called when teardown is requested.
419
- * Can return void or a Promise that resolves when cleanup is complete.
409
+ * Must return `McpUiResourceTeardownResult` (can be an empty object `{}`) or a Promise resolving to it.
420
410
  *
421
411
  * @example Perform cleanup before teardown
422
- * ```typescript
412
+ * ```ts source="./app.examples.ts#App_onteardown_performCleanup"
423
413
  * app.onteardown = async () => {
424
414
  * await saveState();
425
415
  * closeConnections();
426
416
  * console.log("App ready for teardown");
417
+ * return {};
427
418
  * };
428
419
  * ```
429
420
  *
430
- * @see {@link setRequestHandler} for the underlying method
431
- * @see {@link McpUiResourceTeardownRequest} for the request structure
421
+ * @see {@link setRequestHandler `setRequestHandler`} for the underlying method
422
+ * @see {@link McpUiResourceTeardownRequest `McpUiResourceTeardownRequest`} for the request structure
432
423
  */
433
424
  set onteardown(callback: (params: McpUiResourceTeardownRequest["params"], extra: RequestHandlerExtra) => McpUiResourceTeardownResult | Promise<McpUiResourceTeardownResult>);
434
425
  /**
@@ -443,14 +434,14 @@ export declare class App extends Protocol<AppRequest, AppNotification, AppResult
443
434
  * This setter is a convenience wrapper around `setRequestHandler()` that
444
435
  * automatically handles the request schema and extracts the params for you.
445
436
  *
446
- * Register handlers before calling {@link connect} to avoid missing requests.
437
+ * Register handlers before calling {@link connect `connect`} to avoid missing requests.
447
438
  *
448
439
  * @param callback - Async function that executes the tool and returns the result.
449
440
  * The callback will only be invoked if the app declared tool capabilities
450
441
  * in the constructor.
451
442
  *
452
443
  * @example Handle tool calls from the host
453
- * ```typescript
444
+ * ```ts source="./app.examples.ts#App_oncalltool_handleFromHost"
454
445
  * app.oncalltool = async (params, extra) => {
455
446
  * if (params.name === "greet") {
456
447
  * const name = params.arguments?.name ?? "World";
@@ -460,7 +451,7 @@ export declare class App extends Protocol<AppRequest, AppNotification, AppResult
460
451
  * };
461
452
  * ```
462
453
  *
463
- * @see {@link setRequestHandler} for the underlying method
454
+ * @see {@link setRequestHandler `setRequestHandler`} for the underlying method
464
455
  */
465
456
  set oncalltool(callback: (params: CallToolRequest["params"], extra: RequestHandlerExtra) => Promise<CallToolResult>);
466
457
  /**
@@ -475,23 +466,23 @@ export declare class App extends Protocol<AppRequest, AppNotification, AppResult
475
466
  * This setter is a convenience wrapper around `setRequestHandler()` that
476
467
  * automatically handles the request schema and extracts the params for you.
477
468
  *
478
- * Register handlers before calling {@link connect} to avoid missing requests.
469
+ * Register handlers before calling {@link connect `connect`} to avoid missing requests.
479
470
  *
480
- * @param callback - Async function that returns the list of available tools.
481
- * The callback will only be invoked if the app declared tool capabilities
482
- * in the constructor.
471
+ * @param callback - Async function that returns tool names as strings (simplified
472
+ * from full `ListToolsResult` with `Tool` objects). Registration is always
473
+ * allowed; capability validation occurs when handlers are invoked.
483
474
  *
484
475
  * @example Return available tools
485
- * ```typescript
476
+ * ```ts source="./app.examples.ts#App_onlisttools_returnTools"
486
477
  * app.onlisttools = async (params, extra) => {
487
478
  * return {
488
- * tools: ["calculate", "convert", "format"]
479
+ * tools: ["greet", "calculate", "format"],
489
480
  * };
490
481
  * };
491
482
  * ```
492
483
  *
493
- * @see {@link setRequestHandler} for the underlying method
494
- * @see {@link oncalltool} for handling tool execution
484
+ * @see {@link setRequestHandler `setRequestHandler`} for the underlying method
485
+ * @see {@link oncalltool `oncalltool`} for handling tool execution
495
486
  */
496
487
  set onlisttools(callback: (params: ListToolsRequest["params"], extra: RequestHandlerExtra) => Promise<{
497
488
  tools: string[];
@@ -540,11 +531,11 @@ export declare class App extends Protocol<AppRequest, AppNotification, AppResult
540
531
  * between transport failures (thrown) and tool execution failures (returned).
541
532
  *
542
533
  * @example Fetch updated weather data
543
- * ```typescript
534
+ * ```ts source="./app.examples.ts#App_callServerTool_fetchWeather"
544
535
  * try {
545
536
  * const result = await app.callServerTool({
546
537
  * name: "get_weather",
547
- * arguments: { location: "Tokyo" }
538
+ * arguments: { location: "Tokyo" },
548
539
  * });
549
540
  * if (result.isError) {
550
541
  * console.error("Tool returned error:", result.content);
@@ -565,24 +556,47 @@ export declare class App extends Protocol<AppRequest, AppNotification, AppResult
565
556
  *
566
557
  * @param params - Message role and content
567
558
  * @param options - Request options (timeout, etc.)
568
- * @returns Result indicating success or error (no message content returned)
559
+ * @returns Result with optional `isError` flag indicating host rejection
569
560
  *
570
- * @throws {Error} If the host rejects the message
561
+ * @throws {Error} If the request times out or the connection is lost
571
562
  *
572
563
  * @example Send a text message from user interaction
573
- * ```typescript
564
+ * ```ts source="./app.examples.ts#App_sendMessage_textFromInteraction"
574
565
  * try {
575
- * await app.sendMessage({
566
+ * const result = await app.sendMessage({
576
567
  * role: "user",
577
- * content: [{ type: "text", text: "Show me details for item #42" }]
568
+ * content: [{ type: "text", text: "Show me details for item #42" }],
578
569
  * });
570
+ * if (result.isError) {
571
+ * console.error("Host rejected the message");
572
+ * // Handle rejection appropriately for your app
573
+ * }
579
574
  * } catch (error) {
580
575
  * console.error("Failed to send message:", error);
581
- * // Handle error appropriately for your app
576
+ * // Handle transport/protocol error
582
577
  * }
583
578
  * ```
584
579
  *
585
- * @see {@link McpUiMessageRequest} for request structure
580
+ * @example Send follow-up message after offloading large data to model context
581
+ * ```ts source="./app.examples.ts#App_sendMessage_withLargeContext"
582
+ * const markdown = `---
583
+ * word-count: ${fullTranscript.split(/\s+/).length}
584
+ * speaker-names: ${speakerNames.join(", ")}
585
+ * ---
586
+ *
587
+ * ${fullTranscript}`;
588
+ *
589
+ * // Offload long transcript to model context
590
+ * await app.updateModelContext({ content: [{ type: "text", text: markdown }] });
591
+ *
592
+ * // Send brief trigger message
593
+ * await app.sendMessage({
594
+ * role: "user",
595
+ * content: [{ type: "text", text: "Summarize the key points" }],
596
+ * });
597
+ * ```
598
+ *
599
+ * @see {@link McpUiMessageRequest `McpUiMessageRequest`} for request structure
586
600
  */
587
601
  sendMessage(params: McpUiMessageRequest["params"], options?: RequestOptions): Promise<{
588
602
  [x: string]: unknown;
@@ -597,11 +611,11 @@ export declare class App extends Protocol<AppRequest, AppNotification, AppResult
597
611
  * @param params - Log level and message
598
612
  *
599
613
  * @example Log app state for debugging
600
- * ```typescript
614
+ * ```ts source="./app.examples.ts#App_sendLog_debugState"
601
615
  * app.sendLog({
602
616
  * level: "info",
603
617
  * data: "Weather data refreshed",
604
- * logger: "WeatherApp"
618
+ * logger: "WeatherApp",
605
619
  * });
606
620
  * ```
607
621
  *
@@ -611,31 +625,52 @@ export declare class App extends Protocol<AppRequest, AppNotification, AppResult
611
625
  /**
612
626
  * Update the host's model context with app state.
613
627
  *
614
- * Unlike `sendLog`, which is for debugging/telemetry, context updates
615
- * are intended to be available to the model in future reasoning,
616
- * without requiring a follow-up action (like `sendMessage`).
628
+ * Context updates are intended to be available to the model in future
629
+ * turns, without triggering an immediate model response (unlike {@link sendMessage `sendMessage`}).
617
630
  *
618
631
  * The host will typically defer sending the context to the model until the
619
- * next user message (including `ui/message`), and will only send the last
620
- * update received. Each call overwrites any previous context update.
632
+ * next user message either from the actual user or via `sendMessage`. Only
633
+ * the last update is sent; each call overwrites any previous context.
621
634
  *
622
635
  * @param params - Context content and/or structured content
623
636
  * @param options - Request options (timeout, etc.)
624
637
  *
625
638
  * @throws {Error} If the host rejects the context update (e.g., unsupported content type)
639
+ * @throws {Error} If the request times out or the connection is lost
626
640
  *
627
641
  * @example Update model context with current app state
628
- * ```typescript
642
+ * ```ts source="./app.examples.ts#App_updateModelContext_appState"
643
+ * const markdown = `---
644
+ * item-count: ${itemList.length}
645
+ * total-cost: ${totalCost}
646
+ * currency: ${currency}
647
+ * ---
648
+ *
649
+ * User is viewing their shopping cart with ${itemList.length} items selected:
650
+ *
651
+ * ${itemList.map((item) => `- ${item}`).join("\n")}`;
652
+ *
629
653
  * await app.updateModelContext({
630
- * content: [{ type: "text", text: "User selected 3 items totaling $150.00" }]
654
+ * content: [{ type: "text", text: markdown }],
631
655
  * });
632
656
  * ```
633
657
  *
634
- * @example Update with structured content
635
- * ```typescript
636
- * await app.updateModelContext({
637
- * structuredContent: { selectedItems: 3, total: 150.00, currency: "USD" }
638
- * });
658
+ * @example Report runtime error to model
659
+ * ```ts source="./app.examples.ts#App_updateModelContext_reportError"
660
+ * try {
661
+ * const _stream = await navigator.mediaDevices.getUserMedia({ audio: true });
662
+ * // ... use _stream for transcription
663
+ * } catch (err) {
664
+ * // Inform the model that the app is in a degraded state
665
+ * await app.updateModelContext({
666
+ * content: [
667
+ * {
668
+ * type: "text",
669
+ * text: "Error: transcription unavailable",
670
+ * },
671
+ * ],
672
+ * });
673
+ * }
639
674
  * ```
640
675
  *
641
676
  * @returns Promise that resolves when the context update is acknowledged
@@ -653,32 +688,32 @@ export declare class App extends Protocol<AppRequest, AppNotification, AppResult
653
688
  * Request the host to open an external URL in the default browser.
654
689
  *
655
690
  * The host may deny this request based on user preferences or security policy.
656
- * Apps should handle rejection gracefully.
691
+ * Apps should handle rejection gracefully by checking `result.isError`.
657
692
  *
658
693
  * @param params - URL to open
659
694
  * @param options - Request options (timeout, etc.)
660
- * @returns Result indicating success or error
695
+ * @returns Result with `isError: true` if the host denied the request (e.g., blocked domain, user cancelled)
661
696
  *
662
- * @throws {Error} If the host denies the request (e.g., blocked domain, user cancelled)
663
697
  * @throws {Error} If the request times out or the connection is lost
664
698
  *
665
699
  * @example Open documentation link
666
- * ```typescript
667
- * try {
668
- * await app.openLink({ url: "https://docs.example.com" });
669
- * } catch (error) {
670
- * console.error("Failed to open link:", error);
700
+ * ```ts source="./app.examples.ts#App_openLink_documentation"
701
+ * const { isError } = await app.openLink({ url: "https://docs.example.com" });
702
+ * if (isError) {
703
+ * // Host denied the request (e.g., blocked domain, user cancelled)
671
704
  * // Optionally show fallback: display URL for manual copy
705
+ * console.warn("Link request denied");
672
706
  * }
673
707
  * ```
674
708
  *
675
- * @see {@link McpUiOpenLinkRequest} for request structure
709
+ * @see {@link McpUiOpenLinkRequest `McpUiOpenLinkRequest`} for request structure
710
+ * @see {@link McpUiOpenLinkResult `McpUiOpenLinkResult`} for result structure
676
711
  */
677
712
  openLink(params: McpUiOpenLinkRequest["params"], options?: RequestOptions): Promise<{
678
713
  [x: string]: unknown;
679
714
  isError?: boolean | undefined;
680
715
  }>;
681
- /** @deprecated Use {@link openLink} instead */
716
+ /** @deprecated Use {@link openLink `openLink`} instead */
682
717
  sendOpenLink: App["openLink"];
683
718
  /**
684
719
  * Request a change to the display mode.
@@ -692,17 +727,18 @@ export declare class App extends Protocol<AppRequest, AppNotification, AppResult
692
727
  * @param options - Request options (timeout, etc.)
693
728
  * @returns Result containing the actual display mode that was set
694
729
  *
695
- * @example Request fullscreen mode
696
- * ```typescript
697
- * const context = app.getHostContext();
698
- * if (context?.availableDisplayModes?.includes("fullscreen")) {
699
- * const result = await app.requestDisplayMode({ mode: "fullscreen" });
700
- * console.log("Display mode set to:", result.mode);
730
+ * @example Toggle display mode
731
+ * ```ts source="./app.examples.ts#App_requestDisplayMode_toggle"
732
+ * const ctx = app.getHostContext();
733
+ * if (ctx?.availableDisplayModes?.includes("fullscreen")) {
734
+ * const target = ctx.displayMode === "fullscreen" ? "inline" : "fullscreen";
735
+ * const result = await app.requestDisplayMode({ mode: target });
736
+ * console.log("Now in:", result.mode);
701
737
  * }
702
738
  * ```
703
739
  *
704
- * @see {@link McpUiRequestDisplayModeRequest} for request structure
705
- * @see {@link McpUiHostContext} for checking availableDisplayModes
740
+ * @see {@link McpUiRequestDisplayModeRequest `McpUiRequestDisplayModeRequest`} for request structure
741
+ * @see {@link McpUiHostContext `McpUiHostContext`} for checking availableDisplayModes
706
742
  */
707
743
  requestDisplayMode(params: McpUiRequestDisplayModeRequest["params"], options?: RequestOptions): Promise<{
708
744
  [x: string]: unknown;
@@ -717,16 +753,16 @@ export declare class App extends Protocol<AppRequest, AppNotification, AppResult
717
753
  * @param params - New width and height in pixels
718
754
  *
719
755
  * @example Manually notify host of size change
720
- * ```typescript
756
+ * ```ts source="./app.examples.ts#App_sendSizeChanged_manual"
721
757
  * app.sendSizeChanged({
722
758
  * width: 400,
723
- * height: 600
759
+ * height: 600,
724
760
  * });
725
761
  * ```
726
762
  *
727
763
  * @returns Promise that resolves when the notification is sent
728
764
  *
729
- * @see {@link McpUiSizeChangedNotification} for notification structure
765
+ * @see {@link McpUiSizeChangedNotification `McpUiSizeChangedNotification`} for notification structure
730
766
  */
731
767
  sendSizeChanged(params: McpUiSizeChangedNotification["params"]): Promise<void>;
732
768
  /**
@@ -743,8 +779,12 @@ export declare class App extends Protocol<AppRequest, AppNotification, AppResult
743
779
  * @returns Cleanup function to disconnect the observer
744
780
  *
745
781
  * @example Manual setup for custom scenarios
746
- * ```typescript
747
- * const app = new App(appInfo, capabilities, { autoResize: false });
782
+ * ```ts source="./app.examples.ts#App_setupAutoResize_manual"
783
+ * const app = new App(
784
+ * { name: "MyApp", version: "1.0.0" },
785
+ * {},
786
+ * { autoResize: false },
787
+ * );
748
788
  * await app.connect(transport);
749
789
  *
750
790
  * // Later, enable auto-resize manually
@@ -763,34 +803,31 @@ export declare class App extends Protocol<AppRequest, AppNotification, AppResult
763
803
  * 2. Sends `ui/initialize` request with app info and capabilities
764
804
  * 3. Receives host capabilities and context in response
765
805
  * 4. Sends `ui/notifications/initialized` notification
766
- * 5. Sets up auto-resize using {@link setupSizeChangedNotifications} if enabled (default)
806
+ * 5. Sets up auto-resize using {@link setupSizeChangedNotifications `setupSizeChangedNotifications`} if enabled (default)
767
807
  *
768
808
  * If initialization fails, the connection is automatically closed and an error
769
809
  * is thrown.
770
810
  *
771
- * @param transport - Transport layer (typically PostMessageTransport)
811
+ * @param transport - Transport layer (typically {@link PostMessageTransport `PostMessageTransport`})
772
812
  * @param options - Request options for the initialize request
773
813
  *
774
814
  * @throws {Error} If initialization fails or connection is lost
775
815
  *
776
816
  * @example Connect with PostMessageTransport
777
- * ```typescript
778
- * const app = new App(
779
- * { name: "MyApp", version: "1.0.0" },
780
- * {}
781
- * );
817
+ * ```ts source="./app.examples.ts#App_connect_withPostMessageTransport"
818
+ * const app = new App({ name: "MyApp", version: "1.0.0" }, {});
782
819
  *
783
820
  * try {
784
- * await app.connect(new PostMessageTransport(window.parent));
821
+ * await app.connect(new PostMessageTransport(window.parent, window.parent));
785
822
  * console.log("Connected successfully!");
786
823
  * } catch (error) {
787
824
  * console.error("Failed to connect:", error);
788
825
  * }
789
826
  * ```
790
827
  *
791
- * @see {@link McpUiInitializeRequest} for the initialization request structure
792
- * @see {@link McpUiInitializedNotification} for the initialized notification
793
- * @see {@link PostMessageTransport} for the typical transport implementation
828
+ * @see {@link McpUiInitializeRequest `McpUiInitializeRequest`} for the initialization request structure
829
+ * @see {@link McpUiInitializedNotification `McpUiInitializedNotification`} for the initialized notification
830
+ * @see {@link PostMessageTransport `PostMessageTransport`} for the typical transport implementation
794
831
  */
795
832
  connect(transport?: Transport, options?: RequestOptions): Promise<void>;
796
833
  }