@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;AAqCpF;;;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,CAoEvD"}
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
- "*.googleapis.com",
12
- "*.gstatic.com",
13
- "*.googleusercontent.com",
14
- "*.unsplash.com",
15
- "*.cloudinary.com",
16
- "*.imgur.com",
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 = ["*.youtube.com", "*.youtube-nocookie.com"];
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: [...MEDIA_RESOURCE_DOMAINS],
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: 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,CAmDN"}
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
- "*.googleapis.com",
35
- "*.gstatic.com",
36
- "*.googleusercontent.com",
37
- "*.unsplash.com",
38
- "*.cloudinary.com",
39
- "*.imgur.com",
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,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brander/mcp-tools",
3
- "version": "0.2.5",
3
+ "version": "0.2.6",
4
4
  "type": "module",
5
5
  "description": "BranderUX MCP Tools — Add branded interactive UI to any MCP server",
6
6
  "main": "dist/server/lib-entry.js",