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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -29,7 +29,7 @@ Your AI app opens a Databrain sign-in page, you pick one or more workspaces (or
29
29
 
30
30
  When you approve more than one workspace, the AI names the workspace on each call (`workspace` or `workspaceName`); `whoami` lists the ones you approved. With "All workspaces I can access", workspaces you get later are included, and `create_workspace` can make a new one if your role allows it.
31
31
 
32
- The hosted connector includes chart and KPI MCP Apps. `ask_question` returns an inline tile, and `list_widgets` opens a chart chooser in compatible hosts. Both current `_meta.ui.resourceUri` and legacy `_meta['ui/resourceUri']` pointers are included; other hosts retain the text summary and structured data. Tile controls retain the answer's granted workspace. Saving requires `mcp:dashboards:write`, `mcp:query`, the live workspace role, and `APPLY_TO_PRODUCTION` confirmation. No new environment variable is needed, including on self-hosted installs.
32
+ The hosted connector includes chart and KPI MCP Apps. `render_metric_tile` renders an existing saved metric directly without an embed, data app or datamart; `ask_question` returns a new answer as an inline tile, and `list_widgets` opens a chart chooser in compatible hosts. Both current `_meta.ui.resourceUri` and legacy `_meta['ui/resourceUri']` pointers are included; other hosts retain the text summary and structured data. Tile controls retain the answer's granted workspace. Saving requires `mcp:dashboards:write`, `mcp:query`, the live workspace role, and `APPLY_TO_PRODUCTION` confirmation. No new environment variable is needed, including on self-hosted installs. Saved category and measure settings drive bar, line, pie, doughnut, stacked and combo tiles. Gauges render inline, pivot/table tiles show a scrollable table, and text KPIs stay text. Large dashboard documents open a compact chart picker.
33
33
 
34
34
  <details>
35
35
  <summary><b>Claude (claude.ai and Claude Desktop)</b></summary>
@@ -448,13 +448,13 @@ Prompts are guided workflows your AI assistant can follow. Ask for them by name
448
448
  | `ask_question` | Ask a natural language question — gets converted to SQL, returns data + chart suggestion |
449
449
  | `get_semantic_layer` | Inspect semantic layer metadata (table/column descriptions, synonyms, completion score) |
450
450
  | `update_semantic_layer` | Improve semantic layer quality (add descriptions, synonyms, example questions) |
451
- | `start_semantic_layer_generation` | Start semantic-layer generation for a datamart |
452
- | `get_semantic_layer_generation_status` | Check semantic-layer generation progress |
451
+ | `start_semantic_layer_generation` | Start semantic-layer generation for a datamart (hosted OAuth) |
452
+ | `get_semantic_layer_generation_status` | Check semantic-layer generation progress (hosted OAuth) |
453
453
  | `search_semantic_model` | Find relevant v2 entities and their related entities |
454
454
  | `get_semantic_entity` | Read one v2 entity by kind and name with the current content hash |
455
455
  | `propose_semantic_change` | Validate candidate YAML or a patch and return its plan without writing |
456
456
  | `apply_semantic_change` | Preview by default, or apply live with a reviewed hash and production confirmation |
457
- | `eval_semantic_model` | Run saved queries and optional questions and return pass rate and verdicts |
457
+ | `eval_semantic_model` | Check closed-world model assertions (id/question/exercises); does not run SQL |
458
458
 
459
459
  Semantic-layer generation uses the datamart ID returned by `list_datamarts` and calls the service-token API. Pass `datamartId` directly when the ID is already known.
460
460
 
@@ -463,7 +463,7 @@ For a v2 model, the five model tools use `datamartId` and the configured service
463
463
  1. Use `search_semantic_model` with `question` and optional `k` (default 10, maximum 100). If the server has no retrieval route, the tool pulls the model and ranks name, alias, synonyms and description, then includes adjacent entities. Hidden tables and columns are excluded from local search.
464
464
  2. Use `get_semantic_entity` with `kind` and an exact `name`. Column names use `table.column`. Kinds are `table`, `column`, `measure`, `metric`, `join`, `entity`, `glossary`, `saved_query`, `instruction` and `access_rule`.
465
465
  3. Use `propose_semantic_change` with exactly one of `source` (complete YAML), `yaml_patch`, or `change`. It returns the candidate source, validation errors, the server plan and `expected_content_hash`. Invalid source returns errors and no plan.
466
- 4. Use `eval_semantic_model` with the proposed `source` and optional `questions`. Omitting source evaluates the stored model. The server returns pass rate and individual verdicts.
466
+ 4. Use `eval_semantic_model` with the proposed `source` and optional `questions`. Omitting source evaluates the stored model. Each question needs `id`, `question`, and `exercises` (exact model entity names). An omitted list becomes empty. This checks the model; it does not execute SQL.
467
467
  5. Review the plan. Call `apply_semantic_change` with the exact returned `source` and `expected_content_hash`. Its `dry_run` defaults to true. A live apply requires `dry_run: false` and user supplied `confirm: "APPLY_TO_PRODUCTION"`. The assistant must never supply confirmation on its own. Explicit `expected_content_hash: null` selects the first apply only when no layer is stored. Apply changes the live model for all consumers.
468
468
 
469
469
  A YAML patch merges mappings and named lists by name, including tables and columns. Other lists replace the original list. An empty list clears a list. Null removes a field. For example, `yaml_patch: "tables:\n - name: orders\n description: Customer purchases\n"` changes that description and preserves other tables and fields. Patch output normalizes YAML formatting and does not preserve comments. Review the returned source.
@@ -507,12 +507,18 @@ Production writes through `create_or_update_metric_from_query` default to `dry_r
507
507
  | Tool | Description |
508
508
  |------|-------------|
509
509
  | `custom_chart_scaffold` | Return the files of a new chart project (manifest, chart.ts, css, icon, sample data, author guide). Nothing is written or persisted |
510
+ | `custom_chart_edit` | Iterate a hosted draft through Chart studio Bryn when installed; never saves or publishes |
511
+ | `custom_chart_preview` | Compile a draft in memory and preview real sample rows as a sandboxed MCP App tile |
510
512
  | `custom_chart_validate` | Validate a manifest and bundle with the local rules and, when a service token is configured, the server rules. Never persists |
511
513
  | `custom_chart_upload` | Dry-run or upload a built bundle as a private chart (version 1) or a preview version; `publish: true` publishes in the same apply |
512
514
  | `list_custom_charts` | List the company's custom chart types with status and version ids |
513
515
  | `publish_custom_chart` | Dry-run or publish a version so every builder can use chart type `custom:<key>` |
514
516
 
515
- `custom_chart_upload` and `publish_custom_chart` default to `dry_run` and apply only with `confirm: "APPLY_TO_PRODUCTION"`. Hosted scopes: `mcp:custom-charts:read` and `mcp:custom-charts:write`. Build the bundle with the CLI below.
517
+ `custom_chart_upload` and `publish_custom_chart` default to `dry_run` and apply only with `confirm: "APPLY_TO_PRODUCTION"`. Hosted scopes: `mcp:custom-charts:read` and `mcp:custom-charts:write`. Hosted agents can pass `chartTs`, `manifest`, `bundleCss` and `iconSvg` to compile in memory, without local files or imports. `custom_chart_edit` feature-detects the Chart studio Bryn route (#4469); a missing route returns the draft for the calling agent to edit, while an authorization failure stays a failure. `custom_chart_preview` uses sample query rows and slot bindings without saving. Save a version with upload, then ask the user before publishing. Local projects can use the CLI below.
518
+
519
+ Custom tiles load the trusted sandbox runtime through the app-only `load_custom_chart_runtime` tool only when needed, preserving the built-in tile budget. Bundle chunks check live access and the current published pointer/hash on every call; validated immutable artifacts have a bounded content-hash cache. Calculations use the current bounded row page. Stdio credentials use source authoring directly, since Chart studio Bryn requires a hosted sign-in.
520
+
521
+ Published custom metric tiles load their company bundle through the same live grant as the chart result. Code runs in the app/embed runtime inside two opaque sandbox frames, with no network, credentials or privileged host actions. A missing/unpublished type or a host that blocks nested sandbox frames shows a fallback and the rows. Bundles are app-only metadata, outside the model context.
516
522
  </details>
517
523
 
518
524
  ---
@@ -612,3 +618,6 @@ All tokens are managed automatically. You provide your service token once in the
612
618
  ## License
613
619
 
614
620
  MIT
621
+
622
+
623
+ Saved hosted charts: call `list_dashboards`, then `get_dashboard` or `list_widgets` with its UUID/slug and workspace. Omit clientId for the saved dashboard view. Call `render_metric_tile({workspaceName, metricId, clientId?, display:"chart"})` to open a metricRef directly; the saved client must be supplied for a client-scoped metric. `display:"kpi"` returns the saved scalar, or labels the sum of a chart's sole numeric series across the full authorized result; multiple series refuse instead of guessing. Refresh and date-range controls recheck the same workspace and saved client. Use workspaceId for the wid in app links. Tenant/API-key reads still use embedId/clientId, with optional dataAppName for OAuth ambiguity. These operations create no dashboards, metrics or embeds.
@@ -123,19 +123,37 @@ declare const configSchema: z.ZodEffects<z.ZodEffects<z.ZodObject<{
123
123
  }>;
124
124
  type Config = z.infer<typeof configSchema>;
125
125
 
126
- declare const referenceSchema: z.ZodObject<{
126
+ declare const referenceSchema: z.ZodUnion<[z.ZodObject<{
127
127
  embedId: z.ZodString;
128
128
  clientId: z.ZodString;
129
129
  widgetId: z.ZodString;
130
+ dataAppName: z.ZodOptional<z.ZodString>;
130
131
  }, "strict", z.ZodTypeAny, {
131
132
  clientId: string;
132
133
  embedId: string;
133
134
  widgetId: string;
135
+ dataAppName?: string | undefined;
134
136
  }, {
135
137
  clientId: string;
136
138
  embedId: string;
137
139
  widgetId: string;
138
- }>;
140
+ dataAppName?: string | undefined;
141
+ }>, z.ZodObject<{
142
+ dashboardId: z.ZodString;
143
+ widgetId: z.ZodString;
144
+ clientId: z.ZodOptional<z.ZodString>;
145
+ display: z.ZodOptional<z.ZodEnum<["chart", "kpi"]>>;
146
+ }, "strict", z.ZodTypeAny, {
147
+ widgetId: string;
148
+ dashboardId: string;
149
+ clientId?: string | undefined;
150
+ display?: "chart" | "kpi" | undefined;
151
+ }, {
152
+ widgetId: string;
153
+ dashboardId: string;
154
+ clientId?: string | undefined;
155
+ display?: "chart" | "kpi" | undefined;
156
+ }>]>;
139
157
  type ChartReference = z.infer<typeof referenceSchema>;
140
158
  declare const viewSchema: z.ZodObject<{
141
159
  cursor: z.ZodOptional<z.ZodString>;
@@ -157,23 +175,25 @@ declare const viewSchema: z.ZodObject<{
157
175
  }>>;
158
176
  drillId: z.ZodOptional<z.ZodString>;
159
177
  }, "strict", z.ZodTypeAny, {
160
- cursor?: string | undefined;
161
178
  drillId?: string | undefined;
179
+ cursor?: string | undefined;
162
180
  dateRange?: {
163
181
  from: string;
164
182
  to: string;
165
183
  } | undefined;
166
184
  }, {
167
- cursor?: string | undefined;
168
185
  drillId?: string | undefined;
186
+ cursor?: string | undefined;
169
187
  dateRange?: {
170
188
  from: string;
171
189
  to: string;
172
190
  } | undefined;
173
191
  }>;
174
192
  declare const pageSchema: z.ZodEffects<z.ZodObject<{
175
- kind: z.ZodEnum<["chart", "kpi"]>;
193
+ kind: z.ZodEnum<["chart", "kpi", "table"]>;
176
194
  title: z.ZodString;
195
+ description: z.ZodOptional<z.ZodString>;
196
+ rowsTotal: z.ZodOptional<z.ZodNumber>;
177
197
  chartSpec: z.ZodObject<{
178
198
  type: z.ZodString;
179
199
  }, "strict", z.ZodTypeAny, {
@@ -184,6 +204,20 @@ declare const pageSchema: z.ZodEffects<z.ZodObject<{
184
204
  rows: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>>, "many">;
185
205
  columns: z.ZodArray<z.ZodString, "many">;
186
206
  svg: z.ZodOptional<z.ZodString>;
207
+ customChart: z.ZodOptional<z.ZodObject<{
208
+ key: z.ZodString;
209
+ bindings: z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString, "many">>;
210
+ options: z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodBoolean]>>;
211
+ }, "strict", z.ZodTypeAny, {
212
+ options: Record<string, string | number | boolean>;
213
+ key: string;
214
+ bindings: Record<string, string[]>;
215
+ }, {
216
+ options: Record<string, string | number | boolean>;
217
+ key: string;
218
+ bindings: Record<string, string[]>;
219
+ }>>;
220
+ fallback: z.ZodOptional<z.ZodString>;
187
221
  width: z.ZodNumber;
188
222
  height: z.ZodNumber;
189
223
  points: z.ZodArray<z.ZodObject<{
@@ -197,116 +231,148 @@ declare const pageSchema: z.ZodEffects<z.ZodObject<{
197
231
  drillId: z.ZodOptional<z.ZodString>;
198
232
  }, "strict", z.ZodTypeAny, {
199
233
  value: string | number | boolean | null;
200
- key: string;
201
234
  label: string;
202
- x: number;
203
- y: number;
204
235
  width: number;
205
236
  height: number;
237
+ x: number;
238
+ y: number;
239
+ key: string;
206
240
  drillId?: string | undefined;
207
241
  }, {
208
242
  value: string | number | boolean | null;
209
- key: string;
210
243
  label: string;
211
- x: number;
212
- y: number;
213
244
  width: number;
214
245
  height: number;
246
+ x: number;
247
+ y: number;
248
+ key: string;
215
249
  drillId?: string | undefined;
216
250
  }>, "many">;
217
251
  value: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>>;
218
252
  nextCursor: z.ZodOptional<z.ZodString>;
219
253
  }, "strict", z.ZodTypeAny, {
220
- kind: "chart" | "kpi";
221
- title: string;
222
254
  columns: string[];
255
+ rows: Record<string, string | number | boolean | null>[];
256
+ title: string;
223
257
  width: number;
224
258
  height: number;
225
- chartSpec: {
226
- type: string;
227
- };
228
- rows: Record<string, string | number | boolean | null>[];
229
259
  points: {
230
260
  value: string | number | boolean | null;
231
- key: string;
232
261
  label: string;
233
- x: number;
234
- y: number;
235
262
  width: number;
236
263
  height: number;
264
+ x: number;
265
+ y: number;
266
+ key: string;
237
267
  drillId?: string | undefined;
238
268
  }[];
269
+ kind: "chart" | "kpi" | "table";
270
+ chartSpec: {
271
+ type: string;
272
+ };
239
273
  value?: string | number | boolean | null | undefined;
274
+ description?: string | undefined;
240
275
  svg?: string | undefined;
276
+ rowsTotal?: number | undefined;
277
+ customChart?: {
278
+ options: Record<string, string | number | boolean>;
279
+ key: string;
280
+ bindings: Record<string, string[]>;
281
+ } | undefined;
282
+ fallback?: string | undefined;
241
283
  nextCursor?: string | undefined;
242
284
  }, {
243
- kind: "chart" | "kpi";
244
- title: string;
245
285
  columns: string[];
286
+ rows: Record<string, string | number | boolean | null>[];
287
+ title: string;
246
288
  width: number;
247
289
  height: number;
248
- chartSpec: {
249
- type: string;
250
- };
251
- rows: Record<string, string | number | boolean | null>[];
252
290
  points: {
253
291
  value: string | number | boolean | null;
254
- key: string;
255
292
  label: string;
256
- x: number;
257
- y: number;
258
293
  width: number;
259
294
  height: number;
295
+ x: number;
296
+ y: number;
297
+ key: string;
260
298
  drillId?: string | undefined;
261
299
  }[];
300
+ kind: "chart" | "kpi" | "table";
301
+ chartSpec: {
302
+ type: string;
303
+ };
262
304
  value?: string | number | boolean | null | undefined;
305
+ description?: string | undefined;
263
306
  svg?: string | undefined;
307
+ rowsTotal?: number | undefined;
308
+ customChart?: {
309
+ options: Record<string, string | number | boolean>;
310
+ key: string;
311
+ bindings: Record<string, string[]>;
312
+ } | undefined;
313
+ fallback?: string | undefined;
264
314
  nextCursor?: string | undefined;
265
315
  }>, {
266
- kind: "chart" | "kpi";
267
- title: string;
268
316
  columns: string[];
317
+ rows: Record<string, string | number | boolean | null>[];
318
+ title: string;
269
319
  width: number;
270
320
  height: number;
271
- chartSpec: {
272
- type: string;
273
- };
274
- rows: Record<string, string | number | boolean | null>[];
275
321
  points: {
276
322
  value: string | number | boolean | null;
277
- key: string;
278
323
  label: string;
279
- x: number;
280
- y: number;
281
324
  width: number;
282
325
  height: number;
326
+ x: number;
327
+ y: number;
328
+ key: string;
283
329
  drillId?: string | undefined;
284
330
  }[];
331
+ kind: "chart" | "kpi" | "table";
332
+ chartSpec: {
333
+ type: string;
334
+ };
285
335
  value?: string | number | boolean | null | undefined;
336
+ description?: string | undefined;
286
337
  svg?: string | undefined;
338
+ rowsTotal?: number | undefined;
339
+ customChart?: {
340
+ options: Record<string, string | number | boolean>;
341
+ key: string;
342
+ bindings: Record<string, string[]>;
343
+ } | undefined;
344
+ fallback?: string | undefined;
287
345
  nextCursor?: string | undefined;
288
346
  }, {
289
- kind: "chart" | "kpi";
290
- title: string;
291
347
  columns: string[];
348
+ rows: Record<string, string | number | boolean | null>[];
349
+ title: string;
292
350
  width: number;
293
351
  height: number;
294
- chartSpec: {
295
- type: string;
296
- };
297
- rows: Record<string, string | number | boolean | null>[];
298
352
  points: {
299
353
  value: string | number | boolean | null;
300
- key: string;
301
354
  label: string;
302
- x: number;
303
- y: number;
304
355
  width: number;
305
356
  height: number;
357
+ x: number;
358
+ y: number;
359
+ key: string;
306
360
  drillId?: string | undefined;
307
361
  }[];
362
+ kind: "chart" | "kpi" | "table";
363
+ chartSpec: {
364
+ type: string;
365
+ };
308
366
  value?: string | number | boolean | null | undefined;
367
+ description?: string | undefined;
309
368
  svg?: string | undefined;
369
+ rowsTotal?: number | undefined;
370
+ customChart?: {
371
+ options: Record<string, string | number | boolean>;
372
+ key: string;
373
+ bindings: Record<string, string[]>;
374
+ } | undefined;
375
+ fallback?: string | undefined;
310
376
  nextCursor?: string | undefined;
311
377
  }>;
312
378
  type ChartPage = z.infer<typeof pageSchema>;
@@ -1,10 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  createChartAppServer
4
- } from "../chunk-N7X762VU.js";
5
- import "../chunk-5IGP6A6T.js";
6
- import "../chunk-ERTAKB2H.js";
7
- import "../chunk-OCBTNAAO.js";
4
+ } from "../chunk-LACJHQYH.js";
5
+ import "../chunk-ZTHGF27R.js";
6
+ import "../chunk-OLOC2MTA.js";
7
+ import "../chunk-347U6GXR.js";
8
+ import "../chunk-Q5EYDKSA.js";
8
9
  export {
9
10
  createChartAppServer
10
11
  };
@@ -1,13 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  loadConfig
4
- } from "../chunk-CUPL7CAN.js";
4
+ } from "../chunk-V3UW3B6U.js";
5
5
  import {
6
6
  createChartAppServer
7
- } from "../chunk-N7X762VU.js";
8
- import "../chunk-5IGP6A6T.js";
9
- import "../chunk-ERTAKB2H.js";
10
- import "../chunk-OCBTNAAO.js";
7
+ } from "../chunk-LACJHQYH.js";
8
+ import "../chunk-ZTHGF27R.js";
9
+ import "../chunk-OLOC2MTA.js";
10
+ import "../chunk-347U6GXR.js";
11
+ import "../chunk-Q5EYDKSA.js";
11
12
 
12
13
  // src/apps/stdio.ts
13
14
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/apps/stdio.ts"],"sourcesContent":["import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { loadConfig } from '../utils/config.js';\nimport { createChartAppServer } from './server.js';\n\n// Separate opt-in command until the owners integrate both shared entrypoints.\nconst server = createChartAppServer(loadConfig());\nawait server.connect(new StdioServerTransport());\n"],"mappings":";;;;;;;;;;;;AAAA,SAAS,4BAA4B;AAKrC,IAAM,SAAS,qBAAqB,WAAW,CAAC;AAChD,MAAM,OAAO,QAAQ,IAAI,qBAAqB,CAAC;","names":[]}
1
+ {"version":3,"sources":["../../src/apps/stdio.ts"],"sourcesContent":["import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { loadConfig } from '../utils/config.js';\nimport { createChartAppServer } from './server.js';\n\n// Separate opt-in command until the owners integrate both shared entrypoints.\nconst server = createChartAppServer(loadConfig());\nawait server.connect(new StdioServerTransport());\n"],"mappings":";;;;;;;;;;;;;AAAA,SAAS,4BAA4B;AAKrC,IAAM,SAAS,qBAAqB,WAAW,CAAC;AAChD,MAAM,OAAO,QAAQ,IAAI,qBAAqB,CAAC;","names":[]}
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ DIST_FILES,
4
+ buildProject,
5
+ buildSource,
6
+ bundleSizeBytes,
7
+ contentHash,
8
+ readDist,
9
+ readProject,
10
+ validateBundle,
11
+ validateProject
12
+ } from "./chunk-Q5EYDKSA.js";
13
+ export {
14
+ DIST_FILES,
15
+ buildProject,
16
+ buildSource,
17
+ bundleSizeBytes,
18
+ contentHash,
19
+ readDist,
20
+ readProject,
21
+ validateBundle,
22
+ validateProject
23
+ };
24
+ //# sourceMappingURL=bundle-TDQXWIPM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}