@modelcontextprotocol/ext-apps 0.0.1

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.
package/README.md ADDED
@@ -0,0 +1,75 @@
1
+ # @modelcontextprotocol/ext-apps
2
+
3
+ [![API Documentation](https://img.shields.io/badge/docs-API%20Reference-blue)](https://modelcontextprotocol.github.io/ext-apps/api/)
4
+
5
+ This repo contains the SDK and [specification](https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/draft/apps.mdx) for MCP Apps Extension ([SEP-1865](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/1865)).
6
+
7
+ MCP Apps are a proposed standard inspired by [MCP-UI](https://mcpui.dev/) and [OpenAI's Apps SDK](https://developers.openai.com/apps-sdk/) to allow MCP Servers to display interactive UI elements in conversational MCP clients / chatbots.
8
+
9
+ ## Overview
10
+
11
+ This SDK serves two audiences:
12
+
13
+ ### App Developers
14
+
15
+ Build interactive UIs that run inside MCP-enabled chat clients.
16
+
17
+ - **SDK for Apps**: `@modelcontextprotocol/ext-apps` — [API Docs](https://modelcontextprotocol.github.io/ext-apps/api/modules/app.html)
18
+ - **React hooks**: `@modelcontextprotocol/ext-apps/react` — [API Docs](https://modelcontextprotocol.github.io/ext-apps/api/modules/_modelcontextprotocol_ext-apps_react.html)
19
+
20
+ ### Host Developers
21
+
22
+ Embed and communicate with MCP Apps in your chat application.
23
+
24
+ - **SDK for Hosts**: `@modelcontextprotocol/ext-apps/app-bridge` — [API Docs](https://modelcontextprotocol.github.io/ext-apps/api/modules/app-bridge.html)
25
+
26
+ There's no _supported_ host implementation in this repo (beyond the [examples/basic-host](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/basic-host) example).
27
+
28
+ We have [contributed a tentative implementation](https://github.com/MCP-UI-Org/mcp-ui/pull/147) of hosting / iframing / sandboxing logic to the [MCP-UI](https://github.com/idosal/mcp-ui) repository, and expect OSS clients may use it, while other clients might roll their own hosting logic.
29
+
30
+ ## Installation
31
+
32
+ This repo is in flux and isn't published to npm yet. When it is, it will use the `@modelcontextprotocol/ext-apps` package.
33
+
34
+ In the meantime you can depend on the SDK library in a Node.js project by installing it with its git URL:
35
+
36
+ ```bash
37
+ npm install -S git+https://github.com/modelcontextprotocol/ext-apps.git
38
+ ```
39
+
40
+ Your `package.json` will then look like:
41
+
42
+ ```json
43
+ {
44
+ "dependencies": {
45
+ "@modelcontextprotocol/ext-apps": "git+https://github.com/modelcontextprotocol/ext-apps.git"
46
+ }
47
+ }
48
+ ```
49
+
50
+ > [!NOTE]
51
+ > The build tools (`esbuild`, `tsx`, `typescript`) are in `dependencies` rather than `devDependencies`. This is intentional: it allows the `prepare` script to run when the package is installed from git, since npm doesn't install devDependencies for git dependencies.
52
+ >
53
+ > Once the package is published to npm with pre-built `dist/`, these can be moved back to `devDependencies`.
54
+
55
+ ## Examples
56
+
57
+ - [`examples/basic-server-react`](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/basic-server-react) — Example MCP server with tools that return UI Apps (React)
58
+ - [`examples/basic-server-vanillajs`](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/basic-server-vanillajs) — Example MCP server with tools that return UI Apps (vanilla JS)
59
+ - [`examples/basic-host`](https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/basic-host) — Bare-bones example of hosting MCP Apps
60
+
61
+ To run the examples end-to-end:
62
+
63
+ ```
64
+ npm i
65
+ npm run examples:start
66
+ ```
67
+
68
+ Then open http://localhost:8080/
69
+
70
+ ## Resources
71
+
72
+ - [Quickstart Guide](https://modelcontextprotocol.github.io/ext-apps/api/documents/Quickstart.html)
73
+ - [API Documentation](https://modelcontextprotocol.github.io/ext-apps/api/)
74
+ - [Draft Specification](https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/draft/apps.mdx)
75
+ - [SEP-1865 Discussion](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/1865)
@@ -0,0 +1,594 @@
1
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
+ import { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
3
+ import { Implementation, LoggingMessageNotification, Notification, PingRequest, Request, Result } from "@modelcontextprotocol/sdk/types.js";
4
+ import { Protocol, ProtocolOptions, RequestOptions } from "@modelcontextprotocol/sdk/shared/protocol.js";
5
+ import { type McpUiSandboxResourceReadyNotification, type McpUiSizeChangedNotification, type McpUiToolInputNotification, type McpUiToolInputPartialNotification, type McpUiToolResultNotification, McpUiAppCapabilities, McpUiHostCapabilities, McpUiHostContext, McpUiHostContextChangedNotification, McpUiInitializedNotification, McpUiMessageRequest, McpUiMessageResult, McpUiOpenLinkRequest, McpUiOpenLinkResult, McpUiResourceTeardownRequest, McpUiSandboxProxyReadyNotification } from "./types";
6
+ export * from "./types";
7
+ export { RESOURCE_URI_META_KEY } from "./app";
8
+ export { PostMessageTransport } from "./message-transport";
9
+ /**
10
+ * Options for configuring AppBridge behavior.
11
+ *
12
+ * @see ProtocolOptions from @modelcontextprotocol/sdk for available options
13
+ */
14
+ export type HostOptions = ProtocolOptions & {
15
+ hostContext?: McpUiHostContext;
16
+ };
17
+ /**
18
+ * Protocol versions supported by this AppBridge implementation.
19
+ *
20
+ * The SDK automatically handles version negotiation during initialization.
21
+ * Hosts don't need to manage protocol versions manually.
22
+ */
23
+ export declare const SUPPORTED_PROTOCOL_VERSIONS: string[];
24
+ /**
25
+ * Extra metadata passed to request handlers.
26
+ *
27
+ * This type represents the additional context provided by the Protocol class
28
+ * when handling requests, including abort signals and session information.
29
+ * It is extracted from the MCP SDK's request handler signature.
30
+ *
31
+ * @internal
32
+ */
33
+ type RequestHandlerExtra = Parameters<Parameters<AppBridge["setRequestHandler"]>[1]>[1];
34
+ /**
35
+ * Host-side bridge for communicating with a single Guest UI (App).
36
+ *
37
+ * AppBridge extends the MCP SDK's Protocol class and acts as a proxy between
38
+ * the host application and a Guest UI running in an iframe. It automatically
39
+ * forwards MCP server capabilities (tools, resources, prompts) to the Guest UI
40
+ * and handles the initialization handshake.
41
+ *
42
+ * ## Architecture
43
+ *
44
+ * **Guest UI ↔ AppBridge ↔ Host ↔ MCP Server**
45
+ *
46
+ * The bridge proxies requests from the Guest UI to the MCP server and forwards
47
+ * responses back. It also sends host-initiated notifications like tool input
48
+ * and results to the Guest UI.
49
+ *
50
+ * ## Lifecycle
51
+ *
52
+ * 1. **Create**: Instantiate AppBridge with MCP client and capabilities
53
+ * 2. **Connect**: Call `connect()` with transport to establish communication
54
+ * 3. **Wait for init**: Guest UI sends initialize request, bridge responds
55
+ * 4. **Send data**: Call `sendToolInput()`, `sendToolResult()`, etc.
56
+ * 5. **Teardown**: Call `sendResourceTeardown()` before unmounting iframe
57
+ *
58
+ * @example Basic usage
59
+ * ```typescript
60
+ * import { AppBridge, PostMessageTransport } from '@modelcontextprotocol/ext-apps/app-bridge';
61
+ * import { Client } from '@modelcontextprotocol/sdk/client/index.js';
62
+ *
63
+ * // Create MCP client for the server
64
+ * const client = new Client({
65
+ * name: "MyHost",
66
+ * version: "1.0.0",
67
+ * });
68
+ * await client.connect(serverTransport);
69
+ *
70
+ * // Create bridge for the Guest UI
71
+ * const bridge = new AppBridge(
72
+ * client,
73
+ * { name: "MyHost", version: "1.0.0" },
74
+ * { openLinks: {}, serverTools: {}, logging: {} }
75
+ * );
76
+ *
77
+ * // Set up iframe and connect
78
+ * const iframe = document.getElementById('app') as HTMLIFrameElement;
79
+ * const transport = new PostMessageTransport(
80
+ * iframe.contentWindow!,
81
+ * iframe.contentWindow!,
82
+ * );
83
+ *
84
+ * bridge.oninitialized = () => {
85
+ * console.log("Guest UI initialized");
86
+ * // Now safe to send tool input
87
+ * bridge.sendToolInput({ arguments: { location: "NYC" } });
88
+ * };
89
+ *
90
+ * await bridge.connect(transport);
91
+ * ```
92
+ */
93
+ export declare class AppBridge extends Protocol<Request, Notification, Result> {
94
+ private _client;
95
+ private _hostInfo;
96
+ private _capabilities;
97
+ private _appCapabilities?;
98
+ private _hostContext;
99
+ private _appInfo?;
100
+ /**
101
+ * Create a new AppBridge instance.
102
+ *
103
+ * @param _client - MCP client connected to the server (for proxying requests)
104
+ * @param _hostInfo - Host application identification (name and version)
105
+ * @param _capabilities - Features and capabilities the host supports
106
+ * @param options - Configuration options (inherited from Protocol)
107
+ *
108
+ * @example
109
+ * ```typescript
110
+ * const bridge = new AppBridge(
111
+ * mcpClient,
112
+ * { name: "MyHost", version: "1.0.0" },
113
+ * { openLinks: {}, serverTools: {}, logging: {} }
114
+ * );
115
+ * ```
116
+ */
117
+ constructor(_client: Client, _hostInfo: Implementation, _capabilities: McpUiHostCapabilities, options?: HostOptions);
118
+ /**
119
+ * Get the Guest UI's capabilities discovered during initialization.
120
+ *
121
+ * Returns the capabilities that the Guest UI advertised during its
122
+ * initialization request. Returns `undefined` if called before
123
+ * initialization completes.
124
+ *
125
+ * @returns Guest UI capabilities, or `undefined` if not yet initialized
126
+ *
127
+ * @example Check Guest UI capabilities after initialization
128
+ * ```typescript
129
+ * bridge.oninitialized = () => {
130
+ * const caps = bridge.getAppCapabilities();
131
+ * if (caps?.tools) {
132
+ * console.log("Guest UI provides tools");
133
+ * }
134
+ * };
135
+ * ```
136
+ *
137
+ * @see {@link McpUiAppCapabilities} for the capabilities structure
138
+ */
139
+ getAppCapabilities(): McpUiAppCapabilities | undefined;
140
+ /**
141
+ * Get the Guest UI's implementation info discovered during initialization.
142
+ *
143
+ * Returns the Guest UI's name and version as provided in its initialization
144
+ * request. Returns `undefined` if called before initialization completes.
145
+ *
146
+ * @returns Guest UI implementation info, or `undefined` if not yet initialized
147
+ *
148
+ * @example Log Guest UI information after initialization
149
+ * ```typescript
150
+ * bridge.oninitialized = () => {
151
+ * const appInfo = bridge.getAppVersion();
152
+ * if (appInfo) {
153
+ * console.log(`Guest UI: ${appInfo.name} v${appInfo.version}`);
154
+ * }
155
+ * };
156
+ * ```
157
+ */
158
+ getAppVersion(): Implementation | undefined;
159
+ /**
160
+ * Optional handler for ping requests from the Guest UI.
161
+ *
162
+ * The Guest UI can send standard MCP `ping` requests to verify the connection
163
+ * is alive. The AppBridge automatically responds with an empty object, but this
164
+ * handler allows the host to observe or log ping activity.
165
+ *
166
+ * Unlike the other handlers which use setters, this is a direct property
167
+ * assignment. It is optional; if not set, pings are still handled automatically.
168
+ *
169
+ * @param params - Empty params object from the ping request
170
+ * @param extra - Request metadata (abort signal, session info)
171
+ *
172
+ * @example
173
+ * ```typescript
174
+ * bridge.onping = (params, extra) => {
175
+ * console.log("Received ping from Guest UI");
176
+ * };
177
+ * ```
178
+ */
179
+ onping?: (params: PingRequest["params"], extra: RequestHandlerExtra) => void;
180
+ /**
181
+ * Register a handler for size change notifications from the Guest UI.
182
+ *
183
+ * The Guest UI sends `ui/notifications/size-changed` when its rendered content
184
+ * size changes, typically via ResizeObserver. Set this callback to dynamically
185
+ * adjust the iframe container dimensions based on the Guest UI's content.
186
+ *
187
+ * Note: This is for Guest UI → Host communication. To notify the Guest UI of
188
+ * host viewport changes, use {@link app.App.sendSizeChanged}.
189
+ *
190
+ * @example
191
+ * ```typescript
192
+ * bridge.onsizechange = ({ width, height }) => {
193
+ * if (width != null) {
194
+ * iframe.style.width = `${width}px`;
195
+ * }
196
+ * if (height != null) {
197
+ * iframe.style.height = `${height}px`;
198
+ * }
199
+ * };
200
+ * ```
201
+ *
202
+ * @see {@link McpUiSizeChangedNotification} for the notification type
203
+ * @see {@link app.App.sendSizeChanged} for Host → Guest UI size notifications
204
+ */
205
+ set onsizechange(callback: (params: McpUiSizeChangedNotification["params"]) => void);
206
+ /**
207
+ * Register a handler for sandbox proxy ready notifications.
208
+ *
209
+ * This is an internal callback used by web-based hosts implementing the
210
+ * double-iframe sandbox architecture. The sandbox proxy sends
211
+ * `ui/notifications/sandbox-proxy-ready` after it loads and is ready to receive
212
+ * HTML content.
213
+ *
214
+ * When this fires, the host should call {@link sendSandboxResourceReady} with
215
+ * the HTML content to load into the inner sandboxed iframe.
216
+ *
217
+ * @example
218
+ * ```typescript
219
+ * bridge.onsandboxready = async () => {
220
+ * const resource = await mcpClient.request(
221
+ * { method: "resources/read", params: { uri: "ui://my-app" } },
222
+ * ReadResourceResultSchema
223
+ * );
224
+ *
225
+ * bridge.sendSandboxResourceReady({
226
+ * html: resource.contents[0].text,
227
+ * sandbox: "allow-scripts"
228
+ * });
229
+ * };
230
+ * ```
231
+ *
232
+ * @internal
233
+ * @see {@link McpUiSandboxProxyReadyNotification} for the notification type
234
+ * @see {@link sendSandboxResourceReady} for sending content to the sandbox
235
+ */
236
+ set onsandboxready(callback: (params: McpUiSandboxProxyReadyNotification["params"]) => void);
237
+ /**
238
+ * Called when the Guest UI completes initialization.
239
+ *
240
+ * Set this callback to be notified when the Guest UI has finished its
241
+ * initialization handshake and is ready to receive tool input and other data.
242
+ *
243
+ * @example
244
+ * ```typescript
245
+ * bridge.oninitialized = () => {
246
+ * console.log("Guest UI ready");
247
+ * bridge.sendToolInput({ arguments: toolArgs });
248
+ * };
249
+ * ```
250
+ *
251
+ * @see {@link McpUiInitializedNotification} for the notification type
252
+ * @see {@link sendToolInput} for sending tool arguments to the Guest UI
253
+ */
254
+ set oninitialized(callback: (params: McpUiInitializedNotification["params"]) => void);
255
+ /**
256
+ * Register a handler for message requests from the Guest UI.
257
+ *
258
+ * The Guest UI sends `ui/message` requests when it wants to add a message to
259
+ * the host's chat interface. This enables interactive apps to communicate with
260
+ * the user through the conversation thread.
261
+ *
262
+ * The handler should process the message (add it to the chat) and return a
263
+ * result indicating success or failure. For security, the host should NOT
264
+ * return conversation content or follow-up results to prevent information
265
+ * leakage.
266
+ *
267
+ * @param callback - Handler that receives message params and returns a result
268
+ * - params.role - Message role (currently only "user" is supported)
269
+ * - params.content - Message content blocks (text, image, etc.)
270
+ * - extra - Request metadata (abort signal, session info)
271
+ * - Returns: Promise<McpUiMessageResult> with optional isError flag
272
+ *
273
+ * @example
274
+ * ```typescript
275
+ * bridge.onmessage = async ({ role, content }, extra) => {
276
+ * try {
277
+ * await chatManager.addMessage({ role, content, source: "app" });
278
+ * return {}; // Success
279
+ * } catch (error) {
280
+ * console.error("Failed to add message:", error);
281
+ * return { isError: true };
282
+ * }
283
+ * };
284
+ * ```
285
+ *
286
+ * @see {@link McpUiMessageRequest} for the request type
287
+ * @see {@link McpUiMessageResult} for the result type
288
+ */
289
+ set onmessage(callback: (params: McpUiMessageRequest["params"], extra: RequestHandlerExtra) => Promise<McpUiMessageResult>);
290
+ /**
291
+ * Register a handler for external link requests from the Guest UI.
292
+ *
293
+ * The Guest UI sends `ui/open-link` requests when it wants to open an external
294
+ * URL in the host's default browser. The handler should validate the URL and
295
+ * open it according to the host's security policy and user preferences.
296
+ *
297
+ * The host MAY:
298
+ * - Show a confirmation dialog before opening
299
+ * - Block URLs based on a security policy or allowlist
300
+ * - Log the request for audit purposes
301
+ * - Reject the request entirely
302
+ *
303
+ * @param callback - Handler that receives URL params and returns a result
304
+ * - params.url - URL to open in the host's browser
305
+ * - extra - Request metadata (abort signal, session info)
306
+ * - Returns: Promise<McpUiOpenLinkResult> with optional isError flag
307
+ *
308
+ * @example
309
+ * ```typescript
310
+ * bridge.onopenlink = async ({ url }, extra) => {
311
+ * if (!isAllowedDomain(url)) {
312
+ * console.warn("Blocked external link:", url);
313
+ * return { isError: true };
314
+ * }
315
+ *
316
+ * const confirmed = await showDialog({
317
+ * message: `Open external link?\n${url}`,
318
+ * buttons: ["Open", "Cancel"]
319
+ * });
320
+ *
321
+ * if (confirmed) {
322
+ * window.open(url, "_blank", "noopener,noreferrer");
323
+ * return {};
324
+ * }
325
+ *
326
+ * return { isError: true };
327
+ * };
328
+ * ```
329
+ *
330
+ * @see {@link McpUiOpenLinkRequest} for the request type
331
+ * @see {@link McpUiOpenLinkResult} for the result type
332
+ */
333
+ set onopenlink(callback: (params: McpUiOpenLinkRequest["params"], extra: RequestHandlerExtra) => Promise<McpUiOpenLinkResult>);
334
+ /**
335
+ * Register a handler for logging messages from the Guest UI.
336
+ *
337
+ * The Guest UI sends standard MCP `notifications/message` (logging) notifications
338
+ * to report debugging information, errors, warnings, and other telemetry to the
339
+ * host. The host can display these in a console, log them to a file, or send
340
+ * them to a monitoring service.
341
+ *
342
+ * This uses the standard MCP logging notification format, not a UI-specific
343
+ * message type.
344
+ *
345
+ * @param callback - Handler that receives logging params
346
+ * - params.level - Log level: "debug" | "info" | "notice" | "warning" | "error" | "critical" | "alert" | "emergency"
347
+ * - params.logger - Optional logger name/identifier
348
+ * - params.data - Log message and optional structured data
349
+ *
350
+ * @example
351
+ * ```typescript
352
+ * bridge.onloggingmessage = ({ level, logger, data }) => {
353
+ * const prefix = logger ? `[${logger}]` : "[Guest UI]";
354
+ * console[level === "error" ? "error" : "log"](
355
+ * `${prefix} ${level.toUpperCase()}:`,
356
+ * data
357
+ * );
358
+ * };
359
+ * ```
360
+ */
361
+ set onloggingmessage(callback: (params: LoggingMessageNotification["params"]) => void);
362
+ /**
363
+ * Verify that the guest supports the capability required for the given request method.
364
+ * @internal
365
+ */
366
+ assertCapabilityForMethod(method: Request["method"]): void;
367
+ /**
368
+ * Verify that a request handler is registered and supported for the given method.
369
+ * @internal
370
+ */
371
+ assertRequestHandlerCapability(method: Request["method"]): void;
372
+ /**
373
+ * Verify that the host supports the capability required for the given notification method.
374
+ * @internal
375
+ */
376
+ assertNotificationCapability(method: Notification["method"]): void;
377
+ /**
378
+ * Verify that task creation is supported for the given request method.
379
+ * @internal
380
+ */
381
+ protected assertTaskCapability(_method: string): void;
382
+ /**
383
+ * Verify that task handler is supported for the given method.
384
+ * @internal
385
+ */
386
+ protected assertTaskHandlerCapability(_method: string): void;
387
+ /**
388
+ * Get the host capabilities passed to the constructor.
389
+ *
390
+ * @returns Host capabilities object
391
+ *
392
+ * @see {@link McpUiHostCapabilities} for the capabilities structure
393
+ */
394
+ getCapabilities(): McpUiHostCapabilities;
395
+ /**
396
+ * Handle the ui/initialize request from the guest.
397
+ * @internal
398
+ */
399
+ private _oninitialize;
400
+ /**
401
+ * Update the host context and notify the Guest UI of changes.
402
+ *
403
+ * Compares the new context with the current context and sends a
404
+ * `ui/notifications/host-context-changed` notification containing only the
405
+ * fields that have changed. If no fields have changed, no notification is sent.
406
+ *
407
+ * Common use cases include notifying the Guest UI when:
408
+ * - Theme changes (light/dark mode toggle)
409
+ * - Viewport size changes (window resize)
410
+ * - Display mode changes (inline/fullscreen)
411
+ * - Locale or timezone changes
412
+ *
413
+ * @param hostContext - The complete new host context state
414
+ *
415
+ * @example Update theme when user toggles dark mode
416
+ * ```typescript
417
+ * bridge.setHostContext({ theme: "dark" });
418
+ * ```
419
+ *
420
+ * @example Update multiple context fields
421
+ * ```typescript
422
+ * bridge.setHostContext({
423
+ * theme: "dark",
424
+ * viewport: { width: 800, height: 600 }
425
+ * });
426
+ * ```
427
+ *
428
+ * @see {@link McpUiHostContext} for the context structure
429
+ * @see {@link McpUiHostContextChangedNotification} for the notification type
430
+ */
431
+ setHostContext(hostContext: McpUiHostContext): void;
432
+ /**
433
+ * Send a host context change notification to the app.
434
+ * Only sends the fields that have changed (partial update).
435
+ */
436
+ sendHostContextChange(params: McpUiHostContextChangedNotification["params"]): Promise<void> | void;
437
+ /**
438
+ * Send complete tool arguments to the Guest UI.
439
+ *
440
+ * The host MUST send this notification after the Guest UI completes initialization
441
+ * (after {@link oninitialized} callback fires) and complete tool arguments become available.
442
+ * This notification is sent exactly once and is required before {@link sendToolResult}.
443
+ *
444
+ * @param params - Complete tool call arguments
445
+ *
446
+ * @example
447
+ * ```typescript
448
+ * bridge.oninitialized = () => {
449
+ * bridge.sendToolInput({
450
+ * arguments: { location: "New York", units: "metric" }
451
+ * });
452
+ * };
453
+ * ```
454
+ *
455
+ * @see {@link McpUiToolInputNotification} for the notification type
456
+ * @see {@link oninitialized} for the initialization callback
457
+ * @see {@link sendToolResult} for sending results after execution
458
+ */
459
+ sendToolInput(params: McpUiToolInputNotification["params"]): Promise<void>;
460
+ /**
461
+ * Send streaming partial tool arguments to the Guest UI.
462
+ *
463
+ * The host MAY send this notification zero or more times while tool arguments
464
+ * are being streamed, before {@link sendToolInput} is called with complete
465
+ * arguments. This enables progressive rendering of tool arguments in the
466
+ * Guest UI.
467
+ *
468
+ * The arguments represent best-effort recovery of incomplete JSON. Guest UIs
469
+ * SHOULD handle missing or changing fields gracefully between notifications.
470
+ *
471
+ * @param params - Partial tool call arguments (may be incomplete)
472
+ *
473
+ * @example Stream partial arguments as they arrive
474
+ * ```typescript
475
+ * // As streaming progresses...
476
+ * bridge.sendToolInputPartial({ arguments: { loc: "N" } });
477
+ * bridge.sendToolInputPartial({ arguments: { location: "New" } });
478
+ * bridge.sendToolInputPartial({ arguments: { location: "New York" } });
479
+ *
480
+ * // When complete, send final input
481
+ * bridge.sendToolInput({ arguments: { location: "New York", units: "metric" } });
482
+ * ```
483
+ *
484
+ * @see {@link McpUiToolInputPartialNotification} for the notification type
485
+ * @see {@link sendToolInput} for sending complete arguments
486
+ */
487
+ sendToolInputPartial(params: McpUiToolInputPartialNotification["params"]): Promise<void>;
488
+ /**
489
+ * Send tool execution result to the Guest UI.
490
+ *
491
+ * The host MUST send this notification when tool execution completes successfully,
492
+ * provided the UI is still displayed. If the UI was closed before execution
493
+ * completes, the host MAY skip this notification. This must be sent after
494
+ * {@link sendToolInput}.
495
+ *
496
+ * @param params - Standard MCP tool execution result
497
+ *
498
+ * @example
499
+ * ```typescript
500
+ * import { CallToolResultSchema } from '@modelcontextprotocol/sdk/types.js';
501
+ *
502
+ * const result = await mcpClient.request(
503
+ * { method: "tools/call", params: { name: "get_weather", arguments: args } },
504
+ * CallToolResultSchema
505
+ * );
506
+ * bridge.sendToolResult(result);
507
+ * ```
508
+ *
509
+ * @see {@link McpUiToolResultNotification} for the notification type
510
+ * @see {@link sendToolInput} for sending tool arguments before results
511
+ */
512
+ sendToolResult(params: McpUiToolResultNotification["params"]): Promise<void>;
513
+ /**
514
+ * Send HTML resource to the sandbox proxy for secure loading.
515
+ *
516
+ * This is an internal method used by web-based hosts implementing the
517
+ * double-iframe sandbox architecture. After the sandbox proxy signals readiness
518
+ * via `ui/notifications/sandbox-proxy-ready`, the host sends this notification
519
+ * with the HTML content to load.
520
+ *
521
+ * @param params - HTML content and sandbox configuration:
522
+ * - `html`: The HTML content to load into the sandboxed iframe
523
+ * - `sandbox`: Optional sandbox attribute value (e.g., "allow-scripts")
524
+ *
525
+ * @internal
526
+ * @see {@link onsandboxready} for handling the sandbox proxy ready notification
527
+ */
528
+ sendSandboxResourceReady(params: McpUiSandboxResourceReadyNotification["params"]): Promise<void>;
529
+ /**
530
+ * Request graceful shutdown of the Guest UI.
531
+ *
532
+ * The host MUST send this request before tearing down the UI resource (before
533
+ * unmounting the iframe). This gives the Guest UI an opportunity to save state,
534
+ * cancel pending operations, or show confirmation dialogs.
535
+ *
536
+ * The host SHOULD wait for the response before unmounting to prevent data loss.
537
+ *
538
+ * @param params - Empty params object
539
+ * @param options - Request options (timeout, etc.)
540
+ * @returns Promise resolving when Guest UI confirms readiness for teardown
541
+ *
542
+ * @example
543
+ * ```typescript
544
+ * try {
545
+ * await bridge.sendResourceTeardown({});
546
+ * // Guest UI is ready, safe to unmount iframe
547
+ * iframe.remove();
548
+ * } catch (error) {
549
+ * console.error("Teardown failed:", error);
550
+ * }
551
+ * ```
552
+ */
553
+ sendResourceTeardown(params: McpUiResourceTeardownRequest["params"], options?: RequestOptions): Promise<import("./types").McpUiResourceTeardownResult>;
554
+ private forwardRequest;
555
+ private forwardNotification;
556
+ /**
557
+ * Connect to the Guest UI via transport and set up message forwarding.
558
+ *
559
+ * This method establishes the transport connection and automatically sets up
560
+ * request/notification forwarding based on the MCP server's capabilities.
561
+ * It proxies the following server capabilities to the Guest UI:
562
+ * - Tools (tools/call, tools/list_changed)
563
+ * - Resources (resources/list, resources/read, resources/templates/list, resources/list_changed)
564
+ * - Prompts (prompts/list, prompts/list_changed)
565
+ *
566
+ * After calling connect, wait for the `oninitialized` callback before sending
567
+ * tool input and other data to the Guest UI.
568
+ *
569
+ * @param transport - Transport layer (typically PostMessageTransport)
570
+ * @returns Promise resolving when connection is established
571
+ *
572
+ * @throws {Error} If server capabilities are not available. This occurs when
573
+ * connect() is called before the MCP client has completed its initialization
574
+ * with the server. Ensure `await client.connect()` completes before calling
575
+ * `bridge.connect()`.
576
+ *
577
+ * @example
578
+ * ```typescript
579
+ * const bridge = new AppBridge(mcpClient, hostInfo, capabilities);
580
+ * const transport = new PostMessageTransport(
581
+ * iframe.contentWindow!,
582
+ * iframe.contentWindow!,
583
+ * );
584
+ *
585
+ * bridge.oninitialized = () => {
586
+ * console.log("Guest UI ready");
587
+ * bridge.sendToolInput({ arguments: toolArgs });
588
+ * };
589
+ *
590
+ * await bridge.connect(transport);
591
+ * ```
592
+ */
593
+ connect(transport: Transport): Promise<void>;
594
+ }