@frontmcp/uipack 0.7.1 → 0.8.0
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/adapters/index.d.ts +1 -1
- package/adapters/index.d.ts.map +1 -1
- package/adapters/index.js +71 -24
- package/adapters/platform-meta.constants.d.ts +26 -0
- package/adapters/platform-meta.constants.d.ts.map +1 -0
- package/adapters/platform-meta.d.ts +39 -0
- package/adapters/platform-meta.d.ts.map +1 -1
- package/bridge-runtime/iife-generator.d.ts.map +1 -1
- package/bridge-runtime/index.js +125 -7
- package/build/index.js +125 -7
- package/esm/adapters/index.mjs +69 -24
- package/esm/bridge-runtime/index.mjs +125 -7
- package/esm/build/index.mjs +125 -7
- package/esm/index.mjs +180 -31
- package/esm/package.json +5 -2
- package/esm/registry/index.mjs +153 -24
- package/esm/runtime/index.mjs +125 -7
- package/esm/tool-template/index.mjs +125 -7
- package/index.js +180 -31
- package/package.json +5 -2
- package/registry/index.js +153 -24
- package/runtime/index.js +125 -7
- package/tool-template/index.js +125 -7
- package/types/ui-config.d.ts +23 -0
- package/types/ui-config.d.ts.map +1 -1
package/adapters/index.d.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*
|
|
8
8
|
* @packageDocumentation
|
|
9
9
|
*/
|
|
10
|
-
export { type AIPlatformType, type UIMetadata, type BuildUIMetaOptions, type BuildToolDiscoveryMetaOptions, buildUIMeta, buildToolDiscoveryMeta, buildOpenAICSP, buildFrontMCPCSP, } from './platform-meta';
|
|
10
|
+
export { type AIPlatformType, type ExtAppsMimeTypeVariant, type UIMetadata, type BuildUIMetaOptions, type BuildToolDiscoveryMetaOptions, buildUIMeta, buildToolDiscoveryMeta, buildOpenAICSP, buildFrontMCPCSP, getExtAppsMimeType, isExtAppsMimeType, } from './platform-meta';
|
|
11
11
|
export { type ResolvedServingMode, type ResolveServingModeOptions, resolveServingMode, isPlatformModeSupported, getDefaultServingMode, platformUsesStructuredContent, platformSupportsWidgets, } from './serving-mode';
|
|
12
12
|
export { type TextContentBlock, type BuildToolResponseOptions, type ToolResponseContent, buildToolResponseContent, } from './response-builder';
|
|
13
13
|
//# sourceMappingURL=index.d.ts.map
|
package/adapters/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAEL,KAAK,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,sBAAsB,EAE3B,KAAK,UAAU,EACf,KAAK,kBAAkB,EACvB,KAAK,6BAA6B,EAElC,WAAW,EACX,sBAAsB,EACtB,cAAc,EACd,gBAAgB,EAEhB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,yBAAyB,EAE9B,kBAAkB,EAClB,uBAAuB,EACvB,qBAAqB,EACrB,6BAA6B,EAC7B,uBAAuB,GACxB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,wBAAwB,EAC7B,KAAK,mBAAmB,EAExB,wBAAwB,GACzB,MAAM,oBAAoB,CAAC"}
|
package/adapters/index.js
CHANGED
|
@@ -26,6 +26,8 @@ __export(adapters_exports, {
|
|
|
26
26
|
buildToolResponseContent: () => buildToolResponseContent,
|
|
27
27
|
buildUIMeta: () => buildUIMeta,
|
|
28
28
|
getDefaultServingMode: () => getDefaultServingMode,
|
|
29
|
+
getExtAppsMimeType: () => getExtAppsMimeType,
|
|
30
|
+
isExtAppsMimeType: () => isExtAppsMimeType,
|
|
29
31
|
isPlatformModeSupported: () => isPlatformModeSupported,
|
|
30
32
|
platformSupportsWidgets: () => platformSupportsWidgets,
|
|
31
33
|
platformUsesStructuredContent: () => platformUsesStructuredContent,
|
|
@@ -33,7 +35,30 @@ __export(adapters_exports, {
|
|
|
33
35
|
});
|
|
34
36
|
module.exports = __toCommonJS(adapters_exports);
|
|
35
37
|
|
|
38
|
+
// libs/uipack/src/adapters/platform-meta.constants.ts
|
|
39
|
+
var DISPLAY_MODE_MAP = {
|
|
40
|
+
// Standard MCP Apps modes
|
|
41
|
+
inline: "inline",
|
|
42
|
+
fullscreen: "fullscreen",
|
|
43
|
+
pip: "pip",
|
|
44
|
+
// OpenAI-style aliases
|
|
45
|
+
widget: "inline",
|
|
46
|
+
panel: "fullscreen"
|
|
47
|
+
};
|
|
48
|
+
|
|
36
49
|
// libs/uipack/src/adapters/platform-meta.ts
|
|
50
|
+
function getExtAppsMimeType(variant = "standard") {
|
|
51
|
+
switch (variant) {
|
|
52
|
+
case "profile":
|
|
53
|
+
return "text/html;profile=mcp-app";
|
|
54
|
+
case "standard":
|
|
55
|
+
default:
|
|
56
|
+
return "text/html+mcp";
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function isExtAppsMimeType(mimeType) {
|
|
60
|
+
return mimeType === "text/html+mcp" || mimeType === "text/html;profile=mcp-app";
|
|
61
|
+
}
|
|
37
62
|
function buildUIMeta(options) {
|
|
38
63
|
const { uiConfig, platformType, html, token, directUrl, rendererType, contentHash, manifestUri } = options;
|
|
39
64
|
const meta = {};
|
|
@@ -114,6 +139,21 @@ function buildClaudeMeta(meta, uiConfig) {
|
|
|
114
139
|
if (uiConfig.prefersBorder !== void 0) {
|
|
115
140
|
meta["claude/prefersBorder"] = uiConfig.prefersBorder;
|
|
116
141
|
}
|
|
142
|
+
if (uiConfig.resourceUri) {
|
|
143
|
+
meta["ui/resourceUri"] = uiConfig.resourceUri;
|
|
144
|
+
}
|
|
145
|
+
if (uiConfig.csp) {
|
|
146
|
+
const csp = {};
|
|
147
|
+
if (uiConfig.csp.connectDomains?.length) {
|
|
148
|
+
csp.connectDomains = uiConfig.csp.connectDomains;
|
|
149
|
+
}
|
|
150
|
+
if (uiConfig.csp.resourceDomains?.length) {
|
|
151
|
+
csp.resourceDomains = uiConfig.csp.resourceDomains;
|
|
152
|
+
}
|
|
153
|
+
if (Object.keys(csp).length > 0) {
|
|
154
|
+
meta["ui/csp"] = csp;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
117
157
|
return meta;
|
|
118
158
|
}
|
|
119
159
|
function buildGeminiMeta(meta, uiConfig) {
|
|
@@ -152,14 +192,7 @@ function buildGenericMeta(meta, uiConfig) {
|
|
|
152
192
|
}
|
|
153
193
|
}
|
|
154
194
|
if (uiConfig.displayMode) {
|
|
155
|
-
const
|
|
156
|
-
inline: "inline",
|
|
157
|
-
fullscreen: "fullscreen",
|
|
158
|
-
pip: "pip",
|
|
159
|
-
widget: "inline",
|
|
160
|
-
panel: "fullscreen"
|
|
161
|
-
};
|
|
162
|
-
const mappedMode = displayModeMap[uiConfig.displayMode];
|
|
195
|
+
const mappedMode = DISPLAY_MODE_MAP[uiConfig.displayMode];
|
|
163
196
|
if (mappedMode) {
|
|
164
197
|
meta["ui/displayMode"] = mappedMode;
|
|
165
198
|
}
|
|
@@ -187,15 +220,7 @@ function buildExtAppsMeta(meta, uiConfig) {
|
|
|
187
220
|
}
|
|
188
221
|
}
|
|
189
222
|
if (uiConfig.displayMode) {
|
|
190
|
-
const
|
|
191
|
-
inline: "inline",
|
|
192
|
-
fullscreen: "fullscreen",
|
|
193
|
-
pip: "pip",
|
|
194
|
-
// Map OpenAI-style values
|
|
195
|
-
widget: "inline",
|
|
196
|
-
panel: "fullscreen"
|
|
197
|
-
};
|
|
198
|
-
const mappedMode = displayModeMap[uiConfig.displayMode];
|
|
223
|
+
const mappedMode = DISPLAY_MODE_MAP[uiConfig.displayMode];
|
|
199
224
|
if (mappedMode) {
|
|
200
225
|
meta["ui/displayMode"] = mappedMode;
|
|
201
226
|
}
|
|
@@ -254,12 +279,7 @@ function buildToolDiscoveryMeta(options) {
|
|
|
254
279
|
}
|
|
255
280
|
}
|
|
256
281
|
if (uiConfig.displayMode) {
|
|
257
|
-
const
|
|
258
|
-
inline: "inline",
|
|
259
|
-
fullscreen: "fullscreen",
|
|
260
|
-
pip: "pip"
|
|
261
|
-
};
|
|
262
|
-
const mappedMode = displayModeMap[uiConfig.displayMode];
|
|
282
|
+
const mappedMode = DISPLAY_MODE_MAP[uiConfig.displayMode];
|
|
263
283
|
if (mappedMode) {
|
|
264
284
|
meta["ui/displayMode"] = mappedMode;
|
|
265
285
|
}
|
|
@@ -271,7 +291,32 @@ function buildToolDiscoveryMeta(options) {
|
|
|
271
291
|
meta["ui/domain"] = uiConfig.sandboxDomain;
|
|
272
292
|
}
|
|
273
293
|
break;
|
|
274
|
-
|
|
294
|
+
case "claude":
|
|
295
|
+
meta["ui/resourceUri"] = staticWidgetUri;
|
|
296
|
+
meta["ui/mimeType"] = "text/html+mcp";
|
|
297
|
+
if (uiConfig.displayMode) {
|
|
298
|
+
const mappedMode = DISPLAY_MODE_MAP[uiConfig.displayMode];
|
|
299
|
+
if (mappedMode) {
|
|
300
|
+
meta["ui/displayMode"] = mappedMode;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
if (uiConfig.prefersBorder !== void 0) {
|
|
304
|
+
meta["ui/prefersBorder"] = uiConfig.prefersBorder;
|
|
305
|
+
}
|
|
306
|
+
if (uiConfig.csp) {
|
|
307
|
+
const csp = {};
|
|
308
|
+
if (uiConfig.csp.connectDomains?.length) {
|
|
309
|
+
csp.connectDomains = uiConfig.csp.connectDomains;
|
|
310
|
+
}
|
|
311
|
+
if (uiConfig.csp.resourceDomains?.length) {
|
|
312
|
+
csp.resourceDomains = uiConfig.csp.resourceDomains;
|
|
313
|
+
}
|
|
314
|
+
if (Object.keys(csp).length > 0) {
|
|
315
|
+
meta["ui/csp"] = csp;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
break;
|
|
319
|
+
// Gemini, IDEs don't need discovery metadata
|
|
275
320
|
// They use inline HTML at call time
|
|
276
321
|
default:
|
|
277
322
|
break;
|
|
@@ -491,6 +536,8 @@ ${htmlContent}
|
|
|
491
536
|
buildToolResponseContent,
|
|
492
537
|
buildUIMeta,
|
|
493
538
|
getDefaultServingMode,
|
|
539
|
+
getExtAppsMimeType,
|
|
540
|
+
isExtAppsMimeType,
|
|
494
541
|
isPlatformModeSupported,
|
|
495
542
|
platformSupportsWidgets,
|
|
496
543
|
platformUsesStructuredContent,
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared constants for platform metadata adapters.
|
|
3
|
+
*
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* MCP Apps display modes per specification.
|
|
8
|
+
*/
|
|
9
|
+
export type ExtAppsDisplayMode = 'inline' | 'fullscreen' | 'pip';
|
|
10
|
+
/**
|
|
11
|
+
* Mapping from generic display modes to MCP Apps specific values.
|
|
12
|
+
*
|
|
13
|
+
* Maps both standard MCP Apps modes and platform-specific aliases:
|
|
14
|
+
* - inline, fullscreen, pip: Standard MCP Apps modes (pass through)
|
|
15
|
+
* - widget: OpenAI-style alias for 'inline'
|
|
16
|
+
* - panel: OpenAI-style alias for 'fullscreen'
|
|
17
|
+
*/
|
|
18
|
+
export declare const DISPLAY_MODE_MAP: Record<string, ExtAppsDisplayMode>;
|
|
19
|
+
/**
|
|
20
|
+
* Map a display mode string to MCP Apps display mode.
|
|
21
|
+
*
|
|
22
|
+
* @param mode - The display mode string to map
|
|
23
|
+
* @returns The mapped MCP Apps display mode, or undefined if not recognized
|
|
24
|
+
*/
|
|
25
|
+
export declare function mapDisplayMode(mode: string): ExtAppsDisplayMode | undefined;
|
|
26
|
+
//# sourceMappingURL=platform-meta.constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform-meta.constants.d.ts","sourceRoot":"","sources":["../../src/adapters/platform-meta.constants.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,YAAY,GAAG,KAAK,CAAC;AAEjE;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAQ/D,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS,CAE3E"}
|
|
@@ -11,11 +11,50 @@
|
|
|
11
11
|
* @packageDocumentation
|
|
12
12
|
*/
|
|
13
13
|
import type { UITemplateConfig, UIContentSecurityPolicy } from '../types';
|
|
14
|
+
export { DISPLAY_MODE_MAP, type ExtAppsDisplayMode } from './platform-meta.constants';
|
|
14
15
|
/**
|
|
15
16
|
* Supported AI platform types.
|
|
16
17
|
* Used to determine which metadata format to generate.
|
|
17
18
|
*/
|
|
18
19
|
export type AIPlatformType = 'openai' | 'claude' | 'gemini' | 'cursor' | 'continue' | 'cody' | 'generic-mcp' | 'ext-apps' | 'unknown';
|
|
20
|
+
/**
|
|
21
|
+
* MCP Apps MIME type variants.
|
|
22
|
+
*
|
|
23
|
+
* - `'standard'`: `text/html+mcp` - The standard MCP Apps MIME type
|
|
24
|
+
* - `'profile'`: `text/html;profile=mcp-app` - Profile-based MIME type variant
|
|
25
|
+
*/
|
|
26
|
+
export type ExtAppsMimeTypeVariant = 'standard' | 'profile';
|
|
27
|
+
/**
|
|
28
|
+
* Get the appropriate MCP Apps MIME type.
|
|
29
|
+
*
|
|
30
|
+
* MCP Apps supports two MIME type formats:
|
|
31
|
+
* - Standard: `text/html+mcp` (default)
|
|
32
|
+
* - Profile: `text/html;profile=mcp-app`
|
|
33
|
+
*
|
|
34
|
+
* The profile variant may be preferred by some hosts for content negotiation.
|
|
35
|
+
*
|
|
36
|
+
* @param variant - The MIME type variant to use
|
|
37
|
+
* @returns The MCP Apps MIME type string
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```typescript
|
|
41
|
+
* import { getExtAppsMimeType } from '@frontmcp/uipack/adapters';
|
|
42
|
+
*
|
|
43
|
+
* // Default standard MIME type
|
|
44
|
+
* getExtAppsMimeType(); // 'text/html+mcp'
|
|
45
|
+
*
|
|
46
|
+
* // Profile-based MIME type
|
|
47
|
+
* getExtAppsMimeType('profile'); // 'text/html;profile=mcp-app'
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export declare function getExtAppsMimeType(variant?: ExtAppsMimeTypeVariant): string;
|
|
51
|
+
/**
|
|
52
|
+
* Check if a MIME type is a valid MCP Apps MIME type.
|
|
53
|
+
*
|
|
54
|
+
* @param mimeType - The MIME type to check
|
|
55
|
+
* @returns True if the MIME type is a valid MCP Apps MIME type
|
|
56
|
+
*/
|
|
57
|
+
export declare function isExtAppsMimeType(mimeType: string): boolean;
|
|
19
58
|
/**
|
|
20
59
|
* UI metadata to include in tool response _meta field.
|
|
21
60
|
* Contains both universal fields and platform-specific annotations.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platform-meta.d.ts","sourceRoot":"","sources":["../../src/adapters/platform-meta.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"platform-meta.d.ts","sourceRoot":"","sources":["../../src/adapters/platform-meta.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAG1E,OAAO,EAAE,gBAAgB,EAAE,KAAK,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAMtF;;;GAGG;AACH,MAAM,MAAM,cAAc,GACtB,QAAQ,GACR,QAAQ,GACR,QAAQ,GACR,QAAQ,GACR,UAAU,GACV,MAAM,GACN,aAAa,GACb,UAAU,GACV,SAAS,CAAC;AAMd;;;;;GAKG;AACH,MAAM,MAAM,sBAAsB,GAAG,UAAU,GAAG,SAAS,CAAC;AAE5D;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,GAAE,sBAAmC,GAAG,MAAM,CAQvF;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAE3D;AAMD;;;GAGG;AACH,MAAM,WAAW,UAAU;IAEzB,uCAAuC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qCAAqC;IACrC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gDAAgD;IAChD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,yDAAyD;IACzD,cAAc,CAAC,EAAE,MAAM,CAAC;IAGxB,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sDAAsD;IACtD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,sDAAsD;IACtD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gDAAgD;IAChD,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAC;IAGlC,+CAA+C;IAC/C,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,8CAA8C;IAC9C,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC,8EAA8E;IAC9E,+BAA+B,CAAC,EAAE,OAAO,CAAC;IAC1C,gCAAgC;IAChC,kBAAkB,CAAC,EAAE;QACnB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;QAC3B,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;KAC7B,CAAC;IACF,sCAAsC;IACtC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,iCAAiC;IACjC,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,kDAAkD;IAClD,gCAAgC,CAAC,EAAE,MAAM,CAAC;IAC1C,yDAAyD;IACzD,+BAA+B,CAAC,EAAE,MAAM,CAAC;IAGzC,iCAAiC;IACjC,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,sCAAsC;IACtC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,8DAA8D;IAC9D,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC,+CAA+C;IAC/C,sBAAsB,CAAC,EAAE,OAAO,CAAC;IAGjC,gDAAgD;IAChD,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC,kCAAkC;IAClC,oBAAoB,CAAC,EAAE;QACrB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;QAC1B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;KAC5B,CAAC;IACF,wCAAwC;IACxC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,mCAAmC;IACnC,4BAA4B,CAAC,EAAE,MAAM,CAAC;IACtC,iDAAiD;IACjD,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,yCAAyC;IACzC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAG3B,iCAAiC;IACjC,0BAA0B,CAAC,EAAE,MAAM,CAAC;IAGpC,4CAA4C;IAC5C,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,8BAA8B;IAC9B,uBAAuB,CAAC,EAAE,MAAM,CAAC;IAGjC,6CAA6C;IAC7C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,kCAAkC;IAClC,QAAQ,CAAC,EAAE;QACT,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;QAC1B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;KAC5B,CAAC;IACF,yCAAyC;IACzC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iDAAiD;IACjD,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,6BAA6B;IAC7B,gBAAgB,CAAC,EAAE,QAAQ,GAAG,YAAY,GAAG,KAAK,CAAC;IAEnD,gDAAgD;IAChD,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAMD;;GAEG;AACH,MAAM,WAAW,kBAAkB,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,GAAG,OAAO;IAC7D,4BAA4B;IAC5B,QAAQ,EAAE,gBAAgB,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IACpC,6BAA6B;IAC7B,YAAY,EAAE,cAAc,CAAC;IAC7B,4BAA4B;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,0BAA0B;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oCAAoC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sEAAsE;IACtE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sDAAsD;IACtD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sDAAsD;IACtD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAMD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,WAAW,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,GAAG,OAAO,EAAE,OAAO,EAAE,kBAAkB,CAAC,EAAE,EAAE,GAAG,CAAC,GAAG,UAAU,CAyDzG;AA8BD;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,uBAAuB,GAAG;IAC5D,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC7B,CAYA;AAgFD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,uBAAuB,GAAG;IAC9D,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B,CAYA;AAsGD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,WAAW,6BAA6B,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,GAAG,OAAO;IACxE,4BAA4B;IAC5B,QAAQ,EAAE,gBAAgB,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IACpC,6BAA6B;IAC7B,YAAY,EAAE,cAAc,CAAC;IAC7B,yDAAyD;IACzD,eAAe,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,GAAG,OAAO,EAChE,OAAO,EAAE,6BAA6B,CAAC,EAAE,EAAE,GAAG,CAAC,GAC9C,UAAU,CAkHZ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"iife-generator.d.ts","sourceRoot":"","sources":["../../src/bridge-runtime/iife-generator.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,uDAAuD;IACvD,QAAQ,CAAC,EAAE,CAAC,QAAQ,GAAG,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC,EAAE,CAAC;IACvE,2BAA2B;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,2CAA2C;IAC3C,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,wBAAwB;IACxB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,GAAE,oBAAyB,GAAG,MAAM,CAyF7E;
|
|
1
|
+
{"version":3,"file":"iife-generator.d.ts","sourceRoot":"","sources":["../../src/bridge-runtime/iife-generator.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,uDAAuD;IACvD,QAAQ,CAAC,EAAE,CAAC,QAAQ,GAAG,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC,EAAE,CAAC;IACvE,2BAA2B;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,2CAA2C;IAC3C,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,wBAAwB;IACxB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,GAAE,oBAAyB,GAAG,MAAM,CAyF7E;AAm7BD;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,WAAW,EACvD,OAAO,GAAE,IAAI,CAAC,oBAAoB,EAAE,UAAU,CAAM,GACnD,MAAM,CAYR;AAED;;;GAGG;AACH,eAAO,MAAM,uBAAuB,QAAuB,CAAC;AAE5D;;GAEG;AACH,eAAO,MAAM,kBAAkB;;;;;CAK9B,CAAC"}
|
package/bridge-runtime/index.js
CHANGED
|
@@ -211,16 +211,43 @@ var ExtAppsAdapter = {
|
|
|
211
211
|
capabilities: Object.assign({}, DEFAULT_CAPABILITIES, { canPersistState: true, hasNetworkAccess: true }),
|
|
212
212
|
trustedOrigins: ${originsArray},
|
|
213
213
|
trustedOrigin: null,
|
|
214
|
+
originTrustPending: false,
|
|
214
215
|
pendingRequests: {},
|
|
215
216
|
requestId: 0,
|
|
216
217
|
hostCapabilities: {},
|
|
217
218
|
canHandle: function() {
|
|
218
219
|
if (typeof window === 'undefined') return false;
|
|
219
220
|
if (window.parent === window) return false;
|
|
220
|
-
|
|
221
|
+
|
|
222
|
+
// Check for OpenAI SDK - defer to OpenAIAdapter
|
|
223
|
+
if (window.openai && window.openai.canvas) return false;
|
|
221
224
|
if (window.openai && typeof window.openai.callTool === 'function') return false;
|
|
225
|
+
|
|
226
|
+
// Explicit ext-apps marker
|
|
222
227
|
if (window.__mcpPlatform === 'ext-apps') return true;
|
|
223
|
-
return true;
|
|
228
|
+
if (window.__extAppsInitialized) return true;
|
|
229
|
+
|
|
230
|
+
// Claude MCP Apps mode (2026+) - uses ext-apps protocol
|
|
231
|
+
if (window.__mcpAppsEnabled) return true;
|
|
232
|
+
|
|
233
|
+
// Legacy Claude detection - defer to ClaudeAdapter
|
|
234
|
+
if (window.claude) return false;
|
|
235
|
+
if (window.__claudeArtifact) return false;
|
|
236
|
+
if (window.__mcpPlatform === 'claude') return false;
|
|
237
|
+
if (typeof location !== 'undefined') {
|
|
238
|
+
try {
|
|
239
|
+
var url = new URL(location.href);
|
|
240
|
+
var hostname = url.hostname.toLowerCase();
|
|
241
|
+
var isClaudeHost = hostname === 'claude.ai' || (hostname.length > 10 && hostname.slice(-10) === '.claude.ai');
|
|
242
|
+
var isAnthropicHost = hostname === 'anthropic.com' || (hostname.length > 14 && hostname.slice(-14) === '.anthropic.com');
|
|
243
|
+
if (isClaudeHost || isAnthropicHost) return false;
|
|
244
|
+
} catch (e) {
|
|
245
|
+
// If URL parsing fails, fall through to other checks
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Do NOT default to true for any iframe
|
|
250
|
+
return false;
|
|
224
251
|
},
|
|
225
252
|
initialize: function(context) {
|
|
226
253
|
var self = this;
|
|
@@ -262,6 +289,11 @@ var ExtAppsAdapter = {
|
|
|
262
289
|
context.toolInput = params.arguments || {};
|
|
263
290
|
window.dispatchEvent(new CustomEvent('tool:input', { detail: { arguments: context.toolInput } }));
|
|
264
291
|
break;
|
|
292
|
+
case 'ui/notifications/tool-input-partial':
|
|
293
|
+
// Streaming: merge partial input with existing
|
|
294
|
+
context.toolInput = Object.assign({}, context.toolInput, params.arguments || {});
|
|
295
|
+
window.dispatchEvent(new CustomEvent('tool:input-partial', { detail: { arguments: context.toolInput } }));
|
|
296
|
+
break;
|
|
265
297
|
case 'ui/notifications/tool-result':
|
|
266
298
|
context.toolOutput = params.content;
|
|
267
299
|
context.structuredContent = params.structuredContent;
|
|
@@ -272,18 +304,26 @@ var ExtAppsAdapter = {
|
|
|
272
304
|
Object.assign(context.hostContext, params);
|
|
273
305
|
context.notifyContextChange(params);
|
|
274
306
|
break;
|
|
307
|
+
case 'ui/notifications/cancelled':
|
|
308
|
+
window.dispatchEvent(new CustomEvent('tool:cancelled', { detail: { reason: params.reason } }));
|
|
309
|
+
break;
|
|
275
310
|
}
|
|
276
311
|
},
|
|
277
312
|
isOriginTrusted: function(origin) {
|
|
278
313
|
if (this.trustedOrigins.length > 0) {
|
|
279
314
|
return this.trustedOrigins.indexOf(origin) !== -1;
|
|
280
315
|
}
|
|
281
|
-
//
|
|
282
|
-
// SECURITY WARNING:
|
|
283
|
-
// message establishes permanent trust. For production, always configure trustedOrigins.
|
|
316
|
+
// Trust-on-first-use: trust first message origin.
|
|
317
|
+
// SECURITY WARNING: For production, always configure trustedOrigins.
|
|
284
318
|
if (!this.trustedOrigin) {
|
|
319
|
+
// Guard against race condition where multiple messages arrive simultaneously
|
|
320
|
+
if (this.originTrustPending) {
|
|
321
|
+
return false;
|
|
322
|
+
}
|
|
285
323
|
if (window.parent !== window && origin) {
|
|
324
|
+
this.originTrustPending = true;
|
|
286
325
|
this.trustedOrigin = origin;
|
|
326
|
+
this.originTrustPending = false; // Reset after successful trust establishment
|
|
287
327
|
return true;
|
|
288
328
|
}
|
|
289
329
|
return false;
|
|
@@ -353,6 +393,34 @@ var ExtAppsAdapter = {
|
|
|
353
393
|
},
|
|
354
394
|
requestClose: function(context) {
|
|
355
395
|
return this.sendRequest('ui/close', {});
|
|
396
|
+
},
|
|
397
|
+
// Extended ext-apps methods (full specification)
|
|
398
|
+
updateModelContext: function(context, data, merge) {
|
|
399
|
+
if (!this.hostCapabilities.modelContextUpdate) {
|
|
400
|
+
return Promise.reject(new Error('Model context update not supported'));
|
|
401
|
+
}
|
|
402
|
+
return this.sendRequest('ui/updateModelContext', { context: data, merge: merge !== false });
|
|
403
|
+
},
|
|
404
|
+
log: function(context, level, message, data) {
|
|
405
|
+
if (!this.hostCapabilities.logging) {
|
|
406
|
+
// Fallback to console logging if host doesn't support it
|
|
407
|
+
var logFn = console[level] || console.log;
|
|
408
|
+
logFn('[Widget] ' + message, data);
|
|
409
|
+
return Promise.resolve();
|
|
410
|
+
}
|
|
411
|
+
return this.sendRequest('ui/log', { level: level, message: message, data: data });
|
|
412
|
+
},
|
|
413
|
+
registerTool: function(context, name, description, inputSchema) {
|
|
414
|
+
if (!this.hostCapabilities.widgetTools) {
|
|
415
|
+
return Promise.reject(new Error('Widget tool registration not supported'));
|
|
416
|
+
}
|
|
417
|
+
return this.sendRequest('ui/registerTool', { name: name, description: description, inputSchema: inputSchema });
|
|
418
|
+
},
|
|
419
|
+
unregisterTool: function(context, name) {
|
|
420
|
+
if (!this.hostCapabilities.widgetTools) {
|
|
421
|
+
return Promise.reject(new Error('Widget tool unregistration not supported'));
|
|
422
|
+
}
|
|
423
|
+
return this.sendRequest('ui/unregisterTool', { name: name });
|
|
356
424
|
}
|
|
357
425
|
};
|
|
358
426
|
`.trim();
|
|
@@ -372,12 +440,26 @@ var ClaudeAdapter = {
|
|
|
372
440
|
}),
|
|
373
441
|
canHandle: function() {
|
|
374
442
|
if (typeof window === 'undefined') return false;
|
|
443
|
+
|
|
444
|
+
// If MCP Apps is enabled, let ext-apps adapter handle it
|
|
445
|
+
if (window.__mcpAppsEnabled) return false;
|
|
446
|
+
if (window.__mcpPlatform === 'ext-apps') return false;
|
|
447
|
+
if (window.__extAppsInitialized) return false;
|
|
448
|
+
|
|
449
|
+
// Legacy Claude detection
|
|
375
450
|
if (window.__mcpPlatform === 'claude') return true;
|
|
376
451
|
if (window.claude) return true;
|
|
377
452
|
if (window.__claudeArtifact) return true;
|
|
378
453
|
if (typeof location !== 'undefined') {
|
|
379
|
-
|
|
380
|
-
|
|
454
|
+
try {
|
|
455
|
+
var url = new URL(location.href);
|
|
456
|
+
var hostname = url.hostname.toLowerCase();
|
|
457
|
+
var isClaudeHost = hostname === 'claude.ai' || (hostname.length > 10 && hostname.slice(-10) === '.claude.ai');
|
|
458
|
+
var isAnthropicHost = hostname === 'anthropic.com' || (hostname.length > 14 && hostname.slice(-14) === '.anthropic.com');
|
|
459
|
+
if (isClaudeHost || isAnthropicHost) return true;
|
|
460
|
+
} catch (e) {
|
|
461
|
+
// If URL parsing fails, fall through
|
|
462
|
+
}
|
|
381
463
|
}
|
|
382
464
|
return false;
|
|
383
465
|
},
|
|
@@ -722,6 +804,42 @@ FrontMcpBridge.prototype.requestClose = function() {
|
|
|
722
804
|
return this._adapter.requestClose(this._context);
|
|
723
805
|
};
|
|
724
806
|
|
|
807
|
+
// Extended ext-apps methods (full specification)
|
|
808
|
+
FrontMcpBridge.prototype.updateModelContext = function(context, merge) {
|
|
809
|
+
if (!this._adapter) return Promise.reject(new Error('Not initialized'));
|
|
810
|
+
if (!this._adapter.updateModelContext) {
|
|
811
|
+
return Promise.reject(new Error('updateModelContext not supported on this platform'));
|
|
812
|
+
}
|
|
813
|
+
return this._adapter.updateModelContext(this._context, context, merge);
|
|
814
|
+
};
|
|
815
|
+
|
|
816
|
+
FrontMcpBridge.prototype.log = function(level, message, data) {
|
|
817
|
+
if (!this._adapter) return Promise.reject(new Error('Not initialized'));
|
|
818
|
+
if (!this._adapter.log) {
|
|
819
|
+
// Fallback to console
|
|
820
|
+
var logFn = console[level] || console.log;
|
|
821
|
+
logFn('[Widget] ' + message, data);
|
|
822
|
+
return Promise.resolve();
|
|
823
|
+
}
|
|
824
|
+
return this._adapter.log(this._context, level, message, data);
|
|
825
|
+
};
|
|
826
|
+
|
|
827
|
+
FrontMcpBridge.prototype.registerTool = function(name, description, inputSchema) {
|
|
828
|
+
if (!this._adapter) return Promise.reject(new Error('Not initialized'));
|
|
829
|
+
if (!this._adapter.registerTool) {
|
|
830
|
+
return Promise.reject(new Error('registerTool not supported on this platform'));
|
|
831
|
+
}
|
|
832
|
+
return this._adapter.registerTool(this._context, name, description, inputSchema);
|
|
833
|
+
};
|
|
834
|
+
|
|
835
|
+
FrontMcpBridge.prototype.unregisterTool = function(name) {
|
|
836
|
+
if (!this._adapter) return Promise.reject(new Error('Not initialized'));
|
|
837
|
+
if (!this._adapter.unregisterTool) {
|
|
838
|
+
return Promise.reject(new Error('unregisterTool not supported on this platform'));
|
|
839
|
+
}
|
|
840
|
+
return this._adapter.unregisterTool(this._context, name);
|
|
841
|
+
};
|
|
842
|
+
|
|
725
843
|
FrontMcpBridge.prototype.setWidgetState = function(state) {
|
|
726
844
|
Object.assign(this._context.widgetState, state);
|
|
727
845
|
this._saveWidgetState();
|
package/build/index.js
CHANGED
|
@@ -3004,16 +3004,43 @@ var ExtAppsAdapter = {
|
|
|
3004
3004
|
capabilities: Object.assign({}, DEFAULT_CAPABILITIES, { canPersistState: true, hasNetworkAccess: true }),
|
|
3005
3005
|
trustedOrigins: ${originsArray},
|
|
3006
3006
|
trustedOrigin: null,
|
|
3007
|
+
originTrustPending: false,
|
|
3007
3008
|
pendingRequests: {},
|
|
3008
3009
|
requestId: 0,
|
|
3009
3010
|
hostCapabilities: {},
|
|
3010
3011
|
canHandle: function() {
|
|
3011
3012
|
if (typeof window === 'undefined') return false;
|
|
3012
3013
|
if (window.parent === window) return false;
|
|
3013
|
-
|
|
3014
|
+
|
|
3015
|
+
// Check for OpenAI SDK - defer to OpenAIAdapter
|
|
3016
|
+
if (window.openai && window.openai.canvas) return false;
|
|
3014
3017
|
if (window.openai && typeof window.openai.callTool === 'function') return false;
|
|
3018
|
+
|
|
3019
|
+
// Explicit ext-apps marker
|
|
3015
3020
|
if (window.__mcpPlatform === 'ext-apps') return true;
|
|
3016
|
-
return true;
|
|
3021
|
+
if (window.__extAppsInitialized) return true;
|
|
3022
|
+
|
|
3023
|
+
// Claude MCP Apps mode (2026+) - uses ext-apps protocol
|
|
3024
|
+
if (window.__mcpAppsEnabled) return true;
|
|
3025
|
+
|
|
3026
|
+
// Legacy Claude detection - defer to ClaudeAdapter
|
|
3027
|
+
if (window.claude) return false;
|
|
3028
|
+
if (window.__claudeArtifact) return false;
|
|
3029
|
+
if (window.__mcpPlatform === 'claude') return false;
|
|
3030
|
+
if (typeof location !== 'undefined') {
|
|
3031
|
+
try {
|
|
3032
|
+
var url = new URL(location.href);
|
|
3033
|
+
var hostname = url.hostname.toLowerCase();
|
|
3034
|
+
var isClaudeHost = hostname === 'claude.ai' || (hostname.length > 10 && hostname.slice(-10) === '.claude.ai');
|
|
3035
|
+
var isAnthropicHost = hostname === 'anthropic.com' || (hostname.length > 14 && hostname.slice(-14) === '.anthropic.com');
|
|
3036
|
+
if (isClaudeHost || isAnthropicHost) return false;
|
|
3037
|
+
} catch (e) {
|
|
3038
|
+
// If URL parsing fails, fall through to other checks
|
|
3039
|
+
}
|
|
3040
|
+
}
|
|
3041
|
+
|
|
3042
|
+
// Do NOT default to true for any iframe
|
|
3043
|
+
return false;
|
|
3017
3044
|
},
|
|
3018
3045
|
initialize: function(context) {
|
|
3019
3046
|
var self = this;
|
|
@@ -3055,6 +3082,11 @@ var ExtAppsAdapter = {
|
|
|
3055
3082
|
context.toolInput = params.arguments || {};
|
|
3056
3083
|
window.dispatchEvent(new CustomEvent('tool:input', { detail: { arguments: context.toolInput } }));
|
|
3057
3084
|
break;
|
|
3085
|
+
case 'ui/notifications/tool-input-partial':
|
|
3086
|
+
// Streaming: merge partial input with existing
|
|
3087
|
+
context.toolInput = Object.assign({}, context.toolInput, params.arguments || {});
|
|
3088
|
+
window.dispatchEvent(new CustomEvent('tool:input-partial', { detail: { arguments: context.toolInput } }));
|
|
3089
|
+
break;
|
|
3058
3090
|
case 'ui/notifications/tool-result':
|
|
3059
3091
|
context.toolOutput = params.content;
|
|
3060
3092
|
context.structuredContent = params.structuredContent;
|
|
@@ -3065,18 +3097,26 @@ var ExtAppsAdapter = {
|
|
|
3065
3097
|
Object.assign(context.hostContext, params);
|
|
3066
3098
|
context.notifyContextChange(params);
|
|
3067
3099
|
break;
|
|
3100
|
+
case 'ui/notifications/cancelled':
|
|
3101
|
+
window.dispatchEvent(new CustomEvent('tool:cancelled', { detail: { reason: params.reason } }));
|
|
3102
|
+
break;
|
|
3068
3103
|
}
|
|
3069
3104
|
},
|
|
3070
3105
|
isOriginTrusted: function(origin) {
|
|
3071
3106
|
if (this.trustedOrigins.length > 0) {
|
|
3072
3107
|
return this.trustedOrigins.indexOf(origin) !== -1;
|
|
3073
3108
|
}
|
|
3074
|
-
//
|
|
3075
|
-
// SECURITY WARNING:
|
|
3076
|
-
// message establishes permanent trust. For production, always configure trustedOrigins.
|
|
3109
|
+
// Trust-on-first-use: trust first message origin.
|
|
3110
|
+
// SECURITY WARNING: For production, always configure trustedOrigins.
|
|
3077
3111
|
if (!this.trustedOrigin) {
|
|
3112
|
+
// Guard against race condition where multiple messages arrive simultaneously
|
|
3113
|
+
if (this.originTrustPending) {
|
|
3114
|
+
return false;
|
|
3115
|
+
}
|
|
3078
3116
|
if (window.parent !== window && origin) {
|
|
3117
|
+
this.originTrustPending = true;
|
|
3079
3118
|
this.trustedOrigin = origin;
|
|
3119
|
+
this.originTrustPending = false; // Reset after successful trust establishment
|
|
3080
3120
|
return true;
|
|
3081
3121
|
}
|
|
3082
3122
|
return false;
|
|
@@ -3146,6 +3186,34 @@ var ExtAppsAdapter = {
|
|
|
3146
3186
|
},
|
|
3147
3187
|
requestClose: function(context) {
|
|
3148
3188
|
return this.sendRequest('ui/close', {});
|
|
3189
|
+
},
|
|
3190
|
+
// Extended ext-apps methods (full specification)
|
|
3191
|
+
updateModelContext: function(context, data, merge) {
|
|
3192
|
+
if (!this.hostCapabilities.modelContextUpdate) {
|
|
3193
|
+
return Promise.reject(new Error('Model context update not supported'));
|
|
3194
|
+
}
|
|
3195
|
+
return this.sendRequest('ui/updateModelContext', { context: data, merge: merge !== false });
|
|
3196
|
+
},
|
|
3197
|
+
log: function(context, level, message, data) {
|
|
3198
|
+
if (!this.hostCapabilities.logging) {
|
|
3199
|
+
// Fallback to console logging if host doesn't support it
|
|
3200
|
+
var logFn = console[level] || console.log;
|
|
3201
|
+
logFn('[Widget] ' + message, data);
|
|
3202
|
+
return Promise.resolve();
|
|
3203
|
+
}
|
|
3204
|
+
return this.sendRequest('ui/log', { level: level, message: message, data: data });
|
|
3205
|
+
},
|
|
3206
|
+
registerTool: function(context, name, description, inputSchema) {
|
|
3207
|
+
if (!this.hostCapabilities.widgetTools) {
|
|
3208
|
+
return Promise.reject(new Error('Widget tool registration not supported'));
|
|
3209
|
+
}
|
|
3210
|
+
return this.sendRequest('ui/registerTool', { name: name, description: description, inputSchema: inputSchema });
|
|
3211
|
+
},
|
|
3212
|
+
unregisterTool: function(context, name) {
|
|
3213
|
+
if (!this.hostCapabilities.widgetTools) {
|
|
3214
|
+
return Promise.reject(new Error('Widget tool unregistration not supported'));
|
|
3215
|
+
}
|
|
3216
|
+
return this.sendRequest('ui/unregisterTool', { name: name });
|
|
3149
3217
|
}
|
|
3150
3218
|
};
|
|
3151
3219
|
`.trim();
|
|
@@ -3165,12 +3233,26 @@ var ClaudeAdapter = {
|
|
|
3165
3233
|
}),
|
|
3166
3234
|
canHandle: function() {
|
|
3167
3235
|
if (typeof window === 'undefined') return false;
|
|
3236
|
+
|
|
3237
|
+
// If MCP Apps is enabled, let ext-apps adapter handle it
|
|
3238
|
+
if (window.__mcpAppsEnabled) return false;
|
|
3239
|
+
if (window.__mcpPlatform === 'ext-apps') return false;
|
|
3240
|
+
if (window.__extAppsInitialized) return false;
|
|
3241
|
+
|
|
3242
|
+
// Legacy Claude detection
|
|
3168
3243
|
if (window.__mcpPlatform === 'claude') return true;
|
|
3169
3244
|
if (window.claude) return true;
|
|
3170
3245
|
if (window.__claudeArtifact) return true;
|
|
3171
3246
|
if (typeof location !== 'undefined') {
|
|
3172
|
-
|
|
3173
|
-
|
|
3247
|
+
try {
|
|
3248
|
+
var url = new URL(location.href);
|
|
3249
|
+
var hostname = url.hostname.toLowerCase();
|
|
3250
|
+
var isClaudeHost = hostname === 'claude.ai' || (hostname.length > 10 && hostname.slice(-10) === '.claude.ai');
|
|
3251
|
+
var isAnthropicHost = hostname === 'anthropic.com' || (hostname.length > 14 && hostname.slice(-14) === '.anthropic.com');
|
|
3252
|
+
if (isClaudeHost || isAnthropicHost) return true;
|
|
3253
|
+
} catch (e) {
|
|
3254
|
+
// If URL parsing fails, fall through
|
|
3255
|
+
}
|
|
3174
3256
|
}
|
|
3175
3257
|
return false;
|
|
3176
3258
|
},
|
|
@@ -3515,6 +3597,42 @@ FrontMcpBridge.prototype.requestClose = function() {
|
|
|
3515
3597
|
return this._adapter.requestClose(this._context);
|
|
3516
3598
|
};
|
|
3517
3599
|
|
|
3600
|
+
// Extended ext-apps methods (full specification)
|
|
3601
|
+
FrontMcpBridge.prototype.updateModelContext = function(context, merge) {
|
|
3602
|
+
if (!this._adapter) return Promise.reject(new Error('Not initialized'));
|
|
3603
|
+
if (!this._adapter.updateModelContext) {
|
|
3604
|
+
return Promise.reject(new Error('updateModelContext not supported on this platform'));
|
|
3605
|
+
}
|
|
3606
|
+
return this._adapter.updateModelContext(this._context, context, merge);
|
|
3607
|
+
};
|
|
3608
|
+
|
|
3609
|
+
FrontMcpBridge.prototype.log = function(level, message, data) {
|
|
3610
|
+
if (!this._adapter) return Promise.reject(new Error('Not initialized'));
|
|
3611
|
+
if (!this._adapter.log) {
|
|
3612
|
+
// Fallback to console
|
|
3613
|
+
var logFn = console[level] || console.log;
|
|
3614
|
+
logFn('[Widget] ' + message, data);
|
|
3615
|
+
return Promise.resolve();
|
|
3616
|
+
}
|
|
3617
|
+
return this._adapter.log(this._context, level, message, data);
|
|
3618
|
+
};
|
|
3619
|
+
|
|
3620
|
+
FrontMcpBridge.prototype.registerTool = function(name, description, inputSchema) {
|
|
3621
|
+
if (!this._adapter) return Promise.reject(new Error('Not initialized'));
|
|
3622
|
+
if (!this._adapter.registerTool) {
|
|
3623
|
+
return Promise.reject(new Error('registerTool not supported on this platform'));
|
|
3624
|
+
}
|
|
3625
|
+
return this._adapter.registerTool(this._context, name, description, inputSchema);
|
|
3626
|
+
};
|
|
3627
|
+
|
|
3628
|
+
FrontMcpBridge.prototype.unregisterTool = function(name) {
|
|
3629
|
+
if (!this._adapter) return Promise.reject(new Error('Not initialized'));
|
|
3630
|
+
if (!this._adapter.unregisterTool) {
|
|
3631
|
+
return Promise.reject(new Error('unregisterTool not supported on this platform'));
|
|
3632
|
+
}
|
|
3633
|
+
return this._adapter.unregisterTool(this._context, name);
|
|
3634
|
+
};
|
|
3635
|
+
|
|
3518
3636
|
FrontMcpBridge.prototype.setWidgetState = function(state) {
|
|
3519
3637
|
Object.assign(this._context.widgetState, state);
|
|
3520
3638
|
this._saveWidgetState();
|