@brander/mcp-tools 0.2.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.
Files changed (57) hide show
  1. package/README.md +126 -0
  2. package/dist/app/index.html +8406 -0
  3. package/dist/server/brand/brand-loader.d.ts +26 -0
  4. package/dist/server/brand/brand-loader.d.ts.map +1 -0
  5. package/dist/server/brand/brand-loader.js +89 -0
  6. package/dist/server/brand/brand-types.d.ts +93 -0
  7. package/dist/server/brand/brand-types.d.ts.map +1 -0
  8. package/dist/server/brand/brand-types.js +32 -0
  9. package/dist/server/config/server-config.d.ts +16 -0
  10. package/dist/server/config/server-config.d.ts.map +1 -0
  11. package/dist/server/config/server-config.js +71 -0
  12. package/dist/server/config/types.d.ts +21 -0
  13. package/dist/server/config/types.d.ts.map +1 -0
  14. package/dist/server/config/types.js +4 -0
  15. package/dist/server/elements/click-behaviors.d.ts +13 -0
  16. package/dist/server/elements/click-behaviors.d.ts.map +1 -0
  17. package/dist/server/elements/click-behaviors.js +71 -0
  18. package/dist/server/elements/element-functions.d.ts +24 -0
  19. package/dist/server/elements/element-functions.d.ts.map +1 -0
  20. package/dist/server/elements/element-functions.js +167 -0
  21. package/dist/server/index.d.ts +9 -0
  22. package/dist/server/index.d.ts.map +1 -0
  23. package/dist/server/index.js +30 -0
  24. package/dist/server/lib-entry.d.ts +16 -0
  25. package/dist/server/lib-entry.d.ts.map +1 -0
  26. package/dist/server/lib-entry.js +14 -0
  27. package/dist/server/register.d.ts +35 -0
  28. package/dist/server/register.d.ts.map +1 -0
  29. package/dist/server/register.js +49 -0
  30. package/dist/server/resource/html-loader.d.ts +9 -0
  31. package/dist/server/resource/html-loader.d.ts.map +1 -0
  32. package/dist/server/resource/html-loader.js +20 -0
  33. package/dist/server/resource/resource-registry.d.ts +15 -0
  34. package/dist/server/resource/resource-registry.d.ts.map +1 -0
  35. package/dist/server/resource/resource-registry.js +45 -0
  36. package/dist/server/server.d.ts +13 -0
  37. package/dist/server/server.d.ts.map +1 -0
  38. package/dist/server/server.js +36 -0
  39. package/dist/server/tools/element-definitions.d.ts +15 -0
  40. package/dist/server/tools/element-definitions.d.ts.map +1 -0
  41. package/dist/server/tools/element-definitions.js +51 -0
  42. package/dist/server/tools/generate-screen-schema.d.ts +262 -0
  43. package/dist/server/tools/generate-screen-schema.d.ts.map +1 -0
  44. package/dist/server/tools/generate-screen-schema.js +227 -0
  45. package/dist/server/tools/tool-handler.d.ts +11 -0
  46. package/dist/server/tools/tool-handler.d.ts.map +1 -0
  47. package/dist/server/tools/tool-handler.js +83 -0
  48. package/dist/server/tools/tool-registry.d.ts +15 -0
  49. package/dist/server/tools/tool-registry.d.ts.map +1 -0
  50. package/dist/server/tools/tool-registry.js +30 -0
  51. package/dist/server/types/element-types.d.ts +37 -0
  52. package/dist/server/types/element-types.d.ts.map +1 -0
  53. package/dist/server/types/element-types.js +22 -0
  54. package/dist/server/types/mcp-types.d.ts +52 -0
  55. package/dist/server/types/mcp-types.d.ts.map +1 -0
  56. package/dist/server/types/mcp-types.js +4 -0
  57. package/package.json +56 -0
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Brand settings loader — fetches from BranderUX API or reads local JSON file.
3
+ */
4
+ import { BrandSettings, ProjectConfig } from "./brand-types.js";
5
+ interface BrandLoaderOptions {
6
+ projectId: string;
7
+ betaKey: string;
8
+ apiBaseUrl?: string;
9
+ brandSettingsPath?: string;
10
+ }
11
+ /**
12
+ * Load full project configuration from API or local file.
13
+ *
14
+ * Priority:
15
+ * 1. Local JSON file (brandSettingsPath)
16
+ * 2. BranderUX API (betaKey + projectId)
17
+ * 3. Default config (fallback)
18
+ */
19
+ export declare function loadProjectConfig(options: BrandLoaderOptions): Promise<ProjectConfig>;
20
+ /**
21
+ * @deprecated Use loadProjectConfig instead
22
+ * Load brand settings from API or local file (legacy method for backward compatibility).
23
+ */
24
+ export declare function loadBrandSettings(options: BrandLoaderOptions): Promise<BrandSettings>;
25
+ export {};
26
+ //# sourceMappingURL=brand-loader.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Brand settings loader — fetches from BranderUX API or reads local JSON file.
3
+ */
4
+ import { readFileSync } from "fs";
5
+ import { DEFAULT_BRAND_SETTINGS } from "./brand-types.js";
6
+ /**
7
+ * Load full project configuration from API or local file.
8
+ *
9
+ * Priority:
10
+ * 1. Local JSON file (brandSettingsPath)
11
+ * 2. BranderUX API (betaKey + projectId)
12
+ * 3. Default config (fallback)
13
+ */
14
+ export async function loadProjectConfig(options) {
15
+ // 1. Try local file first
16
+ if (options.brandSettingsPath) {
17
+ try {
18
+ return loadConfigFromFile(options.brandSettingsPath);
19
+ }
20
+ catch (error) {
21
+ console.error(`Failed to load config from file: ${options.brandSettingsPath}`, error);
22
+ }
23
+ }
24
+ // 2. Try API
25
+ if (options.betaKey && options.projectId) {
26
+ try {
27
+ return await loadConfigFromApi(options);
28
+ }
29
+ catch (error) {
30
+ console.error("Failed to load config from API", error);
31
+ }
32
+ }
33
+ // 3. Fallback to defaults
34
+ console.warn("Using default config — no betaKey/projectId or local file configured");
35
+ return {
36
+ brandSettings: { ...DEFAULT_BRAND_SETTINGS },
37
+ settings: {},
38
+ screenVisibility: {},
39
+ customScreens: [],
40
+ projectName: "Default Project",
41
+ };
42
+ }
43
+ /**
44
+ * @deprecated Use loadProjectConfig instead
45
+ * Load brand settings from API or local file (legacy method for backward compatibility).
46
+ */
47
+ export async function loadBrandSettings(options) {
48
+ const config = await loadProjectConfig(options);
49
+ return config.brandSettings;
50
+ }
51
+ /** Load project config from a local JSON file */
52
+ function loadConfigFromFile(filePath) {
53
+ const raw = readFileSync(filePath, "utf-8");
54
+ const parsed = JSON.parse(raw);
55
+ return {
56
+ brandSettings: { ...DEFAULT_BRAND_SETTINGS, ...(parsed.brandSettings || {}) },
57
+ settings: parsed.settings || {},
58
+ screenVisibility: parsed.screenVisibility || {},
59
+ customScreens: parsed.customScreens || [],
60
+ projectName: parsed.projectName || "Local Project",
61
+ };
62
+ }
63
+ /** Fetch full project config from the BranderUX API */
64
+ async function loadConfigFromApi(options) {
65
+ const baseUrl = options.apiBaseUrl || "https://app.branderux.com";
66
+ const url = new URL("/api/project/brand-settings", baseUrl);
67
+ url.searchParams.set("projectId", options.projectId);
68
+ url.searchParams.set("betaKey", options.betaKey);
69
+ const response = await fetch(url.toString(), {
70
+ method: "GET",
71
+ headers: {
72
+ "Content-Type": "application/json",
73
+ },
74
+ });
75
+ if (!response.ok) {
76
+ throw new Error(`BranderUX API returned ${response.status}: ${await response.text()}`);
77
+ }
78
+ const data = (await response.json());
79
+ if (!data.brandSettings) {
80
+ throw new Error("API response missing brandSettings field");
81
+ }
82
+ return {
83
+ brandSettings: { ...DEFAULT_BRAND_SETTINGS, ...data.brandSettings },
84
+ settings: data.settings || {},
85
+ screenVisibility: data.screenVisibility || {},
86
+ customScreens: data.customScreens || [],
87
+ projectName: data.projectName || "Unknown Project",
88
+ };
89
+ }
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Standalone BrandSettings types — no imports from main app.
3
+ * Mirrors lib/contexts/BrandStudioContext.tsx interfaces.
4
+ */
5
+ export interface GrayPalette {
6
+ gray50: string;
7
+ gray100: string;
8
+ gray200: string;
9
+ gray300: string;
10
+ gray400: string;
11
+ gray500: string;
12
+ gray600: string;
13
+ gray700: string;
14
+ gray800: string;
15
+ gray900: string;
16
+ }
17
+ export interface ComputedFontStyle {
18
+ fontFamily: string;
19
+ weight: number;
20
+ displayName: string;
21
+ isCustom?: boolean;
22
+ customDescription?: string;
23
+ }
24
+ export interface ComputedLayoutStyle {
25
+ spacing: number;
26
+ elevation: number;
27
+ displayName: string;
28
+ isCustom?: boolean;
29
+ customDescription?: string;
30
+ }
31
+ export interface BrandSettings {
32
+ primaryColor: string;
33
+ secondaryColor: string;
34
+ brandName: string;
35
+ iconUrl: string;
36
+ fontStyle: ComputedFontStyle;
37
+ layoutStyle: ComputedLayoutStyle;
38
+ borderRadius: number;
39
+ shadowIntensity: number;
40
+ darkMode: boolean;
41
+ accentColor: string;
42
+ grayPalette: GrayPalette;
43
+ primaryTextColor: string;
44
+ secondaryTextColor: string;
45
+ tertiaryTextColor: string;
46
+ reasoning?: {
47
+ colors: string;
48
+ typography: string;
49
+ layout: string;
50
+ };
51
+ }
52
+ /** Project settings that control UI behavior and element visibility */
53
+ export interface ProjectSettings {
54
+ maxCustomScreens?: number;
55
+ enableCollaboration?: boolean;
56
+ uiGenerationMode?: "deterministic" | "flexible";
57
+ elementVisibility?: Record<string, boolean>;
58
+ customPages?: Array<{
59
+ id: string;
60
+ name: string;
61
+ query: string;
62
+ }>;
63
+ enableQueryEnhancement?: boolean;
64
+ useToolsAPI?: boolean;
65
+ flexibleModeRules?: string;
66
+ elementStyleVariant?: "classic" | "modern";
67
+ }
68
+ /** Screen visibility map (which screens are enabled) */
69
+ export interface ScreenVisibilityMap {
70
+ [screenId: string]: boolean;
71
+ }
72
+ /** Custom screen definition */
73
+ export interface CustomScreen {
74
+ id: string;
75
+ name: string;
76
+ description?: string;
77
+ config: Record<string, unknown>;
78
+ elements?: Array<Record<string, unknown>>;
79
+ created: string | Date;
80
+ modified: string | Date;
81
+ version?: number;
82
+ }
83
+ /** Complete project configuration loaded from API */
84
+ export interface ProjectConfig {
85
+ brandSettings: BrandSettings;
86
+ settings: ProjectSettings;
87
+ screenVisibility: ScreenVisibilityMap;
88
+ customScreens: CustomScreen[];
89
+ projectName: string;
90
+ }
91
+ export declare const DEFAULT_GRAY_PALETTE: GrayPalette;
92
+ export declare const DEFAULT_BRAND_SETTINGS: BrandSettings;
93
+ //# sourceMappingURL=brand-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brand-types.d.ts","sourceRoot":"","sources":["../../../src/brand/brand-types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Standalone BrandSettings types — no imports from main app.
3
+ * Mirrors lib/contexts/BrandStudioContext.tsx interfaces.
4
+ */
5
+ export const DEFAULT_GRAY_PALETTE = {
6
+ gray50: "#fafafa",
7
+ gray100: "#f5f5f5",
8
+ gray200: "#e5e5e5",
9
+ gray300: "#d4d4d4",
10
+ gray400: "#a3a3a3",
11
+ gray500: "#737373",
12
+ gray600: "#525252",
13
+ gray700: "#404040",
14
+ gray800: "#262626",
15
+ gray900: "#171717",
16
+ };
17
+ export const DEFAULT_BRAND_SETTINGS = {
18
+ primaryColor: "#6366F1",
19
+ secondaryColor: "#06B6D4",
20
+ brandName: "Your Brand",
21
+ iconUrl: "",
22
+ fontStyle: { fontFamily: "'Inter', sans-serif", weight: 500, displayName: "modern" },
23
+ layoutStyle: { spacing: 3, elevation: 1, displayName: "clean" },
24
+ borderRadius: 12,
25
+ shadowIntensity: 2,
26
+ darkMode: true,
27
+ accentColor: "#F59E0B",
28
+ grayPalette: DEFAULT_GRAY_PALETTE,
29
+ primaryTextColor: "#171717",
30
+ secondaryTextColor: "#525252",
31
+ tertiaryTextColor: "#737373",
32
+ };
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Server configuration loading — env vars, JSON file, or direct config.
3
+ */
4
+ import { BranderMCPServerConfig } from "./types.js";
5
+ /**
6
+ * Load server config from environment variables or a JSON config file.
7
+ *
8
+ * Priority:
9
+ * 1. Direct config object (if passed)
10
+ * 2. Environment variables
11
+ * 3. JSON config file (BRANDER_CONFIG_PATH or ./brander-mcp.config.json)
12
+ */
13
+ export declare function loadServerConfig(overrides?: Partial<BranderMCPServerConfig>): BranderMCPServerConfig;
14
+ /** Validate that required config fields are present */
15
+ export declare function validateConfig(config: BranderMCPServerConfig): string[];
16
+ //# sourceMappingURL=server-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-config.d.ts","sourceRoot":"","sources":["../../../src/config/server-config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,sBAAsB,EAAiB,MAAM,YAAY,CAAC;AAMnE;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,SAAS,CAAC,EAAE,OAAO,CAAC,sBAAsB,CAAC,GAC1C,sBAAsB,CAsCxB;AAmBD,uDAAuD;AACvD,wBAAgB,cAAc,CAAC,MAAM,EAAE,sBAAsB,GAAG,MAAM,EAAE,CAoBvE"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Server configuration loading — env vars, JSON file, or direct config.
3
+ */
4
+ import { readFileSync, existsSync } from "fs";
5
+ const DEFAULT_API_BASE_URL = "https://app.branderux.com";
6
+ const DEFAULT_SERVER_NAME = "brander-mcp";
7
+ const DEFAULT_SERVER_VERSION = "0.1.0";
8
+ /**
9
+ * Load server config from environment variables or a JSON config file.
10
+ *
11
+ * Priority:
12
+ * 1. Direct config object (if passed)
13
+ * 2. Environment variables
14
+ * 3. JSON config file (BRANDER_CONFIG_PATH or ./brander-mcp.config.json)
15
+ */
16
+ export function loadServerConfig(overrides) {
17
+ // Try JSON config file
18
+ const fileConfig = loadConfigFile();
19
+ // Merge: overrides > env vars > file config > defaults
20
+ const config = {
21
+ projectId: overrides?.projectId ?? process.env.BRANDER_PROJECT_ID ?? fileConfig?.projectId ?? "",
22
+ betaKey: overrides?.betaKey ?? process.env.BRANDER_BETA_KEY ?? fileConfig?.betaKey ?? "",
23
+ apiBaseUrl: overrides?.apiBaseUrl ??
24
+ process.env.BRANDER_API_BASE_URL ??
25
+ fileConfig?.apiBaseUrl ??
26
+ DEFAULT_API_BASE_URL,
27
+ brandSettingsPath: overrides?.brandSettingsPath ??
28
+ process.env.BRANDER_BRAND_SETTINGS_PATH ??
29
+ fileConfig?.brandSettingsPath,
30
+ serverName: overrides?.serverName ??
31
+ process.env.BRANDER_SERVER_NAME ??
32
+ fileConfig?.serverName ??
33
+ DEFAULT_SERVER_NAME,
34
+ serverVersion: overrides?.serverVersion ?? fileConfig?.serverVersion ?? DEFAULT_SERVER_VERSION,
35
+ transport: overrides?.transport ??
36
+ process.env.BRANDER_TRANSPORT ??
37
+ fileConfig?.transport ??
38
+ "stdio",
39
+ };
40
+ return config;
41
+ }
42
+ /** Try to load a JSON config file */
43
+ function loadConfigFile() {
44
+ const configPath = process.env.BRANDER_CONFIG_PATH ?? "./brander-mcp.config.json";
45
+ if (!existsSync(configPath)) {
46
+ return null;
47
+ }
48
+ try {
49
+ const raw = readFileSync(configPath, "utf-8");
50
+ return JSON.parse(raw);
51
+ }
52
+ catch {
53
+ console.error(`Failed to parse config file: ${configPath}`);
54
+ return null;
55
+ }
56
+ }
57
+ /** Validate that required config fields are present */
58
+ export function validateConfig(config) {
59
+ const errors = [];
60
+ // projectId is always required
61
+ if (!config.projectId) {
62
+ errors.push("BRANDER_PROJECT_ID is required. Set it as an environment variable or in brander-mcp.config.json.");
63
+ }
64
+ // betaKey is required unless using local brand settings file
65
+ if (!config.betaKey && !config.brandSettingsPath) {
66
+ errors.push("BRANDER_BETA_KEY is required for API authentication. " +
67
+ "Provide your beta design partner key (bux_dp_xxx), " +
68
+ "or use BRANDER_BRAND_SETTINGS_PATH for local development.");
69
+ }
70
+ return errors;
71
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * MCP Server configuration types.
3
+ */
4
+ export type TransportMode = "stdio" | "sse";
5
+ export interface BranderMCPServerConfig {
6
+ /** BranderUX project ID — identifies which project's data to load */
7
+ projectId: string;
8
+ /** Beta design partner key (bux_dp_xxx) for authentication */
9
+ betaKey: string;
10
+ /** BranderUX API base URL (defaults to https://app.branderux.com) */
11
+ apiBaseUrl?: string;
12
+ /** Path to local brandSettings.json file (alternative to API for development) */
13
+ brandSettingsPath?: string;
14
+ /** Server name (defaults to "brander-mcp") */
15
+ serverName?: string;
16
+ /** Server version (defaults to package version) */
17
+ serverVersion?: string;
18
+ /** MCP transport type (defaults to "stdio") */
19
+ transport?: TransportMode;
20
+ }
21
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/config/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,KAAK,CAAC;AAE5C,MAAM,WAAW,sBAAsB;IACrC,qEAAqE;IACrE,SAAS,EAAE,MAAM,CAAC;IAElB,8DAA8D;IAC9D,OAAO,EAAE,MAAM,CAAC;IAEhB,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,iFAAiF;IACjF,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,mDAAmD;IACnD,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,+CAA+C;IAC/C,SAAS,CAAC,EAAE,aAAa,CAAC;CAC3B"}
@@ -0,0 +1,4 @@
1
+ /**
2
+ * MCP Server configuration types.
3
+ */
4
+ export {};
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Standalone click behavior registry — no imports from main app.
3
+ * Mirrors types/element-behavior-types.ts ELEMENT_BEHAVIOR_REGISTRY.
4
+ */
5
+ import { ElementType } from "../types/element-types.js";
6
+ export interface ClickedItemBehavior {
7
+ queryTemplate: string;
8
+ description: string;
9
+ }
10
+ export declare const ELEMENT_BEHAVIOR_REGISTRY: Record<ElementType, ClickedItemBehavior>;
11
+ /** Get click behavior for an element type */
12
+ export declare function getClickBehavior(elementType: ElementType): ClickedItemBehavior | undefined;
13
+ //# sourceMappingURL=click-behaviors.d.ts.map
@@ -0,0 +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,CA6D9E,CAAC;AAEF,6CAA6C;AAC7C,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,WAAW,GAAG,mBAAmB,GAAG,SAAS,CAE1F"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Standalone click behavior registry — no imports from main app.
3
+ * Mirrors types/element-behavior-types.ts ELEMENT_BEHAVIOR_REGISTRY.
4
+ */
5
+ import { ElementType } from "../types/element-types.js";
6
+ export const ELEMENT_BEHAVIOR_REGISTRY = {
7
+ [ElementType.HEADER]: {
8
+ queryTemplate: "Show main [title]",
9
+ description: "Headers typically don't have clickable items",
10
+ },
11
+ [ElementType.DATA_TABLE]: {
12
+ queryTemplate: "Show details for [title] (ID: [id])",
13
+ description: "Table rows lead to detail view of the item",
14
+ },
15
+ [ElementType.ITEM_GRID]: {
16
+ queryTemplate: "Show details for [title] (ID: [id])",
17
+ description: "Grid items lead to detail view of the item",
18
+ },
19
+ [ElementType.ITEM_CARD]: {
20
+ queryTemplate: "Show details for [title] (ID: [id])",
21
+ description: "Item cards lead to detail view",
22
+ },
23
+ [ElementType.STATS_GRID]: {
24
+ queryTemplate: "Show analytics for [title]",
25
+ description: "KPI/stat cards lead to analytics view",
26
+ },
27
+ [ElementType.LINE_CHART]: {
28
+ queryTemplate: "Show [label] data from [chartTitle]",
29
+ description: "Chart points lead to detailed data table",
30
+ },
31
+ [ElementType.PIE_CHART]: {
32
+ queryTemplate: "Show [label] data from [chartTitle]",
33
+ description: "Chart segments lead to detailed data table",
34
+ },
35
+ [ElementType.IMAGE]: {
36
+ queryTemplate: "Show details for [title] (ID: [id])",
37
+ description: "Images lead to detail view",
38
+ },
39
+ [ElementType.DETAILS_DATA]: {
40
+ queryTemplate: "Show details for [title] (ID: [id])",
41
+ description: "Detail cards typically stay in details view",
42
+ },
43
+ [ElementType.CHAT_BUBBLE]: {
44
+ queryTemplate: "Continue conversation",
45
+ description: "Text responses that don't need interaction",
46
+ },
47
+ [ElementType.FORM]: {
48
+ queryTemplate: "Submit form data for [formSummary]",
49
+ description: "Form submissions trigger data processing",
50
+ },
51
+ [ElementType.BUTTON]: {
52
+ queryTemplate: "[action]",
53
+ description: "Button action triggers the configured query",
54
+ },
55
+ [ElementType.BAR_CHART]: {
56
+ queryTemplate: "Show [seriesName] data for [category]",
57
+ description: "Bar chart clicks lead to detailed data table for that category",
58
+ },
59
+ [ElementType.ALERT]: {
60
+ queryTemplate: "[actionQuery]",
61
+ description: "Alert action button triggers the configured query",
62
+ },
63
+ [ElementType.SCREEN]: {
64
+ queryTemplate: "",
65
+ description: "Screen composition — click behaviors are per-element",
66
+ },
67
+ };
68
+ /** Get click behavior for an element type */
69
+ export function getClickBehavior(elementType) {
70
+ return ELEMENT_BEHAVIOR_REGISTRY[elementType];
71
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Standalone element functions for the MCP server.
3
+ * Adapted from lib/elements/functions/ — simplified for MCP context
4
+ * where data comes directly from tool input (not TypedScreenData).
5
+ */
6
+ import { ElementType } from "../types/element-types.js";
7
+ /** Validates that raw tool input has enough data to render the element */
8
+ export type VisibilityCheck = (data: Record<string, unknown>) => boolean;
9
+ /** Registry of visibility checks per element type */
10
+ export declare const VISIBILITY_CHECKS: Record<ElementType, VisibilityCheck>;
11
+ /** Check if tool input data is valid for the given element type */
12
+ export declare function isValidElementData(elementType: ElementType, data: Record<string, unknown>): boolean;
13
+ /**
14
+ * Click metadata enrichment per element type.
15
+ * Maps element types to the metadata fields added to click handler payloads.
16
+ * Used by the app-side click handler to build proper query interpolation context.
17
+ */
18
+ export declare const CLICK_METADATA_ENRICHMENT: Record<ElementType, (itemData: Record<string, unknown>) => Record<string, unknown>>;
19
+ /**
20
+ * Build a text summary of tool result for the LLM content channel.
21
+ * Returns a human-readable description of what was rendered.
22
+ */
23
+ export declare function buildContentSummary(elementType: ElementType, data: Record<string, unknown>): string;
24
+ //# sourceMappingURL=element-functions.d.ts.map
@@ -0,0 +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,CAsDlE,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,CA4E/D,CAAC;AAEF;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,WAAW,EACxB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,MAAM,CAsER"}
@@ -0,0 +1,167 @@
1
+ /**
2
+ * Standalone element functions for the MCP server.
3
+ * Adapted from lib/elements/functions/ — simplified for MCP context
4
+ * where data comes directly from tool input (not TypedScreenData).
5
+ */
6
+ import { ElementType } from "../types/element-types.js";
7
+ /** Registry of visibility checks per element type */
8
+ export const VISIBILITY_CHECKS = {
9
+ [ElementType.HEADER]: (data) => Boolean(data?.title),
10
+ [ElementType.CHAT_BUBBLE]: (data) => Boolean(data?.text),
11
+ [ElementType.STATS_GRID]: (data) => Array.isArray(data?.stats) && data.stats.length > 0,
12
+ [ElementType.DATA_TABLE]: (data) => Array.isArray(data?.columns) &&
13
+ Array.isArray(data?.rows) &&
14
+ data.rows.length > 0,
15
+ [ElementType.LINE_CHART]: (data) => {
16
+ const labels = data?.labels;
17
+ const chartData = data?.data;
18
+ return (Array.isArray(labels) &&
19
+ Array.isArray(chartData) &&
20
+ labels.length > 0 &&
21
+ chartData.length > 0 &&
22
+ chartData.length === labels.length);
23
+ },
24
+ [ElementType.PIE_CHART]: (data) => Array.isArray(data?.data) && data.data.length > 0,
25
+ [ElementType.BAR_CHART]: (data) => Array.isArray(data?.categories) &&
26
+ data.categories.length > 0 &&
27
+ Array.isArray(data?.series) &&
28
+ data.series.length > 0,
29
+ [ElementType.ITEM_GRID]: (data) => Array.isArray(data?.items) && data.items.length > 0,
30
+ [ElementType.ITEM_CARD]: (data) => Boolean(data),
31
+ [ElementType.IMAGE]: (data) => Boolean(data?.src),
32
+ [ElementType.DETAILS_DATA]: (data) => Array.isArray(data?.items) && data.items.length > 0,
33
+ [ElementType.FORM]: (data) => Array.isArray(data?.fields) && data.fields.length > 0,
34
+ [ElementType.BUTTON]: (data) => Boolean(data),
35
+ [ElementType.ALERT]: (data) => Boolean(data?.message) && typeof data.message === "string" && data.message.trim().length > 0,
36
+ [ElementType.SCREEN]: (data) => Array.isArray(data?.elements) && data.elements.length > 0,
37
+ };
38
+ /** Check if tool input data is valid for the given element type */
39
+ export function isValidElementData(elementType, data) {
40
+ const check = VISIBILITY_CHECKS[elementType];
41
+ return check ? check(data) : false;
42
+ }
43
+ /**
44
+ * Click metadata enrichment per element type.
45
+ * Maps element types to the metadata fields added to click handler payloads.
46
+ * Used by the app-side click handler to build proper query interpolation context.
47
+ */
48
+ export const CLICK_METADATA_ENRICHMENT = {
49
+ [ElementType.HEADER]: (data) => ({ ...data }),
50
+ [ElementType.CHAT_BUBBLE]: (data) => ({ ...data }),
51
+ [ElementType.STATS_GRID]: (data) => ({
52
+ ...data,
53
+ id: data.id ||
54
+ `${String(data.title || "")
55
+ .toLowerCase()
56
+ .replace(/\s+/g, "-")}-stat`,
57
+ isStatMetric: true,
58
+ }),
59
+ [ElementType.DATA_TABLE]: (data) => ({
60
+ ...data,
61
+ id: data.id,
62
+ title: data.name || data.title || data.id,
63
+ isTableRow: true,
64
+ }),
65
+ [ElementType.LINE_CHART]: (data) => ({
66
+ ...data,
67
+ chartType: "line",
68
+ actionType: "chart_point_click",
69
+ isChartPoint: true,
70
+ }),
71
+ [ElementType.PIE_CHART]: (data) => ({
72
+ ...data,
73
+ chartType: "pie",
74
+ actionType: "chart_point_click",
75
+ isChartPoint: true,
76
+ }),
77
+ [ElementType.BAR_CHART]: (data) => ({
78
+ ...data,
79
+ elementType: "bar-chart",
80
+ actionType: "bar_click",
81
+ }),
82
+ [ElementType.ITEM_GRID]: (data) => ({
83
+ ...data,
84
+ id: data.id,
85
+ title: data.name || data.title || data.id,
86
+ isProduct: true,
87
+ }),
88
+ [ElementType.ITEM_CARD]: (data) => ({
89
+ ...data,
90
+ isProduct: true,
91
+ }),
92
+ [ElementType.IMAGE]: (data) => ({ ...data }),
93
+ [ElementType.DETAILS_DATA]: (data) => ({ ...data }),
94
+ [ElementType.FORM]: (data) => ({
95
+ ...data,
96
+ isFormSubmission: true,
97
+ }),
98
+ [ElementType.BUTTON]: (data) => ({
99
+ ...data,
100
+ elementType: "button",
101
+ buttonType: data.type || "action",
102
+ }),
103
+ [ElementType.ALERT]: (data) => ({
104
+ ...data,
105
+ elementType: "alert",
106
+ actionType: "alert_action_click",
107
+ }),
108
+ [ElementType.SCREEN]: (data) => ({ ...data }),
109
+ };
110
+ /**
111
+ * Build a text summary of tool result for the LLM content channel.
112
+ * Returns a human-readable description of what was rendered.
113
+ */
114
+ export function buildContentSummary(elementType, data) {
115
+ const summaryBuilders = {
116
+ [ElementType.HEADER]: (d) => `Rendered header: "${d.title}"${d.subtitle ? ` — ${d.subtitle}` : ""}`,
117
+ [ElementType.CHAT_BUBBLE]: (d) => {
118
+ const text = String(d.text || "");
119
+ const preview = text.length > 100 ? text.slice(0, 100) + "..." : text;
120
+ return `Displayed message: "${preview}"`;
121
+ },
122
+ [ElementType.STATS_GRID]: (d) => {
123
+ const stats = d.stats;
124
+ return `Rendered stats grid with ${stats?.length || 0} metrics`;
125
+ },
126
+ [ElementType.DATA_TABLE]: (d) => {
127
+ const rows = d.rows;
128
+ const cols = d.columns;
129
+ return `Rendered data table "${d.title || "Table"}" with ${cols?.length || 0} columns and ${rows?.length || 0} rows`;
130
+ },
131
+ [ElementType.LINE_CHART]: (d) => {
132
+ const labels = d.labels;
133
+ return `Rendered line chart "${d.title || "Chart"}" with ${labels?.length || 0} data points`;
134
+ },
135
+ [ElementType.PIE_CHART]: (d) => {
136
+ const segments = d.data;
137
+ return `Rendered pie chart "${d.title || "Chart"}" with ${segments?.length || 0} segments`;
138
+ },
139
+ [ElementType.BAR_CHART]: (d) => {
140
+ const categories = d.categories;
141
+ const series = d.series;
142
+ return `Rendered bar chart "${d.title || "Chart"}" with ${categories?.length || 0} categories and ${series?.length || 0} series`;
143
+ },
144
+ [ElementType.ITEM_GRID]: (d) => {
145
+ const items = d.items;
146
+ return `Rendered item grid "${d.title || "Items"}" with ${items?.length || 0} items`;
147
+ },
148
+ [ElementType.ITEM_CARD]: (d) => `Rendered item card: "${d.title}"${d.price ? ` — ${d.price}` : ""}`,
149
+ [ElementType.IMAGE]: (d) => `Displayed image: "${d.alt || "Image"}"`,
150
+ [ElementType.DETAILS_DATA]: (d) => {
151
+ const items = d.items;
152
+ return `Rendered details display with ${items?.length || 0} data items`;
153
+ },
154
+ [ElementType.FORM]: (d) => {
155
+ const fields = d.fields;
156
+ return `Rendered form "${d.title || "Form"}" with ${fields?.length || 0} fields`;
157
+ },
158
+ [ElementType.BUTTON]: (d) => `Rendered button: "${d.label}"`,
159
+ [ElementType.ALERT]: (d) => `Displayed ${d.severity || "info"} alert: "${d.message}"`,
160
+ [ElementType.SCREEN]: (d) => {
161
+ const elements = d.elements;
162
+ return `Rendered screen with ${elements?.length || 0} elements`;
163
+ },
164
+ };
165
+ const builder = summaryBuilders[elementType];
166
+ return builder ? builder(data) : `Rendered ${elementType} element`;
167
+ }