@brander/mcp-tools 0.2.5 → 0.2.6
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-handler.d.ts","sourceRoot":"","sources":["../../../src/tools/tool-handler.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAKxD,OAAO,EAAE,iBAAiB,EAAiB,SAAS,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"tool-handler.d.ts","sourceRoot":"","sources":["../../../src/tools/tool-handler.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAKxD,OAAO,EAAE,iBAAiB,EAAiB,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAwEpF;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,aAAa,EAAE,aAAa,EAC5B,SAAS,CAAC,EAAE,SAAS,GACpB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,iBAAiB,CAuEvD"}
|
|
@@ -6,25 +6,37 @@ import { buildContentSummary } from "../elements/element-functions.js";
|
|
|
6
6
|
import { RESOURCE_URI } from "../resource/resource-registry.js";
|
|
7
7
|
import { ElementType } from "../types/element-types.js";
|
|
8
8
|
import { getElementDefinition } from "./element-definitions.js";
|
|
9
|
-
/** Domains allowed for media loading (video, images, fonts) */
|
|
9
|
+
/** Domains allowed for media loading (video, images, fonts) — must use https:// prefix per MCP Apps spec */
|
|
10
10
|
const MEDIA_RESOURCE_DOMAINS = [
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
11
|
+
"https://fonts.googleapis.com",
|
|
12
|
+
"https://fonts.gstatic.com",
|
|
13
|
+
"https://lh3.googleusercontent.com",
|
|
14
|
+
"https://commondatastorage.googleapis.com",
|
|
15
|
+
"https://storage.googleapis.com",
|
|
16
|
+
"https://images.unsplash.com",
|
|
17
|
+
"https://res.cloudinary.com",
|
|
18
|
+
"https://i.imgur.com",
|
|
19
|
+
"https://img.youtube.com",
|
|
17
20
|
];
|
|
18
|
-
/** Domains allowed for iframe embedding (e.g. YouTube) */
|
|
19
|
-
const FRAME_DOMAINS = ["
|
|
21
|
+
/** Domains allowed for iframe embedding (e.g. YouTube) — must use https:// prefix per MCP Apps spec */
|
|
22
|
+
const FRAME_DOMAINS = ["https://www.youtube.com", "https://www.youtube-nocookie.com"];
|
|
23
|
+
/** YouTube URL patterns for detecting non-proxyable video sources */
|
|
24
|
+
const YOUTUBE_RE = /(?:youtube\.com\/(?:watch\?v=|embed\/)|youtu\.be\/)/i;
|
|
20
25
|
/** Build _meta with resource URI, CSP connect/resource/frame domains */
|
|
21
|
-
function buildMeta(apiConfig) {
|
|
26
|
+
function buildMeta(apiConfig, extraResourceDomains) {
|
|
22
27
|
const meta = {
|
|
23
28
|
ui: { resourceUri: RESOURCE_URI },
|
|
24
29
|
"ui/resourceUri": RESOURCE_URI,
|
|
25
30
|
};
|
|
31
|
+
const resourceDomains = [...MEDIA_RESOURCE_DOMAINS];
|
|
32
|
+
if (extraResourceDomains) {
|
|
33
|
+
for (const d of extraResourceDomains) {
|
|
34
|
+
if (!resourceDomains.includes(d))
|
|
35
|
+
resourceDomains.push(d);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
26
38
|
const csp = {
|
|
27
|
-
resourceDomains
|
|
39
|
+
resourceDomains,
|
|
28
40
|
frameDomains: [...FRAME_DOMAINS],
|
|
29
41
|
};
|
|
30
42
|
if (apiConfig) {
|
|
@@ -33,12 +45,31 @@ function buildMeta(apiConfig) {
|
|
|
33
45
|
meta.ui.csp = csp;
|
|
34
46
|
return meta;
|
|
35
47
|
}
|
|
48
|
+
/** Extract origins from direct (non-YouTube) video element sources */
|
|
49
|
+
function extractVideoOrigins(elements) {
|
|
50
|
+
const origins = [];
|
|
51
|
+
for (const el of elements) {
|
|
52
|
+
if (el.elementType !== ElementType.VIDEO)
|
|
53
|
+
continue;
|
|
54
|
+
const src = el.props?.src;
|
|
55
|
+
if (!src || YOUTUBE_RE.test(src))
|
|
56
|
+
continue;
|
|
57
|
+
try {
|
|
58
|
+
const origin = new URL(src).origin;
|
|
59
|
+
if (!origins.includes(origin))
|
|
60
|
+
origins.push(origin);
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
// invalid URL — skip
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return origins;
|
|
67
|
+
}
|
|
36
68
|
/**
|
|
37
69
|
* Create the handler for the generate_screen tool.
|
|
38
70
|
* Accepts an array of elements and returns them as a composed screen.
|
|
39
71
|
*/
|
|
40
72
|
export function createScreenHandler(projectConfig, apiConfig) {
|
|
41
|
-
const meta = buildMeta(apiConfig);
|
|
42
73
|
const { brandSettings } = projectConfig;
|
|
43
74
|
return (input) => {
|
|
44
75
|
const rawElements = input.elements || [];
|
|
@@ -54,7 +85,7 @@ export function createScreenHandler(projectConfig, apiConfig) {
|
|
|
54
85
|
customScreens: projectConfig.customScreens,
|
|
55
86
|
apiConfig,
|
|
56
87
|
},
|
|
57
|
-
_meta:
|
|
88
|
+
_meta: buildMeta(apiConfig),
|
|
58
89
|
};
|
|
59
90
|
}
|
|
60
91
|
// Build screen elements with click behaviors
|
|
@@ -72,6 +103,9 @@ export function createScreenHandler(projectConfig, apiConfig) {
|
|
|
72
103
|
}, // Fallback template system
|
|
73
104
|
};
|
|
74
105
|
});
|
|
106
|
+
// Extract video source origins for dynamic CSP whitelisting
|
|
107
|
+
const videoOrigins = extractVideoOrigins(rawElements);
|
|
108
|
+
const meta = buildMeta(apiConfig, videoOrigins.length > 0 ? videoOrigins : undefined);
|
|
75
109
|
// Build text summary — per-element summaries joined
|
|
76
110
|
const summaries = elements.map((el) => {
|
|
77
111
|
const def = getElementDefinition(el.elementType);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-registry.d.ts","sourceRoot":"","sources":["../../../src/tools/tool-registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKpE,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAOlD;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,SAAS,EACjB,aAAa,EAAE,aAAa,EAC5B,SAAS,CAAC,EAAE,SAAS,GACpB,IAAI,
|
|
1
|
+
{"version":3,"file":"tool-registry.d.ts","sourceRoot":"","sources":["../../../src/tools/tool-registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKpE,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAOlD;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,SAAS,EACjB,aAAa,EAAE,aAAa,EAC5B,SAAS,CAAC,EAAE,SAAS,GACpB,IAAI,CAyDN"}
|
|
@@ -31,14 +31,20 @@ export function registerTools(server, projectConfig, apiConfig) {
|
|
|
31
31
|
resourceUri: RESOURCE_URI,
|
|
32
32
|
csp: {
|
|
33
33
|
resourceDomains: [
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
34
|
+
"https://fonts.googleapis.com",
|
|
35
|
+
"https://fonts.gstatic.com",
|
|
36
|
+
"https://lh3.googleusercontent.com",
|
|
37
|
+
"https://commondatastorage.googleapis.com",
|
|
38
|
+
"https://storage.googleapis.com",
|
|
39
|
+
"https://images.unsplash.com",
|
|
40
|
+
"https://res.cloudinary.com",
|
|
41
|
+
"https://i.imgur.com",
|
|
42
|
+
"https://img.youtube.com",
|
|
43
|
+
],
|
|
44
|
+
frameDomains: [
|
|
45
|
+
"https://www.youtube.com",
|
|
46
|
+
"https://www.youtube-nocookie.com",
|
|
40
47
|
],
|
|
41
|
-
frameDomains: ["*.youtube.com", "*.youtube-nocookie.com"],
|
|
42
48
|
},
|
|
43
49
|
},
|
|
44
50
|
"ui/resourceUri": RESOURCE_URI,
|