@databrainhq/mcp-server 0.3.0-rc.10 → 0.3.0-rc.11

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.
@@ -3,22 +3,31 @@ import {
3
3
  CustomChartsApi,
4
4
  DatabrainApiError,
5
5
  apiProblems,
6
- buildProject,
7
- bundleSizeBytes,
8
- contentHash,
9
6
  createCustomChartsApi,
7
+ editWithBryn,
10
8
  logger,
11
- optionSchema,
12
9
  planUpload,
13
- readDist,
14
10
  scaffoldProject,
15
- slotSchema,
16
11
  stringify,
12
+ studioDraftSchema,
17
13
  toolContext,
18
14
  toolError,
19
- toolSuccess,
15
+ toolSuccess
16
+ } from "./chunk-RHK62ZJ6.js";
17
+ import {
18
+ MAX_BUNDLE_CSS_BYTES,
19
+ MAX_BUNDLE_JS_BYTES,
20
+ MAX_ICON_BYTES,
21
+ MAX_MANIFEST_BYTES,
22
+ buildProject,
23
+ buildSource,
24
+ bundleSizeBytes,
25
+ contentHash,
26
+ optionSchema,
27
+ readDist,
28
+ slotSchema,
20
29
  validateBundle
21
- } from "./chunk-OCBTNAAO.js";
30
+ } from "./chunk-Q5EYDKSA.js";
22
31
 
23
32
  // src/apps/contract.ts
24
33
  import { z } from "zod";
@@ -28,6 +37,8 @@ var APP_MIME = "text/html;profile=mcp-app";
28
37
  var RESOURCE_URI_META_KEY = "ui/resourceUri";
29
38
  var PAGE_SIZE = 50;
30
39
  var MAX_RESULT_CHARS = 124e3;
40
+ var MAX_CUSTOM_BUNDLE_CHARS = 6 * (MAX_BUNDLE_JS_BYTES + MAX_BUNDLE_CSS_BYTES + MAX_ICON_BYTES) + MAX_MANIFEST_BYTES + 128;
41
+ var CUSTOM_BUNDLE_CHUNK_CHARS = 32e3;
31
42
  var id = z.string().trim().min(1).max(256);
32
43
  var cell = z.union([z.string().max(2e3), z.number().finite(), z.boolean(), z.null()]);
33
44
  var rowsSchema = z.array(z.record(cell)).max(PAGE_SIZE);
@@ -58,13 +69,19 @@ var pageSchema = z.object({
58
69
  rows: rowsSchema,
59
70
  columns: z.array(z.string().max(128)).max(20),
60
71
  svg: z.string().max(1e5).optional(),
72
+ customChart: z.object({
73
+ key: z.string().regex(/^[a-z][a-z0-9_-]{0,63}$/),
74
+ bindings: z.record(z.array(z.string().max(128)).max(20)),
75
+ options: z.record(z.union([z.string().max(2e3), z.number().finite(), z.boolean()]))
76
+ }).strict().optional(),
77
+ fallback: z.string().max(1e3).optional(),
61
78
  width: z.number().int().min(240).max(1200),
62
79
  height: z.number().int().min(120).max(800),
63
80
  points: z.array(point).max(PAGE_SIZE),
64
81
  value: cell.optional(),
65
82
  nextCursor: z.string().min(1).max(2048).optional()
66
83
  }).strict().superRefine((page, ctx) => {
67
- if (page.kind === "chart" && !page.svg) ctx.addIssue({ code: "custom", message: "SVG required" });
84
+ if (page.kind === "chart" && !page.svg && !page.customChart) ctx.addIssue({ code: "custom", message: "SVG required" });
68
85
  if (page.kind === "kpi" && (page.svg || page.points.length || page.value === void 0)) {
69
86
  ctx.addIssue({ code: "custom", message: "KPI requires a value and no SVG/points" });
70
87
  }
@@ -109,6 +126,188 @@ function chartResult(summary, payload) {
109
126
  });
110
127
  }
111
128
 
129
+ // src/tools/custom-chart/author.ts
130
+ import { z as z3 } from "zod";
131
+
132
+ // src/tools/annotations.ts
133
+ var READ_ONLY = {
134
+ readOnlyHint: true,
135
+ destructiveHint: false,
136
+ idempotentHint: true,
137
+ openWorldHint: false
138
+ };
139
+ var WRITE_IDEMPOTENT = {
140
+ readOnlyHint: false,
141
+ destructiveHint: false,
142
+ idempotentHint: true,
143
+ openWorldHint: false
144
+ };
145
+ var WRITE_CREATE = {
146
+ readOnlyHint: false,
147
+ destructiveHint: false,
148
+ idempotentHint: false,
149
+ openWorldHint: false
150
+ };
151
+ var DESTRUCTIVE = {
152
+ readOnlyHint: false,
153
+ destructiveHint: true,
154
+ idempotentHint: false,
155
+ openWorldHint: false
156
+ };
157
+
158
+ // src/tools/custom-chart/shared.ts
159
+ import { z as z2 } from "zod";
160
+ var slotInputSchema = slotSchema;
161
+ var optionInputSchema = optionSchema;
162
+ var manifestInputSchema = z2.record(z2.unknown()).describe("manifest.json as an object (schemaVersion 2). Validated with the same rules as the server.");
163
+ var bundleInputShape = {
164
+ manifest: manifestInputSchema.optional(),
165
+ chartTs: z2.string().max(64e3).optional().describe("Hosted source: export render(ctx) in TypeScript or JavaScript. Compiled in memory without filesystem or imports. Pass instead of bundleJs/projectDir."),
166
+ bundleJs: z2.string().optional().describe("dist/index.js from `databrain custom-chart build` (the shim plus the chart module)."),
167
+ bundleCss: z2.string().optional().describe("The raw chart.css, kept for provenance."),
168
+ iconSvg: z2.string().optional().describe("icon.svg, at most 16 KiB, no script, no foreignObject, no external href."),
169
+ projectDir: z2.string().optional().describe("Local only: a chart project folder. The tool reads it instead of manifest/bundleJs/iconSvg.")
170
+ };
171
+ function formatProblems(problems) {
172
+ if (problems.length === 0) return "No problems.";
173
+ return problems.map((p) => `${p.path || "/"} ${p.code} ${p.message}`).join("\n");
174
+ }
175
+ function projectDirRefusal() {
176
+ if (process.env.DATABRAIN_HOSTED_PUBLIC_URL) {
177
+ return "projectDir is not available on the hosted server. Pass chartTs, manifest, bundleCss and iconSvg to compile in memory, or pass an already built bundleJs.";
178
+ }
179
+ return null;
180
+ }
181
+ async function resolveBundleInput(params, options) {
182
+ if (params.chartTs !== void 0) {
183
+ if (params.projectDir || params.bundleJs || !params.manifest || !params.iconSvg) {
184
+ return { problems: [], error: "chartTs needs manifest and iconSvg, and cannot be combined with bundleJs or projectDir.", source: "arguments" };
185
+ }
186
+ const result = await buildSource({ manifest: params.manifest, chartTs: params.chartTs, bundleCss: params.bundleCss, iconSvg: params.iconSvg });
187
+ return { bundle: result.outputs, problems: result.problems, source: "arguments" };
188
+ }
189
+ if (params.projectDir) {
190
+ const refusal = projectDirRefusal();
191
+ if (refusal) return { problems: [], error: refusal, source: "projectDir" };
192
+ if (params.manifest || params.bundleJs || params.iconSvg) {
193
+ return { problems: [], error: "Pass either projectDir or manifest/bundleJs/iconSvg, not both.", source: "projectDir" };
194
+ }
195
+ if (options.build) {
196
+ const result = await buildProject(params.projectDir, { write: false });
197
+ if (!result.ok || !result.outputs) return { problems: result.problems, source: "projectDir" };
198
+ const { manifest, bundleJs, bundleCss, iconSvg } = result.outputs;
199
+ return { bundle: { manifest, bundleJs, bundleCss, iconSvg }, problems: [], source: "projectDir" };
200
+ }
201
+ const dist = readDist(params.projectDir);
202
+ if (!dist.bundle) return { problems: dist.problems, source: "projectDir" };
203
+ return { bundle: dist.bundle, problems: [], source: "projectDir" };
204
+ }
205
+ if (!params.manifest) {
206
+ return { problems: [], error: "manifest is required (or pass projectDir when running locally).", source: "arguments" };
207
+ }
208
+ return {
209
+ bundle: {
210
+ manifest: params.manifest,
211
+ bundleJs: params.bundleJs,
212
+ bundleCss: params.bundleCss,
213
+ iconSvg: params.iconSvg
214
+ },
215
+ problems: [],
216
+ source: "arguments"
217
+ };
218
+ }
219
+ async function remoteValidate(client, bundle) {
220
+ try {
221
+ const result = await createCustomChartsApi(client).validate(bundle);
222
+ return { status: "ok", result };
223
+ } catch (err) {
224
+ if (err instanceof DatabrainApiError) {
225
+ if (err.code === "MISSING_SERVICE_TOKEN") {
226
+ return { status: "skipped", reason: "No service token is configured, so only the local validator ran." };
227
+ }
228
+ return { status: "failed", reason: err.message, problems: apiProblems(err) };
229
+ }
230
+ return { status: "failed", reason: err.message, problems: [] };
231
+ }
232
+ }
233
+ function isCompleteBundle(bundle) {
234
+ return typeof bundle.bundleJs === "string" && typeof bundle.iconSvg === "string";
235
+ }
236
+
237
+ // src/tools/custom-chart/author.ts
238
+ function registerCustomChartAuthor(server, client) {
239
+ server.tool(
240
+ "custom_chart_edit",
241
+ "Iterate a custom chart draft with Chart studio Bryn in a granted workspace. Never saves a version or publishes. Feature-detects the backend route. If absent, returns the draft for the calling agent to edit and validate with chartTs, without a local build.",
242
+ {
243
+ key: z3.string().regex(/^[a-z][a-z0-9_-]{0,63}$/),
244
+ workspaceId: z3.string().uuid(),
245
+ message: z3.string().trim().min(1).max(8e3),
246
+ draft: studioDraftSchema,
247
+ sessionId: z3.string().uuid().optional()
248
+ },
249
+ WRITE_CREATE,
250
+ async (input) => {
251
+ try {
252
+ if (input.draft.manifest.id !== input.key) return toolError("The draft manifest id must match key.");
253
+ const result = await editWithBryn(client, input);
254
+ return toolSuccess(JSON.stringify({
255
+ ...result,
256
+ nextStep: result.available ? "Check the returned draft. Validate and preview before saving. Publishing still requires the author to confirm." : "Studio Bryn is not installed. Edit draft.code as plain JavaScript defining render(ctx), then use custom_chart_validate / custom_chart_preview / custom_chart_upload with chartTs=draft.code, manifest, bundleCss=draft.css and iconSvg. Nothing was saved."
257
+ }));
258
+ } catch (error) {
259
+ return error instanceof DatabrainApiError ? error.toToolResponse() : toolError("Bryn could not edit the draft. No version was saved.");
260
+ }
261
+ }
262
+ );
263
+ const preview = server.tool(
264
+ "custom_chart_preview",
265
+ "Validate and preview a draft custom chart as an MCP App tile using bounded sample query rows. No version is saved. Pass chartTs to compile on the server without local files; bindings map manifest slot ids to row column names. Hosts without MCP Apps get the rows and validation result.",
266
+ {
267
+ ...bundleInputShape,
268
+ rows: rowsSchema,
269
+ bindings: z3.record(z3.array(z3.string().max(128)).max(20)),
270
+ options: z3.record(z3.union([z3.string().max(2e3), z3.number().finite(), z3.boolean()])).default({})
271
+ },
272
+ READ_ONLY,
273
+ async (input) => {
274
+ try {
275
+ const resolved = await resolveBundleInput(input, { build: true });
276
+ if (resolved.error) return toolError(resolved.error);
277
+ if (!resolved.bundle || !isCompleteBundle(resolved.bundle)) return toolError(formatProblems(resolved.problems));
278
+ const { validateBundle: validateBundle2 } = await import("./bundle-TDQXWIPM.js");
279
+ const problems = validateBundle2(resolved.bundle);
280
+ if (problems.length) return toolError(formatProblems(problems));
281
+ const manifest = resolved.bundle.manifest;
282
+ const columns = Object.keys(input.rows[0] ?? {});
283
+ const missing = manifest.slots.filter((slot) => slot.required && !(input.bindings[slot.id] ?? []).some((column) => columns.includes(column)));
284
+ if (input.rows.length && missing.length) return toolError(`Bind required slots ${missing.map((slot) => slot.id).join(", ")} to sample columns: ${columns.join(", ") || "(none)"}.`);
285
+ const customChart = { key: manifest.id, bindings: input.bindings, options: input.options };
286
+ const payload = {
287
+ kind: "chart",
288
+ title: manifest.name,
289
+ chartSpec: { type: `custom:${manifest.id}` },
290
+ rows: input.rows,
291
+ columns: Object.keys(input.rows[0] ?? {}),
292
+ width: 600,
293
+ height: 320,
294
+ points: [],
295
+ customChart,
296
+ fallback: "Draft validated. An MCP Apps host can preview it. These are sample rows, not a saved metric."
297
+ };
298
+ if (!hasChartApps(server)) return toolSuccess(JSON.stringify({ ...payload, ok: true }));
299
+ const result = chartResult("Custom chart draft validated. Preview uses sample rows. Nothing was saved or published.", payload);
300
+ result._meta = { ...result._meta, "databrain/custom-chart-bundle": resolved.bundle };
301
+ if (JSON.stringify(result).length > MAX_RESULT_CHARS) return toolError("Draft preview exceeds the MCP host result budget. Reduce the source, CSS or sample rows before previewing.");
302
+ return result;
303
+ } catch (error) {
304
+ return error instanceof DatabrainApiError ? error.toToolResponse() : toolError(error instanceof Error && error.message === "Chart page exceeds payload budget" ? "Draft preview exceeds the MCP host result budget. Reduce the source, CSS or sample rows before previewing." : "Custom chart preview could not be prepared. Check the manifest, source and bindings.");
305
+ }
306
+ }
307
+ );
308
+ tagChartTool(server, preview);
309
+ }
310
+
112
311
  // src/tools/tool-metadata.ts
113
312
  var DEFAULT_TOOL_META = {
114
313
  category: "discovery",
@@ -204,6 +403,10 @@ var TOOL_METADATA = {
204
403
  list_scheduled_reports: { category: "reports", workflowIntent: "reports", effect: "read" },
205
404
  // Custom chart types (DAT-925)
206
405
  // Returns template files; nothing is written or persisted.
406
+ custom_chart_edit: { category: "custom_charts", workflowIntent: "custom_chart", effect: "commit" },
407
+ custom_chart_preview: { category: "custom_charts", workflowIntent: "custom_chart", effect: "read" },
408
+ load_custom_chart_bundle: { category: "custom_charts", workflowIntent: "custom_chart", effect: "read" },
409
+ load_custom_chart_runtime: { category: "custom_charts", workflowIntent: "custom_chart", effect: "read" },
207
410
  custom_chart_scaffold: { category: "custom_charts", workflowIntent: "custom_chart", effect: "read" },
208
411
  // Local rules plus POST /validate, which never persists.
209
412
  custom_chart_validate: { category: "custom_charts", workflowIntent: "custom_chart", effect: "read" },
@@ -214,7 +417,7 @@ var TOOL_METADATA = {
214
417
  };
215
418
 
216
419
  // src/tools/data-app/list-data-apps.ts
217
- import { z as z2 } from "zod";
420
+ import { z as z4 } from "zod";
218
421
 
219
422
  // src/api/dashboards-api.ts
220
423
  var DashboardsApi = class {
@@ -1577,32 +1780,6 @@ function createServiceBundle(client) {
1577
1780
  };
1578
1781
  }
1579
1782
 
1580
- // src/tools/annotations.ts
1581
- var READ_ONLY = {
1582
- readOnlyHint: true,
1583
- destructiveHint: false,
1584
- idempotentHint: true,
1585
- openWorldHint: false
1586
- };
1587
- var WRITE_IDEMPOTENT = {
1588
- readOnlyHint: false,
1589
- destructiveHint: false,
1590
- idempotentHint: true,
1591
- openWorldHint: false
1592
- };
1593
- var WRITE_CREATE = {
1594
- readOnlyHint: false,
1595
- destructiveHint: false,
1596
- idempotentHint: false,
1597
- openWorldHint: false
1598
- };
1599
- var DESTRUCTIVE = {
1600
- readOnlyHint: false,
1601
- destructiveHint: true,
1602
- idempotentHint: false,
1603
- openWorldHint: false
1604
- };
1605
-
1606
1783
  // src/tools/data-app/list-data-apps.ts
1607
1784
  function registerListDataApps(server, client) {
1608
1785
  const services = createServiceBundle(client);
@@ -1610,7 +1787,7 @@ function registerListDataApps(server, client) {
1610
1787
  "list_data_apps",
1611
1788
  "List data apps in your organization. Start here for embed setup.",
1612
1789
  {
1613
- workspaceName: z2.string().optional().describe("Filter by workspace name")
1790
+ workspaceName: z4.string().optional().describe("Filter by workspace name")
1614
1791
  },
1615
1792
  READ_ONLY,
1616
1793
  async (params) => {
@@ -1639,7 +1816,7 @@ function registerListDataApps(server, client) {
1639
1816
  }
1640
1817
 
1641
1818
  // src/tools/data-app/list-tenants.ts
1642
- import { z as z3 } from "zod";
1819
+ import { z as z5 } from "zod";
1643
1820
  var isNonEmptyString4 = (value) => typeof value === "string" && value.trim().length > 0;
1644
1821
  function workspaceIdFrom(workspace) {
1645
1822
  return isNonEmptyString4(workspace.id) && workspace.id || isNonEmptyString4(workspace._id) && workspace._id || isNonEmptyString4(workspace.workspaceId) && workspace.workspaceId || null;
@@ -1677,12 +1854,12 @@ function registerListTenants(server, client) {
1677
1854
  "list_tenants",
1678
1855
  "List available tenants/clients from the workspace tenancy database. Use this to pick a valid clientId before creating guest tokens or editing customer dashboards.",
1679
1856
  {
1680
- workspaceName: z3.string().optional().describe("Workspace name. Preferred for non-technical callers; the tool resolves it to a workspaceId."),
1681
- workspaceId: z3.string().optional().describe("Technical workspace UUID. Provide this instead of workspaceName if already known."),
1682
- searchValue: z3.string().optional().describe("Optional case-insensitive search string for tenant/client labels."),
1683
- limit: z3.number().int().positive().max(500).optional().describe("Maximum number of tenants to return. Backend may apply connector-specific limits."),
1684
- datasourceId: z3.string().optional().describe("Optional datasource UUID override when the workspace has multiple datasource contexts."),
1685
- datamartId: z3.string().optional().describe("Optional datamart UUID override when tenant lookup should use a specific datamart.")
1857
+ workspaceName: z5.string().optional().describe("Workspace name. Preferred for non-technical callers; the tool resolves it to a workspaceId."),
1858
+ workspaceId: z5.string().optional().describe("Technical workspace UUID. Provide this instead of workspaceName if already known."),
1859
+ searchValue: z5.string().optional().describe("Optional case-insensitive search string for tenant/client labels."),
1860
+ limit: z5.number().int().positive().max(500).optional().describe("Maximum number of tenants to return. Backend may apply connector-specific limits."),
1861
+ datasourceId: z5.string().optional().describe("Optional datasource UUID override when the workspace has multiple datasource contexts."),
1862
+ datamartId: z5.string().optional().describe("Optional datamart UUID override when tenant lookup should use a specific datamart.")
1686
1863
  },
1687
1864
  READ_ONLY,
1688
1865
  async (params) => {
@@ -1776,15 +1953,15 @@ function registerListTenants(server, client) {
1776
1953
  }
1777
1954
 
1778
1955
  // src/tools/data-app/create-data-app.ts
1779
- import { z as z4 } from "zod";
1956
+ import { z as z6 } from "zod";
1780
1957
  function registerCreateDataApp(server, client) {
1781
1958
  server.tool(
1782
1959
  "create_data_app",
1783
1960
  "Create a new data app.",
1784
1961
  {
1785
- name: z4.string().describe("Data app name"),
1786
- workspaceName: z4.string().optional().describe("Optional workspace name if required by backend"),
1787
- body: z4.record(z4.unknown()).optional().describe("Raw API body passthrough for POST /api/v2/data-app/")
1962
+ name: z6.string().describe("Data app name"),
1963
+ workspaceName: z6.string().optional().describe("Optional workspace name if required by backend"),
1964
+ body: z6.record(z6.unknown()).optional().describe("Raw API body passthrough for POST /api/v2/data-app/")
1788
1965
  },
1789
1966
  WRITE_CREATE,
1790
1967
  async (params) => {
@@ -1818,7 +1995,7 @@ function registerCreateDataApp(server, client) {
1818
1995
  }
1819
1996
 
1820
1997
  // src/tools/data-app/list-api-tokens.ts
1821
- import { z as z5 } from "zod";
1998
+ import { z as z7 } from "zod";
1822
1999
 
1823
2000
  // src/utils/resolve-resource.ts
1824
2001
  function resolveResource(options) {
@@ -1887,7 +2064,7 @@ function registerListApiTokens(server, client) {
1887
2064
  "list_api_tokens",
1888
2065
  "List API tokens for a data app. Omit dataAppName to auto-resolve.",
1889
2066
  {
1890
- dataAppName: z5.string().optional().describe("Data app name. Omit to list available data apps.")
2067
+ dataAppName: z7.string().optional().describe("Data app name. Omit to list available data apps.")
1891
2068
  },
1892
2069
  READ_ONLY,
1893
2070
  async (params) => {
@@ -1932,16 +2109,16 @@ function registerListApiTokens(server, client) {
1932
2109
  }
1933
2110
 
1934
2111
  // src/tools/data-app/create-api-token.ts
1935
- import { z as z6 } from "zod";
2112
+ import { z as z8 } from "zod";
1936
2113
  function registerCreateApiToken(server, client) {
1937
2114
  const services = createServiceBundle(client);
1938
2115
  server.tool(
1939
2116
  "create_api_token",
1940
2117
  "Create an API token for a data app and activate it for this session. Omit dataAppName to auto-resolve.",
1941
2118
  {
1942
- dataAppName: z6.string().optional().describe("Data app name. Omit to list available data apps."),
1943
- name: z6.string().optional().describe("Optional token name"),
1944
- body: z6.record(z6.unknown()).optional().describe("Raw API body passthrough for POST /api/v2/data-app/api-tokens")
2119
+ dataAppName: z8.string().optional().describe("Data app name. Omit to list available data apps."),
2120
+ name: z8.string().optional().describe("Optional token name"),
2121
+ body: z8.record(z8.unknown()).optional().describe("Raw API body passthrough for POST /api/v2/data-app/api-tokens")
1945
2122
  },
1946
2123
  WRITE_CREATE,
1947
2124
  async (params) => {
@@ -1994,16 +2171,16 @@ Save this in backend secrets immediately. This value may not be returned again.`
1994
2171
  }
1995
2172
 
1996
2173
  // src/tools/data-app/rotate-api-token.ts
1997
- import { z as z7 } from "zod";
2174
+ import { z as z9 } from "zod";
1998
2175
  function registerRotateApiToken(server, client) {
1999
2176
  const services = createServiceBundle(client);
2000
2177
  server.tool(
2001
2178
  "rotate_api_token",
2002
2179
  "Rotate (invalidate and replace) an API token. Previous token becomes stale.",
2003
2180
  {
2004
- dataAppName: z7.string().optional().describe("Data app name. Omit to list available data apps."),
2005
- tokenId: z7.string().optional().describe("Optional token ID to rotate"),
2006
- body: z7.record(z7.unknown()).optional().describe("Raw API body passthrough for rotate endpoint")
2181
+ dataAppName: z9.string().optional().describe("Data app name. Omit to list available data apps."),
2182
+ tokenId: z9.string().optional().describe("Optional token ID to rotate"),
2183
+ body: z9.record(z9.unknown()).optional().describe("Raw API body passthrough for rotate endpoint")
2007
2184
  },
2008
2185
  DESTRUCTIVE,
2009
2186
  async (params) => {
@@ -2122,14 +2299,14 @@ function registerListDatasources(server, client) {
2122
2299
  }
2123
2300
 
2124
2301
  // src/tools/infrastructure/discover-datasource-schema.ts
2125
- import { z as z8 } from "zod";
2302
+ import { z as z10 } from "zod";
2126
2303
  function registerDiscoverDatasourceSchema(server, client) {
2127
2304
  const services = createServiceBundle(client);
2128
2305
  server.tool(
2129
2306
  "discover_datasource_schema",
2130
2307
  "Inspect tables and columns in a datasource. Omit datasourceName to list available datasources.",
2131
2308
  {
2132
- datasourceName: z8.string().optional().describe(
2309
+ datasourceName: z10.string().optional().describe(
2133
2310
  "Name of the datasource to inspect. Omit to list available datasources."
2134
2311
  )
2135
2312
  },
@@ -2212,13 +2389,13 @@ Fix the connection or add a new database in the **Databrain UI**.`
2212
2389
  }
2213
2390
 
2214
2391
  // src/tools/infrastructure/list-datamarts.ts
2215
- import { z as z9 } from "zod";
2392
+ import { z as z11 } from "zod";
2216
2393
  function registerListDatamarts(server, client) {
2217
2394
  server.tool(
2218
2395
  "list_datamarts",
2219
2396
  "List datamarts with table counts and semantic layer scores.",
2220
2397
  {
2221
- dataAppName: z9.string().optional().describe("Filter by data app name")
2398
+ dataAppName: z11.string().optional().describe("Filter by data app name")
2222
2399
  },
2223
2400
  READ_ONLY,
2224
2401
  async (params) => {
@@ -2307,7 +2484,7 @@ function registerListWorkspaces(server, client) {
2307
2484
  }
2308
2485
 
2309
2486
  // src/tools/infrastructure/create-datamart.ts
2310
- import { z as z10 } from "zod";
2487
+ import { z as z12 } from "zod";
2311
2488
 
2312
2489
  // src/tools/widgets/production-guards.ts
2313
2490
  var APPLY_TO_PRODUCTION_CONFIRMATION = "APPLY_TO_PRODUCTION";
@@ -2325,29 +2502,29 @@ function genericProductionSafetyNote() {
2325
2502
  }
2326
2503
 
2327
2504
  // src/tools/infrastructure/create-datamart.ts
2328
- var columnSchema = z10.object({
2329
- name: z10.string(),
2330
- alias: z10.string().optional(),
2331
- label: z10.string().optional(),
2332
- isHide: z10.boolean().optional(),
2333
- isCustomColumn: z10.boolean().optional(),
2334
- sql: z10.string().optional()
2505
+ var columnSchema = z12.object({
2506
+ name: z12.string(),
2507
+ alias: z12.string().optional(),
2508
+ label: z12.string().optional(),
2509
+ isHide: z12.boolean().optional(),
2510
+ isCustomColumn: z12.boolean().optional(),
2511
+ sql: z12.string().optional()
2335
2512
  });
2336
- var tableSchema = z10.object({
2337
- name: z10.string(),
2338
- schemaName: z10.string().optional(),
2339
- clientColumn: z10.string().optional(),
2340
- label: z10.string().optional(),
2341
- columns: z10.array(columnSchema)
2513
+ var tableSchema = z12.object({
2514
+ name: z12.string(),
2515
+ schemaName: z12.string().optional(),
2516
+ clientColumn: z12.string().optional(),
2517
+ label: z12.string().optional(),
2518
+ columns: z12.array(columnSchema)
2342
2519
  });
2343
- var relationshipSchema = z10.object({
2344
- parentTableName: z10.string(),
2345
- parentColumnName: z10.string(),
2346
- childTableName: z10.string(),
2347
- childColumnName: z10.string(),
2348
- cardinality: z10.enum(["OneToOne", "OneToMany", "ManyToOne", "ManyToMany"]),
2349
- join: z10.enum(["INNER JOIN", "LEFT JOIN", "RIGHT JOIN", "FULL JOIN"]),
2350
- relationshipName: z10.string()
2520
+ var relationshipSchema = z12.object({
2521
+ parentTableName: z12.string(),
2522
+ parentColumnName: z12.string(),
2523
+ childTableName: z12.string(),
2524
+ childColumnName: z12.string(),
2525
+ cardinality: z12.enum(["OneToOne", "OneToMany", "ManyToOne", "ManyToMany"]),
2526
+ join: z12.enum(["INNER JOIN", "LEFT JOIN", "RIGHT JOIN", "FULL JOIN"]),
2527
+ relationshipName: z12.string()
2351
2528
  });
2352
2529
  function datamartSuccessMessage(name, result) {
2353
2530
  return `Datamart "${name}" created successfully (ID: ${result.id || result._id || "UNKNOWN"}).
@@ -2368,21 +2545,21 @@ function registerCreateDatamart(server, client) {
2368
2545
  "create_datamart",
2369
2546
  "Create a production datamart from selected tables and relationships. Defaults to dry-run; apply requires explicit confirmation.",
2370
2547
  {
2371
- mode: z10.enum(["dry_run", "apply"]).default("dry_run").describe("dry_run returns the plan only; apply creates the datamart"),
2372
- confirm: z10.string().optional().describe(`Required for apply: ${APPLY_TO_PRODUCTION_CONFIRMATION}`),
2373
- name: z10.string().describe("Unique datamart name"),
2374
- datasourceName: z10.string().optional().describe("Name of the datasource to use. Omit to list available datasources."),
2375
- tableList: z10.array(tableSchema).optional().describe("Array of tables with their columns"),
2376
- relationships: z10.array(relationshipSchema).optional().describe("Join definitions between tables"),
2377
- tenancySettings: z10.object({
2378
- tenancyLevel: z10.enum(["TABLE", "DATABASE"]).optional(),
2379
- clientColumnType: z10.string().optional(),
2380
- schemaName: z10.string().optional(),
2381
- tableName: z10.string().optional(),
2382
- tableClientNameColumn: z10.string().optional(),
2383
- tablePrimaryKeyColumn: z10.string().optional()
2548
+ mode: z12.enum(["dry_run", "apply"]).default("dry_run").describe("dry_run returns the plan only; apply creates the datamart"),
2549
+ confirm: z12.string().optional().describe(`Required for apply: ${APPLY_TO_PRODUCTION_CONFIRMATION}`),
2550
+ name: z12.string().describe("Unique datamart name"),
2551
+ datasourceName: z12.string().optional().describe("Name of the datasource to use. Omit to list available datasources."),
2552
+ tableList: z12.array(tableSchema).optional().describe("Array of tables with their columns"),
2553
+ relationships: z12.array(relationshipSchema).optional().describe("Join definitions between tables"),
2554
+ tenancySettings: z12.object({
2555
+ tenancyLevel: z12.enum(["TABLE", "DATABASE"]).optional(),
2556
+ clientColumnType: z12.string().optional(),
2557
+ schemaName: z12.string().optional(),
2558
+ tableName: z12.string().optional(),
2559
+ tableClientNameColumn: z12.string().optional(),
2560
+ tablePrimaryKeyColumn: z12.string().optional()
2384
2561
  }).optional().describe("Multi-tenant configuration"),
2385
- body: z10.record(z10.unknown()).optional().describe("Raw API body passthrough for POST /api/v2/data-app/datamarts")
2562
+ body: z12.record(z12.unknown()).optional().describe("Raw API body passthrough for POST /api/v2/data-app/datamarts")
2386
2563
  },
2387
2564
  WRITE_CREATE,
2388
2565
  async (params) => {
@@ -2477,14 +2654,14 @@ function registerCreateDatamart(server, client) {
2477
2654
  }
2478
2655
 
2479
2656
  // src/tools/infrastructure/sync-datasource.ts
2480
- import { z as z11 } from "zod";
2657
+ import { z as z13 } from "zod";
2481
2658
  function registerSyncDatasource(server, client) {
2482
2659
  const datasourcesApi = new DatasourcesApi(client);
2483
2660
  server.tool(
2484
2661
  "sync_datasource",
2485
2662
  "Trigger a datasource schema sync to refresh table and column metadata. If datasourceName is omitted and there are multiple datasources, returns the list so the user can choose.",
2486
2663
  {
2487
- datasourceName: z11.string().optional().describe("Name of the datasource to sync. Omit to list available datasources.")
2664
+ datasourceName: z13.string().optional().describe("Name of the datasource to sync. Omit to list available datasources.")
2488
2665
  },
2489
2666
  WRITE_IDEMPOTENT,
2490
2667
  async (params) => {
@@ -2533,7 +2710,7 @@ The schema metadata will be refreshed. You can now use \`discover_datasource_sch
2533
2710
  }
2534
2711
 
2535
2712
  // src/tools/embed/create-embed.ts
2536
- import { z as z12 } from "zod";
2713
+ import { z as z14 } from "zod";
2537
2714
  var DEFAULT_ACCESS_SETTINGS2 = {
2538
2715
  isAllowMetricCreation: false,
2539
2716
  isAllowMetricDeletion: false,
@@ -2546,18 +2723,18 @@ var DEFAULT_ACCESS_SETTINGS2 = {
2546
2723
  isAllowCreateDashboardView: false,
2547
2724
  metricCreationMode: "DRAG_DROP"
2548
2725
  };
2549
- var accessSettingsSchema = z12.object({
2550
- datamartName: z12.string().describe("Name of the datamart (required)"),
2551
- isAllowMetricCreation: z12.boolean().optional().describe("Allow end-users to create metrics"),
2552
- metricCreationMode: z12.enum(["DRAG_DROP", "CHAT"]).optional().describe("Metric creation mode"),
2553
- isAllowMetricDeletion: z12.boolean().optional().describe("Allow metric deletion"),
2554
- isAllowMetricUpdate: z12.boolean().optional().describe("Allow metric editing"),
2555
- isAllowMetricLayoutChange: z12.boolean().optional().describe("Allow layout changes"),
2556
- isAllowManageMetrics: z12.boolean().optional().describe("Show manage metrics UI"),
2557
- isAllowUnderlyingData: z12.boolean().optional().describe("Allow viewing underlying data"),
2558
- isAllowAiPilot: z12.boolean().optional().describe("Enable AI pilot features"),
2559
- isAllowEmailReports: z12.boolean().optional().describe("Allow email report scheduling"),
2560
- isAllowCreateDashboardView: z12.boolean().optional().describe("Allow creating dashboard views")
2726
+ var accessSettingsSchema = z14.object({
2727
+ datamartName: z14.string().describe("Name of the datamart (required)"),
2728
+ isAllowMetricCreation: z14.boolean().optional().describe("Allow end-users to create metrics"),
2729
+ metricCreationMode: z14.enum(["DRAG_DROP", "CHAT"]).optional().describe("Metric creation mode"),
2730
+ isAllowMetricDeletion: z14.boolean().optional().describe("Allow metric deletion"),
2731
+ isAllowMetricUpdate: z14.boolean().optional().describe("Allow metric editing"),
2732
+ isAllowMetricLayoutChange: z14.boolean().optional().describe("Allow layout changes"),
2733
+ isAllowManageMetrics: z14.boolean().optional().describe("Show manage metrics UI"),
2734
+ isAllowUnderlyingData: z14.boolean().optional().describe("Allow viewing underlying data"),
2735
+ isAllowAiPilot: z14.boolean().optional().describe("Enable AI pilot features"),
2736
+ isAllowEmailReports: z14.boolean().optional().describe("Allow email report scheduling"),
2737
+ isAllowCreateDashboardView: z14.boolean().optional().describe("Allow creating dashboard views")
2561
2738
  }).describe("Embed access settings. Only datamartName is required \u2014 all flags default to false.");
2562
2739
  function registerCreateEmbed(server, client) {
2563
2740
  const services = createServiceBundle(client);
@@ -2565,23 +2742,23 @@ function registerCreateEmbed(server, client) {
2565
2742
  "create_embed",
2566
2743
  "Create an embed. Provide dashboardId, workspaceName, accessSettings.datamartName. Add clientId for multi-tenant per-client dashboards. All isAllow* flags default to false.",
2567
2744
  {
2568
- body: z12.record(z12.unknown()).optional().describe(
2745
+ body: z14.record(z14.unknown()).optional().describe(
2569
2746
  "Raw API body passthrough. If provided, all other fields are ignored."
2570
2747
  ),
2571
- dashboardId: z12.string().optional().describe("Dashboard identifier for embed creation"),
2572
- workspaceName: z12.string().optional().describe("Workspace name. Omit to auto-resolve if only one exists."),
2573
- embedType: z12.enum(["dashboard", "metric"]).optional().describe("Embed type"),
2574
- metricId: z12.string().optional().describe("Required for metric embed type"),
2575
- name: z12.string().optional().describe("Human-readable embed config name"),
2748
+ dashboardId: z14.string().optional().describe("Dashboard identifier for embed creation"),
2749
+ workspaceName: z14.string().optional().describe("Workspace name. Omit to auto-resolve if only one exists."),
2750
+ embedType: z14.enum(["dashboard", "metric"]).optional().describe("Embed type"),
2751
+ metricId: z14.string().optional().describe("Required for metric embed type"),
2752
+ name: z14.string().optional().describe("Human-readable embed config name"),
2576
2753
  accessSettings: accessSettingsSchema.optional(),
2577
2754
  // Multi-tenant (dashboard embed) params
2578
- clientId: z12.string().optional().describe(
2755
+ clientId: z14.string().optional().describe(
2579
2756
  "Client identifier for multi-tenant isolation. When provided, creates a dashboard embed (each client gets their own dashboard copy)."
2580
2757
  ),
2581
- templateDashboardId: z12.string().optional().describe("Template dashboard ID to clone metrics from"),
2582
- isImportMetrics: z12.boolean().optional().describe("Import metrics from template dashboard"),
2583
- metricImportMode: z12.enum(["COPY", "LINK"]).optional().describe("COPY duplicates metrics, LINK shares them"),
2584
- isRenameDashboard: z12.boolean().optional().describe("Rename the dashboard for this client")
2758
+ templateDashboardId: z14.string().optional().describe("Template dashboard ID to clone metrics from"),
2759
+ isImportMetrics: z14.boolean().optional().describe("Import metrics from template dashboard"),
2760
+ metricImportMode: z14.enum(["COPY", "LINK"]).optional().describe("COPY duplicates metrics, LINK shares them"),
2761
+ isRenameDashboard: z14.boolean().optional().describe("Rename the dashboard for this client")
2585
2762
  },
2586
2763
  WRITE_CREATE,
2587
2764
  async (params) => {
@@ -2683,14 +2860,14 @@ Next: run \`get_embed_details\` to verify the embed configuration.`
2683
2860
  }
2684
2861
 
2685
2862
  // src/tools/embed/list-embeds.ts
2686
- import { z as z13 } from "zod";
2863
+ import { z as z15 } from "zod";
2687
2864
  function registerListEmbeds(server, client) {
2688
2865
  const services = createServiceBundle(client);
2689
2866
  server.tool(
2690
2867
  "list_embeds",
2691
2868
  "List embed configurations. Requires an API token (use create_api_token first). Use `list_tenants` for authoritative client discovery from the tenancy database.",
2692
2869
  {
2693
- dataAppName: z13.string().optional().describe("Filter by data app name")
2870
+ dataAppName: z15.string().optional().describe("Filter by data app name")
2694
2871
  },
2695
2872
  READ_ONLY,
2696
2873
  async (params) => {
@@ -2741,14 +2918,14 @@ function registerListEmbeds(server, client) {
2741
2918
  }
2742
2919
 
2743
2920
  // src/tools/embed/get-embed-details.ts
2744
- import { z as z14 } from "zod";
2921
+ import { z as z16 } from "zod";
2745
2922
  function registerGetEmbedDetails(server, client) {
2746
2923
  const services = createServiceBundle(client);
2747
2924
  server.tool(
2748
2925
  "get_embed_details",
2749
2926
  "Get full embed configuration including access settings and theme.",
2750
2927
  {
2751
- embedId: z14.string().describe("ID of the embed")
2928
+ embedId: z16.string().describe("ID of the embed")
2752
2929
  },
2753
2930
  READ_ONLY,
2754
2931
  async (params) => {
@@ -2764,7 +2941,7 @@ function registerGetEmbedDetails(server, client) {
2764
2941
  }
2765
2942
 
2766
2943
  // src/tools/embed/update-embed.ts
2767
- import { z as z15 } from "zod";
2944
+ import { z as z17 } from "zod";
2768
2945
 
2769
2946
  // src/tools/embed/helpers.ts
2770
2947
  var GUEST_TOKEN_REMINDER = "\n\n\u26A0\uFE0F **Guest tokens must be regenerated** for these changes to take effect. Existing guest tokens still carry the old settings. Call `generate_guest_token` to create a new token with the updated configuration.";
@@ -2802,15 +2979,15 @@ function registerUpdateEmbed(server, client) {
2802
2979
  "update_embed",
2803
2980
  "Update embed access settings, permissions, theme, or name.",
2804
2981
  {
2805
- embedId: z15.string().describe("ID of the embed to update"),
2806
- body: z15.record(z15.unknown()).optional().describe(
2982
+ embedId: z17.string().describe("ID of the embed to update"),
2983
+ body: z17.record(z17.unknown()).optional().describe(
2807
2984
  "Raw API body for PUT /api/v2/data-app/embeds. If provided, it is sent directly (passthrough mode)."
2808
2985
  ),
2809
- name: z15.string().optional().describe("New name for the embed"),
2810
- accessSettings: z15.record(z15.unknown()).optional().describe(
2986
+ name: z17.string().optional().describe("New name for the embed"),
2987
+ accessSettings: z17.record(z17.unknown()).optional().describe(
2811
2988
  "Partial update of access settings. See `get_embed_details` for current settings."
2812
2989
  ),
2813
- theme: z15.record(z15.unknown()).optional().describe(
2990
+ theme: z17.record(z17.unknown()).optional().describe(
2814
2991
  "Theme configuration object. See databrain://theme-reference for the full schema."
2815
2992
  )
2816
2993
  },
@@ -2856,7 +3033,7 @@ function registerUpdateEmbed(server, client) {
2856
3033
  }
2857
3034
 
2858
3035
  // src/tools/embed/customize-theme.ts
2859
- import { z as z16 } from "zod";
3036
+ import { z as z18 } from "zod";
2860
3037
  var THEME_PRESETS = {
2861
3038
  light: {
2862
3039
  general: {
@@ -2990,7 +3167,7 @@ var ACCESS_PRESETS = {
2990
3167
  metricCreationMode: "CHAT"
2991
3168
  }
2992
3169
  };
2993
- var fontFamilyEnum = z16.enum([
3170
+ var fontFamilyEnum = z18.enum([
2994
3171
  "Inter",
2995
3172
  "Roboto",
2996
3173
  "Open Sans",
@@ -3002,17 +3179,17 @@ var fontFamilyEnum = z16.enum([
3002
3179
  "Nunito",
3003
3180
  "system-ui"
3004
3181
  ]).describe("Font family");
3005
- var tooltipFontSchema = z16.object({
3006
- fontFamily: z16.string().optional(),
3007
- fontSize: z16.number().optional(),
3008
- fontWeight: z16.number().optional(),
3009
- fontColor: z16.string().optional()
3182
+ var tooltipFontSchema = z18.object({
3183
+ fontFamily: z18.string().optional(),
3184
+ fontSize: z18.number().optional(),
3185
+ fontWeight: z18.number().optional(),
3186
+ fontColor: z18.string().optional()
3010
3187
  }).optional();
3011
- var fontConfigInputSchema = z16.object({
3012
- fontSize: z16.number().optional(),
3013
- fontFamily: z16.string().optional(),
3014
- fontWeight: z16.number().optional(),
3015
- color: z16.string().optional()
3188
+ var fontConfigInputSchema = z18.object({
3189
+ fontSize: z18.number().optional(),
3190
+ fontFamily: z18.string().optional(),
3191
+ fontWeight: z18.number().optional(),
3192
+ color: z18.string().optional()
3016
3193
  }).optional();
3017
3194
  function mapToFrontendFontConfig(input) {
3018
3195
  if (!input) return void 0;
@@ -3023,23 +3200,23 @@ function mapToFrontendFontConfig(input) {
3023
3200
  ...input.color && { color: input.color }
3024
3201
  };
3025
3202
  }
3026
- var axisSchema = z16.object({
3027
- hideAxisLines: z16.boolean().optional().describe("Hide axis lines"),
3028
- hideSplitLines: z16.boolean().optional().describe("Hide grid/split lines"),
3029
- hideAxisLabels: z16.boolean().optional().describe("Hide axis labels"),
3030
- hideAxisTicks: z16.boolean().optional().describe("Hide axis tick marks"),
3031
- axisName: z16.string().optional().describe("Axis title text"),
3032
- axisNameOffset: z16.number().optional().describe("Axis title offset from axis"),
3033
- axisLabelMargin: z16.number().optional().describe("Margin between axis labels and chart area in pixels"),
3034
- fontSize: z16.number().optional().describe("Axis label font size"),
3035
- fontFamily: z16.string().optional().describe("Axis label font family"),
3036
- fontWeight: z16.number().optional().describe("Axis label font weight"),
3037
- color: z16.string().optional().describe("Axis label color (hex)"),
3038
- axisColor: z16.string().optional().describe("Axis line color (hex)"),
3039
- axisNameFontConfig: z16.object({
3040
- fontFamily: z16.string().optional(),
3041
- fontSize: z16.number().optional(),
3042
- fontWeight: z16.number().optional()
3203
+ var axisSchema = z18.object({
3204
+ hideAxisLines: z18.boolean().optional().describe("Hide axis lines"),
3205
+ hideSplitLines: z18.boolean().optional().describe("Hide grid/split lines"),
3206
+ hideAxisLabels: z18.boolean().optional().describe("Hide axis labels"),
3207
+ hideAxisTicks: z18.boolean().optional().describe("Hide axis tick marks"),
3208
+ axisName: z18.string().optional().describe("Axis title text"),
3209
+ axisNameOffset: z18.number().optional().describe("Axis title offset from axis"),
3210
+ axisLabelMargin: z18.number().optional().describe("Margin between axis labels and chart area in pixels"),
3211
+ fontSize: z18.number().optional().describe("Axis label font size"),
3212
+ fontFamily: z18.string().optional().describe("Axis label font family"),
3213
+ fontWeight: z18.number().optional().describe("Axis label font weight"),
3214
+ color: z18.string().optional().describe("Axis label color (hex)"),
3215
+ axisColor: z18.string().optional().describe("Axis line color (hex)"),
3216
+ axisNameFontConfig: z18.object({
3217
+ fontFamily: z18.string().optional(),
3218
+ fontSize: z18.number().optional(),
3219
+ fontWeight: z18.number().optional()
3043
3220
  }).optional().describe("Axis title font configuration")
3044
3221
  }).optional();
3045
3222
  function buildAdminTheme(p, presetBase) {
@@ -3195,94 +3372,94 @@ function registerCustomizeTheme(server, client) {
3195
3372
  "customize_embed_theme",
3196
3373
  `Theme an embed: presets (${Object.keys(THEME_PRESETS).join("/")}), colors, fonts, cards, chart appearance, responsive layout, or access presets (${Object.keys(ACCESS_PRESETS).join("/")}).`,
3197
3374
  {
3198
- embedId: z16.string().describe("ID of the embed to theme"),
3199
- body: z16.record(z16.unknown()).optional().describe(
3375
+ embedId: z18.string().describe("ID of the embed to theme"),
3376
+ body: z18.record(z18.unknown()).optional().describe(
3200
3377
  "Raw API body for PUT /api/v2/data-app/embeds. If provided, sent directly and all convenience fields are ignored."
3201
3378
  ),
3202
3379
  // --- Presets ---
3203
- themePreset: z16.enum(["light", "dark", "corporate", "minimal"]).optional().describe("Apply a theme preset as the base. Granular params below override preset values."),
3204
- accessPreset: z16.enum(["view-only", "power-user", "export-only", "ai-enabled"]).optional().describe("Apply an access settings preset"),
3380
+ themePreset: z18.enum(["light", "dark", "corporate", "minimal"]).optional().describe("Apply a theme preset as the base. Granular params below override preset values."),
3381
+ accessPreset: z18.enum(["view-only", "power-user", "export-only", "ai-enabled"]).optional().describe("Apply an access settings preset"),
3205
3382
  // --- General ---
3206
3383
  fontFamily: fontFamilyEnum.optional().describe("Global font family"),
3207
- datePickerFormat: z16.string().optional().describe("Date picker display format"),
3384
+ datePickerFormat: z18.string().optional().describe("Date picker display format"),
3208
3385
  // --- Colors ---
3209
- primaryColor: z16.string().optional().describe("Primary accent color (hex)"),
3210
- backgroundColor: z16.string().optional().describe("Overall background color (hex)"),
3211
- textColor: z16.string().optional().describe("Default text color (hex)"),
3212
- ctaColor: z16.string().optional().describe("Call-to-action button color (hex)"),
3213
- ctaTextColor: z16.string().optional().describe("CTA button text color (hex)"),
3386
+ primaryColor: z18.string().optional().describe("Primary accent color (hex)"),
3387
+ backgroundColor: z18.string().optional().describe("Overall background color (hex)"),
3388
+ textColor: z18.string().optional().describe("Default text color (hex)"),
3389
+ ctaColor: z18.string().optional().describe("Call-to-action button color (hex)"),
3390
+ ctaTextColor: z18.string().optional().describe("CTA button text color (hex)"),
3214
3391
  // --- Dashboard ---
3215
- dashboardBackgroundColor: z16.string().optional().describe("Dashboard container background (hex)"),
3216
- selectBoxSize: z16.enum(["small", "medium", "large"]).optional().describe("Filter select box size"),
3217
- selectBoxVariant: z16.enum(["floating", "outlined", "standard"]).optional().describe("Filter select box style"),
3218
- selectBoxBorderRadius: z16.string().optional().describe('Select box border radius (e.g. "20px")'),
3219
- selectBoxTextColor: z16.string().optional().describe("Select box text color (hex)"),
3220
- metricCardColor: z16.string().optional().describe("Metric card background color (hex)"),
3392
+ dashboardBackgroundColor: z18.string().optional().describe("Dashboard container background (hex)"),
3393
+ selectBoxSize: z18.enum(["small", "medium", "large"]).optional().describe("Filter select box size"),
3394
+ selectBoxVariant: z18.enum(["floating", "outlined", "standard"]).optional().describe("Filter select box style"),
3395
+ selectBoxBorderRadius: z18.string().optional().describe('Select box border radius (e.g. "20px")'),
3396
+ selectBoxTextColor: z18.string().optional().describe("Select box text color (hex)"),
3397
+ metricCardColor: z18.string().optional().describe("Metric card background color (hex)"),
3221
3398
  // --- Card Title ---
3222
- cardTitleFontSize: z16.string().optional().describe('Card title font size (e.g. "16px")'),
3223
- cardTitleFontWeight: z16.string().optional().describe('Card title font weight (e.g. "600")'),
3224
- cardTitleColor: z16.string().optional().describe("Card title text color (hex)"),
3399
+ cardTitleFontSize: z18.string().optional().describe('Card title font size (e.g. "16px")'),
3400
+ cardTitleFontWeight: z18.string().optional().describe('Card title font weight (e.g. "600")'),
3401
+ cardTitleColor: z18.string().optional().describe("Card title text color (hex)"),
3225
3402
  // --- Card Description ---
3226
- cardDescriptionFontSize: z16.string().optional().describe("Card description font size"),
3227
- cardDescriptionFontWeight: z16.string().optional().describe("Card description font weight"),
3228
- cardDescriptionColor: z16.string().optional().describe("Card description text color (hex)"),
3403
+ cardDescriptionFontSize: z18.string().optional().describe("Card description font size"),
3404
+ cardDescriptionFontWeight: z18.string().optional().describe("Card description font weight"),
3405
+ cardDescriptionColor: z18.string().optional().describe("Card description text color (hex)"),
3229
3406
  // --- Card Customization ---
3230
- cardPadding: z16.string().optional().describe("Card internal padding"),
3231
- cardBorderRadius: z16.string().optional().describe("Card border radius"),
3232
- cardShadow: z16.string().optional().describe("Card box-shadow CSS value"),
3233
- disableShadowOnHover: z16.boolean().optional().describe("Disable shadow on card hover"),
3234
- disableCardStroke: z16.boolean().optional().describe("Remove card border stroke"),
3235
- cardStrokeColor: z16.string().optional().describe("Card border stroke color (hex)"),
3407
+ cardPadding: z18.string().optional().describe("Card internal padding"),
3408
+ cardBorderRadius: z18.string().optional().describe("Card border radius"),
3409
+ cardShadow: z18.string().optional().describe("Card box-shadow CSS value"),
3410
+ disableShadowOnHover: z18.boolean().optional().describe("Disable shadow on card hover"),
3411
+ disableCardStroke: z18.boolean().optional().describe("Remove card border stroke"),
3412
+ cardStrokeColor: z18.string().optional().describe("Card border stroke color (hex)"),
3236
3413
  // --- Chart Colors (admin theme level) ---
3237
- chartFontFamily: z16.string().optional().describe("Font family for chart text"),
3238
- chartFontColor: z16.string().optional().describe("Font color for chart text (hex)"),
3239
- chartColors: z16.array(z16.string()).optional().describe("Array of chart series colors (hex)"),
3240
- chartPaletteName: z16.string().optional().describe("Name for a custom palette"),
3241
- chartPaletteColors: z16.array(z16.string()).optional().describe("9 colors for a custom palette"),
3414
+ chartFontFamily: z18.string().optional().describe("Font family for chart text"),
3415
+ chartFontColor: z18.string().optional().describe("Font color for chart text (hex)"),
3416
+ chartColors: z18.array(z18.string()).optional().describe("Array of chart series colors (hex)"),
3417
+ chartPaletteName: z18.string().optional().describe("Name for a custom palette"),
3418
+ chartPaletteColors: z18.array(z18.string()).optional().describe("9 colors for a custom palette"),
3242
3419
  // --- Chart Tooltip (admin theme level) ---
3243
3420
  tooltipHeader: tooltipFontSchema.describe("Tooltip header font config"),
3244
3421
  tooltipLabel: tooltipFontSchema.describe("Tooltip label font config"),
3245
3422
  tooltipValue: tooltipFontSchema.describe("Tooltip value font config"),
3246
3423
  // --- Component Theme ---
3247
- buttonPrimaryColor: z16.string().optional().describe("Primary button background (hex)"),
3248
- buttonPrimaryTextColor: z16.string().optional().describe("Primary button text (hex)"),
3249
- buttonSecondaryColor: z16.string().optional().describe("Secondary button background (hex)"),
3250
- buttonSecondaryTextColor: z16.string().optional().describe("Secondary button text (hex)"),
3251
- checkboxCheckedColor: z16.string().optional().describe("Checked checkbox color (hex)"),
3252
- checkboxUncheckedColor: z16.string().optional().describe("Unchecked checkbox color (hex)"),
3253
- switchEnabledColor: z16.string().optional().describe("Enabled switch color (hex)"),
3254
- switchDisabledColor: z16.string().optional().describe("Disabled switch color (hex)"),
3255
- breadcrumbFontFamily: z16.string().optional().describe("Drill breadcrumb font family"),
3256
- breadcrumbFontColor: z16.string().optional().describe("Drill breadcrumb font color (hex)"),
3257
- breadcrumbActiveColor: z16.string().optional().describe("Active breadcrumb color (hex)"),
3258
- filterBadgeColor: z16.string().optional().describe("Multi-select filter badge color (hex)"),
3259
- filterBadgeTextColor: z16.string().optional().describe("Filter badge text color (hex)"),
3260
- datePickerColor: z16.string().optional().describe("Date picker accent color (hex)"),
3424
+ buttonPrimaryColor: z18.string().optional().describe("Primary button background (hex)"),
3425
+ buttonPrimaryTextColor: z18.string().optional().describe("Primary button text (hex)"),
3426
+ buttonSecondaryColor: z18.string().optional().describe("Secondary button background (hex)"),
3427
+ buttonSecondaryTextColor: z18.string().optional().describe("Secondary button text (hex)"),
3428
+ checkboxCheckedColor: z18.string().optional().describe("Checked checkbox color (hex)"),
3429
+ checkboxUncheckedColor: z18.string().optional().describe("Unchecked checkbox color (hex)"),
3430
+ switchEnabledColor: z18.string().optional().describe("Enabled switch color (hex)"),
3431
+ switchDisabledColor: z18.string().optional().describe("Disabled switch color (hex)"),
3432
+ breadcrumbFontFamily: z18.string().optional().describe("Drill breadcrumb font family"),
3433
+ breadcrumbFontColor: z18.string().optional().describe("Drill breadcrumb font color (hex)"),
3434
+ breadcrumbActiveColor: z18.string().optional().describe("Active breadcrumb color (hex)"),
3435
+ filterBadgeColor: z18.string().optional().describe("Multi-select filter badge color (hex)"),
3436
+ filterBadgeTextColor: z18.string().optional().describe("Filter badge text color (hex)"),
3437
+ datePickerColor: z18.string().optional().describe("Date picker accent color (hex)"),
3261
3438
  // --- Responsive Breakpoints ---
3262
- breakpointXl: z16.number().optional().describe("XL breakpoint width in px"),
3263
- breakpointLg: z16.number().optional().describe("LG breakpoint width in px"),
3264
- breakpointMd: z16.number().optional().describe("MD breakpoint width in px"),
3265
- breakpointSm: z16.number().optional().describe("SM breakpoint width in px"),
3266
- breakpointXs: z16.number().optional().describe("XS breakpoint width in px"),
3439
+ breakpointXl: z18.number().optional().describe("XL breakpoint width in px"),
3440
+ breakpointLg: z18.number().optional().describe("LG breakpoint width in px"),
3441
+ breakpointMd: z18.number().optional().describe("MD breakpoint width in px"),
3442
+ breakpointSm: z18.number().optional().describe("SM breakpoint width in px"),
3443
+ breakpointXs: z18.number().optional().describe("XS breakpoint width in px"),
3267
3444
  // --- Metric Layout Columns ---
3268
- layoutColsXl: z16.number().optional().describe("Grid columns at XL breakpoint"),
3269
- layoutColsLg: z16.number().optional().describe("Grid columns at LG breakpoint"),
3270
- layoutColsMd: z16.number().optional().describe("Grid columns at MD breakpoint"),
3271
- layoutColsSm: z16.number().optional().describe("Grid columns at SM breakpoint"),
3272
- layoutColsXs: z16.number().optional().describe("Grid columns at XS breakpoint"),
3273
- layoutColsXxs: z16.number().optional().describe("Grid columns at XXS breakpoint"),
3445
+ layoutColsXl: z18.number().optional().describe("Grid columns at XL breakpoint"),
3446
+ layoutColsLg: z18.number().optional().describe("Grid columns at LG breakpoint"),
3447
+ layoutColsMd: z18.number().optional().describe("Grid columns at MD breakpoint"),
3448
+ layoutColsSm: z18.number().optional().describe("Grid columns at SM breakpoint"),
3449
+ layoutColsXs: z18.number().optional().describe("Grid columns at XS breakpoint"),
3450
+ layoutColsXxs: z18.number().optional().describe("Grid columns at XXS breakpoint"),
3274
3451
  // --- Chart Appearance (detailed) ---
3275
3452
  tooltipHeaderStyle: fontConfigInputSchema.describe("Tooltip header: fontSize, fontFamily, fontWeight, color"),
3276
3453
  tooltipLabelStyle: fontConfigInputSchema.describe("Tooltip label: fontSize, fontFamily, fontWeight, color"),
3277
3454
  tooltipValueStyle: fontConfigInputSchema.describe("Tooltip value: fontSize, fontFamily, fontWeight, color"),
3278
- labelPosition: z16.enum(["hidden", "top", "left", "right", "bottom", "inside"]).optional().describe("Data label position on charts"),
3279
- radialLabelPosition: z16.enum(["outside", "inside"]).optional().describe("Label position for radial/pie charts"),
3280
- marginTop: z16.number().optional().describe("Chart top margin in pixels"),
3281
- marginLeft: z16.number().optional().describe("Chart left margin in pixels"),
3282
- marginRight: z16.number().optional().describe("Chart right margin in pixels"),
3283
- marginBottom: z16.number().optional().describe("Chart bottom margin in pixels"),
3284
- legendShow: z16.boolean().optional().describe("Show or hide chart legend"),
3285
- legendPosition: z16.enum([
3455
+ labelPosition: z18.enum(["hidden", "top", "left", "right", "bottom", "inside"]).optional().describe("Data label position on charts"),
3456
+ radialLabelPosition: z18.enum(["outside", "inside"]).optional().describe("Label position for radial/pie charts"),
3457
+ marginTop: z18.number().optional().describe("Chart top margin in pixels"),
3458
+ marginLeft: z18.number().optional().describe("Chart left margin in pixels"),
3459
+ marginRight: z18.number().optional().describe("Chart right margin in pixels"),
3460
+ marginBottom: z18.number().optional().describe("Chart bottom margin in pixels"),
3461
+ legendShow: z18.boolean().optional().describe("Show or hide chart legend"),
3462
+ legendPosition: z18.enum([
3286
3463
  "top-left",
3287
3464
  "top-center",
3288
3465
  "top-right",
@@ -3292,17 +3469,17 @@ function registerCustomizeTheme(server, client) {
3292
3469
  "bottom-center",
3293
3470
  "bottom-right"
3294
3471
  ]).optional().describe("Legend position"),
3295
- legendLayout: z16.enum(["horizontal", "vertical"]).optional().describe("Legend layout direction"),
3296
- legendShape: z16.enum(["circle", "rect", "roundRect", "triangle", "diamond", "arrow", "none"]).optional().describe("Legend icon shape"),
3297
- legendFontSize: z16.number().optional().describe("Legend font size"),
3298
- legendFontWeight: z16.number().optional().describe("Legend font weight"),
3299
- legendFontFamily: z16.string().optional().describe("Legend font family"),
3300
- legendColor: z16.string().optional().describe("Legend text color (hex)"),
3301
- legendTruncateLength: z16.number().optional().describe("Max characters before truncating legend"),
3302
- disableLegendScrolling: z16.boolean().optional().describe("Disable scrolling in legend"),
3303
- enableVariableLegendPosition: z16.boolean().optional().describe("Allow user to drag legend"),
3304
- legendTop: z16.number().optional().describe("Custom legend top offset"),
3305
- legendLeft: z16.number().optional().describe("Custom legend left offset"),
3472
+ legendLayout: z18.enum(["horizontal", "vertical"]).optional().describe("Legend layout direction"),
3473
+ legendShape: z18.enum(["circle", "rect", "roundRect", "triangle", "diamond", "arrow", "none"]).optional().describe("Legend icon shape"),
3474
+ legendFontSize: z18.number().optional().describe("Legend font size"),
3475
+ legendFontWeight: z18.number().optional().describe("Legend font weight"),
3476
+ legendFontFamily: z18.string().optional().describe("Legend font family"),
3477
+ legendColor: z18.string().optional().describe("Legend text color (hex)"),
3478
+ legendTruncateLength: z18.number().optional().describe("Max characters before truncating legend"),
3479
+ disableLegendScrolling: z18.boolean().optional().describe("Disable scrolling in legend"),
3480
+ enableVariableLegendPosition: z18.boolean().optional().describe("Allow user to drag legend"),
3481
+ legendTop: z18.number().optional().describe("Custom legend top offset"),
3482
+ legendLeft: z18.number().optional().describe("Custom legend left offset"),
3306
3483
  verticalAxis: axisSchema.describe("Vertical (Y) axis configuration"),
3307
3484
  horizontalAxis: axisSchema.describe("Horizontal (X) axis configuration")
3308
3485
  },
@@ -3377,7 +3554,7 @@ Use \`get_embed_details\` to view the full current theme configuration.` + GUEST
3377
3554
  }
3378
3555
 
3379
3556
  // src/tools/embed/get-demo-link.ts
3380
- import { z as z17 } from "zod";
3557
+ import { z as z19 } from "zod";
3381
3558
  var HOUR_MS = 60 * 60 * 1e3;
3382
3559
  var DEFAULT_EXPIRY_HOURS = 24;
3383
3560
  var MAX_EXPIRY_HOURS = 24 * 30;
@@ -3387,11 +3564,11 @@ function registerGetDemoLink(server, client) {
3387
3564
  "get_demo_link",
3388
3565
  `Get a shareable demo URL for a dashboard embed scoped to a specific clientId \u2014 same link the UI's "Share Demo Link" generates. Loads the dashboard as that end-customer sees it. Use to verify ops-built widgets without a test app.`,
3389
3566
  {
3390
- clientId: z17.string().describe("End-customer identifier to scope the preview to."),
3391
- dashboardName: z17.string().optional().describe("Dashboard name (non-technical). Preferred \u2014 pass with optional `workspaceName`."),
3392
- workspaceName: z17.string().optional().describe("Workspace name. Only needed if `dashboardName` is ambiguous."),
3393
- embedId: z17.string().optional().describe("Technical alternative to `dashboardName`."),
3394
- expiryHours: z17.number().min(1).max(MAX_EXPIRY_HOURS).optional().describe(`Token TTL in hours. Defaults to ${DEFAULT_EXPIRY_HOURS}. Max ${MAX_EXPIRY_HOURS} (30 days).`)
3567
+ clientId: z19.string().describe("End-customer identifier to scope the preview to."),
3568
+ dashboardName: z19.string().optional().describe("Dashboard name (non-technical). Preferred \u2014 pass with optional `workspaceName`."),
3569
+ workspaceName: z19.string().optional().describe("Workspace name. Only needed if `dashboardName` is ambiguous."),
3570
+ embedId: z19.string().optional().describe("Technical alternative to `dashboardName`."),
3571
+ expiryHours: z19.number().min(1).max(MAX_EXPIRY_HOURS).optional().describe(`Token TTL in hours. Defaults to ${DEFAULT_EXPIRY_HOURS}. Max ${MAX_EXPIRY_HOURS} (30 days).`)
3395
3572
  },
3396
3573
  WRITE_CREATE,
3397
3574
  async (params) => {
@@ -3447,70 +3624,70 @@ function registerGetDemoLink(server, client) {
3447
3624
  }
3448
3625
 
3449
3626
  // src/tools/frontend/generate-guest-token.ts
3450
- import { z as z18 } from "zod";
3627
+ import { z as z20 } from "zod";
3451
3628
  function registerGenerateGuestToken(server, client) {
3452
3629
  const services = createServiceBundle(client);
3453
3630
  server.tool(
3454
3631
  "generate_guest_token",
3455
3632
  "Generate a guest token for frontend embedding. Requires clientId. Omit dataAppName to auto-resolve.",
3456
3633
  {
3457
- clientId: z18.string().describe('Unique end-user identifier for multi-tenant filtering. Use "None" if no tenancy.'),
3458
- dataAppName: z18.string().optional().describe("Name of the data app. Omit to list available data apps."),
3459
- body: z18.record(z18.unknown()).optional().describe(
3634
+ clientId: z20.string().describe('Unique end-user identifier for multi-tenant filtering. Use "None" if no tenancy.'),
3635
+ dataAppName: z20.string().optional().describe("Name of the data app. Omit to list available data apps."),
3636
+ body: z20.record(z20.unknown()).optional().describe(
3460
3637
  "Raw API body for POST /api/v2/guest-token/create. If provided, sent directly and convenience fields are ignored."
3461
3638
  ),
3462
- params: z18.object({
3463
- allowedEmbeds: z18.array(z18.string()).optional().describe("Restrict token to specific embed IDs"),
3464
- rlsSettings: z18.array(z18.object({
3465
- metricId: z18.string().describe("Metric ID"),
3466
- values: z18.record(z18.unknown()).describe("RLS values by column name")
3639
+ params: z20.object({
3640
+ allowedEmbeds: z20.array(z20.string()).optional().describe("Restrict token to specific embed IDs"),
3641
+ rlsSettings: z20.array(z20.object({
3642
+ metricId: z20.string().describe("Metric ID"),
3643
+ values: z20.record(z20.unknown()).describe("RLS values by column name")
3467
3644
  })).optional().describe("Legacy alias used in docs/examples; forwarded as params.rlsSettings"),
3468
- appFilters: z18.array(z18.object({
3469
- metricId: z18.string().describe("Metric ID"),
3470
- values: z18.record(z18.unknown()).describe("Filter values by column name")
3645
+ appFilters: z20.array(z20.object({
3646
+ metricId: z20.string().describe("Metric ID"),
3647
+ values: z20.record(z20.unknown()).describe("Filter values by column name")
3471
3648
  })).optional().describe("Metric-level app filters"),
3472
- dashboardAppFilters: z18.array(z18.object({
3473
- dashboardId: z18.string().describe("Dashboard ID"),
3474
- values: z18.record(z18.unknown()).describe("Filter values by dashboard filter name"),
3475
- isShowOnUrl: z18.boolean().optional().describe("Whether filters are shown in URL params")
3649
+ dashboardAppFilters: z20.array(z20.object({
3650
+ dashboardId: z20.string().describe("Dashboard ID"),
3651
+ values: z20.record(z20.unknown()).describe("Filter values by dashboard filter name"),
3652
+ isShowOnUrl: z20.boolean().optional().describe("Whether filters are shown in URL params")
3476
3653
  })).optional().describe("Dashboard-level app filters"),
3477
- hideDashboardFilters: z18.array(z18.string()).optional().describe("Dashboard filter names to hide"),
3478
- userIdentifier: z18.string().optional().describe("End-user identifier for private metrics support"),
3479
- timezone: z18.string().optional().describe('IANA timezone, e.g. "America/New_York"')
3654
+ hideDashboardFilters: z20.array(z20.string()).optional().describe("Dashboard filter names to hide"),
3655
+ userIdentifier: z20.string().optional().describe("End-user identifier for private metrics support"),
3656
+ timezone: z20.string().optional().describe('IANA timezone, e.g. "America/New_York"')
3480
3657
  }).optional().describe("Advanced token params"),
3481
3658
  // Legacy convenience fields (auto-mapped into params for backward compatibility)
3482
- timezone: z18.string().optional().describe("Legacy: moved under params.timezone"),
3483
- allowedEmbeds: z18.array(z18.string()).optional().describe("Legacy: moved under params.allowedEmbeds"),
3484
- rlsSettings: z18.array(z18.object({
3485
- metricId: z18.string().describe("Metric ID"),
3486
- values: z18.record(z18.unknown()).describe("RLS values by column name")
3659
+ timezone: z20.string().optional().describe("Legacy: moved under params.timezone"),
3660
+ allowedEmbeds: z20.array(z20.string()).optional().describe("Legacy: moved under params.allowedEmbeds"),
3661
+ rlsSettings: z20.array(z20.object({
3662
+ metricId: z20.string().describe("Metric ID"),
3663
+ values: z20.record(z20.unknown()).describe("RLS values by column name")
3487
3664
  })).optional().describe("Legacy: moved under params.rlsSettings"),
3488
- appFilters: z18.array(z18.object({
3489
- metricId: z18.string().describe("Metric ID"),
3490
- values: z18.record(z18.unknown()).describe("Filter values by column name")
3665
+ appFilters: z20.array(z20.object({
3666
+ metricId: z20.string().describe("Metric ID"),
3667
+ values: z20.record(z20.unknown()).describe("Filter values by column name")
3491
3668
  })).optional().describe("Legacy: moved under params.appFilters"),
3492
- dashboardAppFilters: z18.array(z18.object({
3493
- dashboardId: z18.string().describe("Dashboard ID to apply filters to"),
3494
- values: z18.record(z18.unknown()).describe("Filter values for this dashboard"),
3495
- isShowOnUrl: z18.boolean().optional().describe("Whether filters are shown in URL params")
3669
+ dashboardAppFilters: z20.array(z20.object({
3670
+ dashboardId: z20.string().describe("Dashboard ID to apply filters to"),
3671
+ values: z20.record(z20.unknown()).describe("Filter values for this dashboard"),
3672
+ isShowOnUrl: z20.boolean().optional().describe("Whether filters are shown in URL params")
3496
3673
  })).optional().describe("Legacy: moved under params.dashboardAppFilters"),
3497
- permissions: z18.object({
3498
- isEnableArchiveMetrics: z18.boolean().optional(),
3499
- isEnableManageMetrics: z18.boolean().optional(),
3500
- isEnableCreateDashboardView: z18.boolean().optional(),
3501
- isEnableMetricUpdation: z18.boolean().optional(),
3502
- isEnableCustomizeLayout: z18.boolean().optional(),
3503
- isEnableUnderlyingData: z18.boolean().optional(),
3504
- isEnableDownloadMetrics: z18.boolean().optional(),
3505
- isShowSideBar: z18.boolean().optional(),
3506
- isShowDashboardName: z18.boolean().optional(),
3507
- isDisableMetricCreation: z18.boolean().optional()
3674
+ permissions: z20.object({
3675
+ isEnableArchiveMetrics: z20.boolean().optional(),
3676
+ isEnableManageMetrics: z20.boolean().optional(),
3677
+ isEnableCreateDashboardView: z20.boolean().optional(),
3678
+ isEnableMetricUpdation: z20.boolean().optional(),
3679
+ isEnableCustomizeLayout: z20.boolean().optional(),
3680
+ isEnableUnderlyingData: z20.boolean().optional(),
3681
+ isEnableDownloadMetrics: z20.boolean().optional(),
3682
+ isShowSideBar: z20.boolean().optional(),
3683
+ isShowDashboardName: z20.boolean().optional(),
3684
+ isDisableMetricCreation: z20.boolean().optional()
3508
3685
  }).optional().describe("Runtime permission overrides (merge with and override embed-level settings)"),
3509
- theme: z18.record(z18.unknown()).optional().describe("Runtime theme overrides (overrides embed-level theme)"),
3510
- hideDashboardFilters: z18.array(z18.string()).optional().describe("Legacy: moved under params.hideDashboardFilters"),
3511
- userIdentifier: z18.string().optional().describe("Legacy: moved under params.userIdentifier"),
3512
- expiryTime: z18.number().optional().describe("Token TTL in milliseconds"),
3513
- datasourceName: z18.string().optional().describe("Datasource name for multi-datasource routing")
3686
+ theme: z20.record(z20.unknown()).optional().describe("Runtime theme overrides (overrides embed-level theme)"),
3687
+ hideDashboardFilters: z20.array(z20.string()).optional().describe("Legacy: moved under params.hideDashboardFilters"),
3688
+ userIdentifier: z20.string().optional().describe("Legacy: moved under params.userIdentifier"),
3689
+ expiryTime: z20.number().optional().describe("Token TTL in milliseconds"),
3690
+ datasourceName: z20.string().optional().describe("Datasource name for multi-datasource routing")
3514
3691
  },
3515
3692
  WRITE_CREATE,
3516
3693
  async (params) => {
@@ -3563,7 +3740,7 @@ Next step: Use \`generate_embed_code\` to get copy-paste-ready frontend code.`
3563
3740
  }
3564
3741
 
3565
3742
  // src/tools/frontend/generate-embed-code.ts
3566
- import { z as z19 } from "zod";
3743
+ import { z as z21 } from "zod";
3567
3744
 
3568
3745
  // src/templates/react.ts
3569
3746
  function kebabCase(str) {
@@ -4559,22 +4736,22 @@ function registerGenerateEmbedCode(server, _client) {
4559
4736
  "generate_embed_code",
4560
4737
  "Generate framework-specific embed code (React, Next.js, Vue, Angular, Svelte, SolidJS, vanilla HTML).",
4561
4738
  {
4562
- embedId: z19.string().describe("The embed ID to generate code for"),
4563
- framework: z19.enum(FRAMEWORKS).describe("Frontend framework"),
4564
- embedType: z19.enum(["dashboard", "metric"]).optional().default("dashboard"),
4565
- options: z19.object({
4566
- enableDownloadCsv: z19.boolean().optional(),
4567
- enableEmailCsv: z19.boolean().optional(),
4568
- enableDownloadAllMetrics: z19.boolean().optional(),
4569
- enableDownloadAllPdf: z19.boolean().optional(),
4570
- disableFullscreen: z19.boolean().optional(),
4571
- isHideTablePreview: z19.boolean().optional(),
4572
- isHideChartSettings: z19.boolean().optional(),
4573
- isStickyDashboardFilters: z19.boolean().optional(),
4574
- enableMultiMetricFilters: z19.boolean().optional(),
4575
- themeName: z19.string().optional(),
4576
- customTheme: z19.record(z19.unknown()).optional(),
4577
- optionsIcon: z19.enum(["kebab-menu-vertical", "download"]).optional()
4739
+ embedId: z21.string().describe("The embed ID to generate code for"),
4740
+ framework: z21.enum(FRAMEWORKS).describe("Frontend framework"),
4741
+ embedType: z21.enum(["dashboard", "metric"]).optional().default("dashboard"),
4742
+ options: z21.object({
4743
+ enableDownloadCsv: z21.boolean().optional(),
4744
+ enableEmailCsv: z21.boolean().optional(),
4745
+ enableDownloadAllMetrics: z21.boolean().optional(),
4746
+ enableDownloadAllPdf: z21.boolean().optional(),
4747
+ disableFullscreen: z21.boolean().optional(),
4748
+ isHideTablePreview: z21.boolean().optional(),
4749
+ isHideChartSettings: z21.boolean().optional(),
4750
+ isStickyDashboardFilters: z21.boolean().optional(),
4751
+ enableMultiMetricFilters: z21.boolean().optional(),
4752
+ themeName: z21.string().optional(),
4753
+ customTheme: z21.record(z21.unknown()).optional(),
4754
+ optionsIcon: z21.enum(["kebab-menu-vertical", "download"]).optional()
4578
4755
  }).optional()
4579
4756
  },
4580
4757
  READ_ONLY,
@@ -4614,17 +4791,17 @@ ${generated.instructions}`;
4614
4791
  }
4615
4792
 
4616
4793
  // src/tools/analytics/list-dashboards.ts
4617
- import { z as z20 } from "zod";
4794
+ import { z as z22 } from "zod";
4618
4795
  function registerListDashboards(server, client) {
4619
4796
  const services = createServiceBundle(client);
4620
4797
  server.tool(
4621
4798
  "list_dashboards",
4622
4799
  "List dashboards globally or for a specific data app.",
4623
4800
  {
4624
- scope: z20.enum(["auto", "global", "data_app"]).optional().describe(
4801
+ scope: z22.enum(["auto", "global", "data_app"]).optional().describe(
4625
4802
  "Dashboard listing scope. auto: use data_app when dataAppName + API token are available, otherwise global."
4626
4803
  ),
4627
- dataAppName: z20.string().optional().describe("Data app name for data_app scope. Ignored for global scope.")
4804
+ dataAppName: z22.string().optional().describe("Data app name for data_app scope. Ignored for global scope.")
4628
4805
  },
4629
4806
  READ_ONLY,
4630
4807
  async (params) => {
@@ -4659,36 +4836,36 @@ function registerListDashboards(server, client) {
4659
4836
  }
4660
4837
 
4661
4838
  // src/tools/dashboard/schema.ts
4662
- import { z as z21 } from "zod";
4663
- var dashboardPositionSchema = z21.object({
4664
- x: z21.number().int().min(0).max(23),
4665
- y: z21.number().int().min(0),
4666
- w: z21.number().int().min(1).max(24),
4667
- h: z21.number().int().min(1).max(40)
4839
+ import { z as z23 } from "zod";
4840
+ var dashboardPositionSchema = z23.object({
4841
+ x: z23.number().int().min(0).max(23),
4842
+ y: z23.number().int().min(0),
4843
+ w: z23.number().int().min(1).max(24),
4844
+ h: z23.number().int().min(1).max(40)
4668
4845
  }).strict();
4669
- var dashboardChartSchema = z21.object({
4670
- type: z21.string(),
4671
- metricRef: z21.string().optional(),
4672
- query: z21.string().optional(),
4673
- companyIntegrationId: z21.string().optional(),
4674
- chartOptions: z21.record(z21.unknown()).optional()
4846
+ var dashboardChartSchema = z23.object({
4847
+ type: z23.string(),
4848
+ metricRef: z23.string().optional(),
4849
+ query: z23.string().optional(),
4850
+ companyIntegrationId: z23.string().optional(),
4851
+ chartOptions: z23.record(z23.unknown()).optional()
4675
4852
  }).passthrough();
4676
- var dashboardTileSchema = z21.object({
4677
- id: z21.string().regex(/^[a-z0-9][a-z0-9-]{0,62}$/),
4678
- kind: z21.literal("databrain-chart"),
4853
+ var dashboardTileSchema = z23.object({
4854
+ id: z23.string().regex(/^[a-z0-9][a-z0-9-]{0,62}$/),
4855
+ kind: z23.literal("databrain-chart"),
4679
4856
  position: dashboardPositionSchema,
4680
- title: z21.string().min(1).max(200),
4857
+ title: z23.string().min(1).max(200),
4681
4858
  chart: dashboardChartSchema.optional()
4682
4859
  }).strict();
4683
4860
  var dashboardDocumentShape = {
4684
- schemaVersion: z21.literal(1),
4685
- title: z21.string().min(1).max(200),
4686
- description: z21.string().max(2e3).optional(),
4687
- layout: z21.object({ columns: z21.union([z21.literal(12), z21.literal(24)]).default(24) }).strict().optional(),
4688
- tiles: z21.array(dashboardTileSchema).min(1).max(50)
4861
+ schemaVersion: z23.literal(1),
4862
+ title: z23.string().min(1).max(200),
4863
+ description: z23.string().max(2e3).optional(),
4864
+ layout: z23.object({ columns: z23.union([z23.literal(12), z23.literal(24)]).default(24) }).strict().optional(),
4865
+ tiles: z23.array(dashboardTileSchema).min(1).max(50)
4689
4866
  };
4690
- var workspaceNameSchema = z21.string().min(1).describe("Target workspace name");
4691
- var idempotencyKeySchema = z21.string().regex(
4867
+ var workspaceNameSchema = z23.string().min(1).describe("Target workspace name");
4868
+ var idempotencyKeySchema = z23.string().regex(
4692
4869
  /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,
4693
4870
  "idempotencyKey must be a UUID v4"
4694
4871
  ).describe("UUID v4 unique to this workspace dashboard create request");
@@ -4741,7 +4918,7 @@ ${stringify(validation)}`
4741
4918
  }
4742
4919
 
4743
4920
  // src/tools/dashboard/generate-dashboard-tiles.ts
4744
- import { z as z22 } from "zod";
4921
+ import { z as z24 } from "zod";
4745
4922
  function registerGenerateDashboardTiles(server, client) {
4746
4923
  const services = createServiceBundle(client);
4747
4924
  server.tool(
@@ -4749,15 +4926,15 @@ function registerGenerateDashboardTiles(server, client) {
4749
4926
  "Generate multiple workspace dashboard tile drafts without persisting them.",
4750
4927
  {
4751
4928
  workspaceName: workspaceNameSchema,
4752
- dataAppName: z22.string().optional().describe("Data app in the workspace; auto-resolved when unique"),
4753
- integrationId: z22.string().optional().describe("Datasource UUID override"),
4754
- integrationName: z22.string().optional().describe("Datasource name override"),
4755
- tiles: z22.array(
4756
- z22.object({
4757
- id: z22.string().regex(/^[a-z0-9][a-z0-9-]{0,62}$/),
4758
- title: z22.string().min(1).max(200),
4929
+ dataAppName: z24.string().optional().describe("Data app in the workspace; auto-resolved when unique"),
4930
+ integrationId: z24.string().optional().describe("Datasource UUID override"),
4931
+ integrationName: z24.string().optional().describe("Datasource name override"),
4932
+ tiles: z24.array(
4933
+ z24.object({
4934
+ id: z24.string().regex(/^[a-z0-9][a-z0-9-]{0,62}$/),
4935
+ title: z24.string().min(1).max(200),
4759
4936
  position: dashboardPositionSchema,
4760
- userInputs: z22.record(z22.unknown())
4937
+ userInputs: z24.record(z24.unknown())
4761
4938
  }).strict()
4762
4939
  ).min(1).max(50)
4763
4940
  },
@@ -4841,14 +5018,14 @@ function registerGenerateDashboardTiles(server, client) {
4841
5018
  }
4842
5019
 
4843
5020
  // src/tools/dashboard/get-dashboard.ts
4844
- import { z as z23 } from "zod";
5021
+ import { z as z25 } from "zod";
4845
5022
  function registerGetDashboard(server, client) {
4846
5023
  server.tool(
4847
5024
  "get_dashboard",
4848
5025
  "Retrieve a workspace dashboard projected back into the versioned tile-list contract.",
4849
5026
  {
4850
5027
  workspaceName: workspaceNameSchema,
4851
- dashboardId: z23.string().min(1).describe("Dashboard identifier returned by create_dashboard")
5028
+ dashboardId: z25.string().min(1).describe("Dashboard identifier returned by create_dashboard")
4852
5029
  },
4853
5030
  READ_ONLY,
4854
5031
  async (params) => {
@@ -4872,7 +5049,7 @@ function registerGetDashboard(server, client) {
4872
5049
  }
4873
5050
 
4874
5051
  // src/tools/dashboard/dashboard-snapshot.ts
4875
- import { z as z24 } from "zod";
5052
+ import { z as z26 } from "zod";
4876
5053
  var SNAPSHOT_REQUEST_MS = 45e3;
4877
5054
  function registerDashboardSnapshot(server, client) {
4878
5055
  server.tool(
@@ -4880,10 +5057,10 @@ function registerDashboardSnapshot(server, client) {
4880
5057
  "Get a PNG picture of a dashboard, or of one chart on it (metricId), as the signed-in user sees it in Databrain. Light or dark, 480 to 1600 px wide. Needs a Databrain sign-in (OAuth), not a service token.",
4881
5058
  {
4882
5059
  workspaceName: workspaceNameSchema.optional(),
4883
- dashboardId: z24.string().min(1).max(200).optional().describe("Dashboard id from list_dashboards. Needed unless metricId is given."),
4884
- metricId: z24.string().min(1).max(200).optional().describe("One chart (metric) id: draw only that chart, from a dashboard it is on."),
4885
- theme: z24.enum(["light", "dark"]).default("light").describe("Picture colours"),
4886
- width: z24.number().int().min(480).max(1600).default(1200).describe("Picture width in pixels")
5060
+ dashboardId: z26.string().min(1).max(200).optional().describe("Dashboard id from list_dashboards. Needed unless metricId is given."),
5061
+ metricId: z26.string().min(1).max(200).optional().describe("One chart (metric) id: draw only that chart, from a dashboard it is on."),
5062
+ theme: z26.enum(["light", "dark"]).default("light").describe("Picture colours"),
5063
+ width: z26.number().int().min(480).max(1600).default(1200).describe("Picture width in pixels")
4887
5064
  },
4888
5065
  READ_ONLY,
4889
5066
  async (params) => {
@@ -4928,18 +5105,18 @@ function registerDashboardSnapshot(server, client) {
4928
5105
 
4929
5106
  // src/apps/preview.ts
4930
5107
  import { createHash } from "crypto";
4931
- import { z as z25 } from "zod";
4932
- var draftSchema = z25.object({
4933
- question: z25.string().min(1).max(2e3),
4934
- sql: z25.string().min(1).max(2e4),
4935
- datamartName: z25.string().min(1).max(256),
4936
- dimensions: z25.array(z25.string().max(128)).max(20).default([]),
4937
- measures: z25.array(z25.string().max(128)).max(20).default([]),
4938
- chartType: z25.string().min(1).max(80),
4939
- title: z25.string().min(1).max(200),
4940
- sessionId: z25.string().max(256).optional(),
5108
+ import { z as z27 } from "zod";
5109
+ var draftSchema = z27.object({
5110
+ question: z27.string().min(1).max(2e3),
5111
+ sql: z27.string().min(1).max(2e4),
5112
+ datamartName: z27.string().min(1).max(256),
5113
+ dimensions: z27.array(z27.string().max(128)).max(20).default([]),
5114
+ measures: z27.array(z27.string().max(128)).max(20).default([]),
5115
+ chartType: z27.string().min(1).max(80),
5116
+ title: z27.string().min(1).max(200),
5117
+ sessionId: z27.string().max(256).optional(),
4941
5118
  /** Workspaces built on this datamart. One means Save needs no choice. */
4942
- workspaces: z25.array(z25.string().max(256)).max(50).default([])
5119
+ workspaces: z27.array(z27.string().max(256)).max(50).default([])
4943
5120
  }).strict();
4944
5121
  var PREVIEW_PATH = "/api/v2/data-app/chart-preview";
4945
5122
  var METRIC_PATH = "/api/mcp/metrics/create";
@@ -5066,7 +5243,7 @@ async function saveDraftAsDashboard(client, draft, input) {
5066
5243
  }
5067
5244
 
5068
5245
  // src/tools/query/ask-question.ts
5069
- import { z as z26 } from "zod";
5246
+ import { z as z28 } from "zod";
5070
5247
 
5071
5248
  // src/tools/query/answer-format.ts
5072
5249
  function formatConfidence(value) {
@@ -5123,16 +5300,16 @@ function registerAskQuestion(server, client) {
5123
5300
  "ask_question",
5124
5301
  "Ask a natural language question \u2014 converts to SQL, returns data + chart suggestion. Requires datamartName with a populated semantic layer.",
5125
5302
  {
5126
- question: z26.string().describe(
5303
+ question: z28.string().describe(
5127
5304
  'The natural language question to ask (e.g. "What was total revenue last month?")'
5128
5305
  ),
5129
- datamartName: z26.string().optional().describe(
5306
+ datamartName: z28.string().optional().describe(
5130
5307
  "Name of the datamart to query. Use `list_datamarts` to find available names. REQUIRED unless exactly one datamart exists (auto-resolved). Do NOT pass a workspace name here."
5131
5308
  ),
5132
- sessionId: z26.string().optional().describe(
5309
+ sessionId: z28.string().optional().describe(
5133
5310
  "Session ID from a previous ask_question response, for follow-up questions."
5134
5311
  ),
5135
- timezone: z26.string().optional().describe('IANA timezone (e.g. "America/New_York"). Defaults to UTC.')
5312
+ timezone: z28.string().optional().describe('IANA timezone (e.g. "America/New_York"). Defaults to UTC.')
5136
5313
  },
5137
5314
  WRITE_CREATE,
5138
5315
  async (params) => {
@@ -5332,14 +5509,14 @@ To fix this:
5332
5509
  }
5333
5510
 
5334
5511
  // src/tools/query/get-semantic-layer.ts
5335
- import { z as z27 } from "zod";
5512
+ import { z as z29 } from "zod";
5336
5513
  function registerGetSemanticLayer(server, client) {
5337
5514
  const services = createServiceBundle(client);
5338
5515
  server.tool(
5339
5516
  "get_semantic_layer",
5340
5517
  "Get semantic layer metadata for a datamart: table/column descriptions, synonyms, completion score. Omit datamartName to auto-resolve.",
5341
5518
  {
5342
- datamartName: z27.string().optional().describe(
5519
+ datamartName: z29.string().optional().describe(
5343
5520
  "Name of the datamart to inspect. Omit to list available datamarts."
5344
5521
  )
5345
5522
  },
@@ -5449,7 +5626,7 @@ ${result.feedback}`);
5449
5626
  }
5450
5627
 
5451
5628
  // src/tools/query/semantic-model.ts
5452
- import { z as z28 } from "zod";
5629
+ import { z as z30 } from "zod";
5453
5630
 
5454
5631
  // src/services/semantic-source.ts
5455
5632
  import { parseDocument, stringify as stringify2 } from "yaml";
@@ -5649,21 +5826,21 @@ function retrieveSemanticSource(source2, question, k) {
5649
5826
  }
5650
5827
 
5651
5828
  // src/tools/query/semantic-model.ts
5652
- var datamartId = z28.string().trim().min(1).max(256).describe("Datamart ID from list_datamarts.");
5653
- var source = z28.string().min(1).max(2e6).describe("Complete proposed semantic model as YAML.");
5654
- var entityKind = z28.enum(["table", "column", "measure", "metric", "join", "entity", "glossary", "saved_query", "instruction", "access_rule"]);
5829
+ var datamartId = z30.string().trim().min(1).max(256).describe("Datamart ID from list_datamarts.");
5830
+ var source = z30.string().min(1).max(2e6).describe("Complete proposed semantic model as YAML.");
5831
+ var entityKind = z30.enum(["table", "column", "measure", "metric", "join", "entity", "glossary", "saved_query", "instruction", "access_rule"]);
5655
5832
  var changeInputs = {
5656
5833
  source: source.optional(),
5657
- yaml_patch: z28.string().min(1).max(2e6).optional().describe("YAML mapping merged into the pulled model. Named lists merge by name. Other lists replace. Null removes a field. An empty list clears it."),
5658
- change: z28.object({
5659
- operation: z28.enum(["upsert", "remove"]),
5834
+ yaml_patch: z30.string().min(1).max(2e6).optional().describe("YAML mapping merged into the pulled model. Named lists merge by name. Other lists replace. Null removes a field. An empty list clears it."),
5835
+ change: z30.object({
5836
+ operation: z30.enum(["upsert", "remove"]),
5660
5837
  kind: entityKind,
5661
- name: z28.string().trim().min(1),
5662
- table: z28.string().trim().min(1).optional().describe("Required for columns. Use the table name and an unqualified column name."),
5663
- value: z28.record(z28.unknown()).optional().describe("Fields to merge for upsert. Omit for remove.")
5838
+ name: z30.string().trim().min(1),
5839
+ table: z30.string().trim().min(1).optional().describe("Required for columns. Use the table name and an unqualified column name."),
5840
+ value: z30.record(z30.unknown()).optional().describe("Fields to merge for upsert. Omit for remove.")
5664
5841
  }).strict().optional().describe("One named entity change. Supply exactly one of source, yaml_patch or change.")
5665
5842
  };
5666
- var expectedHash = z28.string().trim().min(1).nullable().optional().describe("Stored content_hash from the reviewed proposal. Null explicitly means the first apply. Required when dry_run is false.");
5843
+ var expectedHash = z30.string().trim().min(1).nullable().optional().describe("Stored content_hash from the reviewed proposal. Null explicitly means the first apply. Required when dry_run is false.");
5667
5844
  function errorCode(error) {
5668
5845
  const nested = isObject(error.details) && isObject(error.details.error) ? error.details.error : void 0;
5669
5846
  return typeof nested?.code === "string" ? nested.code : error.code;
@@ -5722,7 +5899,7 @@ function registerSearchSemanticModel(server, client) {
5722
5899
  server.tool(
5723
5900
  "search_semantic_model",
5724
5901
  "Find semantic model entities relevant to a question. Ranks names, aliases, synonyms and descriptions, then includes related entities. Uses the stored model and never writes.",
5725
- { datamartId, question: z28.string().trim().min(1).max(1e4), k: z28.number().int().min(1).max(100).default(10) },
5902
+ { datamartId, question: z30.string().trim().min(1).max(1e4), k: z30.number().int().min(1).max(100).default(10) },
5726
5903
  READ_ONLY,
5727
5904
  async ({ datamartId: datamartId2, question, k }) => {
5728
5905
  try {
@@ -5745,7 +5922,7 @@ function registerGetSemanticEntity(server, client) {
5745
5922
  server.tool(
5746
5923
  "get_semantic_entity",
5747
5924
  "Read one entity by kind and exact name from the stored semantic model. For a column, use table.column. Returns the stored content hash for change review.",
5748
- { datamartId, kind: entityKind, name: z28.string().trim().min(1) },
5925
+ { datamartId, kind: entityKind, name: z30.string().trim().min(1) },
5749
5926
  READ_ONLY,
5750
5927
  async ({ datamartId: datamartId2, kind, name }) => {
5751
5928
  try {
@@ -5783,9 +5960,9 @@ function registerApplySemanticChange(server, client) {
5783
5960
  {
5784
5961
  datamartId,
5785
5962
  ...changeInputs,
5786
- dry_run: z28.boolean().default(true),
5963
+ dry_run: z30.boolean().default(true),
5787
5964
  expected_content_hash: expectedHash,
5788
- confirm: z28.string().optional().describe("User supplied APPLY_TO_PRODUCTION after reviewing the plan. Never invent confirmation.")
5965
+ confirm: z30.string().optional().describe("User supplied APPLY_TO_PRODUCTION after reviewing the plan. Never invent confirmation.")
5789
5966
  },
5790
5967
  DESTRUCTIVE,
5791
5968
  async (params) => {
@@ -5809,12 +5986,12 @@ function registerEvalSemanticModel(server, client) {
5809
5986
  server.tool(
5810
5987
  "eval_semantic_model",
5811
5988
  "Evaluate saved queries and optional questions against a proposed or stored semantic model. Returns the pass rate and each verdict with its reason. Runs warehouse queries without changing the model.",
5812
- { datamartId, source: source.optional(), questions: z28.array(z28.union([z28.string().trim().min(1), z28.object({
5813
- name: z28.string().optional(),
5814
- question: z28.string().min(1),
5815
- sql: z28.string().optional(),
5816
- expected_columns: z28.array(z28.string()).optional(),
5817
- expected_empty: z28.boolean().optional()
5989
+ { datamartId, source: source.optional(), questions: z30.array(z30.union([z30.string().trim().min(1), z30.object({
5990
+ name: z30.string().optional(),
5991
+ question: z30.string().min(1),
5992
+ sql: z30.string().optional(),
5993
+ expected_columns: z30.array(z30.string()).optional(),
5994
+ expected_empty: z30.boolean().optional()
5818
5995
  }).strict()])).max(100).optional() },
5819
5996
  READ_ONLY,
5820
5997
  async ({ datamartId: datamartId2, source: source2, questions }) => {
@@ -5829,15 +6006,15 @@ function registerEvalSemanticModel(server, client) {
5829
6006
  }
5830
6007
 
5831
6008
  // src/tools/query/update-semantic-layer.ts
5832
- import { z as z29 } from "zod";
5833
- var columnSchema2 = z29.object({
5834
- name: z29.string().describe("Column name (must exist in the datamart)"),
5835
- description: z29.string().optional().describe("Business-friendly description of what this column represents"),
5836
- synonyms: z29.array(z29.string()).optional().describe(
6009
+ import { z as z31 } from "zod";
6010
+ var columnSchema2 = z31.object({
6011
+ name: z31.string().describe("Column name (must exist in the datamart)"),
6012
+ description: z31.string().optional().describe("Business-friendly description of what this column represents"),
6013
+ synonyms: z31.array(z31.string()).optional().describe(
5837
6014
  'Alternative names users might use for this column (e.g. ["revenue", "sales amount"])'
5838
6015
  ),
5839
- miscellaneousInfo: z29.string().optional().describe("Additional context such as valid values, units, or caveats"),
5840
- columnType: z29.enum([
6016
+ miscellaneousInfo: z31.string().optional().describe("Additional context such as valid values, units, or caveats"),
6017
+ columnType: z31.enum([
5841
6018
  "String",
5842
6019
  "Long String",
5843
6020
  "String (Custom)",
@@ -5852,21 +6029,21 @@ var columnSchema2 = z29.object({
5852
6029
  // The public PUT accepts these three as well (docs: Update Semantic Layer).
5853
6030
  // They were missing here, and zod strips unknown keys, so a caller who set
5854
6031
  // `isIdentifier: true` got a success message and a row with `false`.
5855
- columnTypeConfig: z29.union([z29.record(z29.string(), z29.string()), z29.string(), z29.object({ lowerLimit: z29.number(), upperLimit: z29.number() }), z29.null()]).optional().describe("Shape depends on columnType: value-to-description object for String / String (Custom) / ENUM / Mapper, { lowerLimit, upperLimit } for Range, a string for Expression and JSON. Omit for Identifier, Number and Long String."),
5856
- isIdentifier: z29.boolean().optional().describe("Mark the column as an identifier (primary or foreign key)."),
5857
- isNotIndexed: z29.boolean().optional().describe("Exclude the column from AI indexing.")
6032
+ columnTypeConfig: z31.union([z31.record(z31.string(), z31.string()), z31.string(), z31.object({ lowerLimit: z31.number(), upperLimit: z31.number() }), z31.null()]).optional().describe("Shape depends on columnType: value-to-description object for String / String (Custom) / ENUM / Mapper, { lowerLimit, upperLimit } for Range, a string for Expression and JSON. Omit for Identifier, Number and Long String."),
6033
+ isIdentifier: z31.boolean().optional().describe("Mark the column as an identifier (primary or foreign key)."),
6034
+ isNotIndexed: z31.boolean().optional().describe("Exclude the column from AI indexing.")
5858
6035
  });
5859
- var tableSchema2 = z29.object({
5860
- name: z29.string().describe("Table name (must exist in the datamart)"),
5861
- schemaName: z29.string().optional().describe("Schema the table lives in, when the datamart has the same table name in more than one schema."),
5862
- description: z29.string().optional().describe(
6036
+ var tableSchema2 = z31.object({
6037
+ name: z31.string().describe("Table name (must exist in the datamart)"),
6038
+ schemaName: z31.string().optional().describe("Schema the table lives in, when the datamart has the same table name in more than one schema."),
6039
+ description: z31.string().optional().describe(
5863
6040
  "Business-friendly description of what this table represents"
5864
6041
  ),
5865
- synonyms: z29.array(z29.string()).optional().describe("Alternative names for this table"),
5866
- miscellaneousInfo: z29.string().optional().describe(
6042
+ synonyms: z31.array(z31.string()).optional().describe("Alternative names for this table"),
6043
+ miscellaneousInfo: z31.string().optional().describe(
5867
6044
  "Additional context such as how the table relates to other tables"
5868
6045
  ),
5869
- columns: z29.array(columnSchema2).optional().describe("Column-level semantic definitions to update")
6046
+ columns: z31.array(columnSchema2).optional().describe("Column-level semantic definitions to update")
5870
6047
  });
5871
6048
  function columnKey(tableName, columnName) {
5872
6049
  return `${tableName.toLowerCase()}\0${columnName.toLowerCase()}`;
@@ -5943,13 +6120,13 @@ function registerUpdateSemanticLayer(server, client) {
5943
6120
  "update_semantic_layer",
5944
6121
  "Populate or update the semantic layer for a datamart. Add table/column descriptions, synonyms, context. Required before ask_question works. Auto-generate descriptions from column names when empty.",
5945
6122
  {
5946
- datamartName: z29.string().optional().describe(
6123
+ datamartName: z31.string().optional().describe(
5947
6124
  "Name of the datamart to update. Omit to list available datamarts."
5948
6125
  ),
5949
- tables: z29.array(tableSchema2).optional().describe(
6126
+ tables: z31.array(tableSchema2).optional().describe(
5950
6127
  "Table and column definitions to update. Only include tables/columns you want to change."
5951
6128
  ),
5952
- feedback: z29.string().optional().describe(
6129
+ feedback: z31.string().optional().describe(
5953
6130
  'General feedback or context about the datamart (e.g. "This datamart contains e-commerce data for the US market").'
5954
6131
  )
5955
6132
  },
@@ -6011,7 +6188,7 @@ You can now:
6011
6188
  }
6012
6189
 
6013
6190
  // src/tools/query/semantic-generation.ts
6014
- import { z as z30 } from "zod";
6191
+ import { z as z32 } from "zod";
6015
6192
  function nonEmptyString(value) {
6016
6193
  return typeof value === "string" && value.trim().length > 0 ? value : null;
6017
6194
  }
@@ -6117,9 +6294,9 @@ function registerStartSemanticLayerGeneration(server, client) {
6117
6294
  "start_semantic_layer_generation",
6118
6295
  "Start backend semantic-layer auto-generation for a datamart. Returns an async job id to poll.",
6119
6296
  {
6120
- datamartName: z30.string().optional().describe("Datamart name. Omit to list available datamarts"),
6121
- workspaceName: z30.string().optional().describe("Workspace linked to the datamart. Use when datamartName resolution needs a dataMartId bridge."),
6122
- datamartId: z30.string().optional().describe("Datamart UUID. Use only when already known.")
6297
+ datamartName: z32.string().optional().describe("Datamart name. Omit to list available datamarts"),
6298
+ workspaceName: z32.string().optional().describe("Workspace linked to the datamart. Use when datamartName resolution needs a dataMartId bridge."),
6299
+ datamartId: z32.string().optional().describe("Datamart UUID. Use only when already known.")
6123
6300
  },
6124
6301
  WRITE_CREATE,
6125
6302
  async (params) => {
@@ -6161,9 +6338,9 @@ function registerGetSemanticLayerGenerationStatus(server, client) {
6161
6338
  "get_semantic_layer_generation_status",
6162
6339
  "Get semantic-layer auto-generation job status for a datamart.",
6163
6340
  {
6164
- datamartName: z30.string().optional().describe("Datamart name. Omit to list available datamarts"),
6165
- workspaceName: z30.string().optional().describe("Workspace linked to the datamart. Use when datamartName resolution needs a dataMartId bridge."),
6166
- datamartId: z30.string().optional().describe("Datamart UUID. Use only when already known.")
6341
+ datamartName: z32.string().optional().describe("Datamart name. Omit to list available datamarts"),
6342
+ workspaceName: z32.string().optional().describe("Workspace linked to the datamart. Use when datamartName resolution needs a dataMartId bridge."),
6343
+ datamartId: z32.string().optional().describe("Datamart UUID. Use only when already known.")
6167
6344
  },
6168
6345
  READ_ONLY,
6169
6346
  async (params) => {
@@ -6200,7 +6377,7 @@ function registerGetSemanticLayerGenerationStatus(server, client) {
6200
6377
  }
6201
6378
 
6202
6379
  // src/tools/widgets/list-widgets.ts
6203
- import { z as z31 } from "zod";
6380
+ import { z as z33 } from "zod";
6204
6381
  function widgetReferenceId(widget) {
6205
6382
  for (const candidate2 of [widget.externalMetricId, widget.id, widget._id, widget.metricId]) {
6206
6383
  if (typeof candidate2 === "string" && candidate2.trim().length > 0) return candidate2.trim();
@@ -6213,10 +6390,10 @@ function registerListWidgets(server, client) {
6213
6390
  "list_widgets",
6214
6391
  "List widgets on a customer dashboard. Non-technical flow: pass `clientId` + `dashboardName` (+ optional `workspaceName` if ambiguous). Returns each widget's externalMetricId (uuid, used for update/remove), metricId (slug), name, published state, and creator identifier.",
6215
6392
  {
6216
- clientId: z31.string().describe("Client/tenant identifier for this dashboard"),
6217
- dashboardName: z31.string().optional().describe("Dashboard name (non-technical). Preferred input \u2014 pass this with optional `workspaceName` instead of `embedId`."),
6218
- workspaceName: z31.string().optional().describe("Workspace name (non-technical). Only needed if `dashboardName` is ambiguous across workspaces."),
6219
- embedId: z31.string().optional().describe("Technical alternative to `dashboardName`. Pass only if you already have the embed identifier.")
6393
+ clientId: z33.string().describe("Client/tenant identifier for this dashboard"),
6394
+ dashboardName: z33.string().optional().describe("Dashboard name (non-technical). Preferred input \u2014 pass this with optional `workspaceName` instead of `embedId`."),
6395
+ workspaceName: z33.string().optional().describe("Workspace name (non-technical). Only needed if `dashboardName` is ambiguous across workspaces."),
6396
+ embedId: z33.string().optional().describe("Technical alternative to `dashboardName`. Pass only if you already have the embed identifier.")
6220
6397
  },
6221
6398
  READ_ONLY,
6222
6399
  async (params) => {
@@ -6280,29 +6457,29 @@ function registerListWidgets(server, client) {
6280
6457
  }
6281
6458
 
6282
6459
  // src/tools/widgets/add-widget.ts
6283
- import { z as z32 } from "zod";
6460
+ import { z as z34 } from "zod";
6284
6461
  function registerAddWidget(server, client) {
6285
6462
  const services = createServiceBundle(client);
6286
6463
  server.tool(
6287
6464
  "add_widget",
6288
6465
  "Add a widget to a customer dashboard. Non-technical flow: pass `clientId` + `dashboardName` (+ optional `workspaceName` if ambiguous). Cloning via `templateMetricId` is the recommended path \u2014 query, chart config, and datasource are all inherited. Data app and datasource auto-resolve; never ask the user for them.",
6289
6466
  {
6290
- clientId: z32.string().describe("Client/tenant identifier (widget is created in their scope)"),
6291
- dashboardName: z32.string().optional().describe("Dashboard name (non-technical). Preferred input \u2014 pass this with optional `workspaceName` instead of `embedId`."),
6292
- workspaceName: z32.string().optional().describe("Workspace name (non-technical). Only needed if `dashboardName` is ambiguous across workspaces."),
6293
- embedId: z32.string().optional().describe("Technical alternative to `dashboardName`. Pass only if you already have the embed identifier."),
6294
- dataAppName: z32.string().optional().describe("Technical override. Auto-resolved from the embed; non-technical callers should leave this blank."),
6295
- templateMetricId: z32.string().optional().describe("Source widget metricId to clone from. Copies query, chartOptions, and datasource fields; caller can override via other params."),
6296
- name: z32.string().optional().describe("Widget name (overrides template)"),
6297
- metricId: z32.string().optional().describe("Unique slug for the new widget (auto-generated if omitted)"),
6298
- query: z32.string().optional().describe("SQL query body (overrides template)"),
6299
- chartOptions: z32.record(z32.unknown()).optional().describe("Chart config JSON (chart type, colors, legend, axes). Overrides template."),
6300
- description: z32.string().optional(),
6301
- companyIntegrationId: z32.string().optional().describe("Datasource UUID override. Auto-resolved from `embedId` or sole active datasource; leave blank unless the user explicitly picked one by ID."),
6302
- integrationName: z32.string().optional().describe('Datasource display name (e.g. "Snowflake"). Use this when the user picks a datasource by name \u2014 the id is looked up automatically.'),
6303
- isPublished: z32.boolean().optional().describe("Publish immediately (default true)"),
6304
- body: z32.record(z32.unknown()).optional().describe("Raw createMetric body passthrough. If provided, used as-is (after defaults). Overrides all other params."),
6305
- widgets: z32.array(z32.record(z32.unknown())).min(1).max(50).optional().describe("Batch of raw createMetric bodies. Dashboard attachment is added to each body.")
6467
+ clientId: z34.string().describe("Client/tenant identifier (widget is created in their scope)"),
6468
+ dashboardName: z34.string().optional().describe("Dashboard name (non-technical). Preferred input \u2014 pass this with optional `workspaceName` instead of `embedId`."),
6469
+ workspaceName: z34.string().optional().describe("Workspace name (non-technical). Only needed if `dashboardName` is ambiguous across workspaces."),
6470
+ embedId: z34.string().optional().describe("Technical alternative to `dashboardName`. Pass only if you already have the embed identifier."),
6471
+ dataAppName: z34.string().optional().describe("Technical override. Auto-resolved from the embed; non-technical callers should leave this blank."),
6472
+ templateMetricId: z34.string().optional().describe("Source widget metricId to clone from. Copies query, chartOptions, and datasource fields; caller can override via other params."),
6473
+ name: z34.string().optional().describe("Widget name (overrides template)"),
6474
+ metricId: z34.string().optional().describe("Unique slug for the new widget (auto-generated if omitted)"),
6475
+ query: z34.string().optional().describe("SQL query body (overrides template)"),
6476
+ chartOptions: z34.record(z34.unknown()).optional().describe("Chart config JSON (chart type, colors, legend, axes). Overrides template."),
6477
+ description: z34.string().optional(),
6478
+ companyIntegrationId: z34.string().optional().describe("Datasource UUID override. Auto-resolved from `embedId` or sole active datasource; leave blank unless the user explicitly picked one by ID."),
6479
+ integrationName: z34.string().optional().describe('Datasource display name (e.g. "Snowflake"). Use this when the user picks a datasource by name \u2014 the id is looked up automatically.'),
6480
+ isPublished: z34.boolean().optional().describe("Publish immediately (default true)"),
6481
+ body: z34.record(z34.unknown()).optional().describe("Raw createMetric body passthrough. If provided, used as-is (after defaults). Overrides all other params."),
6482
+ widgets: z34.array(z34.record(z34.unknown())).min(1).max(50).optional().describe("Batch of raw createMetric bodies. Dashboard attachment is added to each body.")
6306
6483
  },
6307
6484
  WRITE_CREATE,
6308
6485
  async (params) => {
@@ -6450,20 +6627,20 @@ Use \`list_widgets\` to verify, or \`update_widget\`/\`remove_widget\` to adjust
6450
6627
  }
6451
6628
 
6452
6629
  // src/tools/widgets/update-widget.ts
6453
- import { z as z33 } from "zod";
6630
+ import { z as z35 } from "zod";
6454
6631
  function registerUpdateWidget(server, client) {
6455
6632
  const services = createServiceBundle(client);
6456
6633
  server.tool(
6457
6634
  "update_widget",
6458
6635
  "Update a widget on a customer dashboard. Non-technical flow: pass `clientId` + `dashboardName` (+ optional `workspaceName` if ambiguous) + `externalMetricId` + `set`. Data app auto-resolves from the dashboard.",
6459
6636
  {
6460
- externalMetricId: z33.string().describe("Internal uuid of the widget (externalMetrics.id). Not the user-facing metricId slug."),
6461
- clientId: z33.string().describe("Client/tenant identifier"),
6462
- dashboardName: z33.string().optional().describe("Dashboard name (non-technical). Preferred input \u2014 pass this with optional `workspaceName` instead of `embedId`."),
6463
- workspaceName: z33.string().optional().describe("Workspace name (non-technical). Only needed if `dashboardName` is ambiguous across workspaces."),
6464
- embedId: z33.string().optional().describe("Technical alternative to `dashboardName`. Pass only if you already have the embed identifier."),
6465
- dataAppName: z33.string().optional().describe("Technical override. Auto-resolved from the dashboard; non-technical callers should leave this blank."),
6466
- set: z33.record(z33.unknown()).describe("Partial patch. Keys can include: name, query, chartOptions, description, isPublished, isLive, selectedGroupBy, drillDownSettings, limit, etc.")
6637
+ externalMetricId: z35.string().describe("Internal uuid of the widget (externalMetrics.id). Not the user-facing metricId slug."),
6638
+ clientId: z35.string().describe("Client/tenant identifier"),
6639
+ dashboardName: z35.string().optional().describe("Dashboard name (non-technical). Preferred input \u2014 pass this with optional `workspaceName` instead of `embedId`."),
6640
+ workspaceName: z35.string().optional().describe("Workspace name (non-technical). Only needed if `dashboardName` is ambiguous across workspaces."),
6641
+ embedId: z35.string().optional().describe("Technical alternative to `dashboardName`. Pass only if you already have the embed identifier."),
6642
+ dataAppName: z35.string().optional().describe("Technical override. Auto-resolved from the dashboard; non-technical callers should leave this blank."),
6643
+ set: z35.record(z35.unknown()).describe("Partial patch. Keys can include: name, query, chartOptions, description, isPublished, isLive, selectedGroupBy, drillDownSettings, limit, etc.")
6467
6644
  },
6468
6645
  WRITE_IDEMPOTENT,
6469
6646
  async (params) => {
@@ -6526,19 +6703,19 @@ Use \`list_widgets\` to verify.`
6526
6703
  }
6527
6704
 
6528
6705
  // src/tools/widgets/remove-widget.ts
6529
- import { z as z34 } from "zod";
6706
+ import { z as z36 } from "zod";
6530
6707
  function registerRemoveWidget(server, client) {
6531
6708
  const services = createServiceBundle(client);
6532
6709
  server.tool(
6533
6710
  "remove_widget",
6534
6711
  "Remove a widget from a customer dashboard. Non-technical flow: pass `clientId` + `dashboardName` (+ optional `workspaceName` if ambiguous) + `externalMetricId`. Per-client soft delete \u2014 the widget stays on the template dashboard and on other customers' dashboards.",
6535
6712
  {
6536
- externalMetricId: z34.string().describe("Internal uuid of the widget (externalMetrics.id)"),
6537
- clientId: z34.string().describe("Client/tenant identifier \u2014 the widget will be hidden for this client only"),
6538
- dashboardName: z34.string().optional().describe("Dashboard name (non-technical). Preferred input \u2014 pass this with optional `workspaceName` instead of `embedId`."),
6539
- workspaceName: z34.string().optional().describe("Workspace name (non-technical). Only needed if `dashboardName` is ambiguous across workspaces."),
6540
- embedId: z34.string().optional().describe("Technical alternative to `dashboardName`. Pass only if you already have the embed identifier."),
6541
- dataAppName: z34.string().optional().describe("Technical override. Auto-resolved from the dashboard; non-technical callers should leave this blank.")
6713
+ externalMetricId: z36.string().describe("Internal uuid of the widget (externalMetrics.id)"),
6714
+ clientId: z36.string().describe("Client/tenant identifier \u2014 the widget will be hidden for this client only"),
6715
+ dashboardName: z36.string().optional().describe("Dashboard name (non-technical). Preferred input \u2014 pass this with optional `workspaceName` instead of `embedId`."),
6716
+ workspaceName: z36.string().optional().describe("Workspace name (non-technical). Only needed if `dashboardName` is ambiguous across workspaces."),
6717
+ embedId: z36.string().optional().describe("Technical alternative to `dashboardName`. Pass only if you already have the embed identifier."),
6718
+ dataAppName: z36.string().optional().describe("Technical override. Auto-resolved from the dashboard; non-technical callers should leave this blank.")
6542
6719
  },
6543
6720
  DESTRUCTIVE,
6544
6721
  async (params) => {
@@ -6594,21 +6771,21 @@ Note: this is a per-client soft delete. The widget remains available for other c
6594
6771
  }
6595
6772
 
6596
6773
  // src/tools/widgets/generate-widget.ts
6597
- import { z as z35 } from "zod";
6774
+ import { z as z37 } from "zod";
6598
6775
  function registerGenerateWidget(server, client) {
6599
6776
  const services = createServiceBundle(client);
6600
6777
  const tool = server.tool(
6601
6778
  "generate_widget",
6602
6779
  "AI-generate a widget draft from a natural-language prompt. Does NOT persist \u2014 returns a draft to pass to `add_widget`. Non-technical flow: `clientId` + `dashboardName` (+ `workspaceName` if ambiguous); data app and datasource auto-resolve. Never ask the user for data app, datasource, or integration.",
6603
6780
  {
6604
- clientId: z35.string().describe("Client/tenant identifier"),
6605
- userInputs: z35.record(z35.unknown()).describe('Prompt + context object. Typical shape: { prompt: "calls per day over last 30 days", schema: {...}, examples: [...] }. Backend decides which keys it honors.'),
6606
- dashboardName: z35.string().optional().describe("Dashboard name (non-technical). Preferred input for CS/CX flows \u2014 pass this with optional `workspaceName` instead of `embedId`."),
6607
- workspaceName: z35.string().optional().describe("Workspace name (non-technical). Only needed if `dashboardName` is ambiguous across workspaces."),
6608
- embedId: z35.string().optional().describe("Technical alternative to `dashboardName`. Pass only if you already have the embed identifier."),
6609
- dataAppName: z35.string().optional().describe("Technical override. Auto-resolved from the embed; non-technical callers should leave this blank."),
6610
- integrationId: z35.string().optional().describe("Technical override \u2014 the datasource UUID. Non-technical callers must leave this blank; the datasource is inherited from the dashboard's existing widgets."),
6611
- integrationName: z35.string().optional().describe("Technical override \u2014 datasource display name. Non-technical callers must leave this blank; the datasource is inherited from the dashboard's existing widgets.")
6781
+ clientId: z37.string().describe("Client/tenant identifier"),
6782
+ userInputs: z37.record(z37.unknown()).describe('Prompt + context object. Typical shape: { prompt: "calls per day over last 30 days", schema: {...}, examples: [...] }. Backend decides which keys it honors.'),
6783
+ dashboardName: z37.string().optional().describe("Dashboard name (non-technical). Preferred input for CS/CX flows \u2014 pass this with optional `workspaceName` instead of `embedId`."),
6784
+ workspaceName: z37.string().optional().describe("Workspace name (non-technical). Only needed if `dashboardName` is ambiguous across workspaces."),
6785
+ embedId: z37.string().optional().describe("Technical alternative to `dashboardName`. Pass only if you already have the embed identifier."),
6786
+ dataAppName: z37.string().optional().describe("Technical override. Auto-resolved from the embed; non-technical callers should leave this blank."),
6787
+ integrationId: z37.string().optional().describe("Technical override \u2014 the datasource UUID. Non-technical callers must leave this blank; the datasource is inherited from the dashboard's existing widgets."),
6788
+ integrationName: z37.string().optional().describe("Technical override \u2014 datasource display name. Non-technical callers must leave this blank; the datasource is inherited from the dashboard's existing widgets.")
6612
6789
  },
6613
6790
  READ_ONLY,
6614
6791
  async (params) => {
@@ -6693,9 +6870,9 @@ function registerGenerateWidget(server, client) {
6693
6870
  }
6694
6871
 
6695
6872
  // src/tools/widgets/create-or-update-metric-from-query.ts
6696
- import { z as z36 } from "zod";
6697
- var modeSchema = z36.enum(["dry_run", "apply"]).default("dry_run");
6698
- var conflictStrategySchema = z36.enum(["fail", "update", "create_new"]).default("fail");
6873
+ import { z as z38 } from "zod";
6874
+ var modeSchema = z38.enum(["dry_run", "apply"]).default("dry_run");
6875
+ var conflictStrategySchema = z38.enum(["fail", "update", "create_new"]).default("fail");
6699
6876
  function makePlanText(plan) {
6700
6877
  return JSON.stringify(plan, null, 2);
6701
6878
  }
@@ -6712,22 +6889,22 @@ function registerCreateOrUpdateMetricFromQuery(server, client) {
6712
6889
  "[EMBEDDING] Create or update a production metric/widget on a customer dashboard from validated SQL. Requires clientId (multi-tenant embed). Defaults to dry-run; apply requires explicit confirmation.",
6713
6890
  {
6714
6891
  mode: modeSchema.describe("dry_run returns the plan only; apply executes after confirmation"),
6715
- confirm: z36.string().optional().describe(`Required for apply: ${APPLY_TO_PRODUCTION_CONFIRMATION}`),
6892
+ confirm: z38.string().optional().describe(`Required for apply: ${APPLY_TO_PRODUCTION_CONFIRMATION}`),
6716
6893
  conflictStrategy: conflictStrategySchema.describe("What to do if metricId already exists on the target dashboard"),
6717
- clientId: z36.string().describe("Client/tenant identifier for the dashboard widget scope"),
6718
- workspaceName: z36.string().describe("Target workspace name"),
6719
- dashboardName: z36.string().optional().describe("Dashboard name to attach to"),
6720
- embedId: z36.string().optional().describe("Technical embed id alternative to dashboardName"),
6721
- dataAppName: z36.string().optional().describe("Optional data app override"),
6722
- name: z36.string().describe("Metric/widget display name"),
6723
- metricId: z36.string().describe("Stable metric slug to create or update"),
6724
- query: z36.string().describe("SQL query already validated against the warehouse"),
6725
- description: z36.string().optional().describe("Metric description"),
6726
- chartOptions: z36.record(z36.unknown()).optional().describe("Chart configuration JSON"),
6727
- companyIntegrationId: z36.string().optional().describe("Datasource UUID override"),
6728
- integrationName: z36.string().optional().describe("Datasource display name override"),
6729
- isPublished: z36.boolean().optional().describe("Publish after apply. Defaults to false for production safety"),
6730
- requestedBy: z36.string().optional().describe("Human operator/request context to store on the metric when supported")
6894
+ clientId: z38.string().describe("Client/tenant identifier for the dashboard widget scope"),
6895
+ workspaceName: z38.string().describe("Target workspace name"),
6896
+ dashboardName: z38.string().optional().describe("Dashboard name to attach to"),
6897
+ embedId: z38.string().optional().describe("Technical embed id alternative to dashboardName"),
6898
+ dataAppName: z38.string().optional().describe("Optional data app override"),
6899
+ name: z38.string().describe("Metric/widget display name"),
6900
+ metricId: z38.string().describe("Stable metric slug to create or update"),
6901
+ query: z38.string().describe("SQL query already validated against the warehouse"),
6902
+ description: z38.string().optional().describe("Metric description"),
6903
+ chartOptions: z38.record(z38.unknown()).optional().describe("Chart configuration JSON"),
6904
+ companyIntegrationId: z38.string().optional().describe("Datasource UUID override"),
6905
+ integrationName: z38.string().optional().describe("Datasource display name override"),
6906
+ isPublished: z38.boolean().optional().describe("Publish after apply. Defaults to false for production safety"),
6907
+ requestedBy: z38.string().optional().describe("Human operator/request context to store on the metric when supported")
6731
6908
  },
6732
6909
  WRITE_IDEMPOTENT,
6733
6910
  async (params) => {
@@ -6887,8 +7064,8 @@ function registerCreateOrUpdateMetricFromQuery(server, client) {
6887
7064
  }
6888
7065
 
6889
7066
  // src/tools/widgets/create-workspace-metric.ts
6890
- import { z as z37 } from "zod";
6891
- var modeSchema2 = z37.enum(["dry_run", "apply"]).default("dry_run");
7067
+ import { z as z39 } from "zod";
7068
+ var modeSchema2 = z39.enum(["dry_run", "apply"]).default("dry_run");
6892
7069
  function registerCreateWorkspaceMetric(server, client) {
6893
7070
  server.tool(
6894
7071
  "create_workspace_metric",
@@ -6897,18 +7074,18 @@ function registerCreateWorkspaceMetric(server, client) {
6897
7074
  mode: modeSchema2.describe(
6898
7075
  "dry_run validates the SQL only (no write); apply creates or updates the metric after confirmation"
6899
7076
  ),
6900
- confirm: z37.string().optional().describe(`Required for apply: ${APPLY_TO_PRODUCTION_CONFIRMATION}`),
6901
- workspaceName: z37.string().describe("Target workspace name"),
6902
- name: z37.string().describe("Metric display name"),
6903
- query: z37.string().describe(
7077
+ confirm: z39.string().optional().describe(`Required for apply: ${APPLY_TO_PRODUCTION_CONFIRMATION}`),
7078
+ workspaceName: z39.string().describe("Target workspace name"),
7079
+ name: z39.string().describe("Metric display name"),
7080
+ query: z39.string().describe(
6904
7081
  "SQL query to validate and store. In a TABLE-tenancy workspace never compare the client column to a fixed client value; use `client_id_variable` so each client sees only its own rows (the backend refuses it with TENANT_KEY_LITERAL)."
6905
7082
  ),
6906
- metricId: z37.string().optional().describe(
7083
+ metricId: z39.string().optional().describe(
6907
7084
  "Stable metric slug. Pass an existing slug to UPDATE that metric in place. Omit to create \u2014 the slug is derived deterministically from the name (no random/uniqueness suffix), so re-running with the same name upserts the same metric rather than creating a duplicate."
6908
7085
  ),
6909
- description: z37.string().optional().describe("Metric description"),
6910
- datasourceId: z37.string().optional().describe("Datasource UUID override; defaults to the workspace datasource"),
6911
- isPublished: z37.boolean().optional().describe(
7086
+ description: z39.string().optional().describe("Metric description"),
7087
+ datasourceId: z39.string().optional().describe("Datasource UUID override; defaults to the workspace datasource"),
7088
+ isPublished: z39.boolean().optional().describe(
6912
7089
  "Publish after apply. Defaults to false. Applies to creates; on updates the existing publish state is preserved."
6913
7090
  )
6914
7091
  },
@@ -6964,25 +7141,25 @@ function registerCreateWorkspaceMetric(server, client) {
6964
7141
  }
6965
7142
 
6966
7143
  // src/tools/widgets/validate-metric-spec.ts
6967
- import { z as z38 } from "zod";
7144
+ import { z as z40 } from "zod";
6968
7145
  function registerValidateMetricSpec(server, client) {
6969
7146
  const services = createServiceBundle(client);
6970
7147
  server.tool(
6971
7148
  "validate_metric_spec",
6972
7149
  "Validate a production metric spec from SQL without saving it. Resolves dashboard, data app, datasource, conflicts, and required fields.",
6973
7150
  {
6974
- clientId: z38.string().describe("Client/tenant identifier used to validate dashboard widget scope"),
6975
- workspaceName: z38.string().describe("Target production-backed workspace name"),
6976
- dashboardName: z38.string().optional().describe("Dashboard name to attach to"),
6977
- embedId: z38.string().optional().describe("Technical embed id alternative to dashboardName"),
6978
- dataAppName: z38.string().optional().describe("Optional data app override"),
6979
- name: z38.string().describe("Metric/widget display name"),
6980
- metricId: z38.string().describe("Stable metric slug to create or update"),
6981
- query: z38.string().describe("SQL query already validated against the warehouse"),
6982
- description: z38.string().optional().describe("Metric description"),
6983
- chartOptions: z38.record(z38.unknown()).optional().describe("Chart configuration JSON"),
6984
- companyIntegrationId: z38.string().optional().describe("Datasource UUID override"),
6985
- integrationName: z38.string().optional().describe("Datasource display name override")
7151
+ clientId: z40.string().describe("Client/tenant identifier used to validate dashboard widget scope"),
7152
+ workspaceName: z40.string().describe("Target production-backed workspace name"),
7153
+ dashboardName: z40.string().optional().describe("Dashboard name to attach to"),
7154
+ embedId: z40.string().optional().describe("Technical embed id alternative to dashboardName"),
7155
+ dataAppName: z40.string().optional().describe("Optional data app override"),
7156
+ name: z40.string().describe("Metric/widget display name"),
7157
+ metricId: z40.string().describe("Stable metric slug to create or update"),
7158
+ query: z40.string().describe("SQL query already validated against the warehouse"),
7159
+ description: z40.string().optional().describe("Metric description"),
7160
+ chartOptions: z40.record(z40.unknown()).optional().describe("Chart configuration JSON"),
7161
+ companyIntegrationId: z40.string().optional().describe("Datasource UUID override"),
7162
+ integrationName: z40.string().optional().describe("Datasource display name override")
6986
7163
  },
6987
7164
  READ_ONLY,
6988
7165
  async (params) => {
@@ -7073,20 +7250,20 @@ function registerValidateMetricSpec(server, client) {
7073
7250
  }
7074
7251
 
7075
7252
  // src/tools/reports/list-scheduled-reports.ts
7076
- import { z as z39 } from "zod";
7253
+ import { z as z41 } from "zod";
7077
7254
  function registerListScheduledReports(server, client) {
7078
7255
  const services = createServiceBundle(client);
7079
7256
  server.tool(
7080
7257
  "list_scheduled_reports",
7081
7258
  "List configured scheduled reports for a specific client/dashboard embed. Shows schedule metadata, not delivery success history.",
7082
7259
  {
7083
- clientId: z39.string().describe("Client/tenant identifier. Required by the current backend API for non-empty results"),
7084
- dashboardName: z39.string().optional().describe("Dashboard name to inspect"),
7085
- workspaceName: z39.string().optional().describe("Workspace name if dashboardName is ambiguous"),
7086
- embedId: z39.string().optional().describe("Technical embed id alternative to dashboardName"),
7087
- userIdentifier: z39.string().optional().describe("Optional creator/user filter"),
7088
- pageNumber: z39.number().int().positive().optional().describe("Page number when pagination is enabled"),
7089
- isPagination: z39.boolean().optional().describe("Enable backend pagination")
7260
+ clientId: z41.string().describe("Client/tenant identifier. Required by the current backend API for non-empty results"),
7261
+ dashboardName: z41.string().optional().describe("Dashboard name to inspect"),
7262
+ workspaceName: z41.string().optional().describe("Workspace name if dashboardName is ambiguous"),
7263
+ embedId: z41.string().optional().describe("Technical embed id alternative to dashboardName"),
7264
+ userIdentifier: z41.string().optional().describe("Optional creator/user filter"),
7265
+ pageNumber: z41.number().int().positive().optional().describe("Page number when pagination is enabled"),
7266
+ isPagination: z41.boolean().optional().describe("Enable backend pagination")
7090
7267
  },
7091
7268
  READ_ONLY,
7092
7269
  async (params) => {
@@ -7196,90 +7373,18 @@ function registerWhoami(server, client) {
7196
7373
  }
7197
7374
 
7198
7375
  // src/tools/custom-chart/scaffold.ts
7199
- import { z as z41 } from "zod";
7200
-
7201
- // src/tools/custom-chart/shared.ts
7202
- import { z as z40 } from "zod";
7203
- var slotInputSchema = slotSchema;
7204
- var optionInputSchema = optionSchema;
7205
- var manifestInputSchema = z40.record(z40.unknown()).describe("manifest.json as an object (schemaVersion 2). Validated with the same rules as the server.");
7206
- var bundleInputShape = {
7207
- manifest: manifestInputSchema.optional(),
7208
- bundleJs: z40.string().optional().describe("dist/index.js from `databrain custom-chart build` (the shim plus the chart module)."),
7209
- bundleCss: z40.string().optional().describe("The raw chart.css, kept for provenance."),
7210
- iconSvg: z40.string().optional().describe("icon.svg, at most 16 KiB, no script, no foreignObject, no external href."),
7211
- projectDir: z40.string().optional().describe("Local only: a chart project folder. The tool reads it instead of manifest/bundleJs/iconSvg.")
7212
- };
7213
- function formatProblems(problems) {
7214
- if (problems.length === 0) return "No problems.";
7215
- return problems.map((p) => `${p.path || "/"} ${p.code} ${p.message}`).join("\n");
7216
- }
7217
- function projectDirRefusal() {
7218
- if (process.env.DATABRAIN_HOSTED_PUBLIC_URL) {
7219
- return "projectDir is not available on the hosted server. Pass manifest, bundleJs, bundleCss and iconSvg instead.";
7220
- }
7221
- return null;
7222
- }
7223
- async function resolveBundleInput(params, options) {
7224
- if (params.projectDir) {
7225
- const refusal = projectDirRefusal();
7226
- if (refusal) return { problems: [], error: refusal, source: "projectDir" };
7227
- if (params.manifest || params.bundleJs || params.iconSvg) {
7228
- return { problems: [], error: "Pass either projectDir or manifest/bundleJs/iconSvg, not both.", source: "projectDir" };
7229
- }
7230
- if (options.build) {
7231
- const result = await buildProject(params.projectDir, { write: false });
7232
- if (!result.ok || !result.outputs) return { problems: result.problems, source: "projectDir" };
7233
- const { manifest, bundleJs, bundleCss, iconSvg } = result.outputs;
7234
- return { bundle: { manifest, bundleJs, bundleCss, iconSvg }, problems: [], source: "projectDir" };
7235
- }
7236
- const dist = readDist(params.projectDir);
7237
- if (!dist.bundle) return { problems: dist.problems, source: "projectDir" };
7238
- return { bundle: dist.bundle, problems: [], source: "projectDir" };
7239
- }
7240
- if (!params.manifest) {
7241
- return { problems: [], error: "manifest is required (or pass projectDir when running locally).", source: "arguments" };
7242
- }
7243
- return {
7244
- bundle: {
7245
- manifest: params.manifest,
7246
- bundleJs: params.bundleJs,
7247
- bundleCss: params.bundleCss,
7248
- iconSvg: params.iconSvg
7249
- },
7250
- problems: [],
7251
- source: "arguments"
7252
- };
7253
- }
7254
- async function remoteValidate(client, bundle) {
7255
- try {
7256
- const result = await createCustomChartsApi(client).validate(bundle);
7257
- return { status: "ok", result };
7258
- } catch (err) {
7259
- if (err instanceof DatabrainApiError) {
7260
- if (err.code === "MISSING_SERVICE_TOKEN") {
7261
- return { status: "skipped", reason: "No service token is configured, so only the local validator ran." };
7262
- }
7263
- return { status: "failed", reason: err.message, problems: apiProblems(err) };
7264
- }
7265
- return { status: "failed", reason: err.message, problems: [] };
7266
- }
7267
- }
7268
- function isCompleteBundle(bundle) {
7269
- return typeof bundle.bundleJs === "string" && typeof bundle.iconSvg === "string";
7270
- }
7271
-
7272
- // src/tools/custom-chart/scaffold.ts
7376
+ import { transformSync } from "esbuild";
7377
+ import { z as z42 } from "zod";
7273
7378
  function registerCustomChartScaffold(server, _client) {
7274
7379
  server.tool(
7275
7380
  "custom_chart_scaffold",
7276
- "Return the files of a new custom chart project (manifest.json, chart.ts, chart.css, icon.svg, sample data, guide). Nothing is written or persisted; write the files yourself.",
7381
+ "Return the files of a new custom chart project (manifest.json, chart.ts, chart.css, icon.svg, sample data, guide). Nothing is persisted. For a hosted AI app, edit the returned draft and pass chartTs to validate, preview and upload without local files.",
7277
7382
  {
7278
- key: z41.string().describe("Chart key, becomes chart type custom:<key>. Lowercase letters, digits, _ and -, 64 max."),
7279
- name: z41.string().describe("Display name shown in the chart picker, 1 to 256 characters."),
7280
- description: z41.string().optional().describe("Optional description, up to 500 characters."),
7281
- slots: z41.array(slotInputSchema).optional().describe("Data slots. Defaults to category (dimension), value (measure), target (optional measure)."),
7282
- options: z41.array(optionInputSchema).optional().describe("Chart options. Defaults to the template options (labels, subtitle, radius, colour, sort).")
7383
+ key: z42.string().describe("Chart key, becomes chart type custom:<key>. Lowercase letters, digits, _ and -, 64 max."),
7384
+ name: z42.string().describe("Display name shown in the chart picker, 1 to 256 characters."),
7385
+ description: z42.string().optional().describe("Optional description, up to 500 characters."),
7386
+ slots: z42.array(slotInputSchema).optional().describe("Data slots. Defaults to category (dimension), value (measure), target (optional measure)."),
7387
+ options: z42.array(optionInputSchema).optional().describe("Chart options. Defaults to the template options (labels, subtitle, radius, colour, sort).")
7283
7388
  },
7284
7389
  READ_ONLY,
7285
7390
  async (params) => {
@@ -7302,7 +7407,19 @@ ${formatProblems(result.problems)}`);
7302
7407
  key: params.key,
7303
7408
  chartType: `custom:${params.key}`,
7304
7409
  files: result.files,
7305
- nextStep: result.nextStep
7410
+ draft: {
7411
+ code: transformSync(result.files["chart.ts"], { loader: "ts", format: "esm" }).code.replace(/export\s*\{[^}]*\};?\s*$/, ""),
7412
+ css: result.files["chart.css"],
7413
+ manifest: JSON.parse(result.files["manifest.json"]),
7414
+ sampleData: (() => {
7415
+ const sample = JSON.parse(result.files["sample-data.json"]);
7416
+ return { columns: sample.columns.map(({ id: id2, label, type, slotId }) => ({ id: id2, label, type, ...slotId ? { slotId } : {} })), rows: sample.rows };
7417
+ })(),
7418
+ name: params.name,
7419
+ description: params.description ?? "",
7420
+ iconSvg: result.files["icon.svg"]
7421
+ },
7422
+ nextStep: "Hosted: pass draft to custom_chart_edit with a description and workspaceId. Then validate/preview/upload using chartTs=draft.code, manifest, bundleCss=draft.css and iconSvg. Upload saves a version; publishing requires explicit confirmation. Local project: " + result.nextStep
7306
7423
  },
7307
7424
  null,
7308
7425
  2
@@ -7371,18 +7488,18 @@ function registerCustomChartValidate(server, client) {
7371
7488
  }
7372
7489
 
7373
7490
  // src/tools/custom-chart/upload.ts
7374
- import { z as z42 } from "zod";
7491
+ import { z as z43 } from "zod";
7375
7492
  function registerCustomChartUpload(server, client) {
7376
7493
  const api = createCustomChartsApi(client);
7377
7494
  server.tool(
7378
7495
  "custom_chart_upload",
7379
7496
  "Upload a built custom chart bundle to the company. Creates the chart (private, version 1) or a new preview version. Defaults to dry_run; apply requires explicit confirmation and can publish in the same call.",
7380
7497
  {
7381
- mode: z42.enum(["dry_run", "apply"]).default("dry_run").describe("dry_run validates and returns the plan; apply uploads."),
7382
- confirm: z42.string().optional().describe(`Required for apply: ${APPLY_TO_PRODUCTION_CONFIRMATION}`),
7383
- publish: z42.boolean().default(false).describe("After a successful apply, publish the uploaded version so every builder can use it."),
7384
- name: z42.string().optional().describe("Display name override. Defaults to manifest.name."),
7385
- description: z42.string().optional().describe("Description override. Defaults to manifest.description."),
7498
+ mode: z43.enum(["dry_run", "apply"]).default("dry_run").describe("dry_run validates and returns the plan; apply uploads."),
7499
+ confirm: z43.string().optional().describe(`Required for apply: ${APPLY_TO_PRODUCTION_CONFIRMATION}`),
7500
+ publish: z43.boolean().default(false).describe("After a successful apply, publish the uploaded version so every builder can use it."),
7501
+ name: z43.string().optional().describe("Display name override. Defaults to manifest.name."),
7502
+ description: z43.string().optional().describe("Description override. Defaults to manifest.description."),
7386
7503
  ...bundleInputShape
7387
7504
  },
7388
7505
  WRITE_CREATE,
@@ -7523,17 +7640,17 @@ function registerListCustomCharts(server, client) {
7523
7640
  }
7524
7641
 
7525
7642
  // src/tools/custom-chart/publish.ts
7526
- import { z as z43 } from "zod";
7643
+ import { z as z44 } from "zod";
7527
7644
  function registerPublishCustomChart(server, client) {
7528
7645
  const api = createCustomChartsApi(client);
7529
7646
  server.tool(
7530
7647
  "publish_custom_chart",
7531
7648
  "Publish a custom chart version so every builder in the company can use chart type custom:<key>. Defaults to the preview version. Defaults to dry_run; apply requires explicit confirmation.",
7532
7649
  {
7533
- key: z43.string().describe("The chart key (manifest.id), for example revenue-bars."),
7534
- versionId: z43.string().optional().describe("A specific version id to publish. Defaults to the preview version."),
7535
- mode: z43.enum(["dry_run", "apply"]).default("dry_run").describe("dry_run shows what would be published; apply publishes."),
7536
- confirm: z43.string().optional().describe(`Required for apply: ${APPLY_TO_PRODUCTION_CONFIRMATION}`)
7650
+ key: z44.string().describe("The chart key (manifest.id), for example revenue-bars."),
7651
+ versionId: z44.string().optional().describe("A specific version id to publish. Defaults to the preview version."),
7652
+ mode: z44.enum(["dry_run", "apply"]).default("dry_run").describe("dry_run shows what would be published; apply publishes."),
7653
+ confirm: z44.string().optional().describe(`Required for apply: ${APPLY_TO_PRODUCTION_CONFIRMATION}`)
7537
7654
  },
7538
7655
  WRITE_IDEMPOTENT,
7539
7656
  async (params) => {
@@ -7728,6 +7845,7 @@ function registerAllTools(server, client) {
7728
7845
  registerGenerateWidget(server, client);
7729
7846
  registerListScheduledReports(server, client);
7730
7847
  registerCustomChartScaffold(server, client);
7848
+ registerCustomChartAuthor(server, client);
7731
7849
  registerCustomChartValidate(server, client);
7732
7850
  registerCustomChartUpload(server, client);
7733
7851
  registerListCustomCharts(server, client);
@@ -11066,20 +11184,23 @@ function registerAllPrompts(server) {
11066
11184
  }
11067
11185
 
11068
11186
  export {
11069
- createServiceBundle,
11070
11187
  READ_ONLY,
11071
11188
  WRITE_CREATE,
11072
- APPLY_TO_PRODUCTION_CONFIRMATION,
11073
11189
  CHART_URI,
11074
11190
  KPI_URI,
11075
11191
  APP_MIME,
11192
+ MAX_CUSTOM_BUNDLE_CHARS,
11193
+ CUSTOM_BUNDLE_CHUNK_CHARS,
11076
11194
  rowsSchema,
11077
11195
  referenceSchema,
11078
11196
  viewSchema,
11079
11197
  pageSchema,
11198
+ bounded,
11080
11199
  appMeta,
11081
11200
  enableChartApps,
11082
11201
  chartResult,
11202
+ createServiceBundle,
11203
+ APPLY_TO_PRODUCTION_CONFIRMATION,
11083
11204
  draftSchema,
11084
11205
  PREVIEW_PATH,
11085
11206
  RENDER_TYPES,
@@ -11090,4 +11211,4 @@ export {
11090
11211
  registerAllResources,
11091
11212
  registerAllPrompts
11092
11213
  };
11093
- //# sourceMappingURL=chunk-ERTAKB2H.js.map
11214
+ //# sourceMappingURL=chunk-ES2LUP4U.js.map