skybridge 0.0.0-dev.4f33eea → 0.0.0-dev.51c9c19

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.
@@ -0,0 +1,22 @@
1
+ import { type McpUiHostContext, type McpUiInitializeRequest } from "../types/ext-apps.js";
2
+ type McpAppInitializationOptions = Pick<McpUiInitializeRequest["params"], "appInfo">;
3
+ export declare class McpAppBridge {
4
+ context: McpUiHostContext | null;
5
+ private listeners;
6
+ private pendingRequests;
7
+ private nextId;
8
+ private initialized;
9
+ private appInitializationOptions;
10
+ constructor(options: McpAppInitializationOptions);
11
+ subscribe: (onChange: () => void) => () => boolean;
12
+ private request;
13
+ private emit;
14
+ private setContext;
15
+ private init;
16
+ private handleMessage;
17
+ private connect;
18
+ private notify;
19
+ }
20
+ export declare function getMcpHost(options?: Partial<McpAppInitializationOptions>): McpAppBridge;
21
+ export declare function useMcpAppBridge<K extends keyof McpUiHostContext>(key: K, options?: Partial<McpAppInitializationOptions>): McpUiHostContext[K] | undefined;
22
+ export {};
@@ -0,0 +1,105 @@
1
+ import { useSyncExternalStore } from "react";
2
+ import { LATEST_PROTOCOL_VERSION, } from "../types/ext-apps.js";
3
+ export class McpAppBridge {
4
+ context = null;
5
+ listeners = new Set();
6
+ pendingRequests = new Map();
7
+ nextId = 1;
8
+ initialized;
9
+ appInitializationOptions;
10
+ constructor(options) {
11
+ this.initialized = false;
12
+ this.appInitializationOptions = {
13
+ appInfo: options.appInfo,
14
+ appCapabilities: {},
15
+ protocolVersion: LATEST_PROTOCOL_VERSION,
16
+ };
17
+ }
18
+ subscribe = (onChange) => {
19
+ this.listeners.add(onChange);
20
+ this.init();
21
+ return () => this.listeners.delete(onChange);
22
+ };
23
+ request({ method, params, }) {
24
+ const id = this.nextId++;
25
+ return new Promise((resolve, reject) => {
26
+ this.pendingRequests.set(id, {
27
+ resolve: resolve,
28
+ reject,
29
+ });
30
+ window.parent.postMessage({ jsonrpc: "2.0", id, method, params }, "*");
31
+ });
32
+ }
33
+ emit() {
34
+ this.listeners.forEach((l) => {
35
+ l();
36
+ });
37
+ }
38
+ setContext(context) {
39
+ if (context !== undefined)
40
+ this.context = context;
41
+ this.emit();
42
+ }
43
+ init() {
44
+ if (this.initialized)
45
+ return;
46
+ this.initialized = true;
47
+ if (typeof window === "undefined" || window.parent === window) {
48
+ return;
49
+ }
50
+ window.addEventListener("message", this.handleMessage);
51
+ this.connect();
52
+ }
53
+ handleMessage = (event) => {
54
+ const data = event.data;
55
+ if (data?.jsonrpc !== "2.0")
56
+ return;
57
+ if (data.id !== undefined && this.pendingRequests.has(data.id)) {
58
+ const request = this.pendingRequests.get(data.id);
59
+ if (request) {
60
+ this.pendingRequests.delete(data.id);
61
+ if (data.error) {
62
+ request.reject(new Error(data.error.message));
63
+ }
64
+ else {
65
+ request.resolve(data.result);
66
+ }
67
+ }
68
+ return;
69
+ }
70
+ if (data.method === "ui/notifications/host-context-changed") {
71
+ this.setContext({ ...this.context, ...data.params });
72
+ }
73
+ };
74
+ async connect() {
75
+ try {
76
+ const result = await this.request({
77
+ method: "ui/initialize",
78
+ params: this.appInitializationOptions,
79
+ });
80
+ this.setContext(result.hostContext);
81
+ this.notify({ method: "ui/notifications/initialized" });
82
+ }
83
+ catch (err) {
84
+ console.error(err);
85
+ }
86
+ }
87
+ notify(notification) {
88
+ window.parent.postMessage({ jsonrpc: "2.0", ...notification }, "*");
89
+ }
90
+ }
91
+ let instance = null;
92
+ const defaultOptions = {
93
+ appInfo: { name: "skybridge-app", version: "0.0.1" },
94
+ };
95
+ export function getMcpHost(options) {
96
+ if (!instance) {
97
+ instance = new McpAppBridge({ ...defaultOptions, ...options });
98
+ }
99
+ return instance;
100
+ }
101
+ export function useMcpAppBridge(key, options) {
102
+ const host = getMcpHost(options);
103
+ return useSyncExternalStore(host.subscribe, () => host.context?.[key]);
104
+ }
105
+ //# sourceMappingURL=use-mcp-app-bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-mcp-app-bridge.js","sourceRoot":"","sources":["../../../../src/web/hooks/use-mcp-app-bridge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,46 @@
1
+ import { act, renderHook, waitFor } from "@testing-library/react";
2
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
3
+ describe("useMcpAppBridge", () => {
4
+ let mockPostMessage;
5
+ const useHook = async () => {
6
+ const { useMcpAppBridge } = await import("./use-mcp-app-bridge.js");
7
+ return useMcpAppBridge;
8
+ };
9
+ beforeEach(() => {
10
+ vi.resetModules();
11
+ mockPostMessage = vi.fn();
12
+ Object.defineProperty(window, "parent", {
13
+ value: { postMessage: mockPostMessage },
14
+ writable: true,
15
+ configurable: true,
16
+ });
17
+ });
18
+ afterEach(() => {
19
+ vi.clearAllMocks();
20
+ });
21
+ it("should return the theme value from host context", async () => {
22
+ const useMcpAppBridge = await useHook();
23
+ const { result } = renderHook(() => useMcpAppBridge("theme"));
24
+ const initCall = mockPostMessage.mock.calls.find((call) => call[0].method === "ui/initialize");
25
+ if (initCall) {
26
+ act(() => {
27
+ window.dispatchEvent(new MessageEvent("message", {
28
+ data: {
29
+ jsonrpc: "2.0",
30
+ id: initCall[0].id,
31
+ result: {
32
+ protocolVersion: "2025-06-18",
33
+ hostInfo: { name: "test-host", version: "1.0.0" },
34
+ hostCapabilities: {},
35
+ hostContext: { theme: "light" },
36
+ },
37
+ },
38
+ }));
39
+ });
40
+ }
41
+ await waitFor(() => {
42
+ expect(result.current).toBe("light");
43
+ });
44
+ });
45
+ });
46
+ //# sourceMappingURL=use-mcp-app-bridge.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-mcp-app-bridge.test.js","sourceRoot":"","sources":["../../../../src/web/hooks/use-mcp-app-bridge.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAEzE,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,IAAI,eAAyC,CAAC;IAE9C,MAAM,OAAO,GAAG,KAAK,IAAI,EAAE;QACzB,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,yBAAyB,CAAC,CAAC;QACpE,OAAO,eAAe,CAAC;IACzB,CAAC,CAAC;IAEF,UAAU,CAAC,GAAG,EAAE;QACd,EAAE,CAAC,YAAY,EAAE,CAAC;QAClB,eAAe,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1B,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,QAAQ,EAAE;YACtC,KAAK,EAAE,EAAE,WAAW,EAAE,eAAe,EAAE;YACvC,QAAQ,EAAE,IAAI;YACd,YAAY,EAAE,IAAI;SACnB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,EAAE,CAAC,aAAa,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;QAC/D,MAAM,eAAe,GAAG,MAAM,OAAO,EAAE,CAAC;QACxC,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;QAE9D,MAAM,QAAQ,GAAG,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAC9C,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,eAAe,CAC7C,CAAC;QAEF,IAAI,QAAQ,EAAE,CAAC;YACb,GAAG,CAAC,GAAG,EAAE;gBACP,MAAM,CAAC,aAAa,CAClB,IAAI,YAAY,CAAC,SAAS,EAAE;oBAC1B,IAAI,EAAE;wBACJ,OAAO,EAAE,KAAK;wBACd,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE;wBAClB,MAAM,EAAE;4BACN,eAAe,EAAE,YAAY;4BAC7B,QAAQ,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE;4BACjD,gBAAgB,EAAE,EAAE;4BACpB,WAAW,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE;yBAChC;qBACF;iBACF,CAAC,CACH,CAAC;YACJ,CAAC,CAAC,CAAC;QACL,CAAC;QAED,MAAM,OAAO,CAAC,GAAG,EAAE;YACjB,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,421 @@
1
+ /**
2
+ * MCP Apps Protocol Types (spec.types.ts)
3
+ *
4
+ * This file contains pure TypeScript interface definitions for the MCP Apps protocol.
5
+ * These types are the source of truth and are used to generate Zod schemas via ts-to-zod.
6
+ *
7
+ * - Use `@description` JSDoc tags to generate `.describe()` calls on schemas
8
+ * - Run `npm run generate:schemas` to regenerate schemas from these types
9
+ *
10
+ * @see https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/draft/apps.mdx
11
+ */
12
+ import type { CallToolResult, ContentBlock, Implementation, RequestId, Tool } from "@modelcontextprotocol/sdk/types.js";
13
+ /**
14
+ * Current protocol version supported by this SDK.
15
+ *
16
+ * The SDK automatically handles version negotiation during initialization.
17
+ * Apps and hosts don't need to manage protocol versions manually.
18
+ */
19
+ export declare const LATEST_PROTOCOL_VERSION = "2025-11-21";
20
+ /**
21
+ * @description Color theme preference for the host environment.
22
+ */
23
+ export type McpUiTheme = "light" | "dark";
24
+ /**
25
+ * @description Display mode for UI presentation.
26
+ */
27
+ export type McpUiDisplayMode = "inline" | "fullscreen" | "pip";
28
+ /**
29
+ * @description CSS variable keys available to MCP apps for theming.
30
+ */
31
+ export type McpUiStyleVariableKey = "--color-background-primary" | "--color-background-secondary" | "--color-background-tertiary" | "--color-background-inverse" | "--color-background-ghost" | "--color-background-info" | "--color-background-danger" | "--color-background-success" | "--color-background-warning" | "--color-background-disabled" | "--color-text-primary" | "--color-text-secondary" | "--color-text-tertiary" | "--color-text-inverse" | "--color-text-info" | "--color-text-danger" | "--color-text-success" | "--color-text-warning" | "--color-text-disabled" | "--color-text-ghost" | "--color-border-primary" | "--color-border-secondary" | "--color-border-tertiary" | "--color-border-inverse" | "--color-border-ghost" | "--color-border-info" | "--color-border-danger" | "--color-border-success" | "--color-border-warning" | "--color-border-disabled" | "--color-ring-primary" | "--color-ring-secondary" | "--color-ring-inverse" | "--color-ring-info" | "--color-ring-danger" | "--color-ring-success" | "--color-ring-warning" | "--font-sans" | "--font-mono" | "--font-weight-normal" | "--font-weight-medium" | "--font-weight-semibold" | "--font-weight-bold" | "--font-text-xs-size" | "--font-text-sm-size" | "--font-text-md-size" | "--font-text-lg-size" | "--font-heading-xs-size" | "--font-heading-sm-size" | "--font-heading-md-size" | "--font-heading-lg-size" | "--font-heading-xl-size" | "--font-heading-2xl-size" | "--font-heading-3xl-size" | "--font-text-xs-line-height" | "--font-text-sm-line-height" | "--font-text-md-line-height" | "--font-text-lg-line-height" | "--font-heading-xs-line-height" | "--font-heading-sm-line-height" | "--font-heading-md-line-height" | "--font-heading-lg-line-height" | "--font-heading-xl-line-height" | "--font-heading-2xl-line-height" | "--font-heading-3xl-line-height" | "--border-radius-xs" | "--border-radius-sm" | "--border-radius-md" | "--border-radius-lg" | "--border-radius-xl" | "--border-radius-full" | "--border-width-regular" | "--shadow-hairline" | "--shadow-sm" | "--shadow-md" | "--shadow-lg";
32
+ /**
33
+ * @description Style variables for theming MCP apps.
34
+ *
35
+ * Individual style keys are optional - hosts may provide any subset of these values.
36
+ * Values are strings containing CSS values (colors, sizes, font stacks, etc.).
37
+ *
38
+ * Note: This type uses `Record<K, string | undefined>` rather than `Partial<Record<K, string>>`
39
+ * for compatibility with Zod schema generation. Both are functionally equivalent for validation.
40
+ */
41
+ export type McpUiStyles = Record<McpUiStyleVariableKey, string | undefined>;
42
+ /**
43
+ * @description Request to open an external URL in the host's default browser.
44
+ * @see {@link app.App.sendOpenLink} for the method that sends this request
45
+ */
46
+ export interface McpUiOpenLinkRequest {
47
+ method: "ui/open-link";
48
+ params: {
49
+ /** @description URL to open in the host's browser */
50
+ url: string;
51
+ };
52
+ }
53
+ /**
54
+ * @description Result from opening a URL.
55
+ * @see {@link McpUiOpenLinkRequest}
56
+ */
57
+ export interface McpUiOpenLinkResult {
58
+ /** @description True if the host failed to open the URL (e.g., due to security policy). */
59
+ isError?: boolean;
60
+ /**
61
+ * Index signature required for MCP SDK `Protocol` class compatibility.
62
+ * Note: The schema intentionally omits this to enforce strict validation.
63
+ */
64
+ [key: string]: unknown;
65
+ }
66
+ /**
67
+ * @description Request to send a message to the host's chat interface.
68
+ * @see {@link app.App.sendMessage} for the method that sends this request
69
+ */
70
+ export interface McpUiMessageRequest {
71
+ method: "ui/message";
72
+ params: {
73
+ /** @description Message role, currently only "user" is supported. */
74
+ role: "user";
75
+ /** @description Message content blocks (text, image, etc.). */
76
+ content: ContentBlock[];
77
+ };
78
+ }
79
+ /**
80
+ * @description Result from sending a message.
81
+ * @see {@link McpUiMessageRequest}
82
+ */
83
+ export interface McpUiMessageResult {
84
+ /** @description True if the host rejected or failed to deliver the message. */
85
+ isError?: boolean;
86
+ /**
87
+ * Index signature required for MCP SDK `Protocol` class compatibility.
88
+ * Note: The schema intentionally omits this to enforce strict validation.
89
+ */
90
+ [key: string]: unknown;
91
+ }
92
+ /**
93
+ * @description Notification that the sandbox proxy iframe is ready to receive content.
94
+ * @internal
95
+ * @see https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/draft/apps.mdx#sandbox-proxy
96
+ */
97
+ export interface McpUiSandboxProxyReadyNotification {
98
+ method: "ui/notifications/sandbox-proxy-ready";
99
+ params: Record<string, unknown>;
100
+ }
101
+ /**
102
+ * @description Notification containing HTML resource for the sandbox proxy to load.
103
+ * @internal
104
+ * @see https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/draft/apps.mdx#sandbox-proxy
105
+ */
106
+ export interface McpUiSandboxResourceReadyNotification {
107
+ method: "ui/notifications/sandbox-resource-ready";
108
+ params: {
109
+ /** @description HTML content to load into the inner iframe. */
110
+ html: string;
111
+ /** @description Optional override for the inner iframe's sandbox attribute. */
112
+ sandbox?: string;
113
+ /** @description CSP configuration from resource metadata. */
114
+ csp?: {
115
+ /** @description Origins for network requests (fetch/XHR/WebSocket). */
116
+ connectDomains?: string[];
117
+ /** @description Origins for static resources (scripts, images, styles, fonts). */
118
+ resourceDomains?: string[];
119
+ };
120
+ };
121
+ }
122
+ /**
123
+ * @description Notification of UI size changes (bidirectional: Guest <-> Host).
124
+ * @see {@link app.App.sendSizeChanged} for the method to send this from Guest UI
125
+ */
126
+ export interface McpUiSizeChangedNotification {
127
+ method: "ui/notifications/size-changed";
128
+ params: {
129
+ /** @description New width in pixels. */
130
+ width?: number;
131
+ /** @description New height in pixels. */
132
+ height?: number;
133
+ };
134
+ }
135
+ /**
136
+ * @description Notification containing complete tool arguments (Host -> Guest UI).
137
+ */
138
+ export interface McpUiToolInputNotification {
139
+ method: "ui/notifications/tool-input";
140
+ params: {
141
+ /** @description Complete tool call arguments as key-value pairs. */
142
+ arguments?: Record<string, unknown>;
143
+ };
144
+ }
145
+ /**
146
+ * @description Notification containing partial/streaming tool arguments (Host -> Guest UI).
147
+ */
148
+ export interface McpUiToolInputPartialNotification {
149
+ method: "ui/notifications/tool-input-partial";
150
+ params: {
151
+ /** @description Partial tool call arguments (incomplete, may change). */
152
+ arguments?: Record<string, unknown>;
153
+ };
154
+ }
155
+ /**
156
+ * @description Notification containing tool execution result (Host -> Guest UI).
157
+ */
158
+ export interface McpUiToolResultNotification {
159
+ method: "ui/notifications/tool-result";
160
+ /** @description Standard MCP tool execution result. */
161
+ params: CallToolResult;
162
+ }
163
+ /**
164
+ * @description Notification that tool execution was cancelled (Host -> Guest UI).
165
+ * Host MUST send this if tool execution was cancelled for any reason (user action,
166
+ * sampling error, classifier intervention, etc.).
167
+ */
168
+ export interface McpUiToolCancelledNotification {
169
+ method: "ui/notifications/tool-cancelled";
170
+ params: {
171
+ /** @description Optional reason for the cancellation (e.g., "user action", "timeout"). */
172
+ reason?: string;
173
+ };
174
+ }
175
+ /**
176
+ * @description CSS blocks that can be injected by apps.
177
+ */
178
+ export interface McpUiHostCss {
179
+ /** @description CSS for font loading (@font-face rules or @import statements). Apps must apply using applyHostFonts(). */
180
+ fonts?: string;
181
+ }
182
+ /**
183
+ * @description Style configuration for theming MCP apps.
184
+ */
185
+ export interface McpUiHostStyles {
186
+ /** @description CSS variables for theming the app. */
187
+ variables?: McpUiStyles;
188
+ /** @description CSS blocks that apps can inject. */
189
+ css?: McpUiHostCss;
190
+ }
191
+ /**
192
+ * @description Rich context about the host environment provided to Guest UIs.
193
+ */
194
+ export interface McpUiHostContext {
195
+ /** @description Allow additional properties for forward compatibility. */
196
+ [key: string]: unknown;
197
+ /** @description Metadata of the tool call that instantiated this App. */
198
+ toolInfo?: {
199
+ /** @description JSON-RPC id of the tools/call request. */
200
+ id: RequestId;
201
+ /** @description Tool definition including name, inputSchema, etc. */
202
+ tool: Tool;
203
+ };
204
+ /** @description Current color theme preference. */
205
+ theme?: McpUiTheme;
206
+ /** @description Style configuration for theming the app. */
207
+ styles?: McpUiHostStyles;
208
+ /** @description How the UI is currently displayed. */
209
+ displayMode?: McpUiDisplayMode;
210
+ /** @description Display modes the host supports. */
211
+ availableDisplayModes?: string[];
212
+ /** @description Current and maximum dimensions available to the UI. */
213
+ viewport?: {
214
+ /** @description Current viewport width in pixels. */
215
+ width: number;
216
+ /** @description Current viewport height in pixels. */
217
+ height: number;
218
+ /** @description Maximum available height in pixels (if constrained). */
219
+ maxHeight?: number;
220
+ /** @description Maximum available width in pixels (if constrained). */
221
+ maxWidth?: number;
222
+ };
223
+ /** @description User's language and region preference in BCP 47 format. */
224
+ locale?: string;
225
+ /** @description User's timezone in IANA format. */
226
+ timeZone?: string;
227
+ /** @description Host application identifier. */
228
+ userAgent?: string;
229
+ /** @description Platform type for responsive design decisions. */
230
+ platform?: "web" | "desktop" | "mobile";
231
+ /** @description Device input capabilities. */
232
+ deviceCapabilities?: {
233
+ /** @description Whether the device supports touch input. */
234
+ touch?: boolean;
235
+ /** @description Whether the device supports hover interactions. */
236
+ hover?: boolean;
237
+ };
238
+ /** @description Mobile safe area boundaries in pixels. */
239
+ safeAreaInsets?: {
240
+ /** @description Top safe area inset in pixels. */
241
+ top: number;
242
+ /** @description Right safe area inset in pixels. */
243
+ right: number;
244
+ /** @description Bottom safe area inset in pixels. */
245
+ bottom: number;
246
+ /** @description Left safe area inset in pixels. */
247
+ left: number;
248
+ };
249
+ }
250
+ /**
251
+ * @description Notification that host context has changed (Host -> Guest UI).
252
+ * @see {@link McpUiHostContext} for the full context structure
253
+ */
254
+ export interface McpUiHostContextChangedNotification {
255
+ method: "ui/notifications/host-context-changed";
256
+ /** @description Partial context update containing only changed fields. */
257
+ params: McpUiHostContext;
258
+ }
259
+ /**
260
+ * @description Request for graceful shutdown of the Guest UI (Host -> Guest UI).
261
+ * @see {@link app-bridge.AppBridge.teardownResource} for the host method that sends this
262
+ */
263
+ export interface McpUiResourceTeardownRequest {
264
+ method: "ui/resource-teardown";
265
+ params: Record<string, unknown>;
266
+ }
267
+ /**
268
+ * @description Result from graceful shutdown request.
269
+ * @see {@link McpUiResourceTeardownRequest}
270
+ */
271
+ export interface McpUiResourceTeardownResult {
272
+ /**
273
+ * Index signature required for MCP SDK `Protocol` class compatibility.
274
+ */
275
+ [key: string]: unknown;
276
+ }
277
+ /**
278
+ * @description Capabilities supported by the host application.
279
+ * @see {@link McpUiInitializeResult} for the initialization result that includes these capabilities
280
+ */
281
+ export interface McpUiHostCapabilities {
282
+ /** @description Experimental features (structure TBD). */
283
+ experimental?: Record<string, unknown>;
284
+ /** @description Host supports opening external URLs. */
285
+ openLinks?: Record<string, unknown>;
286
+ /** @description Host can proxy tool calls to the MCP server. */
287
+ serverTools?: {
288
+ /** @description Host supports tools/list_changed notifications. */
289
+ listChanged?: boolean;
290
+ };
291
+ /** @description Host can proxy resource reads to the MCP server. */
292
+ serverResources?: {
293
+ /** @description Host supports resources/list_changed notifications. */
294
+ listChanged?: boolean;
295
+ };
296
+ /** @description Host accepts log messages. */
297
+ logging?: Record<string, unknown>;
298
+ }
299
+ /**
300
+ * @description Capabilities provided by the Guest UI (App).
301
+ * @see {@link McpUiInitializeRequest} for the initialization request that includes these capabilities
302
+ */
303
+ export interface McpUiAppCapabilities {
304
+ /** @description Experimental features (structure TBD). */
305
+ experimental?: Record<string, unknown>;
306
+ /** @description App exposes MCP-style tools that the host can call. */
307
+ tools?: {
308
+ /** @description App supports tools/list_changed notifications. */
309
+ listChanged?: boolean;
310
+ };
311
+ }
312
+ /**
313
+ * @description Initialization request sent from Guest UI to Host.
314
+ * @see {@link app.App.connect} for the method that sends this request
315
+ */
316
+ export interface McpUiInitializeRequest {
317
+ method: "ui/initialize";
318
+ params: {
319
+ /** @description App identification (name and version). */
320
+ appInfo: Implementation;
321
+ /** @description Features and capabilities this app provides. */
322
+ appCapabilities: McpUiAppCapabilities;
323
+ /** @description Protocol version this app supports. */
324
+ protocolVersion: string;
325
+ };
326
+ }
327
+ /**
328
+ * @description Initialization result returned from Host to Guest UI.
329
+ * @see {@link McpUiInitializeRequest}
330
+ */
331
+ export interface McpUiInitializeResult {
332
+ /** @description Negotiated protocol version string (e.g., "2025-11-21"). */
333
+ protocolVersion: string;
334
+ /** @description Host application identification and version. */
335
+ hostInfo: Implementation;
336
+ /** @description Features and capabilities provided by the host. */
337
+ hostCapabilities: McpUiHostCapabilities;
338
+ /** @description Rich context about the host environment. */
339
+ hostContext: McpUiHostContext;
340
+ /**
341
+ * Index signature required for MCP SDK `Protocol` class compatibility.
342
+ * Note: The schema intentionally omits this to enforce strict validation.
343
+ */
344
+ [key: string]: unknown;
345
+ }
346
+ /**
347
+ * @description Notification that Guest UI has completed initialization (Guest UI -> Host).
348
+ * @see {@link app.App.connect} for the method that sends this notification
349
+ */
350
+ export interface McpUiInitializedNotification {
351
+ method: "ui/notifications/initialized";
352
+ params?: object;
353
+ }
354
+ /**
355
+ * @description Content Security Policy configuration for UI resources.
356
+ */
357
+ export interface McpUiResourceCsp {
358
+ /** @description Origins for network requests (fetch/XHR/WebSocket). */
359
+ connectDomains?: string[];
360
+ /** @description Origins for static resources (scripts, images, styles, fonts). */
361
+ resourceDomains?: string[];
362
+ }
363
+ /**
364
+ * @description UI Resource metadata for security and rendering configuration.
365
+ */
366
+ export interface McpUiResourceMeta {
367
+ /** @description Content Security Policy configuration. */
368
+ csp?: McpUiResourceCsp;
369
+ /** @description Dedicated origin for widget sandbox. */
370
+ domain?: string;
371
+ /** @description Visual boundary preference - true if UI prefers a visible border. */
372
+ prefersBorder?: boolean;
373
+ }
374
+ /**
375
+ * @description Request to change the display mode of the UI.
376
+ * The host will respond with the actual display mode that was set,
377
+ * which may differ from the requested mode if not supported.
378
+ * @see {@link app.App.requestDisplayMode} for the method that sends this request
379
+ */
380
+ export interface McpUiRequestDisplayModeRequest {
381
+ method: "ui/request-display-mode";
382
+ params: {
383
+ /** @description The display mode being requested. */
384
+ mode: McpUiDisplayMode;
385
+ };
386
+ }
387
+ /**
388
+ * @description Result from requesting a display mode change.
389
+ * @see {@link McpUiRequestDisplayModeRequest}
390
+ */
391
+ export interface McpUiRequestDisplayModeResult {
392
+ /** @description The display mode that was actually set. May differ from requested if not supported. */
393
+ mode: McpUiDisplayMode;
394
+ /**
395
+ * Index signature required for MCP SDK `Protocol` class compatibility.
396
+ * Note: The schema intentionally omits this to enforce strict validation.
397
+ */
398
+ [key: string]: unknown;
399
+ }
400
+ /**
401
+ * @description Tool visibility scope - who can access the tool.
402
+ */
403
+ export type McpUiToolVisibility = "model" | "app";
404
+ /**
405
+ * @description UI-related metadata for tools.
406
+ */
407
+ export interface McpUiToolMeta {
408
+ /**
409
+ * URI of the UI resource to display for this tool.
410
+ * This is converted to `_meta["ui/resourceUri"]`.
411
+ *
412
+ * @example "ui://weather/widget.html"
413
+ */
414
+ resourceUri: string;
415
+ /**
416
+ * @description Who can access this tool. Default: ["model", "app"]
417
+ * - "model": Tool visible to and callable by the agent
418
+ * - "app": Tool callable by the app from this server only
419
+ */
420
+ visibility?: McpUiToolVisibility[];
421
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * MCP Apps Protocol Types (spec.types.ts)
3
+ *
4
+ * This file contains pure TypeScript interface definitions for the MCP Apps protocol.
5
+ * These types are the source of truth and are used to generate Zod schemas via ts-to-zod.
6
+ *
7
+ * - Use `@description` JSDoc tags to generate `.describe()` calls on schemas
8
+ * - Run `npm run generate:schemas` to regenerate schemas from these types
9
+ *
10
+ * @see https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/draft/apps.mdx
11
+ */
12
+ /**
13
+ * Current protocol version supported by this SDK.
14
+ *
15
+ * The SDK automatically handles version negotiation during initialization.
16
+ * Apps and hosts don't need to manage protocol versions manually.
17
+ */
18
+ export const LATEST_PROTOCOL_VERSION = "2025-11-21";
19
+ //# sourceMappingURL=ext-apps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ext-apps.js","sourceRoot":"","sources":["../../../../src/web/types/ext-apps.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAUH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,YAAY,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skybridge",
3
- "version": "0.0.0-dev.4f33eea",
3
+ "version": "0.0.0-dev.51c9c19",
4
4
  "description": "Skybridge is a framework for building ChatGPT apps",
5
5
  "type": "module",
6
6
  "files": [