@brander/mcp-tools 0.2.2 → 0.2.4
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/dist/app/index.html +986 -986
- package/dist/server/brand/brand-loader.d.ts +6 -0
- package/dist/server/brand/brand-loader.d.ts.map +1 -1
- package/dist/server/brand/brand-loader.js +1 -1
- package/dist/server/elements/click-behaviors.d.ts.map +1 -1
- package/dist/server/elements/click-behaviors.js +4 -0
- package/dist/server/elements/element-functions.d.ts.map +1 -1
- package/dist/server/elements/element-functions.js +6 -0
- package/dist/server/register.d.ts +5 -1
- package/dist/server/register.d.ts.map +1 -1
- package/dist/server/resource/resource-registry.d.ts.map +1 -1
- package/dist/server/resource/resource-registry.js +3 -1
- package/dist/server/tools/element-definitions.d.ts +2 -1
- package/dist/server/tools/element-definitions.d.ts.map +1 -1
- package/dist/server/tools/element-definitions.js +7 -2
- package/dist/server/tools/generate-screen-schema.d.ts +34 -3
- package/dist/server/tools/generate-screen-schema.d.ts.map +1 -1
- package/dist/server/tools/generate-screen-schema.js +51 -15
- package/dist/server/tools/tool-registry.d.ts.map +1 -1
- package/dist/server/tools/tool-registry.js +13 -3
- package/dist/server/types/element-types.d.ts +1 -15
- package/dist/server/types/element-types.d.ts.map +1 -1
- package/dist/server/types/element-types.js +1 -0
- package/package.json +1 -1
|
@@ -4,6 +4,12 @@
|
|
|
4
4
|
import { BrandSettings, ProjectConfig } from "./brand-types.js";
|
|
5
5
|
interface BrandLoaderOptions {
|
|
6
6
|
projectId: string;
|
|
7
|
+
/**
|
|
8
|
+
* Public design-partner key (bux_dp_xxx). This is a publishable identifier
|
|
9
|
+
* (like a Stripe publishable key) — it scopes API access to a specific project
|
|
10
|
+
* but does not grant write access or expose secrets. Safe to embed in client
|
|
11
|
+
* configs, MCP tool results, and localStorage.
|
|
12
|
+
*/
|
|
7
13
|
betaKey: string;
|
|
8
14
|
apiBaseUrl?: string;
|
|
9
15
|
brandSettingsPath?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"brand-loader.d.ts","sourceRoot":"","sources":["../../../src/brand/brand-loader.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,aAAa,EAA0B,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAExF,UAAU,kBAAkB;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,aAAa,CAAC,CA4B3F;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,aAAa,CAAC,CAG3F"}
|
|
1
|
+
{"version":3,"file":"brand-loader.d.ts","sourceRoot":"","sources":["../../../src/brand/brand-loader.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,aAAa,EAA0B,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAExF,UAAU,kBAAkB;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;OAKG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,aAAa,CAAC,CA4B3F;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,aAAa,CAAC,CAG3F"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"click-behaviors.d.ts","sourceRoot":"","sources":["../../../src/elements/click-behaviors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAExD,MAAM,WAAW,mBAAmB;IAClC,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,yBAAyB,EAAE,MAAM,CAAC,WAAW,EAAE,mBAAmB,
|
|
1
|
+
{"version":3,"file":"click-behaviors.d.ts","sourceRoot":"","sources":["../../../src/elements/click-behaviors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAExD,MAAM,WAAW,mBAAmB;IAClC,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,yBAAyB,EAAE,MAAM,CAAC,WAAW,EAAE,mBAAmB,CAiE9E,CAAC;AAEF,6CAA6C;AAC7C,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,WAAW,GAAG,mBAAmB,GAAG,SAAS,CAE1F"}
|
|
@@ -60,6 +60,10 @@ export const ELEMENT_BEHAVIOR_REGISTRY = {
|
|
|
60
60
|
queryTemplate: "[actionQuery]",
|
|
61
61
|
description: "Alert action button triggers the configured query",
|
|
62
62
|
},
|
|
63
|
+
[ElementType.VIDEO]: {
|
|
64
|
+
queryTemplate: "[action]",
|
|
65
|
+
description: "Discuss button fires the configured action query about the video",
|
|
66
|
+
},
|
|
63
67
|
[ElementType.SCREEN]: {
|
|
64
68
|
queryTemplate: "",
|
|
65
69
|
description: "Screen composition — click behaviors are per-element",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"element-functions.d.ts","sourceRoot":"","sources":["../../../src/elements/element-functions.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAExD,0EAA0E;AAC1E,MAAM,MAAM,eAAe,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC;AAEzE,qDAAqD;AACrD,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,WAAW,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"element-functions.d.ts","sourceRoot":"","sources":["../../../src/elements/element-functions.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAExD,0EAA0E;AAC1E,MAAM,MAAM,eAAe,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC;AAEzE,qDAAqD;AACrD,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,WAAW,EAAE,eAAe,CAwDlE,CAAC;AAEF,mEAAmE;AACnE,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,WAAW,EACxB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAGT;AAED;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,EAAE,MAAM,CAC5C,WAAW,EACX,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAiF/D,CAAC;AAEF;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,WAAW,EACxB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,MAAM,CAwER"}
|
|
@@ -33,6 +33,7 @@ export const VISIBILITY_CHECKS = {
|
|
|
33
33
|
[ElementType.FORM]: (data) => Array.isArray(data?.fields) && data.fields.length > 0,
|
|
34
34
|
[ElementType.BUTTON]: (data) => Boolean(data),
|
|
35
35
|
[ElementType.ALERT]: (data) => Boolean(data?.message) && typeof data.message === "string" && data.message.trim().length > 0,
|
|
36
|
+
[ElementType.VIDEO]: (data) => Boolean(data?.src),
|
|
36
37
|
[ElementType.SCREEN]: (data) => Array.isArray(data?.elements) && data.elements.length > 0,
|
|
37
38
|
};
|
|
38
39
|
/** Check if tool input data is valid for the given element type */
|
|
@@ -105,6 +106,10 @@ export const CLICK_METADATA_ENRICHMENT = {
|
|
|
105
106
|
elementType: "alert",
|
|
106
107
|
actionType: "alert_action_click",
|
|
107
108
|
}),
|
|
109
|
+
[ElementType.VIDEO]: (data) => ({
|
|
110
|
+
...data,
|
|
111
|
+
elementType: "video",
|
|
112
|
+
}),
|
|
108
113
|
[ElementType.SCREEN]: (data) => ({ ...data }),
|
|
109
114
|
};
|
|
110
115
|
/**
|
|
@@ -157,6 +162,7 @@ export function buildContentSummary(elementType, data) {
|
|
|
157
162
|
},
|
|
158
163
|
[ElementType.BUTTON]: (d) => `Rendered button: "${d.label}"`,
|
|
159
164
|
[ElementType.ALERT]: (d) => `Displayed ${d.severity || "info"} alert: "${d.message}"`,
|
|
165
|
+
[ElementType.VIDEO]: (d) => `Rendered video player: "${d.title || d.src}"`,
|
|
160
166
|
[ElementType.SCREEN]: (d) => {
|
|
161
167
|
const elements = d.elements;
|
|
162
168
|
return `Rendered screen with ${elements?.length || 0} elements`;
|
|
@@ -14,7 +14,11 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
14
14
|
export interface BranderToolsConfig {
|
|
15
15
|
/** BranderUX project ID — identifies which project's brand + screens to load */
|
|
16
16
|
projectId: string;
|
|
17
|
-
/**
|
|
17
|
+
/**
|
|
18
|
+
* Public design-partner key (bux_dp_xxx). This is a publishable identifier — it
|
|
19
|
+
* scopes API access to a specific project but does not grant write access or expose
|
|
20
|
+
* secrets. Safe to include in client-side configs and version control.
|
|
21
|
+
*/
|
|
18
22
|
betaKey: string;
|
|
19
23
|
/** BranderUX API base URL (defaults to https://branderux.com) */
|
|
20
24
|
apiBaseUrl?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../src/register.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAQpE,MAAM,WAAW,kBAAkB;IACjC,gFAAgF;IAChF,SAAS,EAAE,MAAM,CAAC;IAElB
|
|
1
|
+
{"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../src/register.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAQpE,MAAM,WAAW,kBAAkB;IACjC,gFAAgF;IAChF,SAAS,EAAE,MAAM,CAAC;IAElB;;;;OAIG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB,iEAAiE;IACjE,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,iFAAiF;IACjF,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;;;GASG;AACH,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,IAAI,CAAC,CA2Bf"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resource-registry.d.ts","sourceRoot":"","sources":["../../../src/resource/resource-registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAGxD,eAAO,MAAM,YAAY,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"resource-registry.d.ts","sourceRoot":"","sources":["../../../src/resource/resource-registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAGxD,eAAO,MAAM,YAAY,kCAAkC,CAAC;AAoB5D;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,aAAa,GAAG,IAAI,CAwBhG"}
|
|
@@ -16,7 +16,9 @@ function injectInitialConfig(html, projectConfig) {
|
|
|
16
16
|
screenVisibility: projectConfig.screenVisibility,
|
|
17
17
|
customScreens: projectConfig.customScreens,
|
|
18
18
|
};
|
|
19
|
-
|
|
19
|
+
// Escape </ sequences to prevent script tag injection (e.g. "</script>" in config values)
|
|
20
|
+
const safeJson = JSON.stringify(config).replace(/</g, "\\u003c");
|
|
21
|
+
const script = `<script>window.__BRANDER_INITIAL_CONFIG__=${safeJson};</script>`;
|
|
20
22
|
// Insert before closing </head> so it runs before the app bundle
|
|
21
23
|
return html.replace("</head>", `${script}</head>`);
|
|
22
24
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Element definitions — static metadata for the
|
|
2
|
+
* Element definitions — static metadata for the 15 BranderUX element types.
|
|
3
3
|
*
|
|
4
4
|
* Inlined here so the compiled dist/server can run as standalone Node.js without
|
|
5
5
|
* depending on @brander/elements TypeScript source at runtime (CJS/ESM interop issue).
|
|
@@ -9,6 +9,7 @@ interface ElementInfo {
|
|
|
9
9
|
name: string;
|
|
10
10
|
description: string;
|
|
11
11
|
}
|
|
12
|
+
export declare const ELEMENT_INFO: ElementInfo[];
|
|
12
13
|
/** Get element info by type (for names, click behaviors, summaries) */
|
|
13
14
|
export declare function getElementDefinition(elementType: string): ElementInfo | undefined;
|
|
14
15
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"element-definitions.d.ts","sourceRoot":"","sources":["../../../src/tools/element-definitions.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,UAAU,WAAW;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB;
|
|
1
|
+
{"version":3,"file":"element-definitions.d.ts","sourceRoot":"","sources":["../../../src/tools/element-definitions.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,UAAU,WAAW;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,YAAY,EAAE,WAAW,EA4CrC,CAAC;AAIF,uEAAuE;AACvE,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAEjF"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Element definitions — static metadata for the
|
|
2
|
+
* Element definitions — static metadata for the 15 BranderUX element types.
|
|
3
3
|
*
|
|
4
4
|
* Inlined here so the compiled dist/server can run as standalone Node.js without
|
|
5
5
|
* depending on @brander/elements TypeScript source at runtime (CJS/ESM interop issue).
|
|
6
6
|
*/
|
|
7
|
-
const ELEMENT_INFO = [
|
|
7
|
+
export const ELEMENT_INFO = [
|
|
8
8
|
{ id: "header", name: "Header", description: "Page header with title and subtitle" },
|
|
9
9
|
{ id: "stats-grid", name: "Stats Grid", description: "Grid of KPI statistics with trends" },
|
|
10
10
|
{
|
|
@@ -43,6 +43,11 @@ const ELEMENT_INFO = [
|
|
|
43
43
|
name: "Alert",
|
|
44
44
|
description: "Notification banner for messages, warnings, and feedback",
|
|
45
45
|
},
|
|
46
|
+
{
|
|
47
|
+
id: "video",
|
|
48
|
+
name: "Video Player",
|
|
49
|
+
description: "Embedded video player for YouTube URLs or direct mp4/webm files",
|
|
50
|
+
},
|
|
46
51
|
];
|
|
47
52
|
const ELEMENT_INFO_MAP = new Map(ELEMENT_INFO.map((e) => [e.id, e]));
|
|
48
53
|
/** Get element info by type (for names, click behaviors, summaries) */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Self-contained generate_screen Zod schema + tool description for the MCP server.
|
|
3
3
|
*
|
|
4
|
-
* All
|
|
4
|
+
* All 15 element prop schemas are defined here so the compiled dist/server can run
|
|
5
5
|
* as a standalone Node.js server without depending on @brander/elements at runtime.
|
|
6
6
|
* (Avoids CJS/ESM interop issues — brander-elements is CJS but mcp-tools is ESM.)
|
|
7
7
|
*/
|
|
@@ -255,8 +255,39 @@ export declare const generateScreenInputSchema: z.ZodObject<{
|
|
|
255
255
|
actionQuery: z.ZodOptional<z.ZodString>;
|
|
256
256
|
}, z.core.$strip>;
|
|
257
257
|
clickQuery: z.ZodOptional<z.ZodString>;
|
|
258
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
259
|
+
elementType: z.ZodLiteral<"video">;
|
|
260
|
+
props: z.ZodObject<{
|
|
261
|
+
id: z.ZodString;
|
|
262
|
+
src: z.ZodString;
|
|
263
|
+
title: z.ZodOptional<z.ZodString>;
|
|
264
|
+
description: z.ZodOptional<z.ZodString>;
|
|
265
|
+
action: z.ZodOptional<z.ZodString>;
|
|
266
|
+
aspectRatio: z.ZodOptional<z.ZodEnum<{
|
|
267
|
+
"16:9": "16:9";
|
|
268
|
+
"4:3": "4:3";
|
|
269
|
+
"1:1": "1:1";
|
|
270
|
+
}>>;
|
|
271
|
+
autoplay: z.ZodOptional<z.ZodBoolean>;
|
|
272
|
+
}, z.core.$strip>;
|
|
273
|
+
clickQuery: z.ZodOptional<z.ZodString>;
|
|
258
274
|
}, z.core.$strip>], "elementType">>;
|
|
259
275
|
}, z.core.$strip>;
|
|
260
|
-
|
|
261
|
-
|
|
276
|
+
interface DescriptionConfig {
|
|
277
|
+
elementVisibility?: Record<string, boolean>;
|
|
278
|
+
customScreens?: Array<{
|
|
279
|
+
name: string;
|
|
280
|
+
config?: {
|
|
281
|
+
elements?: Array<{
|
|
282
|
+
elementType?: string;
|
|
283
|
+
}>;
|
|
284
|
+
};
|
|
285
|
+
elements?: Array<{
|
|
286
|
+
elementType?: string;
|
|
287
|
+
}>;
|
|
288
|
+
}>;
|
|
289
|
+
}
|
|
290
|
+
/** Build the generate_screen tool description dynamically from project config */
|
|
291
|
+
export declare function buildGenerateScreenDescription(config?: DescriptionConfig): string;
|
|
292
|
+
export {};
|
|
262
293
|
//# sourceMappingURL=generate-screen-schema.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate-screen-schema.d.ts","sourceRoot":"","sources":["../../../src/tools/generate-screen-schema.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"generate-screen-schema.d.ts","sourceRoot":"","sources":["../../../src/tools/generate-screen-schema.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA6PxB,2DAA2D;AAC3D,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAIpC,CAAC;AAMH,UAAU,iBAAiB;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5C,aAAa,CAAC,EAAE,KAAK,CAAC;QACpB,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,CAAC,EAAE;YAAE,QAAQ,CAAC,EAAE,KAAK,CAAC;gBAAE,WAAW,CAAC,EAAE,MAAM,CAAA;aAAE,CAAC,CAAA;SAAE,CAAC;QACxD,QAAQ,CAAC,EAAE,KAAK,CAAC;YAAE,WAAW,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KAC5C,CAAC,CAAC;CACJ;AAED,iFAAiF;AACjF,wBAAgB,8BAA8B,CAAC,MAAM,CAAC,EAAE,iBAAiB,GAAG,MAAM,CAqCjF"}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Self-contained generate_screen Zod schema + tool description for the MCP server.
|
|
3
3
|
*
|
|
4
|
-
* All
|
|
4
|
+
* All 15 element prop schemas are defined here so the compiled dist/server can run
|
|
5
5
|
* as a standalone Node.js server without depending on @brander/elements at runtime.
|
|
6
6
|
* (Avoids CJS/ESM interop issues — brander-elements is CJS but mcp-tools is ESM.)
|
|
7
7
|
*/
|
|
8
8
|
import { z } from "zod";
|
|
9
|
+
import { ELEMENT_INFO } from "./element-definitions.js";
|
|
9
10
|
// ============================================================================
|
|
10
|
-
// ELEMENT PROP SCHEMAS (
|
|
11
|
+
// ELEMENT PROP SCHEMAS (15 element types)
|
|
11
12
|
// ============================================================================
|
|
12
13
|
const headerPropsSchema = z.object({
|
|
13
14
|
title: z.string().describe("Main page title"),
|
|
@@ -87,10 +88,7 @@ const itemGridPropsSchema = z.object({
|
|
|
87
88
|
title: z.string().describe("Item name"),
|
|
88
89
|
description: z.string().optional().describe("Item description"),
|
|
89
90
|
price: z.string().describe("Item price"),
|
|
90
|
-
image: z
|
|
91
|
-
.string()
|
|
92
|
-
.optional()
|
|
93
|
-
.describe("REAL image URL (e.g., https://images.unsplash.com/...)"),
|
|
91
|
+
image: z.string().optional().describe("Image URL"),
|
|
94
92
|
category: z.string().optional().describe("Item category"),
|
|
95
93
|
rating: z.number().optional().describe("Rating score"),
|
|
96
94
|
stock: z.number().optional().describe("Stock quantity"),
|
|
@@ -188,8 +186,22 @@ const alertPropsSchema = z.object({
|
|
|
188
186
|
actionText: z.string().optional().describe("Optional action button text"),
|
|
189
187
|
actionQuery: z.string().optional().describe("Query to send when action button clicked"),
|
|
190
188
|
});
|
|
189
|
+
const videoPropsSchema = z.object({
|
|
190
|
+
id: z.string().describe("Unique video element identifier"),
|
|
191
|
+
src: z
|
|
192
|
+
.string()
|
|
193
|
+
.describe("Video URL — YouTube (youtube.com/watch or youtu.be), or direct .mp4/.webm file URL"),
|
|
194
|
+
title: z.string().optional().describe("Video title shown below the player"),
|
|
195
|
+
description: z.string().optional().describe("Brief description shown below the title"),
|
|
196
|
+
action: z
|
|
197
|
+
.string()
|
|
198
|
+
.optional()
|
|
199
|
+
.describe("Query sent to the AI when the user clicks the Discuss button"),
|
|
200
|
+
aspectRatio: z.enum(["16:9", "4:3", "1:1"]).optional().describe("Video player aspect ratio"),
|
|
201
|
+
autoplay: z.boolean().optional().describe("Auto-play video when rendered"),
|
|
202
|
+
});
|
|
191
203
|
// ============================================================================
|
|
192
|
-
// SCREEN SCHEMA — discriminated union of all
|
|
204
|
+
// SCREEN SCHEMA — discriminated union of all 15 element types
|
|
193
205
|
// ============================================================================
|
|
194
206
|
const clickQuery = z
|
|
195
207
|
.string()
|
|
@@ -210,6 +222,7 @@ const screenElementSchema = z.discriminatedUnion("elementType", [
|
|
|
210
222
|
z.object({ elementType: z.literal("form"), props: formPropsSchema, clickQuery }),
|
|
211
223
|
z.object({ elementType: z.literal("button"), props: buttonPropsSchema, clickQuery }),
|
|
212
224
|
z.object({ elementType: z.literal("alert"), props: alertPropsSchema, clickQuery }),
|
|
225
|
+
z.object({ elementType: z.literal("video"), props: videoPropsSchema, clickQuery }),
|
|
213
226
|
]);
|
|
214
227
|
/** Full input schema for the MCP `generate_screen` tool */
|
|
215
228
|
export const generateScreenInputSchema = z.object({
|
|
@@ -217,11 +230,34 @@ export const generateScreenInputSchema = z.object({
|
|
|
217
230
|
.array(screenElementSchema)
|
|
218
231
|
.describe("Ordered array of elements to render. Each element has an elementType and props."),
|
|
219
232
|
});
|
|
220
|
-
/**
|
|
221
|
-
export
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
233
|
+
/** Build the generate_screen tool description dynamically from project config */
|
|
234
|
+
export function buildGenerateScreenDescription(config) {
|
|
235
|
+
const elementVisibility = config?.elementVisibility ?? {};
|
|
236
|
+
const customScreens = config?.customScreens ?? [];
|
|
237
|
+
// Filter elements by visibility (default = enabled if not in map)
|
|
238
|
+
const enabledElements = ELEMENT_INFO.filter((e) => elementVisibility[e.id] !== false);
|
|
239
|
+
const enabledSet = new Set(enabledElements.map((e) => e.id));
|
|
240
|
+
const elementList = enabledElements.map((e) => e.id).join(", ");
|
|
241
|
+
// Build screen patterns from the project's custom screens
|
|
242
|
+
const patterns = [];
|
|
243
|
+
for (const screen of customScreens) {
|
|
244
|
+
const els = (screen.config?.elements ?? screen.elements ?? [])
|
|
245
|
+
.map((e) => e.elementType)
|
|
246
|
+
.filter((t) => !!t && enabledSet.has(t));
|
|
247
|
+
if (els.length > 0) {
|
|
248
|
+
const unique = [...new Set(els)];
|
|
249
|
+
patterns.push(`- ${screen.name}: ${unique.join(" → ")}`);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
const patternsSection = patterns.length > 0
|
|
253
|
+
? "Compose screens from an ordered array of elements. Available screen patterns:\n" +
|
|
254
|
+
patterns.join("\n") +
|
|
255
|
+
"\n\n"
|
|
256
|
+
: "";
|
|
257
|
+
return ("Render branded, interactive UI screens. Outputs styled visual components (charts, tables, grids, forms) " +
|
|
258
|
+
"using the project's brand colors, fonts, and layout — displayed as a rich visual panel.\n\n" +
|
|
259
|
+
patternsSection +
|
|
260
|
+
"For interactivity, add clickQuery with [placeholder] tokens filled from element data on click. " +
|
|
261
|
+
'Example: clickQuery: "Show details for [title] with full order history"\n\n' +
|
|
262
|
+
`Available elements: ${elementList}`);
|
|
263
|
+
}
|
|
@@ -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;
|
|
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,CAsCN"}
|
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
* Uses the high-level McpServer.registerTool() API for composability — customers
|
|
5
5
|
* can register their own tools alongside BranderUX tools on the same server.
|
|
6
6
|
*/
|
|
7
|
-
import { generateScreenInputSchema,
|
|
7
|
+
import { generateScreenInputSchema, buildGenerateScreenDescription, } from "./generate-screen-schema.js";
|
|
8
8
|
import { createScreenHandler } from "./tool-handler.js";
|
|
9
9
|
import { RESOURCE_URI } from "../resource/resource-registry.js";
|
|
10
|
+
import { ELEMENT_INFO } from "./element-definitions.js";
|
|
10
11
|
const TOOL_NAME = "generate_screen";
|
|
11
12
|
/**
|
|
12
13
|
* Register the BranderUX generate_screen tool with the MCP server.
|
|
@@ -14,8 +15,16 @@ const TOOL_NAME = "generate_screen";
|
|
|
14
15
|
*/
|
|
15
16
|
export function registerTools(server, projectConfig, apiConfig) {
|
|
16
17
|
const handler = createScreenHandler(projectConfig, apiConfig);
|
|
18
|
+
// Build description dynamically from project's element/screen visibility + custom screens
|
|
19
|
+
const description = buildGenerateScreenDescription({
|
|
20
|
+
elementVisibility: projectConfig.settings.elementVisibility,
|
|
21
|
+
customScreens: projectConfig.customScreens,
|
|
22
|
+
});
|
|
23
|
+
// Count enabled elements
|
|
24
|
+
const elementVisibility = projectConfig.settings.elementVisibility ?? {};
|
|
25
|
+
const enabledCount = ELEMENT_INFO.filter((e) => elementVisibility[e.id] !== false).length;
|
|
17
26
|
server.registerTool(TOOL_NAME, {
|
|
18
|
-
description
|
|
27
|
+
description,
|
|
19
28
|
inputSchema: generateScreenInputSchema,
|
|
20
29
|
_meta: {
|
|
21
30
|
ui: { resourceUri: RESOURCE_URI },
|
|
@@ -26,5 +35,6 @@ export function registerTools(server, projectConfig, apiConfig) {
|
|
|
26
35
|
// but our handler expects Record<string, unknown>
|
|
27
36
|
return handler(args);
|
|
28
37
|
});
|
|
29
|
-
console.error(`Registered BranderUX tool: ${TOOL_NAME} ` +
|
|
38
|
+
console.error(`Registered BranderUX tool: ${TOOL_NAME} ` +
|
|
39
|
+
`(${enabledCount} element types, resource: ${RESOURCE_URI})`);
|
|
30
40
|
}
|
|
@@ -17,21 +17,7 @@ export declare enum ElementType {
|
|
|
17
17
|
BUTTON = "button",
|
|
18
18
|
BAR_CHART = "bar-chart",
|
|
19
19
|
ALERT = "alert",
|
|
20
|
+
VIDEO = "video",
|
|
20
21
|
SCREEN = "screen"
|
|
21
22
|
}
|
|
22
|
-
export interface ToolSchema {
|
|
23
|
-
name: string;
|
|
24
|
-
description: string;
|
|
25
|
-
input_schema: {
|
|
26
|
-
type: "object";
|
|
27
|
-
properties: Record<string, unknown>;
|
|
28
|
-
required?: string[];
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
export interface ElementDefinition {
|
|
32
|
-
id: ElementType;
|
|
33
|
-
name: string;
|
|
34
|
-
description: string;
|
|
35
|
-
toolSchema: ToolSchema;
|
|
36
|
-
}
|
|
37
23
|
//# sourceMappingURL=element-types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"element-types.d.ts","sourceRoot":"","sources":["../../../src/types/element-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,oBAAY,WAAW;IACrB,MAAM,WAAW;IACjB,UAAU,eAAe;IACzB,UAAU,eAAe;IACzB,UAAU,eAAe;IACzB,SAAS,cAAc;IACvB,SAAS,cAAc;IACvB,SAAS,cAAc;IACvB,KAAK,UAAU;IACf,YAAY,iBAAiB;IAC7B,WAAW,gBAAgB;IAC3B,IAAI,SAAS;IACb,MAAM,WAAW;IACjB,SAAS,cAAc;IACvB,KAAK,UAAU;IACf,
|
|
1
|
+
{"version":3,"file":"element-types.d.ts","sourceRoot":"","sources":["../../../src/types/element-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,oBAAY,WAAW;IACrB,MAAM,WAAW;IACjB,UAAU,eAAe;IACzB,UAAU,eAAe;IACzB,UAAU,eAAe;IACzB,SAAS,cAAc;IACvB,SAAS,cAAc;IACvB,SAAS,cAAc;IACvB,KAAK,UAAU;IACf,YAAY,iBAAiB;IAC7B,WAAW,gBAAgB;IAC3B,IAAI,SAAS;IACb,MAAM,WAAW;IACjB,SAAS,cAAc;IACvB,KAAK,UAAU;IACf,KAAK,UAAU;IACf,MAAM,WAAW;CAClB"}
|