@databrainhq/mcp-server 0.3.0-rc.13 → 0.3.0-rc.14
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/.mcp.json +6 -1
- package/dist/apps/server.d.ts +102 -389
- package/dist/apps/server.js +5 -5
- package/dist/apps/stdio.d.ts +1 -2
- package/dist/apps/stdio.js +6 -6
- package/dist/{bundle-TDQXWIPM.js → bundle-QJNCUMNY.js} +2 -2
- package/dist/{chunk-Q5EYDKSA.js → chunk-2F7V6RZR.js} +511 -107
- package/dist/chunk-2F7V6RZR.js.map +1 -0
- package/dist/{chunk-AEQTEE5C.js → chunk-AWICHHDU.js} +153 -61
- package/dist/chunk-AWICHHDU.js.map +1 -0
- package/dist/{chunk-X44C5GW2.js → chunk-CEGHG5U3.js} +59 -18
- package/dist/chunk-CEGHG5U3.js.map +1 -0
- package/dist/{chunk-233VGFHY.js → chunk-NIC5MAGC.js} +317 -147
- package/dist/chunk-NIC5MAGC.js.map +1 -0
- package/dist/{chunk-DTFYHLYN.js → chunk-S65KA3Z7.js} +26 -11
- package/dist/chunk-S65KA3Z7.js.map +1 -0
- package/dist/{chunk-PSJVYD4W.js → chunk-UYFFFAYV.js} +11722 -10560
- package/dist/chunk-UYFFFAYV.js.map +1 -0
- package/dist/{chunk-HCYZN7I3.js → chunk-VQ5G5AZV.js} +10 -7
- package/dist/chunk-VQ5G5AZV.js.map +1 -0
- package/dist/cli.d.ts +16 -15
- package/dist/cli.js +134 -36
- package/dist/cli.js.map +1 -1
- package/dist/custom-chart/custom-runtime.js +6 -6
- package/dist/custom-chart/template/chart.ts +116 -28
- package/dist/custom-chart/template/icon.svg +1 -1
- package/dist/custom-chart/template/manifest.json +66 -12
- package/dist/custom-chart/template/sample-data.json +21 -3
- package/dist/index.d.ts +1 -2
- package/dist/index.js +20 -10
- package/dist/index.js.map +1 -1
- package/dist/{main-VEKNKWL5.js → main-QCBVJSSR.js} +348 -155
- package/dist/main-QCBVJSSR.js.map +1 -0
- package/dist/{test-only-LJGOY2QA.js → test-only-6474NMTR.js} +12 -8
- package/dist/test-only-6474NMTR.js.map +1 -0
- package/package.json +20 -9
- package/dist/chunk-233VGFHY.js.map +0 -1
- package/dist/chunk-AEQTEE5C.js.map +0 -1
- package/dist/chunk-DTFYHLYN.js.map +0 -1
- package/dist/chunk-HCYZN7I3.js.map +0 -1
- package/dist/chunk-PSJVYD4W.js.map +0 -1
- package/dist/chunk-Q5EYDKSA.js.map +0 -1
- package/dist/chunk-X44C5GW2.js.map +0 -1
- package/dist/main-VEKNKWL5.js.map +0 -1
- package/dist/test-only-LJGOY2QA.js.map +0 -1
- /package/dist/{bundle-TDQXWIPM.js.map → bundle-QJNCUMNY.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/prompts/brand-my-embed.ts","../src/prompts/customize-customer-dashboard.ts","../src/prompts/embed-blank-dashboard.ts","../src/prompts/embed-existing-dashboard.ts","../src/prompts/populate-semantic-layer.ts","../src/prompts/query-data.ts","../src/prompts/sql-to-metric-migration.ts","../src/prompts/sql-to-workspace-metric.ts","../src/prompts/registry.ts","../src/resources/content/api-reference.ts","../src/resources/content/embedding-guide.ts","../src/resources/content/filter-reference.ts","../src/resources/content/getting-started.ts","../src/resources/content/multi-tenancy-guide.ts","../src/resources/content/permission-schema.ts","../src/resources/content/self-serve-reference.ts","../src/resources/content/semantic-layer-guide.ts","../src/resources/content/theme-reference.ts","../src/resources/content/use-case-guides.ts","../src/resources/content/web-component-reference.ts","../src/resources/registry.ts","../src/apps/contract.ts","../src/apps/feature.ts","../src/tools/analytics/list-dashboards.ts","../src/api/dashboards-api.ts","../src/api/data-apps-api.ts","../src/api/datamarts-api.ts","../src/api/datasources-api.ts","../src/api/embeds-api.ts","../src/api/guest-token-api.ts","../src/api/query-api.ts","../src/api/scheduled-reports-api.ts","../src/api/semantic-model-api.ts","../src/api/tenants-api.ts","../src/api/widgets-api.ts","../src/api/workspaces-api.ts","../src/services/discovery-service.ts","../src/services/embed-service.ts","../src/services/guest-token-service.ts","../src/services/widget-service.ts","../src/services/factory.ts","../src/tools/annotations.ts","../src/tools/auth/whoami.ts","../src/tools/custom-chart/author.ts","../src/tools/custom-chart/shared.ts","../src/tools/custom-chart/list.ts","../src/tools/custom-chart/publish.ts","../src/tools/widgets/production-guards.ts","../src/tools/custom-chart/scaffold.ts","../src/tools/custom-chart/upload.ts","../src/tools/custom-chart/validate.ts","../src/tools/dashboard/schema.ts","../src/tools/dashboard/create-dashboard.ts","../src/tools/dashboard/dashboard-snapshot.ts","../src/tools/dashboard/generate-dashboard-tiles.ts","../src/utils/resolve-resource.ts","../src/tools/dashboard/get-dashboard.ts","../src/tools/data-app/create-api-token.ts","../src/tools/data-app/create-data-app.ts","../src/tools/data-app/list-api-tokens.ts","../src/tools/data-app/list-data-apps.ts","../src/tools/data-app/list-tenants.ts","../src/tools/data-app/rotate-api-token.ts","../src/tools/embed/create-embed.ts","../src/tools/embed/customize-theme.ts","../src/tools/embed/helpers.ts","../src/tools/embed/get-demo-link.ts","../src/tools/embed/get-embed-details.ts","../src/tools/embed/list-embeds.ts","../src/tools/embed/update-embed.ts","../src/tools/frontend/generate-embed-code.ts","../src/templates/angular.ts","../src/templates/nextjs.ts","../src/templates/react.ts","../src/templates/solidjs.ts","../src/templates/svelte.ts","../src/templates/vanilla.ts","../src/templates/vue.ts","../src/templates/index.ts","../src/tools/frontend/generate-guest-token.ts","../src/tools/infrastructure/create-datamart.ts","../src/tools/infrastructure/discover-datasource-schema.ts","../src/tools/infrastructure/list-datamarts.ts","../src/tools/infrastructure/list-datasources.ts","../src/tools/infrastructure/list-workspaces.ts","../src/tools/infrastructure/sync-datasource.ts","../src/apps/preview.ts","../src/tools/query/ask-question.ts","../src/tools/query/answer-format.ts","../src/tools/query/get-semantic-layer.ts","../src/tools/query/semantic-generation.ts","../src/tools/query/semantic-model.ts","../src/services/semantic-source.ts","../src/services/semantic-retrieval.ts","../src/tools/query/update-semantic-layer.ts","../src/tools/reports/list-scheduled-reports.ts","../src/tools/tool-metadata.ts","../src/tools/tool-titles.ts","../src/tools/widgets/add-widget.ts","../src/tools/widgets/create-or-update-metric-from-query.ts","../src/tools/widgets/create-workspace-metric.ts","../src/tools/widgets/generate-widget.ts","../src/tools/widgets/list-widgets.ts","../src/tools/widgets/remove-widget.ts","../src/tools/widgets/update-widget.ts","../src/tools/widgets/validate-metric-spec.ts","../src/tools/registry.ts"],"sourcesContent":["export const brandMyEmbedPrompt = `You are helping the user brand and visually customize their embedded Databrain dashboard. Follow these steps.\n\n**Step 1 — Identify the Embed**\nCall \\`list_embeds\\` to show available embeds. Ask the user which one they want to brand. Then call \\`get_embed_details\\` to see the current theme and configuration.\n\n**Step 2 — Understand Brand Requirements**\nAsk the user about their brand. Gather as many of these as they can provide:\n- **Primary brand color** (e.g. \"#4F46E5\")\n- **Secondary/accent color**\n- **Font family** (e.g. Inter, Roboto, Open Sans, system default)\n- **Style preference** — modern/rounded vs corporate/sharp vs minimal/clean\n- **Dark or light mode?**\n- **Any specific chart colors they want?**\n\nIf they're unsure, suggest starting with a preset (\\`light\\`, \\`dark\\`, \\`corporate\\`, or \\`minimal\\`) using \\`customize_embed_theme\\` with the \\`themePreset\\` parameter, and refining from there.\n\n**Step 3 — Apply Theme**\nUse \\`customize_embed_theme\\` with the gathered brand values. Map their preferences to:\n- \\`primaryColor\\`, \\`backgroundColor\\`, \\`textColor\\` — from their brand colors\n- \\`fontFamily\\` — from their font choice\n- \\`cardBorderRadius\\` — \"12px\" for modern/rounded, \"4px\" for corporate, \"0px\" for minimal\n- \\`cardShadow\\` — subtle shadow for modern, \"none\" for minimal\n- \\`dashboardBackgroundColor\\` — slightly off-white for light, dark gray for dark\n- \\`chartColors\\` — if they provided specific colors, use those\n\nAlso set component-level theme if they have button/checkbox color preferences:\n- \\`buttonPrimaryColor\\`, \\`buttonPrimaryTextColor\\`\n- \\`checkboxCheckedColor\\`, \\`switchEnabledColor\\`\n- \\`datePickerColor\\` — accent color for date pickers\n- \\`metricCardColor\\` — metric card background color (via adminTheme.dashboard)\n\n**Step 4 — Configure Chart Appearance**\nUse \\`customize_embed_theme\\` with the chart appearance params to fine-tune charts:\n- Set \\`legendPosition\\` — \"bottom-center\" is a safe default\n- Set \\`legendShape\\` — \"circle\" for modern, \"rect\" for corporate\n- Set \\`legendLayout\\` — \"horizontal\" usually works best\n- Set chart colors if not already done via theme\n\nAsk if they want to customize tooltip fonts, axis styling, or label positions.\n\n**Step 5 — Configure Display Options**\nUse \\`update_embed\\` (body passthrough) to clean up the UI:\n- Ask if they want to hide the dashboard name (\\`hideDashboardName\\`)\n- Ask about card shadows and borders\n- Ask about download/export options they want to show\n- Suggest disabling chart settings and table preview for a cleaner look for end-users\n- Ask if they want click-to-fullscreen on metric titles (\\`enableTitleClickFullscreen\\`)\n- Ask about export notification position (\\`exportMsgPosition\\`: bottom, top, center, etc.)\n- Ask about a custom no-data image (\\`noDataImg\\` URL or \\`noDataFoundSvg\\` inline SVG)\n- Ask about a custom settings icon (\\`settingsIconName\\`, \\`settingsIconSvg\\`)\n- Ask about long-description tooltip styling (\\`longDescriptionWidth\\`, \\`longDescriptionFontColor\\`)\n\n**Step 6 — Responsive Layout (Optional)**\nIf the user's embed will appear at different screen sizes, configure responsive breakpoints via \\`customize_embed_theme\\`:\n- \\`breakpointXl/Lg/Md/Sm/Xs\\` — screen-width thresholds\n- \\`layoutColsXl/Lg/Md/Sm/Xs/Xxs\\` — number of grid columns at each breakpoint\nThis gives control over how metric cards reflow on mobile, tablet, and desktop.\n\n**Three Approaches to Theming:**\n1. **Named Theme Presets**: Use \\`customize_embed_theme\\` with \\`themePreset\\` (light, dark, corporate, minimal). Quick start, consistent look.\n2. **Inline Custom Theme**: Use \\`customize_embed_theme\\` with granular params for full control over colors, fonts, spacing. Best for exact brand matching.\n3. **Admin Theme Options**: Configure theme settings in the Databrain admin panel and let them cascade to embeds. Best for org-wide consistency.\n\n**Step 7 — Preview and Iterate**\nTell the user to refresh their embed to see the changes. Ask:\n- \"Does this match your brand?\"\n- \"Anything you'd like to adjust — colors, fonts, spacing, chart styling?\"\n\nIterate by calling the relevant tools again with adjusted values. Remember: all customization tools merge with existing config, so they only need to send what changed.\n\n**Important:** After any theme or styling changes, existing guest tokens still carry the old configuration. Remind the user to **regenerate guest tokens** (or reload their app) for changes to take effect.\n\n**Reference**: Use \\`databrain://theme-reference\\` for the full theme schema and \\`databrain://web-component-reference\\` for all component attributes.`;\n","export const customizeCustomerDashboardPrompt = `You are guiding widget CRUD on a specific customer's dashboard. This is the \"tweak per customer\" flow for a non-technical CS/CX/support user: add, modify, or remove individual widgets for one customer without touching the template or other customers.\n\n**CRITICAL: This is an interactive, step-by-step guide. STOP after each step, show the user what you found, and wait for their input. Never batch multiple steps. Never assume the customer or dashboard.**\n\n**Minimum info the user needs to provide: \\`clientId\\` + \\`dashboardName\\`.** Everything else (data app, datasource, embed id, integration id) is auto-resolved. NEVER ask the user for any of those.\n\n**Key concepts (read before starting):**\n- **Dashboard** = the named analytics view the customer sees (e.g. \"Demo Dashboard\", \"Airline Marketing\"). This is what the user will name.\n- **Workspace** = an optional container grouping dashboards. Only ask for this if the dashboard name is ambiguous.\n- **Client/customer** = the tenant whose copy of the dashboard we're editing. Identified by \\`clientId\\`.\n- **Widget** = a single visualization on a dashboard. Has two ids: \\`metricId\\` (slug, shown in lists) and \\`externalMetricId\\` (uuid, used for update/remove).\n- **Per-client scope**: \\`remove_widget\\` is a per-client soft delete — the widget stays on the template dashboard and on other customers' copies.\n\n**Forbidden questions — DO NOT ASK the user for any of these:**\n- Data app name, \\`dataAppName\\`\n- Datasource name, \\`integrationName\\`, \\`integrationId\\`, \\`companyIntegrationId\\`\n- Embed id, \\`embedId\\`\n- External dashboard id, dashboard id, internal UUIDs\n\nIf the user offers any of these proactively, accept and use them, but never prompt for them.\n\n**Step 1 — Identify the customer and dashboard**\nSTOP and ASK the user:\n- \"Which customer/client are we customizing for?\" (capture as \\`clientId\\`)\n- \"Which dashboard?\" (capture as \\`dashboardName\\`)\n\nOnly ask about workspace if the tool reports the dashboard name is ambiguous across workspaces.\n\n**Step 2 — Survey the current widgets**\nCall \\`list_widgets({ clientId, dashboardName, workspaceName? })\\`.\nSTOP and present the list: \\`{externalMetricId, metricId, name, isPublished, createdByUser}\\` per widget. Keep the \\`externalMetricId\\` values from this response — you'll need them verbatim for update/remove. Show the user the human-readable names; the uuids are yours to reference internally.\nASK: \"What would you like to change? (add / modify / remove) — and which widgets?\"\n\n**Step 3a — ADD a widget**\nBusiness-user flow. NEVER ask for SQL, datasource, or chart config unless the user explicitly says they want to write raw SQL.\n\n1. **Clone an existing chart** (default — try this first):\n - ASK: \"Which existing chart should I copy from?\" Call \\`list_widgets\\` and present the widgets by name. Let the user pick by name.\n - Call \\`add_widget({ clientId, dashboardName, workspaceName?, templateMetricId, name? })\\` using the picked widget's \\`metricId\\`. Query, chart config, and datasource are inherited automatically.\n\n2. **Describe the chart in plain English** (AI generate — use if no suitable template exists):\n - ASK: \"Describe the chart you want\" (e.g., \"calls per day over last 30 days\").\n - Call \\`generate_widget({ clientId, dashboardName, workspaceName?, userInputs: { prompt: \"...\" } })\\`.\n - Review the returned \\`draft\\` with the user. If they approve, call \\`add_widget({ clientId, dashboardName, workspaceName?, body: <draft + externalDashboardIds> })\\` to persist.\n - If they want changes, re-run \\`generate_widget\\` with a refined prompt.\n - If \\`generate_widget\\` reports \"Could not auto-detect the datasource\", STOP and ASK the user to choose: (a) pick an existing chart to copy from (recommended — call \\`list_widgets\\`, present widgets by name, then use \\`add_widget\\` with \\`templateMetricId\\`); or (b) pick a datasource by name from the list in the error (only if the user already knows it). Wait for the user's choice — do not guess.\n\n**Advanced — write SQL directly** (technical users only; ONLY if the user explicitly asks to write SQL):\n- ASK for: \\`name\\`, \\`query\\` (SQL), \\`chartOptions\\`.\n- Call \\`add_widget({ clientId, dashboardName, name, query, chartOptions })\\` — datasource still auto-resolves from the dashboard.\n\nShow the user the new widget's \\`externalMetricId\\` and \\`metricId\\` after each add.\n\n**Step 3b — UPDATE a widget**\nIf the user wants to modify a widget, STOP and ASK:\n- Which widget? (let the user pick by name, then look up the widget's \\`externalMetricId\\` from the Step 2 \\`list_widgets\\` response — this is the uuid, NOT the \\`metricId\\` slug. If you skipped Step 2, call \\`list_widgets\\` first to fetch it — never ask the user for a uuid.)\n- What to change? (name, query, chartOptions, isPublished, etc.)\n\nCall \\`update_widget({ externalMetricId, clientId, dashboardName, workspaceName?, set: {<partial patch>} })\\`.\nShow the user the confirmation and list the changed fields.\n\n**Step 3c — REMOVE a widget**\nIf the user wants to remove a widget, STOP and CONFIRM:\n- \"This is a per-customer soft delete. The widget will be hidden for \\`<clientId>\\` only — other customers and the template dashboard are unaffected. Proceed?\"\n\nLook up the widget's \\`externalMetricId\\` from the Step 2 \\`list_widgets\\` response (call it first if you skipped Step 2). Never ask the user for the uuid.\nWait for explicit confirmation before calling \\`remove_widget({ externalMetricId, clientId, dashboardName, workspaceName? })\\`.\n\n**Step 4 — Verify**\nCall \\`list_widgets({ clientId, dashboardName, workspaceName? })\\` again. Present the updated list and confirm the changes match what the user asked for.\n\n**Step 5 — Hand off the demo link**\nAlways close with a demo link so the user can verify visually. Call \\`get_demo_link({ clientId, dashboardName, workspaceName? })\\` — it returns the same URL the Databrain UI's \"Share Demo Link\" button generates: a hosted preview page that loads the dashboard exactly as that \\`clientId\\` will see it. Default expiry is 24h; pass \\`expiryHours\\` to override.\n\nPresent the URL to the user and remind them: (a) only \\`isPublished: true\\` widgets appear in the preview, so flag any unpublished widgets from the Step 4 \\`list_widgets\\` output; (b) if they already have the embed wired up in their own app, the cached frontend guest token there must be refreshed before changes appear.\n\n**Important rules:**\n- STOP after each step. Present results and wait for user input before proceeding.\n- Always pass \\`externalMetricId\\` (uuid) to \\`update_widget\\` / \\`remove_widget\\`, NOT the \\`metricId\\` slug.\n- Never ask for data app, datasource, integration, or embed identifiers — they all auto-resolve from \\`dashboardName\\`.\n- Never batch add + update + remove without confirming each one.\n\nAfter completion, suggest: \\`brand-my-embed\\` if they want to adjust theme, or \\`manage-embeds\\` if they want to tweak access settings / options.`;\n","export const embedBlankDashboardPrompt = `You are guiding a multi-tenant setup where each client gets their own blank (or template-based) dashboard. This is ideal for SaaS platforms where each customer sees their own analytics.\n\n**CRITICAL: This is an interactive, step-by-step guide. You MUST stop after each step, show the user what you found, and wait for their input before proceeding. Never batch multiple steps. Never assume answers.**\n\n**Token model (important — never confuse these):**\n- Service token (DATABRAIN_SERVICE_TOKEN): org-level, already configured. Used for infrastructure. Never ask the user for this.\n- API token: per data app, created via \\`create_api_token\\`. Used for embedding operations. Managed automatically.\n\n**Key concept: Dashboard Embeds vs Standard Embeds**\n- Standard embeds (\\`create_embed\\` without \\`clientId\\`) share one dashboard across all clients — row-level security via \\`clientId\\` in guest token.\n- Dashboard embeds (\\`create_embed\\` with \\`clientId\\`) give each client their own dashboard copy — ideal when clients need to create their own metrics or customize their view.\n- Use dashboard embeds when: clients need metric creation, each client needs a different layout, or you want per-client dashboard isolation.\n\n**Step 1 — Verify Prerequisites**\nCall \\`list_data_apps\\` to find the target data app. STOP and present the list — ASK the user to confirm which one.\nCall \\`list_api_tokens\\` — if no token exists, call \\`create_api_token\\`.\n\n**Step 2 — Identify the Source Dashboard**\nCall \\`list_dashboards\\` to find the template/source dashboard.\nSTOP and present the list. ASK the user which dashboard to use as the template.\nIf the user wants a completely blank dashboard, tell them to create one in the Databrain UI first and come back.\nIf using a template: note the \\`dashboardId\\` — this becomes the \\`templateDashboardId\\`.\nDo NOT proceed until the user confirms.\n\n**Step 3 — Set Up Multi-Tenancy**\nSTOP and ASK the user:\n- \"What column in your database identifies each client?\" (e.g., \\`company_id\\`, \\`tenant_id\\`)\n- \"What are the client IDs you want to provision?\"\n\nCall \\`list_datamarts\\` to verify the datamart has proper tenancy configuration.\nIf the datamart doesn't have \\`clientColumn\\` set, tell the user they need to update it in the Databrain UI or create a new datamart with \\`tenancySettings\\`.\nDo NOT proceed until tenancy is confirmed.\n\n**Step 4 — Create Dashboard Embeds (per client)**\nFor each client the user specified, call \\`create_embed\\` with:\n- \\`dashboardId\\`: the blank/source dashboard ID\n- \\`workspaceName\\`: from the dashboard data\n- \\`clientId\\`: the client's unique identifier\n- \\`accessSettings: { datamartName: \"<resolved>\" }\\` — only datamartName is needed, the tool fills all other required fields with secure defaults. Do NOT add isAllow* fields yourself.\n- Optionally: \\`templateDashboardId\\`, \\`isImportMetrics\\`, \\`metricImportMode\\` if cloning from a template\n\nShow the user each created embed. If they have many clients, show the pattern and suggest programmatic creation.\n\n**Step 5 — Configure Access Settings (if needed)**\nSTOP and ASK: \"Do you need to enable any special features? (metric creation, AI pilot, email reports, etc.)\"\nIf yes, use \\`update_embed\\` with the specific flags they want. If no, skip this step.\n\n**Step 6 — Generate Guest Tokens (per client)**\nSTOP and ASK: \"What \\`clientId\\` should I generate a guest token for?\"\nCall \\`generate_guest_token\\` with the user's answer, \\`dataAppName\\`, and default permissions.\nThe \\`clientId\\` in the guest token MUST match the \\`clientId\\` used when creating the dashboard embed.\n\n**Step 7 — Generate Frontend Code**\nSTOP and ASK: \"Which frontend framework? (React, Next.js, Vue, Angular, Svelte, SolidJS, vanilla JS)\"\nCall \\`generate_embed_code\\` with any of the embed IDs.\nThe frontend code is the same for all clients — the \\`clientId\\` in the guest token determines which dashboard they see.\n\n**Important rules:**\n- STOP after each step. Present results and wait for user input before proceeding.\n- When calling \\`create_embed\\` with \\`clientId\\`, only pass \\`accessSettings: { datamartName }\\` — the tool fills in all required defaults automatically. Do NOT enumerate isAllow* fields.\n- \\`clientId\\` must be consistent between embed creation and guest token generation.\n- After setup, suggest: \\`brand-my-embed\\` for theming. For filters, metric creation, or permissions, just describe what you need and use \\`update_embed\\` / \\`generate_guest_token\\` directly.`;\n","export const embedExistingDashboardPrompt = `You are guiding a user who already has data apps and dashboards set up in the Databrain UI and wants to embed an existing dashboard. This is the most common use case.\n\n**CRITICAL: This is an interactive, step-by-step guide. You MUST stop after each step, show the user what you found, and wait for their choice before proceeding. Never batch multiple steps. Never assume answers.**\n\n**Token model (important — never confuse these):**\n- Service token (DATABRAIN_SERVICE_TOKEN): org-level, already configured in MCP server config. Used for discovery and data app management. Never ask the user for this.\n- API token: per data app, created/rotated via \\`create_api_token\\` or \\`rotate_api_token\\`. Used for embedding operations. Managed automatically — never ask the user for it.\n\n**Step 1 — List Data Apps**\nCall \\`list_data_apps\\` to show all available data apps.\nSTOP and present the list to the user. If multiple: ask them to pick. If one: confirm with the user.\nDo NOT proceed until the user confirms which data app to use.\n\n**Step 2 — Ensure API Token**\nCall \\`list_api_tokens\\` for the chosen data app.\n- If a token exists: use it.\n- If no token: call \\`create_api_token\\` to generate one.\nTell the user the token is ready. Do not ask the user for any token.\n\n**Step 3 — Select Workspace**\nCall \\`list_workspaces\\` to discover available workspaces.\n- If one workspace: auto-select and tell the user.\n- If multiple: STOP and present the list. ASK which workspace to use.\nThis ensures dashboards are listed from the correct workspace context.\n\n**Step 4 — List Dashboards**\nCall \\`list_dashboards\\` (with the workspace context) to show dashboards.\nSTOP and present the list with names and IDs. ASK the user which dashboard they want to embed.\nNote the \\`workspaceName\\` from their chosen dashboard — this is needed for embed creation.\nDo NOT proceed until the user picks a dashboard.\n\n**Step 5 — Create Embed**\nBefore creating, check: call \\`list_embeds\\` to see if an embed already exists for this dashboard.\nIf one exists, STOP and ASK: \"An embed already exists for this dashboard. Want to use it, or create a new one?\"\nIf creating new: resolve datamartName by calling \\`list_datamarts\\`, then call \\`create_embed\\` with:\n- \\`dashboardId\\`: from the chosen dashboard\n- \\`workspaceName\\`: from the dashboard data (NOT the data app name)\n- \\`accessSettings: { datamartName: \"<resolved>\" }\\` — only datamartName is needed, the tool fills in all other required defaults automatically. Do NOT add isAllow* fields yourself.\n\n**Step 6 — Verify Embed**\nCall \\`get_embed_details\\` to verify the embed is properly configured.\nShow the user the embed ID and status.\n\n**Step 7 — Generate Guest Token**\nSTOP and ASK the user: \"What is your client/tenant identifier (clientId)?\"\nOnly after they answer, call \\`generate_guest_token\\` with \\`clientId\\`, \\`dataAppName\\`, and default permissions.\n\n**Step 8 — Generate Frontend Code**\nSTOP and ASK: \"Which frontend framework? (React, Next.js, Vue, Angular, Svelte, SolidJS, vanilla JS)\"\nOnly after they answer, call \\`generate_embed_code\\` with the \\`embedId\\`.\n\n**Important rules:**\n- STOP after each step. Present results and wait for user input before proceeding.\n- When calling \\`create_embed\\`, only pass \\`accessSettings: { datamartName }\\` — the tool fills in all required defaults automatically. Do NOT enumerate isAllow* fields.\n- Prefer existing embeds when the user already has one for their target dashboard.\n- NEVER ask for service or API tokens — both are handled automatically.\n- \\`workspaceName\\` comes from dashboard data, not from the data app name.\n- After setup, suggest: \\`brand-my-embed\\` for theming. For filters, localization, or permissions, just describe what you need and use \\`update_embed\\` / \\`generate_guest_token\\` directly.`;\n","export const populateSemanticLayerPrompt = `You are helping the user populate the semantic layer for a Databrain datamart. The semantic layer provides table/column descriptions, synonyms, and context that the AI needs to convert natural language questions into accurate SQL.\n\n**For a v2 semantic model**\nIf \\`list_datamarts\\` reports \\`semanticLayerVersion: \"v2\"\\`, or the selected datamart is already known to use v2, use this workflow instead of the legacy steps below:\n1. Inspect relevant entities with \\`search_semantic_model\\` and \\`get_semantic_entity\\`, using the datamart ID.\n2. Call \\`propose_semantic_change\\` with a YAML patch or structured change. Show its errors and plan. Correct errors before continuing.\n3. Call \\`eval_semantic_model\\` with the returned source. For scored assertions, supply questions with id, question and exercises (exact model entity names); this does not run SQL. Show the verdicts and let the user review the candidate.\n4. Stop for the user's explicit \\`APPLY_TO_PRODUCTION\\` confirmation. Never supply it yourself.\n5. Call \\`apply_semantic_change\\` with the exact reviewed source, its \\`expected_content_hash\\`, \\`dry_run: false\\` and the user's confirmation. A conflict requires a new proposal and review.\n6. Call \\`get_semantic_entity\\` and inspect the changed entity. Do not call \\`update_semantic_layer\\` for a v2 model.\n\n**Why this matters:** Without a populated semantic layer, \\`ask_question\\` cannot generate SQL — every query will fail with \"out of context.\" Populating the semantic layer is the critical step between having a datamart and being able to query it.\n\n**Step 1 — Identify the Datamart**\nUse \\`list_datamarts\\` to find the target datamart. If only one exists, use it automatically.\n\n**Step 2 — Inspect Current State**\nCall \\`get_semantic_layer\\` with the datamartName. This returns:\n- All synced tables and columns (these come from the database — they already exist)\n- Any existing descriptions, synonyms, or context\n- A completion score (0–100%)\n\nIf the completion score is above 80% and descriptions look good, tell the user the semantic layer is already in good shape and offer to proceed to querying.\n\n**Step 3 — Auto-Generate Descriptions**\nThis is the key step. For each table and its columns, generate business-friendly descriptions based on the names and data types. You are an LLM — use your knowledge to infer what tables and columns represent.\n\nGuidelines for generating descriptions:\n- **Table descriptions:** Explain what the table contains in 1-2 sentences. Example: \\`orders\\` → \"Contains customer purchase orders with line items, totals, and fulfillment status.\"\n- **Column descriptions:** Explain the business meaning. Example: \\`total_amount\\` → \"Total order value in the customer's local currency, including tax and shipping.\"\n- **Synonyms:** Add common alternative names users might say. Example: \\`total_amount\\` → [\"revenue\", \"order total\", \"sales amount\"]\n- **Column types:** Only use supported semantic types: \"String\", \"Long String\", \"ENUM\", \"Mapper\", \"Range\", \"Expression\", \"Identifier\", \"Number\", or \"JSON\". Omit \\`columnType\\` for date and boolean database columns.\n\nAsk the user if they want to review and refine the descriptions before applying, or if you should go ahead and apply them directly.\n\n**Step 4 — Apply Descriptions**\nCall \\`update_semantic_layer\\` with:\n- \\`datamartName\\`: the target datamart\n- \\`tables\\`: array of table objects, each with \\`name\\`, \\`description\\`, \\`synonyms\\`, and \\`columns\\` (each column with \\`name\\`, \\`description\\`, \\`synonyms\\`, \\`columnType\\`)\n- \\`feedback\\`: optional general context (e.g. \"E-commerce platform data for US market, dates are in UTC\")\n\nYou can update all tables in a single call or break it into multiple calls for large schemas.\n\n**Step 5 — Verify**\nCall \\`get_semantic_layer\\` again to verify the completion score improved. If it's above 50%, the datamart is ready for querying. Above 80% is ideal.\n\n**Step 6 — Test a Query**\nSuggest a sample question based on the tables you described and run it with \\`ask_question\\`. This validates that the semantic layer is working correctly.\n\n**Example Flow:**\n1. \\`get_semantic_layer\\` → sees \\`orders\\`, \\`customers\\`, \\`products\\` tables with 0% completion\n2. Generate descriptions for all tables and key columns\n3. \\`update_semantic_layer\\` with the generated descriptions\n4. \\`get_semantic_layer\\` → confirms 75% completion\n5. \\`ask_question\\` with \"What was total revenue last month?\" → works!\n\n**Important Notes:**\n- Tables and columns are already synced from the database — you do NOT need to add or create them\n- Do NOT send the user to the Databrain UI for semantic layer population — do it here via \\`update_semantic_layer\\`\n- If the user has domain-specific knowledge, ask them to help refine descriptions (e.g. what \"status=3\" means)\n- Prioritize tables and columns that users are most likely to query\n- For very large schemas (50+ tables), start with the most important tables and expand as needed\n`;\n","export const queryDataPrompt = `You are helping the user query their data using natural language. Databrain's AI converts questions into SQL, runs them against the database, and returns results with chart type suggestions.\n\n**Pre-requisites for \\`ask_question\\`**\nBoth conditions must be satisfied BEFORE calling \\`ask_question\\`. The tool enforces these checks automatically and will reject the call if either is missing — so verify early rather than getting an error.\n\n1. **A datamart must exist** — it defines which tables the AI can query.\n2. **The datamart's semantic layer must have at least one table** — it provides the descriptions, synonyms, and context the AI needs to generate correct SQL. Without it, every question will fail with \"out of context.\"\n\nIf either pre-requisite is missing, **ask the user** whether they want to set it up and guide them through the steps below. Do not silently attempt to query.\n\n**Step 1 — Discover Available Data**\nUse \\`list_datamarts\\` to see what datamarts are available. Each datamart maps to a set of database tables.\n\nIf **no datamarts exist**, tell the user they need to create one in the **Databrain UI**:\n1. Use \\`list_datasources\\` to check if a database connection exists — share the results with the user\n2. Use \\`discover_datasource_schema\\` to show available tables and columns — this helps the user decide which tables to include\n3. Tell the user to go to the Databrain platform to create a datamart using those tables\n4. Once the user confirms the datamart is created, re-run \\`list_datamarts\\` and proceed to the semantic layer check\n\nIf **no datasources exist either**, the user must first connect their database in the **Databrain UI**.\n\n**For a v2 semantic model**\nIf the datamart uses v2, inspect the question's entities with \\`search_semantic_model\\` and \\`get_semantic_entity\\`. Then continue to Step 2. If metadata needs correction, use \\`propose_semantic_change\\`, evaluate its source with \\`eval_semantic_model\\`, and show the plan. Only apply the reviewed source and expected hash through \\`apply_semantic_change\\` after the user supplies \\`APPLY_TO_PRODUCTION\\`. Never use the legacy \\`update_semantic_layer\\` steps below for v2.\n\n**Step 1b — Verify the Semantic Layer**\nAfter confirming a datamart exists, use \\`get_semantic_layer\\` to check its tables. The semantic layer is built on the **datamart** (not the raw datasource) — do NOT use \\`discover_datasource_schema\\` to populate it.\n\nThere are two distinct states — handle each differently:\n\n**A) Tables exist but have NO descriptions** — The data is already synced (tables and columns are there), but descriptions and synonyms are missing. The AI needs these to map natural language to SQL. **Do NOT tell the user to go to the UI — the tables are already there and you can fix this yourself.**\n\nPopulate the semantic layer right now:\n1. \\`get_semantic_layer\\` — review the table and column names\n2. **Auto-generate descriptions** — you are an LLM, use the table/column names to infer business-friendly descriptions (e.g. \\`orders\\` → \"Customer purchase orders\", \\`total_amount\\` → \"Order total including tax\"). Also add synonyms (e.g. \\`total_amount\\` → [\"revenue\", \"sales amount\"])\n3. \\`update_semantic_layer\\` — push the generated descriptions. You can update all tables in one call.\n4. Re-check with \\`get_semantic_layer\\` to confirm the completion score improved\n5. Proceed to Step 2\n\nFor a more detailed workflow, use the \\`populate-semantic-layer\\` prompt.\nAsk the user if they'd like to review the descriptions before applying, or go ahead directly.\n\n**B) No tables at all (0 tables)** — This means the datamart may not be set up correctly. Tell the user to check the datamart in the **Databrain UI**.\n\nOnly proceed to Step 2 once the semantic layer has tables WITH descriptions.\n\n**Step 2 — Ask the Question**\nUse \\`ask_question\\` with:\n- \\`question\\`: The user's natural language question\n- \\`datamartName\\`: The name of the datamart to query (use the name from \\`list_datamarts\\`)\n- \\`timezone\\`: If the user's data involves dates/times, set this to their timezone\n\nIMPORTANT: Always pass \\`datamartName\\`. Do NOT pass a workspace name — it is not the same thing. Use \\`list_datamarts\\` to find the correct datamart name.\n\nThe tool returns:\n- **Data** — rows and columns from the query\n- **Suggested chart type** — \\`bar\\`, \\`line\\`, \\`table\\`, \\`singleValue\\`, \\`map\\`, or \\`pie\\`\n- **Confidence** — 0–100% score indicating how confident the AI is in the query\n- **Reasoning** — explanation of how the SQL was constructed\n- **Session ID** — for follow-up questions\n\n**Step 3 — Present Results**\nFormat the results naturally based on the suggested chart type:\n- \\`singleValue\\` → highlight the number prominently\n- \\`table\\` → present as a formatted table\n- \\`bar\\`/\\`line\\`/\\`pie\\` → describe the data and mention the chart suggestion\n- Always mention the confidence level if below 80%\n\n**Step 4 — Follow-up Questions**\nIf the user asks a follow-up, pass the \\`sessionId\\` from the previous response. The AI will use the conversation context for better SQL generation.\n\nExamples of follow-up patterns:\n- \"Break that down by region\" → uses previous query context\n- \"What about last quarter instead?\" → modifies the time filter\n- \"Show only the top 10\" → adds a limit\n\n**Improving Query Quality**\nIf the confidence is low or results seem wrong:\n1. Check the semantic layer with \\`get_semantic_layer\\` — poor documentation leads to poor queries\n2. If the completion score is below 50%, auto-generate better descriptions and push them with \\`update_semantic_layer\\`:\n - Table descriptions explaining what each table contains\n - Column descriptions with business context\n - Synonyms for columns (e.g. \"revenue\" for \\`total_amount\\`)\n - Example questions that demonstrate common query patterns\n3. Ask the user for domain-specific context if column meanings are ambiguous\n4. Re-run the question after improving the semantic layer\n\n**Common Scenarios**\n- \"What was revenue last month?\" → single question, likely returns a singleValue or table\n- \"Show me monthly revenue trend for the past year\" → time series, should suggest line chart\n- \"Compare sales by region\" → categorical, should suggest bar chart\n- \"How many active customers do we have?\" → single value\n- \"Give me the raw transaction data for today\" → table with many rows\n\n**Important Notes**\n- \\`ask_question\\` uses the service token — no API token or embed setup needed\n- Always pass \\`datamartName\\` (not workspace name) to \\`ask_question\\`\n- The semantic layer significantly affects query quality — encourage documentation if it's sparse\n- For very large result sets, the tool truncates to 50 rows — let the user know if this happens\n- If the user wants to save a query as a reusable metric, they'll need to use the Databrain UI\n- NEVER try to query a datasource directly — always go through a datamart with a populated semantic layer\n`;\n","export const sqlToMetricMigrationPrompt = `You are helping migrate validated warehouse SQL into Databrain metrics/widgets for a production-backed workspace.\n\nThis workflow is built for agent-assisted SQL migration: the user already has SQL converted and validated against their warehouse. Your job is to resolve the Databrain dashboard/data-app/datasource context, validate the metric spec, produce a dry-run plan, and only apply after explicit confirmation.\n\n**Critical safety rules**\n- Default to dry-run. Never apply on the first pass.\n- Applying requires the exact confirmation string: \\`APPLY_TO_PRODUCTION\\`.\n- Service-token mode means writes are attributed as system until OAuth ships. State that clearly before apply.\n- Do not create datasources or workspaces in this workflow.\n- If a datamart is needed, use \\`create_datamart\\` in \\`dry_run\\` first; apply only after confirmation.\n- Keep \\`isPublished: false\\` unless the user explicitly asks to publish.\n\n**Minimum inputs**\n- \\`clientId\\`\n- \\`workspaceName\\`\n- \\`dashboardName\\` or \\`embedId\\`\n- \\`metricId\\`\n- \\`name\\`\n- \\`query\\`\n- Optional: \\`description\\`, \\`chartOptions\\`, \\`integrationName\\`, \\`companyIntegrationId\\`\n\n**Step 1 — Check context**\nCall:\n\\`\\`\\`\nlist_workspaces\nlist_dashboards({ workspaceName })\nlist_widgets({ clientId, dashboardName, workspaceName })\n\\`\\`\\`\nShow the current target dashboard and existing widgets. If \\`metricId\\` already exists, tell the user they must choose \\`conflictStrategy: \"update\"\\` or \\`\"create_new\"\\`.\n\n**Step 2 — Validate without saving**\nCall:\n\\`\\`\\`\nvalidate_metric_spec({\n clientId,\n workspaceName,\n dashboardName,\n metricId,\n name,\n query,\n description,\n chartOptions\n})\n\\`\\`\\`\nPresent the resolved data app, datasource, embed id, dashboard id, and any conflict.\n\n**Step 3 — Dry-run the write**\nCall:\n\\`\\`\\`\ncreate_or_update_metric_from_query({\n mode: \"dry_run\",\n conflictStrategy,\n clientId,\n workspaceName,\n dashboardName,\n metricId,\n name,\n query,\n description,\n chartOptions,\n isPublished: false\n})\n\\`\\`\\`\nShow the exact plan. Stop and ask the user to review it.\n\n**Step 4 — Apply only after explicit confirmation**\nOnly after the user approves, call:\n\\`\\`\\`\ncreate_or_update_metric_from_query({\n mode: \"apply\",\n confirm: \"APPLY_TO_PRODUCTION\",\n conflictStrategy,\n clientId,\n workspaceName,\n dashboardName,\n metricId,\n name,\n query,\n description,\n chartOptions,\n isPublished: false,\n requestedBy: \"<human/operator context>\"\n})\n\\`\\`\\`\nNever invent the confirmation. The user must provide explicit approval.\n\n**Step 5 — Verify**\nCall:\n\\`\\`\\`\nlist_widgets({ clientId, dashboardName, workspaceName })\nget_demo_link({ clientId, dashboardName, workspaceName })\n\\`\\`\\`\nTell the user that unpublished widgets may not appear in the preview until published.\n\n**Scheduled reports**\nIf the user asks about schedule visibility, call:\n\\`\\`\\`\nlist_scheduled_reports({ clientId, dashboardName, workspaceName })\n\\`\\`\\`\nClarify that this lists configured schedules only. Delivery success/failure history is not yet persisted in the MCP/API surface.`;\n","export const sqlToWorkspaceMetricPrompt = `You are helping turn validated warehouse SQL into an INTERNAL Databrain metric — a workspace-level metric for the team's own analytics. This is NOT embedding: there is no customer, no clientId, and the metric is not attached to any dashboard.\n\nUse this flow when the user says things like \"I have this SQL, make it a metric in Databrain\", \"migrate my query\", \"add an unpublished metric\", or \"update/fix the SQL on an existing workspace metric\" — and they are not setting up a customer-facing embed. If the goal is a widget on a customer's embedded dashboard, use the sql-to-metric-migration prompt instead (that one requires a clientId).\n\n**Why this path**\n- \\`create_workspace_metric\\` is workspace-scoped, unpublished, and uses the org service token. No clientId.\n- It upserts on \\`metricId\\`: pass an existing metric's \\`metricId\\` to UPDATE it in place (the query and its Dimensions/Measures are re-derived; archived/draft and publish state are preserved); omit \\`metricId\\` to CREATE a new metric.\n- The metric is intentionally NOT attached to a dashboard — attaching/publishing is a separate step the user does later.\n\n**Critical safety rules**\n- Default to dry-run. Never apply on the first pass.\n- Applying requires the exact confirmation string: \\`APPLY_TO_PRODUCTION\\`.\n- Service-token mode means writes are attributed as system until OAuth ships. State that clearly before apply.\n- Keep \\`isPublished: false\\` unless the user explicitly asks to publish.\n\n**Minimum inputs**\n- \\`workspaceName\\`\n- \\`name\\`\n- \\`query\\`\n- Optional: \\`description\\`, \\`datasourceId\\` (defaults to the workspace datasource), \\`metricId\\` (a stable slug). **Omit \\`metricId\\` to create** (it's generated from the name). **To UPDATE an existing metric, pass its exact \\`metricId\\`** — carry that same value through BOTH the dry-run and apply calls, or the update won't target the existing metric. If the user is editing a metric and you don't know its \\`metricId\\`, ask them for the exact slug it was created with (there is no workspace-metric list tool).\n\n**Step 1 — Confirm the workspace and datasource**\nCall:\n\\`\\`\\`\nlist_workspaces\ndiscover_datasource_schema({ datasourceName })\n\\`\\`\\`\nConfirm the target workspace and that the columns referenced by the SQL exist. This avoids the most common validation failure.\n\n**Step 2 — Dry-run (validate the SQL, no write)**\nCall:\n\\`\\`\\`\ncreate_workspace_metric({\n mode: \"dry_run\",\n workspaceName,\n name,\n query,\n description,\n metricId, // include the existing metricId when UPDATING; omit to create\n isPublished: false\n})\n\\`\\`\\`\nThe dry-run validates the SQL against the workspace datasource and returns the output columns — it does NOT report whether apply will create or update. Show the result and the output columns. Stop and ask the user to review.\n\n**Step 3 — Apply only after explicit confirmation**\nOnly after the user approves, call:\n\\`\\`\\`\ncreate_workspace_metric({\n mode: \"apply\",\n confirm: \"APPLY_TO_PRODUCTION\",\n workspaceName,\n name,\n query,\n description,\n metricId, // pass the SAME metricId used in the dry-run when UPDATING\n isPublished: false\n})\n\\`\\`\\`\nNever invent the confirmation. Pass the same \\`metricId\\` you used in the dry-run so an update targets the intended metric. On create, the metric is unpublished and unattached; on update, the existing metric is rewritten in place. Either way its Dimensions/Measures are (re-)hydrated from the query, and archived/draft + publish state are preserved on update; tell the user they can publish/attach it to a dashboard as a separate step when ready.`;\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { brandMyEmbedPrompt } from './brand-my-embed.js';\nimport { customizeCustomerDashboardPrompt } from './customize-customer-dashboard.js';\nimport { embedBlankDashboardPrompt } from './embed-blank-dashboard.js';\nimport { embedExistingDashboardPrompt } from './embed-existing-dashboard.js';\nimport { populateSemanticLayerPrompt } from './populate-semantic-layer.js';\nimport { queryDataPrompt } from './query-data.js';\nimport { sqlToMetricMigrationPrompt } from './sql-to-metric-migration.js';\nimport { sqlToWorkspaceMetricPrompt } from './sql-to-workspace-metric.js';\n\ninterface PromptDef {\n name: string;\n description: string;\n content: string;\n}\n\nconst prompts: PromptDef[] = [\n {\n name: 'embed-existing-dashboard',\n description:\n 'Embed a dashboard that already exists in the Databrain UI: select data app → ensure token → pick dashboard → create embed',\n content: embedExistingDashboardPrompt,\n },\n {\n name: 'embed-blank-dashboard',\n description:\n 'Multi-tenant blank dashboard setup: each client gets their own dashboard copy via create_embed with clientId',\n content: embedBlankDashboardPrompt,\n },\n {\n name: 'brand-my-embed',\n description:\n 'Customize colors, fonts, chart styles, and component theme to match your brand',\n content: brandMyEmbedPrompt,\n },\n {\n name: 'query-data',\n description:\n 'Query your data with natural language: ask questions, get results with chart suggestions, manage the semantic layer',\n content: queryDataPrompt,\n },\n {\n name: 'populate-semantic-layer',\n description:\n 'Auto-generate and push table/column descriptions to enable natural language querying on a datamart',\n content: populateSemanticLayerPrompt,\n },\n {\n name: 'customize-customer-dashboard',\n description:\n \"Add, modify, or remove widgets on a specific customer's dashboard embed. Per-client scope — changes only affect that customer.\",\n content: customizeCustomerDashboardPrompt,\n },\n {\n name: 'sql-to-metric-migration',\n description:\n 'Production-safe SQL-to-metric migration workflow: validate, dry-run, then apply with explicit confirmation.',\n content: sqlToMetricMigrationPrompt,\n },\n {\n name: 'sql-to-workspace-metric',\n description:\n 'Internal analytics: turn validated SQL into an unpublished workspace metric (no clientId, not embedding). Validate, dry-run, then apply with confirmation.',\n content: sqlToWorkspaceMetricPrompt,\n },\n];\n\nexport function registerAllPrompts(server: McpServer): void {\n for (const prompt of prompts) {\n server.prompt(prompt.name, prompt.description, async () => ({\n messages: [\n {\n role: 'user' as const,\n content: {\n type: 'text' as const,\n text: prompt.content,\n },\n },\n ],\n }));\n }\n}\n","export const apiReferenceContent = `\n# Databrain API Reference\n\n## Authentication\n\nAll API requests require authentication via one of two token types passed in the\n\\`Authorization\\` header:\n\n### Service Token\n- **Purpose**: Manage workspace-level resources (datasources, data apps, datamarts, API tokens).\n- **Header**: \\`Authorization: Bearer <service-token>\\`\n- **Scope**: Entire workspace. Found in workspace settings.\n- **Used for**: CRUD on datasources, data apps, datamarts, and API token management.\n\n### API Token\n- **Purpose**: Manage data-app-scoped resources and generate guest tokens.\n- **Header**: \\`Authorization: Bearer <api-token>\\`\n- **Scope**: A single data app. One API token per data app.\n- **Used for**: Embed CRUD, dashboard/metric listing, guest token generation, and data queries.\n\n> **Important**: Service Tokens and API Tokens are **not interchangeable**. Use the\n> correct token type for each endpoint.\n\n---\n\n## Base URL\n\nAll endpoints are relative to your Databrain instance base URL:\n\\`\\`\\`\nhttps://api.usedatabrain.com\n\\`\\`\\`\n\n---\n\n## Datasource Endpoints\n\n### Create Datasource\n\\`\\`\\`\nPOST /api/v2/datasource/\nAuthorization: Bearer <service-token>\nContent-Type: application/json\n\\`\\`\\`\n\nCreates a new database connection. Request body includes:\n- \\`name\\` (string) - Display name for the datasource\n- \\`dbName\\` (string) - Database name\n- \\`host\\` (string) - Database host\n- \\`port\\` (string) - Database port\n- \\`username\\` (string) - Database username\n- \\`password\\` (string) - Database password\n- \\`type\\` (string) - Database type (e.g., \\`POSTGRESQL\\`, \\`MYSQL\\`, \\`BIGQUERY\\`, \\`SNOWFLAKE\\`, \\`REDSHIFT\\`, \\`DATABRICKS\\`, \\`CLICKHOUSE\\`, \\`MONGODB\\`)\n- \\`isSSL\\` (boolean) - Whether to use SSL\n\nReturns the created datasource object with its \\`id\\`.\n\n### List Datasources\n\\`\\`\\`\nGET /api/v2/datasource/\nAuthorization: Bearer <service-token>\n\\`\\`\\`\n\nReturns an array of all datasources in the workspace.\n\n### Sync Datasource\n\\`\\`\\`\nPOST /api/v2/datasource/sync\nAuthorization: Bearer <service-token>\nContent-Type: application/json\n\\`\\`\\`\n\nBody: \\`{ \"datasourceId\": \"<id>\" }\\`\n\nTriggers a metadata sync that imports table and column information from the connected\ndatabase. **This must be called after creating a datasource** before datamarts become\navailable.\n\n---\n\n## Data App Endpoints\n\n### Create Data App\n\\`\\`\\`\nPOST /api/v2/data-app/\nAuthorization: Bearer <service-token>\nContent-Type: application/json\n\\`\\`\\`\n\nBody: \\`{ \"name\": \"My App\", \"description\": \"optional description\" }\\`\n\nCreates a new data app (workspace container).\n\n### List Data Apps\n\\`\\`\\`\nGET /api/v2/data-app/\nAuthorization: Bearer <service-token>\n\\`\\`\\`\n\nReturns all data apps in the workspace.\n\n---\n\n## API Token Endpoints\n\n### Create API Token\n\\`\\`\\`\nPOST /api/v2/data-app/api-tokens\nAuthorization: Bearer <service-token>\nContent-Type: application/json\n\\`\\`\\`\n\nBody: \\`{ \"dataAppId\": \"<data-app-id>\", \"name\": \"Token Name\", \"description\": \"optional\" }\\`\n\nCreates an API token scoped to the specified data app. This token is required for\ngenerating guest tokens. **Store it securely; it cannot be retrieved again after creation.**\n\n---\n\n## Datamart Endpoints\n\n### Create / Assign Datamarts\n\\`\\`\\`\nPOST /api/v2/data-app/datamarts\nAuthorization: Bearer <service-token>\nContent-Type: application/json\n\\`\\`\\`\n\nAssigns datamarts (tables/views from synced datasources) to a data app.\n\nBody: \\`{ \"dataAppId\": \"<id>\", \"datamartIds\": [\"<datamart-id-1>\", \"<datamart-id-2>\"] }\\`\n\n### List Datamarts\n\\`\\`\\`\nGET /api/v2/data-app/datamarts?dataAppId=<id>\nAuthorization: Bearer <service-token>\n\\`\\`\\`\n\nReturns all datamarts assigned to the specified data app. Also returns datamarts\navailable from synced datasources when using additional query parameters.\n\n---\n\n## Embed Endpoints\n\n### Create Embed\n\\`\\`\\`\nPOST /api/v2/data-app/embeds\nAuthorization: Bearer <api-token>\nContent-Type: application/json\n\\`\\`\\`\n\n**Note**: Embed endpoints use an **API Token** (data-app-scoped), not a Service Token.\n\nCreates an embed configuration linking a dashboard to embeddable settings.\n\nKey body fields:\n- \\`dataAppId\\` (string) - The data app ID\n- \\`dashboardId\\` (string) - The dashboard to embed\n- \\`name\\` (string) - Embed config name\n- \\`theme\\` (object) - Optional theme configuration\n- \\`accessSettings\\` (object) - Optional access/permission settings\n\n### List Embeds\n\\`\\`\\`\nGET /api/v2/data-app/embeds?dataAppId=<id>\nAuthorization: Bearer <api-token>\n\\`\\`\\`\n\nReturns all embed configurations for a data app.\n\n### Get Embed\n\\`\\`\\`\nGET /api/v2/data-app/embeds?embedId=<embed-id>\nAuthorization: Bearer <api-token>\n\\`\\`\\`\n\nReturns a single embed configuration by ID.\n\n### Update Embed\n\\`\\`\\`\nPUT /api/v2/data-app/embeds\nAuthorization: Bearer <api-token>\nContent-Type: application/json\n\\`\\`\\`\n\nBody must include \\`embedId\\` and \\`accessSettings\\`. Fetch the current embed via GET first and merge your changes to avoid overwriting existing settings.\n\n---\n\n## Guest Token Endpoint\n\n### Generate Guest Token\n\\`\\`\\`\nPOST /api/v2/guest-token/create\nAuthorization: Bearer <api-token>\nContent-Type: application/json\n\\`\\`\\`\n\n**Note**: This endpoint uses an **API Token**, not a Service Token.\n\nKey body fields:\n- \\`clientId\\` (string, required) - Tenant identifier for multi-tenancy / row-level security\n- \\`dataAppName\\` (string, required) - Name of the data app\n- \\`params.allowedEmbeds\\` (array) - Optional allowlist of embed IDs\n- \\`params.appFilters\\` (array) - Global/metric-level server-side filters\n- \\`params.dashboardAppFilters\\` (array) - Dashboard-specific filters\n- \\`params.hideDashboardFilters\\` (array) - Filter names to hide\n- \\`params.userIdentifier\\` (string) - User-level private metric context\n- \\`params.timezone\\` (string) - IANA timezone\n- \\`permissions\\` (object) - Runtime permission overrides (e.g. \\`isEnableDownloadMetrics\\`)\n- \\`theme\\` (object) - Runtime theme overrides\n- \\`expiryTime\\` (number) - Token TTL in milliseconds\n- \\`datasourceName\\` (string) - Multi-datasource routing\n\n> **Rejected fields**: \\`accessSettings\\` is not accepted on guest token requests.\n\nReturns: \\`{ \"token\": \"<guest-token>\", \"expiresAt\": \"<timestamp>\" }\\`\n\n---\n\n## Query Endpoint\n\n### Query Metric Data\n\\`\\`\\`\nPOST /api/v2/data-app/query\nAuthorization: Bearer <api-token>\nContent-Type: application/json\n\\`\\`\\`\n\nExecutes a metric query and returns data.\n\nBody:\n- \\`metricId\\` (string) - The metric to query\n- \\`filters\\` (array) - Runtime filters to apply\n- \\`limit\\` (number) - Row limit\n- \\`offset\\` (number) - Pagination offset\n\nReturns the query result data as rows and columns.\n\n---\n\n## Dashboard Endpoints\n\n### List Dashboards\n\\`\\`\\`\nGET /api/v2/data-app/dashboards?dataAppId=<id>\nAuthorization: Bearer <api-token>\n\\`\\`\\`\n\nReturns all dashboards in a data app. Note: dashboards are **created in the Databrain\nUI**, not via the API.\n\n### List Metrics\n\\`\\`\\`\nGET /api/v2/data-app/metrics?dashboardId=<id>\nAuthorization: Bearer <api-token>\n\\`\\`\\`\n\nReturns all metrics within a dashboard.\n\n---\n\n## Error Handling\n\nAll endpoints return standard HTTP status codes:\n- \\`200\\` - Success\n- \\`201\\` - Created\n- \\`400\\` - Bad request (missing or invalid parameters)\n- \\`401\\` - Unauthorized (invalid or missing token)\n- \\`403\\` - Forbidden (token does not have required scope)\n- \\`404\\` - Resource not found\n- \\`500\\` - Internal server error\n\nError responses include a JSON body:\n\\`\\`\\`json\n{\n \"error\": \"Error message describing the issue\"\n}\n\\`\\`\\`\n\n---\n\n## Rate Limits\n\nAPI calls are subject to rate limiting. If you receive a \\`429\\` status code, back off\nand retry after the duration indicated in the \\`Retry-After\\` header.\n`;\n","export const embeddingGuideContent = `\n# Databrain Embedding Guide\n\n## Overview\n\nDatabrain provides embeddable analytics through **web components**. These are framework-\nagnostic custom HTML elements that render dashboards and individual metrics inside your\napplication.\n\nTwo primary components are available:\n- \\`<dbn-dashboard>\\` - Embeds a full dashboard with all its metrics\n- \\`<dbn-metric>\\` - Embeds a single metric/chart\n\nThe embedding flow follows three steps:\n1. **Create an embed configuration** (server-side, one-time setup)\n2. **Generate a guest token** (server-side, per user session)\n3. **Render the web component** (client-side, in your frontend)\n\n---\n\n## Installation\n\nInstall the Databrain plugin package:\n\n\\`\\`\\`bash\nnpm install @databrainhq/plugin\n\\`\\`\\`\n\nOr with yarn:\n\\`\\`\\`bash\nyarn add @databrainhq/plugin\n\\`\\`\\`\n\nOr with pnpm:\n\\`\\`\\`bash\npnpm add @databrainhq/plugin\n\\`\\`\\`\n\nAfter installation, import the package in your application entry point to register the\nweb components:\n\n\\`\\`\\`typescript\nimport '@databrainhq/plugin';\n\\`\\`\\`\n\nThis registers the \\`<dbn-dashboard>\\` and \\`<dbn-metric>\\` custom elements globally.\n\n---\n\n## Step-by-Step Embedding Flow\n\n### Step 1: Create an Embed Configuration\n\nUsing the Databrain API (or the MCP tools), create an embed configuration that links\na dashboard to your embedding preferences:\n\n\\`\\`\\`json\n{\n \"dataAppId\": \"your-data-app-id\",\n \"dashboardId\": \"your-dashboard-id\",\n \"name\": \"Customer Analytics Embed\",\n \"theme\": { },\n \"accessSettings\": { }\n}\n\\`\\`\\`\n\nThis returns an \\`embedId\\` that you will use when generating guest tokens.\n\n### Step 2: Generate a Guest Token (Server-Side)\n\nOn your backend server, call the guest token endpoint. **Never generate guest tokens\non the client side**, as this would expose your API token.\n\n\\`\\`\\`typescript\n// Server-side code (e.g., Express.js route handler)\nconst response = await fetch('https://api.usedatabrain.com/api/v2/guest-token/create', {\n method: 'POST',\n headers: {\n 'Authorization': \\`Bearer \\${apiToken}\\`, // API Token, NOT Service Token\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n embedId: 'your-embed-id',\n clientId: 'tenant-123', // For multi-tenancy\n appFilters: [], // Global filters\n dashboardAppFilters: [], // Dashboard-specific filters\n }),\n});\n\nconst { token } = await response.json();\n// Return this token to the frontend\n\\`\\`\\`\n\n### Step 3: Add the Web Component (Client-Side)\n\nPass the guest token to the web component in your HTML:\n\n\\`\\`\\`html\n<dbn-dashboard\n token=\"<guest-token>\"\n dashboard-id=\"<dashboard-id>\"\n></dbn-dashboard>\n\\`\\`\\`\n\nOr for a single metric:\n\n\\`\\`\\`html\n<dbn-metric\n token=\"<guest-token>\"\n metric-id=\"<metric-id>\"\n></dbn-metric>\n\\`\\`\\`\n\n---\n\n## Framework Integration Notes\n\n### React\n\n\\`\\`\\`tsx\nimport '@databrainhq/plugin';\nimport { useEffect, useState } from 'react';\n\nfunction Dashboard() {\n const [token, setToken] = useState<string>('');\n\n useEffect(() => {\n fetch('/api/guest-token')\n .then(res => res.json())\n .then(data => setToken(data.token));\n }, []);\n\n if (!token) return <div>Loading...</div>;\n\n return (\n <dbn-dashboard\n token={token}\n dashboard-id=\"your-dashboard-id\"\n />\n );\n}\n\\`\\`\\`\n\nYou may need to add type declarations for the custom elements:\n\n\\`\\`\\`typescript\n// src/types/dbn.d.ts\ndeclare namespace JSX {\n interface IntrinsicElements {\n 'dbn-dashboard': React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement> & {\n token?: string;\n 'dashboard-id'?: string;\n };\n 'dbn-metric': React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement> & {\n token?: string;\n 'metric-id'?: string;\n };\n }\n}\n\\`\\`\\`\n\n### Next.js\n\nUse dynamic imports to avoid SSR issues since web components require the DOM:\n\n\\`\\`\\`tsx\n'use client';\n\nimport dynamic from 'next/dynamic';\n\nconst DashboardEmbed = dynamic(() => {\n import('@databrainhq/plugin');\n return Promise.resolve(({ token, dashboardId }: { token: string; dashboardId: string }) => (\n <dbn-dashboard token={token} dashboard-id={dashboardId} />\n ));\n}, { ssr: false });\n\\`\\`\\`\n\n### Vue\n\n\\`\\`\\`vue\n<template>\n <dbn-dashboard\n v-if=\"token\"\n :token=\"token\"\n :dashboard-id=\"dashboardId\"\n />\n</template>\n\n<script setup>\nimport '@databrainhq/plugin';\nimport { ref, onMounted } from 'vue';\n\nconst token = ref('');\nconst dashboardId = 'your-dashboard-id';\n\nonMounted(async () => {\n const res = await fetch('/api/guest-token');\n const data = await res.json();\n token.value = data.token;\n});\n</script>\n\\`\\`\\`\n\nConfigure Vue to recognize custom elements:\n\n\\`\\`\\`typescript\n// vite.config.ts\nexport default defineConfig({\n plugins: [\n vue({\n template: {\n compilerOptions: {\n isCustomElement: (tag) => tag.startsWith('dbn-'),\n },\n },\n }),\n ],\n});\n\\`\\`\\`\n\n### Angular\n\nAdd \\`CUSTOM_ELEMENTS_SCHEMA\\` to your module:\n\n\\`\\`\\`typescript\nimport { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';\nimport '@databrainhq/plugin';\n\n@NgModule({\n schemas: [CUSTOM_ELEMENTS_SCHEMA],\n})\nexport class AppModule {}\n\\`\\`\\`\n\nThen use in templates:\n\n\\`\\`\\`html\n<dbn-dashboard\n [attr.token]=\"guestToken\"\n [attr.dashboard-id]=\"dashboardId\"\n></dbn-dashboard>\n\\`\\`\\`\n\n### Svelte\n\n\\`\\`\\`svelte\n<script>\n import '@databrainhq/plugin';\n import { onMount } from 'svelte';\n\n let token = '';\n const dashboardId = 'your-dashboard-id';\n\n onMount(async () => {\n const res = await fetch('/api/guest-token');\n const data = await res.json();\n token = data.token;\n });\n</script>\n\n{#if token}\n <dbn-dashboard {token} dashboard-id={dashboardId} />\n{/if}\n\\`\\`\\`\n\n### SolidJS\n\n\\`\\`\\`tsx\nimport '@databrainhq/plugin';\nimport { createResource } from 'solid-js';\n\nfunction Dashboard() {\n const [token] = createResource(async () => {\n const res = await fetch('/api/guest-token');\n const data = await res.json();\n return data.token;\n });\n\n return (\n <Show when={token()}>\n <dbn-dashboard token={token()} dashboard-id=\"your-dashboard-id\" />\n </Show>\n );\n}\n\\`\\`\\`\n\n### Vanilla JavaScript\n\n\\`\\`\\`html\n<script type=\"module\">\n import '@databrainhq/plugin';\n</script>\n\n<dbn-dashboard id=\"dashboard\"></dbn-dashboard>\n\n<script>\n fetch('/api/guest-token')\n .then(res => res.json())\n .then(data => {\n const el = document.getElementById('dashboard');\n el.setAttribute('token', data.token);\n el.setAttribute('dashboard-id', 'your-dashboard-id');\n });\n</script>\n\\`\\`\\`\n\n---\n\n## Security Best Practices\n\n### Never Expose the API Token Client-Side\nThe API token has broad permissions for the data app. It must only be used on your\nbackend server. Exposing it in frontend code, environment variables accessible to\nthe browser, or client-side bundles is a security risk.\n\n### Always Generate Guest Tokens Server-Side\nGuest tokens should be generated by your backend and passed to the frontend. This\nensures that your API token stays secret and that you can apply tenant-specific\nfilters and permissions.\n\n### Use Short-Lived Guest Tokens\nGuest tokens have an expiration time. Generate fresh tokens for each user session.\nImplement token refresh logic if sessions are long-lived.\n\n### Apply Tenant Filters via Guest Tokens\nFor multi-tenant applications, always pass \\`clientId\\` and appropriate \\`appFilters\\`\nwhen generating the guest token. This ensures row-level security is enforced\nserver-side and cannot be bypassed by the end user.\n\n### Validate User Identity Before Token Generation\nBefore generating a guest token, verify the requesting user's identity and\nauthorization in your application. Only generate tokens with the appropriate\nscope and filters for that user.\n`;\n","export const filterReferenceContent = `\n# Databrain Filter Reference\n\n## Overview\n\nFilters in Databrain allow you to restrict and scope the data displayed in dashboards\nand metrics. Filters can be applied at multiple levels: via guest tokens (server-side),\nvia the query API (runtime), or via dashboard-level configuration in the UI.\n\n---\n\n## Filter Types\n\n### String Filters\n\nString filters operate on text/varchar columns.\n\n| Operator | Description | Example Value |\n|------------|------------------------------------|--------------------------|\n| \\`=\\` | Exact match | \\`\"active\"\\` |\n| \\`IN\\` | Matches any value in a list | \\`[\"active\", \"pending\"]\\` |\n| \\`NOT IN\\` | Excludes values in a list | \\`[\"deleted\", \"archived\"]\\`|\n| \\`LIKE\\` | Pattern match (use % as wildcard) | \\`\"%corp%\"\\` |\n\n**JSON Examples:**\n\n\\`\\`\\`json\n{\n \"columnName\": \"status\",\n \"tableName\": \"orders\",\n \"operator\": \"=\",\n \"value\": \"active\",\n \"type\": \"string\"\n}\n\\`\\`\\`\n\n\\`\\`\\`json\n{\n \"columnName\": \"region\",\n \"tableName\": \"customers\",\n \"operator\": \"IN\",\n \"value\": [\"US\", \"CA\", \"UK\"],\n \"type\": \"string\"\n}\n\\`\\`\\`\n\n\\`\\`\\`json\n{\n \"columnName\": \"company_name\",\n \"tableName\": \"accounts\",\n \"operator\": \"LIKE\",\n \"value\": \"%technologies%\",\n \"type\": \"string\"\n}\n\\`\\`\\`\n\n### Number Filters\n\nNumber filters operate on numeric columns (integer, float, decimal).\n\n| Operator | Description | Example Value |\n|-------------|-------------------------|-----------------|\n| \\`=\\` | Equal to | \\`100\\` |\n| \\`<\\` | Less than | \\`50\\` |\n| \\`>\\` | Greater than | \\`1000\\` |\n| \\`<=\\` | Less than or equal | \\`99\\` |\n| \\`>=\\` | Greater than or equal | \\`10\\` |\n| \\`<>\\` | Not equal to | \\`0\\` |\n| \\`BETWEEN\\` | Within a range (inclusive)| \\`[10, 100]\\` |\n\n**JSON Examples:**\n\n\\`\\`\\`json\n{\n \"columnName\": \"amount\",\n \"tableName\": \"transactions\",\n \"operator\": \">=\",\n \"value\": 1000,\n \"type\": \"number\"\n}\n\\`\\`\\`\n\n\\`\\`\\`json\n{\n \"columnName\": \"quantity\",\n \"tableName\": \"order_items\",\n \"operator\": \"BETWEEN\",\n \"value\": [1, 100],\n \"type\": \"number\"\n}\n\\`\\`\\`\n\n### Null Filters\n\nNull filters check for the presence or absence of values.\n\n| Operator | Description |\n|----------------|--------------------------------|\n| \\`IS NULL\\` | Column value is null/missing |\n| \\`IS NOT NULL\\` | Column value exists |\n\n**JSON Examples:**\n\n\\`\\`\\`json\n{\n \"columnName\": \"deleted_at\",\n \"tableName\": \"users\",\n \"operator\": \"IS NULL\",\n \"type\": \"null\"\n}\n\\`\\`\\`\n\n\\`\\`\\`json\n{\n \"columnName\": \"email\",\n \"tableName\": \"contacts\",\n \"operator\": \"IS NOT NULL\",\n \"type\": \"null\"\n}\n\\`\\`\\`\n\n---\n\n## Filter Application Methods\n\n### 1. Guest Token Filters (Server-Side)\n\nFilters applied via the guest token are enforced server-side and **cannot be removed\nor modified by end users**. This is the most secure way to apply filters, especially\nfor multi-tenancy.\n\n#### appFilters (Global Filters)\n\nApplied to **all metrics** across all dashboards in the embed:\n\n\\`\\`\\`json\n{\n \"embedId\": \"embed-123\",\n \"appFilters\": [\n {\n \"columnName\": \"organization_id\",\n \"tableName\": \"events\",\n \"operator\": \"=\",\n \"value\": \"org-456\",\n \"type\": \"string\"\n },\n {\n \"columnName\": \"is_active\",\n \"tableName\": \"events\",\n \"operator\": \"=\",\n \"value\": 1,\n \"type\": \"number\"\n }\n ]\n}\n\\`\\`\\`\n\n#### dashboardAppFilters (Dashboard-Specific Filters)\n\nApplied to specific dashboards. Useful when an embed includes multiple dashboards\nand you want different filters per dashboard:\n\n\\`\\`\\`json\n{\n \"embedId\": \"embed-123\",\n \"dashboardAppFilters\": [\n {\n \"dashboardId\": \"dashboard-abc\",\n \"filters\": [\n {\n \"columnName\": \"department\",\n \"tableName\": \"employees\",\n \"operator\": \"IN\",\n \"value\": [\"engineering\", \"product\"],\n \"type\": \"string\"\n }\n ]\n },\n {\n \"dashboardId\": \"dashboard-xyz\",\n \"filters\": [\n {\n \"columnName\": \"region\",\n \"tableName\": \"sales\",\n \"operator\": \"=\",\n \"value\": \"APAC\",\n \"type\": \"string\"\n }\n ]\n }\n ]\n}\n\\`\\`\\`\n\n### 2. Runtime Filters via API\n\nWhen querying metric data directly via the API, you can pass runtime filters:\n\n\\`\\`\\`json\n{\n \"metricId\": \"metric-789\",\n \"filters\": [\n {\n \"columnName\": \"created_at\",\n \"tableName\": \"orders\",\n \"operator\": \">=\",\n \"value\": \"2024-01-01\",\n \"type\": \"string\"\n }\n ],\n \"limit\": 100\n}\n\\`\\`\\`\n\n### 3. Dashboard-Level Filters (UI)\n\nFilters can also be configured in the Databrain dashboard UI. These allow end users\nto interactively filter data using dropdowns, date pickers, and search inputs. The\navailable filter columns and behavior are configured when building the dashboard.\n\nDashboard-level filters can be combined with guest token filters. Guest token filters\nalways take precedence and cannot be overridden by UI filters.\n\n---\n\n## Filter Combination Rules\n\n- Multiple filters are combined with **AND** logic.\n- Filters from different levels stack: guest token filters AND dashboard filters AND\n runtime filters all apply simultaneously.\n- Guest token filters cannot be overridden or removed by the end user.\n- If the same column is filtered at multiple levels, all conditions must be satisfied.\n\n---\n\n## Filter Format Summary\n\nEvery filter object follows this structure:\n\n\\`\\`\\`json\n{\n \"columnName\": \"string - the column name in the database table\",\n \"tableName\": \"string - the table name (must match a datamart table)\",\n \"operator\": \"string - the comparison operator\",\n \"value\": \"string | number | array - the filter value(s)\",\n \"type\": \"string - one of: string, number, null\"\n}\n\\`\\`\\`\n\n### Notes\n\n- \\`tableName\\` must reference a table that exists as a datamart in the data app.\n- \\`columnName\\` must be a valid column in that table.\n- For \\`IN\\` and \\`NOT IN\\` operators, \\`value\\` must be an array.\n- For \\`BETWEEN\\`, \\`value\\` must be a two-element array \\`[min, max]\\`.\n- For \\`IS NULL\\` and \\`IS NOT NULL\\`, the \\`value\\` field is ignored (can be omitted or null).\n- Date filtering is typically done using string comparisons with ISO format dates.\n`;\n","export const gettingStartedContent = `\n# Getting Started with Databrain\n\n## Entity Model\n\nDatabrain follows a hierarchical entity model. Understanding this hierarchy is critical\nbefore performing any operations:\n\n\\`\\`\\`\nDatasource\n └── Datamart (a table or view from the datasource)\n └── Semantic Layer (business metadata on a datamart)\n\nData App (workspace container)\n ├── API Token (authenticates embed/API calls for this data app)\n ├── Dashboard (created in the Databrain UI, contains metrics)\n │ └── Metric (a chart/visualization within a dashboard)\n ├── Embed (configuration linking a dashboard to an embeddable component)\n │ └── Guest Token (short-lived token for end-user access)\n └── Datamarts (datamarts assigned to this data app)\n\\`\\`\\`\n\n### Key Relationships\n\n- A **Datasource** represents a database connection (Postgres, MySQL, BigQuery, etc.).\n- A **Datamart** is a specific table or view exposed from a datasource.\n- A **Semantic Layer** enriches a datamart with column descriptions, synonyms, and example questions for AI features.\n- A **Data App** is the top-level workspace that groups dashboards, metrics, embeds, and API tokens.\n- An **API Token** is scoped to a data app and is required to generate guest tokens.\n- A **Dashboard** is a collection of metrics, always created via the Databrain UI.\n- A **Metric** is an individual chart or visualization within a dashboard.\n- An **Embed** links a dashboard (or metric) to embeddable web component configuration.\n- A **Guest Token** is a short-lived, scoped token generated server-side for end-user access.\n\n---\n\n## Onboarding Funnel\n\nFollow these steps in order to go from zero to an embedded dashboard:\n\n### Step 1: Create a Datasource\nConnect your database by providing connection credentials (host, port, database name,\nusername, password, SSL settings). Supported databases include PostgreSQL, MySQL,\nRedshift, BigQuery, Snowflake, Databricks, ClickHouse, MongoDB, and more.\n\n### Step 2: Sync the Datasource\nAfter creating a datasource, you **must** sync it to import table and column metadata.\nThis populates the list of available datamarts.\n\n### Step 3: Create a Data App\nA data app acts as a workspace. All dashboards, metrics, embeds, and API tokens belong\nto a data app.\n\n### Step 4: Assign Datamarts to the Data App\nSelect which datamarts (tables/views) from your synced datasource should be available\nin this data app.\n\n### Step 5: Create an API Token\nGenerate an API token scoped to the data app. This token is used server-side to\ngenerate guest tokens. Never expose this token on the client side.\n\n### Step 6: Create a Dashboard (in the Databrain UI)\nDashboards cannot be created via the API. Log in to the Databrain web application,\nnavigate to your data app, and create a dashboard with the visual builder.\n\n### Step 7: Add Metrics to the Dashboard\nUse the drag-and-drop or AI-assisted metric builder inside the dashboard to create\ncharts and visualizations.\n\n### Step 8: Create an Embed Configuration\nCreate an embed config that links your dashboard to embeddable settings (theme,\naccess controls, allowed filters, etc.).\n\n### Step 9: Generate a Guest Token (Server-Side)\nOn your backend, call the guest token endpoint with the API token, embed config,\nand any tenant-specific filters. This returns a short-lived token.\n\n### Step 10: Render the Web Component\nPass the guest token to the \\`<dbn-dashboard>\\` or \\`<dbn-metric>\\` web component in\nyour frontend application.\n\n---\n\n## Quick-Start Checklist\n\nBefore you begin, ensure you have:\n\n- [ ] A **Databrain account** with access to the workspace\n- [ ] A **Service Token** (found in workspace settings; used for API calls to manage resources)\n- [ ] **Database credentials** for the datasource you want to connect (host, port, db name, user, password)\n- [ ] A frontend application where you want to embed dashboards\n\n### Service Token vs API Token\n\n| Token Type | Purpose | Scope | Where Used |\n|----------------|--------------------------------------------|---------------|--------------------|\n| Service Token | Explore resources (list datasources, datamarts, apps) | Workspace | Server-side API |\n| API Token | Generate guest tokens for embedding | Data App | Server-side only |\n| Guest Token | End-user access to embedded dashboards | Embed + filters| Client-side (web component) |\n\n---\n\n## Common Pitfalls\n\n### 1. Forgetting to Sync the Datasource\nCreating a datasource does **not** automatically import its tables. You must explicitly\ncall the sync endpoint (\\`POST /api/v2/datasource/sync\\`) after creation. Without syncing,\nno datamarts will be available.\n\n### 2. Not Creating an API Token Before Embed Operations\nGuest tokens require an API token scoped to the data app. If you attempt to generate\na guest token without first creating an API token, the call will fail. Always create the\nAPI token immediately after setting up the data app.\n\n### 3. Dashboards Must Be Created in the UI\nThe Databrain API does not support creating dashboards programmatically. Dashboards\nmust be created through the Databrain web application. The API can list dashboards and\ntheir metrics, but creation and design happen in the UI.\n\n### 4. Datamarts Must Be Assigned to a Data App\nEven after syncing a datasource, datamarts are not automatically available in a data app.\nYou must explicitly assign datamarts to the data app using the datamarts endpoint.\n\n### 5. Guest Tokens Are Short-Lived\nGuest tokens expire. Your backend should generate a fresh guest token for each user\nsession or implement token refresh logic. Do not cache guest tokens for extended periods.\n\n### 6. Semantic Layer Is Required for AI Features\nIf you want to use AI Pilot (natural language querying), you must populate the semantic\nlayer for your datamarts. Use the MCP tools \\`get_semantic_layer\\` and \\`update_semantic_layer\\`\nto add table/column descriptions, synonyms, and example questions. When the semantic layer\nis empty, the AI assistant can auto-generate descriptions from column names — use the\n\\`populate-semantic-layer\\` prompt for a guided workflow. Without a semantic layer, the AI\nwill not have enough context to generate accurate queries.\n\n### 7. Embed Config Must Reference an Existing Dashboard\nWhen creating an embed, the dashboard ID must reference a dashboard that already exists\nin the data app. Create the dashboard in the UI first, then create the embed config.\n`;\n","export const multiTenancyGuideContent = `\n# Databrain Multi-Tenancy Guide\n\n## Overview\n\nMulti-tenancy allows you to use a single Databrain setup to serve multiple customers\n(tenants), each seeing only their own data. This is essential for SaaS applications\nwhere a shared database contains data for many organizations, but each customer\nshould only access their own records.\n\nDatabrain enforces multi-tenancy through a combination of:\n- **clientId** in guest tokens for tenant identification\n- **clientColumn** mapping in datamarts for row-level filtering\n- **Tenancy level** configuration for table or database isolation\n\n---\n\n## Tenancy Levels\n\n### TABLE Level Tenancy\n\nThe most common approach. All tenants share the same database and tables, but each\nrow belongs to a specific tenant identified by a tenant column.\n\n**How it works:**\n- Each table has a column that identifies the tenant (e.g., \\`organization_id\\`, \\`company_id\\`, \\`tenant_id\\`)\n- When a guest token is generated with a \\`clientId\\`, Databrain automatically adds\n a \\`WHERE\\` clause filtering on the tenant column\n- End users only see rows where the tenant column matches their \\`clientId\\`\n\n**Example schema:**\n\\`\\`\\`sql\nCREATE TABLE orders (\n id SERIAL PRIMARY KEY,\n org_id VARCHAR(50), -- tenant column\n customer VARCHAR(100),\n amount DECIMAL(10,2),\n created_at TIMESTAMP\n);\n\\`\\`\\`\n\n**Configuration:**\n\\`\\`\\`json\n{\n \"tenancyLevel\": \"TABLE\",\n \"clientColumn\": {\n \"orders\": \"org_id\",\n \"customers\": \"org_id\",\n \"invoices\": \"organization_id\"\n }\n}\n\\`\\`\\`\n\n### DATABASE Level Tenancy\n\nEach tenant has their own database (or schema). Databrain routes queries to the\nappropriate database based on the \\`clientId\\`.\n\n**How it works:**\n- Each tenant's data lives in a separate database or schema\n- The \\`clientId\\` maps to a specific database connection\n- Queries are executed against the tenant-specific database\n\n**When to use:**\n- Strict data isolation requirements (compliance, regulatory)\n- Tenants with very different data volumes\n- Legacy systems where each customer already has a separate database\n\n---\n\n## clientId in Guest Tokens\n\nThe \\`clientId\\` is the primary mechanism for identifying which tenant is accessing\nthe embedded dashboard.\n\n### Setting clientId\n\nWhen generating a guest token on your backend, include the \\`clientId\\` parameter:\n\n\\`\\`\\`json\n{\n \"embedId\": \"embed-789\",\n \"clientId\": \"acme-corp\",\n \"appFilters\": [],\n \"dashboardAppFilters\": []\n}\n\\`\\`\\`\n\n### How clientId Works\n\n1. Your backend authenticates the user and determines their tenant/organization\n2. The backend generates a guest token with the appropriate \\`clientId\\`\n3. Databrain uses the \\`clientId\\` to apply row-level security:\n - For TABLE tenancy: adds \\`WHERE tenant_column = 'clientId'\\` to all queries\n - For DATABASE tenancy: routes the query to the tenant's database\n4. The end user sees only their tenant's data\n\n### Security\n\n- The \\`clientId\\` is embedded in the guest token and **cannot be modified client-side**\n- Guest tokens are short-lived and signed, preventing tampering\n- Always set \\`clientId\\` on your server, never accept it from the client\n\n---\n\n## clientColumn Mapping in Datamarts\n\nFor TABLE-level tenancy, each datamart (table) needs a **clientColumn** mapping that\ntells Databrain which column contains the tenant identifier.\n\n### Configuration\n\nThe client column mapping is set per table in the datamart configuration:\n\n\\`\\`\\`json\n{\n \"datamartId\": \"datamart-orders\",\n \"clientColumn\": \"org_id\"\n}\n\\`\\`\\`\n\n### Different Column Names Per Table\n\nDifferent tables may use different column names for the tenant identifier. The\nmapping supports per-table configuration:\n\n\\`\\`\\`json\n{\n \"clientColumnMapping\": {\n \"orders\": \"org_id\",\n \"customers\": \"organization_id\",\n \"products\": \"company_id\",\n \"events\": \"tenant_id\"\n }\n}\n\\`\\`\\`\n\n### Important Notes\n\n- Every table that should be tenant-filtered **must** have a client column mapping\n- If a table does not have a client column mapping, queries against it will return\n **all rows** regardless of tenant (this may be intentional for shared reference\n tables like countries, currencies, etc.)\n- The client column must contain values that match the \\`clientId\\` passed in the\n guest token\n\n---\n\n## tableTenancySettings in Embeds\n\nEmbed configurations can include \\`tableTenancySettings\\` to define or override\ntenancy behavior at the embed level.\n\n### Structure\n\n\\`\\`\\`json\n{\n \"dataAppId\": \"app-123\",\n \"dashboardId\": \"dash-456\",\n \"name\": \"Multi-Tenant Embed\",\n \"tableTenancySettings\": {\n \"tenancyLevel\": \"TABLE\",\n \"clientColumnMapping\": {\n \"orders\": \"org_id\",\n \"customers\": \"organization_id\",\n \"invoices\": \"company_id\"\n },\n \"sharedTables\": [\"countries\", \"currencies\", \"product_categories\"]\n }\n}\n\\`\\`\\`\n\n### sharedTables\n\nTables listed in \\`sharedTables\\` are exempt from tenant filtering. Use this for\nreference/lookup tables that contain data common to all tenants:\n\n- Country codes\n- Currency lists\n- Product category hierarchies\n- Shared configuration tables\n\n---\n\n## Complete Example: SaaS Application\n\n### Scenario\n\nYou run a SaaS project management tool. Multiple companies use your platform, and\neach company should only see their own projects, tasks, and team members.\n\n### Database Schema\n\n\\`\\`\\`sql\n-- All tables have an org_id column for tenant isolation\nCREATE TABLE projects (\n id SERIAL PRIMARY KEY,\n org_id VARCHAR(50) NOT NULL,\n name VARCHAR(200),\n status VARCHAR(20),\n budget DECIMAL(12,2)\n);\n\nCREATE TABLE tasks (\n id SERIAL PRIMARY KEY,\n org_id VARCHAR(50) NOT NULL,\n project_id INTEGER REFERENCES projects(id),\n title VARCHAR(200),\n assignee VARCHAR(100),\n status VARCHAR(20),\n due_date DATE\n);\n\nCREATE TABLE team_members (\n id SERIAL PRIMARY KEY,\n org_id VARCHAR(50) NOT NULL,\n name VARCHAR(100),\n role VARCHAR(50),\n email VARCHAR(200)\n);\n\n-- Shared reference table (no org_id)\nCREATE TABLE task_statuses (\n code VARCHAR(20) PRIMARY KEY,\n label VARCHAR(50),\n sort_order INTEGER\n);\n\\`\\`\\`\n\n### Step 1: Create Datasource and Sync\n\nConnect your database and sync to import all tables as datamarts.\n\n### Step 2: Create Data App and Assign Datamarts\n\nCreate a data app and assign the \\`projects\\`, \\`tasks\\`, \\`team_members\\`, and\n\\`task_statuses\\` datamarts.\n\n### Step 3: Configure Client Column Mapping\n\nSet the client column for each tenant-scoped table:\n\n\\`\\`\\`json\n{\n \"clientColumnMapping\": {\n \"projects\": \"org_id\",\n \"tasks\": \"org_id\",\n \"team_members\": \"org_id\"\n }\n}\n\\`\\`\\`\n\nNote: \\`task_statuses\\` has no mapping because it is a shared reference table.\n\n### Step 4: Create Dashboard and Embed\n\nCreate a dashboard in the UI with metrics like:\n- Project count by status\n- Tasks completed this month\n- Team member workload\n- Budget utilization\n\nThen create an embed configuration with tenancy settings:\n\n\\`\\`\\`json\n{\n \"dataAppId\": \"app-123\",\n \"dashboardId\": \"dash-456\",\n \"name\": \"Customer Dashboard\",\n \"tableTenancySettings\": {\n \"tenancyLevel\": \"TABLE\",\n \"clientColumnMapping\": {\n \"projects\": \"org_id\",\n \"tasks\": \"org_id\",\n \"team_members\": \"org_id\"\n },\n \"sharedTables\": [\"task_statuses\"]\n }\n}\n\\`\\`\\`\n\n### Step 5: Generate Guest Tokens Per Tenant\n\nOn your backend, when a user from tenant A (org_id = \"tenant_a\") logs in:\n\n\\`\\`\\`typescript\n// Server-side\nconst guestToken = await fetch('https://api.usedatabrain.com/api/v2/guest-token/create', {\n method: 'POST',\n headers: {\n 'Authorization': \\`Bearer \\${apiToken}\\`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n embedId: 'embed-789',\n clientId: 'tenant_a', // Maps to org_id values in the database\n }),\n});\n\\`\\`\\`\n\nWhen a user from tenant B (org_id = \"tenant_b\") logs in:\n\n\\`\\`\\`typescript\nconst guestToken = await fetch('https://api.usedatabrain.com/api/v2/guest-token/create', {\n method: 'POST',\n headers: {\n 'Authorization': \\`Bearer \\${apiToken}\\`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n embedId: 'embed-789',\n clientId: 'tenant_b',\n }),\n});\n\\`\\`\\`\n\n### Step 6: Render\n\nBoth users see the same dashboard layout and metrics, but:\n- Tenant A sees only their projects, tasks, and team members\n- Tenant B sees only their projects, tasks, and team members\n- Both see all task statuses (shared reference table)\n\n### Result\n\n\\`\\`\\`\nTenant A user sees:\n - 12 projects (all with org_id = 'tenant_a')\n - 87 tasks\n - 15 team members\n\nTenant B user sees:\n - 8 projects (all with org_id = 'tenant_b')\n - 45 tasks\n - 9 team members\n\\`\\`\\`\n\n---\n\n## Best Practices\n\n### 1. Always Set clientId Server-Side\nNever accept the \\`clientId\\` from the client. Determine the tenant from your\napplication's authentication/session layer.\n\n### 2. Map All Tenant-Scoped Tables\nEnsure every table that contains tenant-specific data has a client column mapping.\nMissing mappings will leak data across tenants.\n\n### 3. Explicitly Mark Shared Tables\nUse \\`sharedTables\\` to document which tables are intentionally unfiltered. This\nmakes the configuration self-documenting and prevents accidental data exposure.\n\n### 4. Use Consistent Tenant Column Values\nEnsure the \\`clientId\\` values you pass in guest tokens exactly match the values\nin your database tenant columns. Mismatches (case sensitivity, leading/trailing\nspaces) will result in empty dashboards.\n\n### 5. Test with Multiple Tenants\nAlways test your embedding with at least two different \\`clientId\\` values to verify\nthat data isolation is working correctly.\n\n### 6. Combine with appFilters for Fine-Grained Control\nYou can use \\`appFilters\\` alongside \\`clientId\\` for additional filtering within a\ntenant. For example, filter by department or user role within an organization.\n`;\n","export const permissionSchemaContent = `# Permission & Access Schema Reference\n\n## Embed Access Settings\nFields accepted in embed create/update (\\`accessSettings\\` in PUT /api/v2/data-app/embeds). Auth: API token. These are the embed-level defaults.\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| datamartName | string | — | Datamart used by this embed |\n| isAllowMetricCreation | boolean | false | |\n| isAllowMetricDeletion | boolean | false | |\n| isAllowMetricUpdate | boolean | false | Allow modifying metrics |\n| isAllowMetricLayoutChange | boolean | false | Allow layout changes |\n| isAllowManageMetrics | boolean | false | Allow managing metrics |\n| isAllowUnderlyingData | boolean | false | Allow viewing underlying data |\n| isAllowAiPilot | boolean | false | |\n| isAllowEmailReports | boolean | false | |\n| isAllowCreateDashboardView | boolean | false | |\n| metricCreationMode | enum | DRAG_DROP | DRAG_DROP or CHAT |\n| joinModel | enum | — | single or multi (join strategy) |\n| isIncrementalJoin | boolean | — | Legacy — prefer joinModel |\n| tableTenancySettings | array | — | Multi-tenant: [{name, clientColumn}] |\n\n## Guest Token Permissions\nFields accepted in \\`permissions\\` when generating a guest token (POST /api/v2/guest-token/create). Auth: API token. These override embed-level defaults per session.\n\n| Field | Type |\n|-------|------|\n| isEnableArchiveMetrics | boolean |\n| isEnableManageMetrics | boolean |\n| isEnableCreateDashboardView | boolean |\n| isEnableMetricUpdation | boolean |\n| isEnableCustomizeLayout | boolean |\n| isEnableUnderlyingData | boolean |\n| isEnableDownloadMetrics | boolean |\n| isShowSideBar | boolean |\n| isShowDashboardName | boolean |\n| isDisableMetricCreation | boolean |\n\n**Rejected fields:** \\`accessSettings\\`, \\`allowedEmbeds\\` — these are NOT accepted by the guest token endpoint.\n\n## Guest Token Top-Level Fields\nRequired: \\`clientId\\`, \\`dataAppName\\`\nOptional: \\`timezone\\`, \\`appFilters\\`, \\`dashboardAppFilters\\`, \\`permissions\\`, \\`theme\\`, \\`hideDashboardFilters\\`, \\`expiryTime\\`, \\`datasourceName\\`\nRejected: \\`allowedEmbeds\\`, \\`accessSettings\\`\n\n## Precedence Rules\nWhen the same capability is set at multiple levels, highest precedence wins:\n\n1. **Web component \\`options\\` attribute** (highest — client-side, not secure)\n2. **Guest token \\`permissions\\`** (server-side, per session)\n3. **Embed \\`accessSettings\\`** (server-side, default)\n\n> Embed accessSettings use \\`isAllow*\\` naming. Guest token permissions use \\`isEnable*\\`/\\`isShow*\\`/\\`isDisable*\\` naming. They are different schemas.\n\n## Known Limitations\n- \\`isAllowMetricCreation\\` in accessSettings may return 500 — enable via Databrain UI (Settings > Customize Layout) as workaround.\n- \\`accessSettings\\` and \\`allowedEmbeds\\` are rejected by the guest token endpoint — use \\`permissions\\` instead.\n- After updating embed settings, existing guest tokens still carry old config. Regenerate guest tokens for changes to take effect.\n`;\n","export const selfServeReferenceContent = `\n# Databrain Self-Serve Access Settings Reference\n\n## Overview\n\nAccess settings control what end users can do within an embedded dashboard or metric.\nThese settings determine whether users can create, edit, or delete metrics, change\nlayouts, use AI features, drill down into data, and more.\n\nAccess settings can be configured at three levels (from lowest to highest precedence):\n1. **Embed configuration** - Default settings for the embed\n2. **Guest token** - Runtime overrides when generating the token\n3. **Web component** - Client-side overrides via the \\`options\\` attribute\n\n---\n\n## Access Setting Flags\n\nAll access settings are boolean flags prefixed with \\`isAllow\\`. By default, most\nsettings are \\`false\\` (disabled) unless explicitly enabled.\n\n### Metric Operations\n\n| Flag | Default | Description |\n|-----------------------------|---------|----------------------------------------------------------|\n| \\`isAllowMetricCreation\\` | false | Allow users to create new metrics in the dashboard |\n| \\`isAllowMetricDeletion\\` | false | Allow users to delete existing metrics |\n| \\`isAllowMetricUpdate\\` | false | Allow users to modify metric configurations |\n| \\`isAllowMetricLayoutChange\\` | false | Allow users to change metric layout |\n| \\`isAllowManageMetrics\\` | false | Allow users to manage metrics |\n\n### Data and Display\n\n| Flag | Default | Description |\n|-----------------------------|---------|----------------------------------------------------------|\n| \\`isAllowUnderlyingData\\` | false | Allow users to view underlying data |\n| \\`isAllowCreateDashboardView\\`| false | Allow users to create dashboard views |\n\n### AI Features\n\n| Flag | Default | Description |\n|-----------------------------|---------|----------------------------------------------------------|\n| \\`isAllowAiPilot\\` | false | Enable the AI Pilot for natural language data queries |\n\n### Reports\n\n| Flag | Default | Description |\n|-----------------------------|---------|----------------------------------------------------------|\n| \\`isAllowEmailReports\\` | false | Allow sending email reports |\n\n### Configuration\n\n| Flag | Default | Description |\n|-----------------------------|---------|----------------------------------------------------------|\n| \\`metricCreationMode\\` | DRAG_DROP | Metric creation mode: DRAG_DROP or CHAT |\n| \\`joinModel\\` | single | Join strategy: single or multi |\n| \\`datamartName\\` | — | Datamart used by this embed |\n\n---\n\n## Metric Creation Modes\n\nWhen \\`isAllowMetricCreation\\` is enabled, you can control how users create metrics\nusing the \\`metricCreationMode\\` setting:\n\n### DRAG_DROP\nThe traditional visual metric builder. Users select dimensions, measures, and chart\ntypes through a drag-and-drop interface.\n\n\\`\\`\\`json\n{\n \"isAllowMetricCreation\": true,\n \"metricCreationMode\": \"DRAG_DROP\"\n}\n\\`\\`\\`\n\n### CHAT\nAI-powered metric creation. Users describe what they want in natural language and\nthe AI generates the metric. Requires a semantic layer on the underlying datamarts.\n\n\\`\\`\\`json\n{\n \"isAllowMetricCreation\": true,\n \"metricCreationMode\": \"CHAT\"\n}\n\\`\\`\\`\n\n> **Note**: CHAT mode requires:\n> - Semantic layer populated for the datamarts (use \\`get_semantic_layer\\` / \\`update_semantic_layer\\` via MCP, or the \\`populate-semantic-layer\\` prompt to auto-generate descriptions)\n> - \\`isAllowAiPilot\\` should also be enabled for the best experience\n\n---\n\n## Applying Access Settings\n\n### At Embed Configuration Level\n\nSet default access settings when creating or updating an embed:\n\n\\`\\`\\`json\n{\n \"dataAppId\": \"app-123\",\n \"dashboardId\": \"dash-456\",\n \"name\": \"Customer Embed\",\n \"accessSettings\": {\n \"isAllowMetricCreation\": false,\n \"isAllowMetricUpdate\": false,\n \"isAllowUnderlyingData\": true,\n \"isAllowAiPilot\": false,\n \"isAllowEmailReports\": false\n }\n}\n\\`\\`\\`\n\n### Runtime Overrides via Guest Token\n\nOverride permissions at guest token generation time using the \\`permissions\\` field.\nThis is useful for role-based access where different users get different permissions.\n\n> **Important**: The guest token API accepts \\`permissions\\`, NOT \\`accessSettings\\`.\n> Sending \\`accessSettings\\` or \\`allowedEmbeds\\` in a guest token request will return a 400 error.\n\n\\`\\`\\`json\n{\n \"clientId\": \"tenant-abc\",\n \"dataAppName\": \"My App\",\n \"permissions\": {\n \"isEnableManageMetrics\": true,\n \"isEnableDownloadMetrics\": true,\n \"isEnableUnderlyingData\": true,\n \"isEnableCustomizeLayout\": true\n }\n}\n\\`\\`\\`\n\n**Accepted \\`permissions\\` fields:**\n| Field | Description |\n|---|---|\n| \\`isEnableArchiveMetrics\\` | Allow archiving metrics |\n| \\`isEnableManageMetrics\\` | Allow managing metrics |\n| \\`isEnableCreateDashboardView\\` | Allow creating dashboard views |\n| \\`isEnableMetricUpdation\\` | Allow editing metrics |\n| \\`isEnableCustomizeLayout\\` | Allow layout customization |\n| \\`isEnableUnderlyingData\\` | Allow viewing underlying data |\n| \\`isEnableDownloadMetrics\\` | Allow downloading metric data |\n| \\`isShowSideBar\\` | Show the sidebar |\n| \\`isShowDashboardName\\` | Show the dashboard name |\n| \\`isDisableMetricCreation\\` | Disable metric creation |\n\nGuest token permissions **merge with and override** embed-level access settings. Only the\nflags you specify are overridden; unspecified flags keep their embed-level values.\n\n### Component-Level Overrides\n\nOverride access settings via the web component \\`options\\` attribute:\n\n\\`\\`\\`html\n<dbn-dashboard\n token=\"...\"\n dashboard-id=\"...\"\n options='{\n \"accessSettings\": {\n \"isAllowUnderlyingData\": true,\n \"isAllowEmailReports\": true\n }\n }'\n></dbn-dashboard>\n\\`\\`\\`\n\n> **Security Note**: Component-level overrides are client-side and can be modified by\n> end users with browser developer tools. For security-sensitive settings, always\n> enforce them via guest token or embed configuration (server-side).\n\n---\n\n## Precedence Order\n\nWhen the same flag is set at multiple levels, the highest precedence wins:\n\n1. **Web component \\`options\\`** (highest - client-side)\n2. **Guest token \\`permissions\\`** (server-side, per session)\n3. **Embed configuration \\`accessSettings\\`** (server-side, default)\n\n> **Best Practice**: Set restrictive defaults at the embed level. Use guest token\n> overrides to grant additional permissions to specific users or roles. Avoid relying\n> on component-level overrides for security.\n\n---\n\n## Common Configurations\n\n### View-Only Dashboard\n\\`\\`\\`json\n{\n \"isAllowMetricCreation\": false,\n \"isAllowMetricDeletion\": false,\n \"isAllowMetricUpdate\": false,\n \"isAllowMetricLayoutChange\": false,\n \"isAllowManageMetrics\": false,\n \"isAllowAiPilot\": false,\n \"isAllowEmailReports\": false\n}\n\\`\\`\\`\n\n### Power User Dashboard\n\\`\\`\\`json\n{\n \"isAllowMetricCreation\": true,\n \"isAllowMetricUpdate\": true,\n \"isAllowMetricDeletion\": true,\n \"isAllowMetricLayoutChange\": true,\n \"isAllowManageMetrics\": true,\n \"isAllowUnderlyingData\": true,\n \"isAllowAiPilot\": true,\n \"isAllowEmailReports\": true,\n \"isAllowCreateDashboardView\": true,\n \"metricCreationMode\": \"CHAT\"\n}\n\\`\\`\\`\n\n### Export-Enabled Dashboard\n\\`\\`\\`json\n{\n \"isAllowMetricCreation\": false,\n \"isAllowMetricUpdate\": false,\n \"isAllowUnderlyingData\": true,\n \"isAllowEmailReports\": true\n}\n\\`\\`\\`\n`;\n","export const semanticLayerGuideContent = `\n\n## Semantic models v2\n\nThe v2 source is one YAML document. Use the configured service credential and a datamart ID from \\`list_datamarts\\`.\n\n1. \\`search_semantic_model\\` finds entities by question. \\`get_semantic_entity\\` reads one entity by kind and name. Column names use table.column.\n2. \\`propose_semantic_change\\` takes complete source YAML, a YAML patch or one structured change. It returns candidate source, validation errors, a plan and the stored expected hash without writing.\n3. \\`eval_semantic_model\\` checks closed-world assertions against the proposed source; optional questions use id, question and exercises (exact entity names). It does not execute SQL.\n4. \\`apply_semantic_change\\` defaults to a dry run. Live apply requires the exact reviewed source, \\`expected_content_hash\\`, \\`dry_run: false\\` and user supplied \\`confirm: \"APPLY_TO_PRODUCTION\"\\`. Never supply confirmation yourself. Apply changes the live model for all consumers. On a conflict, prepare a fresh proposal and review it again.\n\nYAML patches merge mappings and named lists by name. Other lists replace. Empty lists clear; null removes a field. Structured changes use operation upsert or remove, kind, name, and value for upsert. Column changes also require table. Patch output normalizes formatting and comments, so review the returned source before apply.\n\nThe legacy maintenance workflow below applies to datamarts that have not moved to v2. Do not call \\`update_semantic_layer\\` for v2.\n\n# Databrain Semantic Layer Guide\n\n## What Is the Semantic Layer?\n\nThe semantic layer is a metadata layer that sits on top of your datamarts (database tables\nand views). It provides **business context** that helps both humans and AI understand the\nmeaning and relationships in your data.\n\nWithout a semantic layer, column names like \\`cust_id\\`, \\`amt_usd\\`, or \\`cat_cd\\` are\nopaque. The semantic layer translates these into business-friendly descriptions, making\nyour data accessible to non-technical users and enabling AI-powered features.\n\n---\n\n## Components of a Semantic Layer\n\n### Table Descriptions\nA natural language description of what the table represents.\n\n**Example:**\n- Table: \\`orders\\`\n- Description: \"Contains all customer orders including order date, status, total amount, and shipping details. Each row represents a single order.\"\n\n### Column Descriptions\nA natural language description for each column explaining its meaning, valid values,\nand business context.\n\n**Example:**\n| Column | Description |\n|----------------|----------------------------------------------------------|\n| \\`order_id\\` | Unique identifier for the order |\n| \\`customer_id\\` | Foreign key linking to the customers table |\n| \\`status\\` | Order status: pending, processing, shipped, delivered, cancelled |\n| \\`total_amount\\` | Total order value in USD, including tax and shipping |\n| \\`created_at\\` | Timestamp when the order was placed (UTC) |\n\n### Synonyms\nAlternative names or terms that users might use to refer to a table or column.\nSynonyms improve AI query understanding.\n\n**Example:**\n- Column \\`total_amount\\` synonyms: \\`[\"order total\", \"revenue\", \"sale amount\", \"order value\"]\\`\n- Column \\`created_at\\` synonyms: \\`[\"order date\", \"purchase date\", \"date placed\"]\\`\n- Table \\`orders\\` synonyms: \\`[\"purchases\", \"transactions\", \"sales\"]\\`\n\n### Example Questions\nSample natural language questions that can be answered using the data in this table.\nThese serve as few-shot examples for the AI.\n\n**Example:**\n- \"What is the total revenue by month?\"\n- \"Show me the top 10 customers by order count\"\n- \"What is the average order value for each product category?\"\n- \"How many orders were cancelled last quarter?\"\n- \"What is the trend of daily orders over the past 6 months?\"\n\n---\n\n## Auto-Generation\n\nThe semantic layer is populated and maintained entirely via MCP tools. When it's empty,\nthe AI assistant can auto-generate business-friendly descriptions from table and column\nnames. Use the \\`populate-semantic-layer\\` prompt for a detailed step-by-step workflow,\nor follow the manual steps below.\n\n### Step 1: Review the Current Semantic Layer\n\nUse the \\`get_semantic_layer\\` tool to inspect what metadata already exists:\n\n\\`\\`\\`\nTool: get_semantic_layer\nParameters:\n - datamartName: \"my_datamart\"\n\\`\\`\\`\n\nThis returns:\n- Table descriptions and column descriptions\n- Synonyms and example questions\n- A completion score (0-100%)\n\n### Step 2: Update the Semantic Layer\n\nUse the \\`update_semantic_layer\\` tool to add or improve metadata:\n\n\\`\\`\\`\nTool: update_semantic_layer\nParameters:\n - datamartName: \"my_datamart\"\n - tables: [{ name: \"orders\", description: \"Customer orders...\", columns: [...] }]\n - feedback: \"This datamart covers e-commerce data for the US market\"\n\\`\\`\\`\n\nYou can update table descriptions, column descriptions, synonyms, and general\nfeedback. Only include the tables and columns you want to change — existing\nmetadata for other tables/columns is preserved.\n\n### Step 3: Review and Iterate\n\nAfter updating, call \\`get_semantic_layer\\` again to verify the changes and check\nthe updated completion score. Then use \\`ask_question\\` to test query accuracy with\nthe improved semantic layer. Iterate until the results are satisfactory.\n\n---\n\n## Completion Score\n\nThe semantic layer has a **completion score** (0-100%) that measures how thoroughly\nyour datamarts are documented.\n\n### How It Is Calculated\n\nThe score considers:\n- **Table description** - Does the table have a description?\n- **Column coverage** - What percentage of columns have descriptions?\n- **Synonym coverage** - Do columns have synonyms defined?\n- **Example questions** - Are example questions provided?\n\n### Why It Matters\n\n| Score Range | Impact |\n|-------------|----------------------------------------------------------------|\n| 0-25% | AI Pilot will produce poor results; basic features only |\n| 25-50% | AI can answer simple questions but struggles with ambiguity |\n| 50-75% | Good coverage; AI handles most queries accurately |\n| 75-100% | Excellent; AI Pilot performs at its best |\n\n**A higher completion score directly improves AI Pilot accuracy.** The semantic layer\nprovides the context the AI needs to:\n- Understand which columns to use for a given question\n- Resolve ambiguous terms (e.g., \"revenue\" could mean \\`total_amount\\` or \\`net_amount\\`)\n- Generate correct SQL joins between tables\n- Apply appropriate aggregations and filters\n\n---\n\n## When to Use the Semantic Layer\n\n### Required For:\n- **AI Pilot** (\\`isAllowAiPilot\\`) - The AI chat interface requires semantic layer\n context to generate accurate queries. Without it, the AI will not know what your\n columns mean and will produce unreliable results.\n- **CHAT metric creation mode** - When users create metrics via natural language,\n the semantic layer guides the AI in interpreting their requests.\n- **AI-powered features** - AI-generated data summaries and recommendations\n use semantic context for more meaningful insights.\n\n### Recommended For:\n- **All production embeds** - Even without AI features, the semantic layer improves\n the user experience by providing descriptive column names and context in the UI.\n- **Onboarding new team members** - The semantic layer serves as living documentation\n for your data model.\n\n### Not Required For:\n- **Basic embedding without AI features** - If you only need to display pre-built\n dashboards and metrics without AI capabilities, the semantic layer is optional\n (but still recommended).\n\n---\n\n## Best Practices\n\n### 1. Start with What Exists\nUse \\`get_semantic_layer\\` to review current metadata and identify gaps. Focus on\nadding descriptions and synonyms where they are missing.\n\n### 2. Prioritize High-Traffic Tables\nFocus on the tables that are most frequently queried or that appear in the most\nmetrics. These benefit most from accurate semantic metadata.\n\n### 3. Use Domain-Specific Language\nWrite descriptions and synonyms in the language your business users actually use,\nnot technical database terminology.\n\n### 4. Include Edge Cases in Examples\nAdd example questions that cover edge cases, date ranges, comparisons, and\naggregations your users commonly need.\n\n### 5. Keep It Updated\nWhen your schema changes (new columns, renamed tables), regenerate or update the\nsemantic layer to stay current.\n\n### 6. Aim for 75%+ Completion\nA completion score of 75% or higher ensures reliable AI Pilot performance. Below\nthis threshold, expect decreased accuracy in AI-generated queries.\n\n---\n\n## Semantic Layer vs Raw Schema\n\n| Aspect | Raw Schema | With Semantic Layer |\n|---------------------|-----------------------------|--------------------------------------|\n| Column reference | \\`cust_id\\` | \"Customer ID - unique identifier\" |\n| AI understanding | Guesses from name | Knows exact meaning and context |\n| User experience | Technical column names | Business-friendly labels |\n| Query accuracy | Hit or miss | Consistently high |\n| Ambiguity handling | Cannot resolve | Uses synonyms and descriptions |\n`;\n","export const themeReferenceContent = `\n# Databrain Theme Reference\n\n## Overview\n\nThemes control the visual appearance of embedded dashboards and metrics. Databrain\nsupports predefined themes and fully custom theme configurations. Themes can be applied\nat multiple levels: embed configuration, guest token, or web component attributes.\n\n---\n\n## Theme Categories\n\nThemes are organized into categories, each controlling a specific visual area:\n\n### general\nTop-level appearance settings that apply globally.\n\n| Property | Type | Description |\n|-------------------|---------|------------------------------------------|\n| \\`fontFamily\\` | string | Primary font family |\n| \\`backgroundColor\\` | string | Overall background color |\n| \\`primaryColor\\` | string | Primary accent color |\n| \\`secondaryColor\\` | string | Secondary accent color |\n| \\`textColor\\` | string | Default text color |\n| \\`borderColor\\` | string | Default border color |\n| \\`borderRadius\\` | string | Default border radius (e.g., \"8px\") |\n\n### dashboard\nDashboard container and layout styling.\n\n| Property | Type | Description |\n|-----------------------|---------|--------------------------------------|\n| \\`backgroundColor\\` | string | Dashboard background color |\n| \\`ctaColor\\` | string | Call-to-action button color |\n| \\`ctaTextColor\\` | string | CTA button text color |\n| \\`selectBoxSize\\` | string | Filter select box size: \"small\", \"medium\", \"large\" |\n| \\`selectBoxVariant\\` | string | Filter select box style: \"floating\", \"static\" |\n| \\`selectBoxBorderRadius\\` | string | Select box border radius (e.g. \"20px\") |\n| \\`selectBoxTextColor\\` | string | Select box text color |\n| \\`metricCardColor\\` | string | Metric card background color |\n| \\`padding\\` | string | Dashboard padding |\n| \\`gap\\` | string | Gap between metric cards |\n\n### chart\nDefault chart appearance settings.\n\n| Property | Type | Description |\n|----------------------|----------|--------------------------------------|\n| \\`colorPalette\\` | string[] | Array of colors for chart series |\n| \\`backgroundColor\\` | string | Chart area background color |\n| \\`axisColor\\` | string | Axis line color |\n| \\`axisLabelColor\\` | string | Axis label text color |\n| \\`gridColor\\` | string | Grid line color |\n| \\`tooltipBackground\\` | string | Tooltip background color |\n| \\`tooltipTextColor\\` | string | Tooltip text color |\n| \\`legendColor\\` | string | Legend text color |\n\n### cardTitle\nMetric card title styling.\n\n| Property | Type | Description |\n|----------------|---------|------------------------------------------|\n| \\`fontSize\\` | string | Title font size (e.g., \"16px\") |\n| \\`fontWeight\\` | string | Title font weight (e.g., \"600\") |\n| \\`color\\` | string | Title text color |\n| \\`fontFamily\\` | string | Title font family override |\n\n### cardDescription\nMetric card description styling.\n\n| Property | Type | Description |\n|----------------|---------|------------------------------------------|\n| \\`fontSize\\` | string | Description font size |\n| \\`fontWeight\\` | string | Description font weight |\n| \\`color\\` | string | Description text color |\n| \\`fontFamily\\` | string | Description font family override |\n\n### cardCustomization\nMetric card container styling.\n\n| Property | Type | Description |\n|-----------------------|---------|--------------------------------------|\n| \\`padding\\` | string | Card internal padding |\n| \\`borderRadius\\` | string | Card border radius |\n| \\`shadow\\` | string | Card box shadow |\n| \\`disableShadowOnHover\\` | boolean | Disable shadow on card hover |\n| \\`disableStroke\\` | boolean | Remove card border stroke |\n| \\`metricStrokeColor\\` | string | Card border stroke color |\n\n### chartCustomization\nFine-grained chart element styling.\n\n| Property | Type | Description |\n|------------------------|---------|------------------------------------|\n| \\`barBorderRadius\\` | string | Border radius for bar charts |\n| \\`barWidth\\` | string | Bar width in bar charts |\n| \\`lineWidth\\` | string | Line width in line charts |\n| \\`pointSize\\` | string | Data point size in line/scatter |\n| \\`areaOpacity\\` | string | Area fill opacity (0-1) |\n| \\`pieBorderWidth\\` | string | Border width for pie chart slices |\n| \\`doughnutCutout\\` | string | Cutout percentage for doughnut |\n\n### Component-Level Theme (ThemeType)\nLow-level UI component styling set via the \\`theme\\` property (separate from adminThemeOptions).\n\n| Property | Type | Description |\n|--------------------------------------------|---------|--------------------------------------------|\n| \\`button.primary\\` | string | Primary button background color |\n| \\`button.secondary\\` | string | Secondary button background color |\n| \\`button.primaryText\\` | string | Primary button text color |\n| \\`button.secondaryText\\` | string | Secondary button text color |\n| \\`checkbox.checked\\` | string | Checked checkbox color |\n| \\`checkbox.unChecked\\` | string | Unchecked checkbox color |\n| \\`switch.enabled\\` | string | Enabled switch color |\n| \\`switch.disabled\\` | string | Disabled switch color |\n| \\`drillBreadCrumbs.fontFamily\\` | string | Drill breadcrumb font family |\n| \\`drillBreadCrumbs.fontColor\\` | string | Drill breadcrumb font color |\n| \\`drillBreadCrumbs.activeColor\\` | string | Active breadcrumb color |\n| \\`multiSelectFilterDropdown.badgeColor\\` | string | Multi-select filter badge color |\n| \\`multiSelectFilterDropdown.badgeTextColor\\`| string | Multi-select filter badge text color |\n| \\`datePickerColor\\` | string | Date picker accent color |\n| \\`breakpoint\\` | object | Responsive breakpoints: \\`{ xl, lg, md, sm, xs }\\` (px widths) |\n| \\`metricLayoutCols\\` | object | Grid columns per breakpoint: \\`{ xl, lg, md, sm, xs, xxs }\\` |\n\n### Chart Tooltip Font Properties\nTooltip font objects use short property names (not prefixed):\n\n| Property | Type | Description |\n|----------|--------|--------------------|\n| \\`size\\` | number | Font size in px |\n| \\`family\\` | string | Font family |\n| \\`weight\\` | number | Font weight |\n| \\`color\\` | string | Font color (hex) |\n\nThese apply to \\`chartAppearance.chartTooltip.tooltipHeader\\`, \\`.labelStyle\\`, and \\`.valueStyle\\`.\n\n### Axis Properties\nBoth \\`verticalAxis\\` and \\`horizontalAxis\\` in \\`chartAppearance\\` support:\n\n| Property | Type | Description |\n|-------------------|---------|-------------------------------------------|\n| \\`axisLabelMargin\\` | number | Margin between axis labels and chart area |\n| \\`axisNameFontConfig\\` | object | Axis title font: \\`{ fontFamily, fontSize, fontWeight }\\` |\n\n(In addition to \\`hideAxisLines\\`, \\`hideSplitLines\\`, \\`hideAxisLabels\\`, \\`hideAxisTicks\\`, \\`axisName\\`, \\`axisNameOffset\\`, \\`fontSize\\`, \\`fontFamily\\`, \\`fontWeight\\`, \\`color\\`, \\`axisColor\\`.)\n\n---\n\n## Predefined Themes\n\nDatabrain offers predefined themes that can be referenced by name:\n\n- **light** - Clean light theme with white backgrounds\n- **dark** - Dark theme with dark backgrounds and light text\n- **modern** - Contemporary styling with subtle shadows and rounded corners\n- **minimal** - Minimalist design with reduced visual elements\n- **corporate** - Professional styling suited for business dashboards\n\nTo use a predefined theme, reference it by name in the embed or guest token configuration.\n\n---\n\n## Custom Theme JSON Structure\n\nA full custom theme object:\n\n\\`\\`\\`json\n{\n \"general\": {\n \"fontFamily\": \"Inter, sans-serif\",\n \"backgroundColor\": \"#ffffff\",\n \"primaryColor\": \"#4F46E5\",\n \"secondaryColor\": \"#10B981\",\n \"textColor\": \"#1F2937\",\n \"borderColor\": \"#E5E7EB\",\n \"borderRadius\": \"8px\"\n },\n \"dashboard\": {\n \"backgroundColor\": \"#F9FAFB\",\n \"padding\": \"24px\",\n \"gap\": \"16px\",\n \"filterBarBackground\": \"#FFFFFF\"\n },\n \"chart\": {\n \"colorPalette\": [\"#4F46E5\", \"#10B981\", \"#F59E0B\", \"#EF4444\", \"#8B5CF6\", \"#06B6D4\"],\n \"backgroundColor\": \"transparent\",\n \"axisColor\": \"#9CA3AF\",\n \"axisLabelColor\": \"#6B7280\",\n \"gridColor\": \"#F3F4F6\",\n \"tooltipBackground\": \"#1F2937\",\n \"tooltipTextColor\": \"#FFFFFF\",\n \"legendColor\": \"#374151\"\n },\n \"cardTitle\": {\n \"fontSize\": \"16px\",\n \"fontWeight\": \"600\",\n \"color\": \"#111827\",\n \"fontFamily\": \"Inter, sans-serif\"\n },\n \"cardDescription\": {\n \"fontSize\": \"13px\",\n \"fontWeight\": \"400\",\n \"color\": \"#6B7280\",\n \"fontFamily\": \"Inter, sans-serif\"\n },\n \"cardCustomization\": {\n \"backgroundColor\": \"#FFFFFF\",\n \"borderColor\": \"#E5E7EB\",\n \"borderWidth\": \"1px\",\n \"borderRadius\": \"12px\",\n \"padding\": \"20px\",\n \"shadow\": \"0 1px 3px rgba(0,0,0,0.1)\"\n },\n \"chartCustomization\": {\n \"barBorderRadius\": \"4px\",\n \"lineWidth\": \"2px\",\n \"pointSize\": \"4px\",\n \"areaOpacity\": \"0.1\"\n }\n}\n\\`\\`\\`\n\nYou do not need to specify all properties. Any omitted properties will use the\ndefaults from the active base theme.\n\n---\n\n## How to Apply Themes\n\n### Via Embed Configuration\n\nSet the theme when creating or updating an embed:\n\n\\`\\`\\`json\n{\n \"dataAppId\": \"app-123\",\n \"dashboardId\": \"dash-456\",\n \"name\": \"Themed Embed\",\n \"theme\": {\n \"general\": {\n \"primaryColor\": \"#4F46E5\",\n \"fontFamily\": \"Inter, sans-serif\"\n },\n \"chart\": {\n \"colorPalette\": [\"#4F46E5\", \"#10B981\", \"#F59E0B\"]\n }\n }\n}\n\\`\\`\\`\n\n### Via Guest Token (Runtime Override)\n\nApply or override theme settings at guest token generation time:\n\n\\`\\`\\`json\n{\n \"embedId\": \"embed-789\",\n \"theme\": {\n \"general\": {\n \"primaryColor\": \"#DC2626\"\n },\n \"dashboard\": {\n \"backgroundColor\": \"#FEF2F2\"\n }\n }\n}\n\\`\\`\\`\n\nGuest token theme settings override embed-level theme settings.\n\n### Via Web Component Attribute\n\nPass a theme JSON string as an attribute on the web component:\n\n\\`\\`\\`html\n<dbn-dashboard\n token=\"guest-token\"\n dashboard-id=\"dash-456\"\n options='{\"theme\": {\"general\": {\"primaryColor\": \"#4F46E5\"}}}'\n></dbn-dashboard>\n\\`\\`\\`\n\n### Theme Precedence (Highest to Lowest)\n\n1. Web component attribute theme\n2. Guest token theme\n3. Embed configuration theme\n4. Predefined/default theme\n`;\n","export const useCaseGuidesContent = `# Databrain Use Case Guides\n\nDatabrain supports 3 core use cases for embedding analytics. Each maps to a specific MCP prompt and tool sequence.\n\n---\n\n## Use Case 1: Embed an Existing Dashboard\n**When to use:** You already have dashboards built in the Databrain UI and want to embed them in your app.\n**Prompt:** \\`embed-existing-dashboard\\`\n**Path:** UI-first — dashboards are created in Databrain, then embedded programmatically.\n**Tool sequence:** \\`list_data_apps\\` → \\`list_api_tokens\\`/\\`create_api_token\\` → \\`list_workspaces\\` → \\`list_dashboards\\` → \\`create_embed\\` → \\`generate_guest_token\\` → \\`generate_embed_code\\`\n\n## Use Case 2: Embed Blank Dashboards (Multi-Tenant)\n**When to use:** Each of your customers/clients needs their own dashboard — blank or cloned from a template. Ideal for SaaS multi-tenant scenarios.\n**Prompt:** \\`embed-blank-dashboard\\`\n**Path:** Per-client dashboard creation using \\`create_embed\\` with \\`clientId\\`.\n**Tool sequence:** \\`list_data_apps\\` → \\`list_datamarts\\` → \\`create_embed\\` with \\`clientId\\` (per client) → \\`generate_guest_token\\` → \\`generate_embed_code\\`\n**Key concepts:** \\`clientId\\` for tenant isolation, \\`templateDashboardId\\` for cloning, \\`tableTenancySettings\\` for row-level security.\n\n## Use Case 3: Explore and Query Data\n**When to use:** You want to explore available data and ask questions using natural language.\n**Prompt:** \\`query-data\\` (or \\`populate-semantic-layer\\` if starting from an empty semantic layer)\n**Path:** Exploration + querying (datasources, datamarts, and workspaces are created in the Databrain UI). The semantic layer is populated via MCP tools.\n**Tool sequence:** \\`list_datamarts\\` → \\`get_semantic_layer\\` → if semantic layer is empty, auto-generate descriptions and push with \\`update_semantic_layer\\` → \\`ask_question\\`\n**Alternative:** \\`list_datasources\\` → \\`discover_datasource_schema\\` (to explore raw tables before creating datamarts in the UI)\n\n---\n\n## Customization (After Any Setup)\n\nOnce an embed exists, use the \\`brand-my-embed\\` prompt for theming. For everything else, describe what you need and the assistant uses tools directly:\n\n| Task | How |\n|------|-----|\n| Colors, fonts, chart styles | Prompt: \\`brand-my-embed\\` |\n| Filters (string, date, SQL) | \\`update_embed\\` with \\`options.globalFilterOptions\\` via body passthrough |\n| Localization / translations | \\`update_embed\\` with \\`componentAttributes\\` via body passthrough |\n| Permissions / access controls | \\`update_embed\\` + \\`generate_guest_token\\` with permissions |\n| Metric creation modes | \\`update_embed\\` accessSettings + \\`generate_guest_token\\` |\n| Manage / audit embeds | \\`list_embeds\\` → \\`get_embed_details\\` |\n| Semantic layer | Prompt: \\`populate-semantic-layer\\` or \\`get_semantic_layer\\` / \\`update_semantic_layer\\` |\n\n---\n\n## Choosing the Right Path\n\n| Question | Answer → Use Case |\n|----------|-------------------|\n| Do you have dashboards in Databrain UI? | Yes → Use Case 1 |\n| Does each client need their own dashboard? | Yes → Use Case 2 |\n| Want to explore or query your data? | Yes → Use Case 3 |\n| Just need to brand/customize? | Use \\`brand-my-embed\\` prompt or describe what you need |\n`;\n","export const webComponentReferenceContent = `\n# Databrain Web Component Reference\n\n## Overview\n\nDatabrain provides two web components for embedding analytics into any web application:\n\n- \\`<dbn-dashboard>\\` - Renders a full dashboard with all its metrics\n- \\`<dbn-metric>\\` - Renders a single metric/chart\n\nBoth are standard web components (custom HTML elements) and work in any framework\nor vanilla HTML/JavaScript.\n\n---\n\n## Installation\n\n\\`\\`\\`bash\nnpm install @databrainhq/plugin\n\\`\\`\\`\n\nImport in your application entry point:\n\n\\`\\`\\`typescript\nimport '@databrainhq/plugin';\n\\`\\`\\`\n\n---\n\n## \\`<dbn-dashboard>\\`\n\nEmbeds a complete dashboard including all its metrics, filters, and layout.\n\n### Required Attributes\n\n| Attribute | Type | Description |\n|------------------|--------|--------------------------------------------|\n| \\`token\\` | string | Guest token generated server-side |\n| \\`dashboard-id\\` | string | ID of the dashboard to render |\n\n### Basic Usage\n\n\\`\\`\\`html\n<dbn-dashboard\n token=\"eyJhbGciOi...\"\n dashboard-id=\"dash-abc-123\"\n></dbn-dashboard>\n\\`\\`\\`\n\n---\n\n## \\`<dbn-metric>\\`\n\nEmbeds a single metric/chart from a dashboard.\n\n### Required Attributes\n\n| Attribute | Type | Description |\n|----------------|--------|--------------------------------------------|\n| \\`token\\` | string | Guest token generated server-side |\n| \\`metric-id\\` | string | ID of the metric to render |\n\n### Basic Usage\n\n\\`\\`\\`html\n<dbn-metric\n token=\"eyJhbGciOi...\"\n metric-id=\"metric-xyz-456\"\n></dbn-metric>\n\\`\\`\\`\n\n---\n\n## Display Control Attributes\n\nThese boolean attributes control the visibility of UI elements within the embedded\ncomponents.\n\n| Attribute | Component | Description |\n|--------------------------------|-------------|------------------------------------------------|\n| \\`is-hide-table-preview\\` | both | Hides the table/data preview toggle |\n| \\`is-hide-chart-settings\\` | both | Hides the chart settings/configuration panel |\n| \\`disable-fullscreen\\` | both | Disables the fullscreen toggle button |\n| \\`enable-title-click-fullscreen\\`| both | Clicking metric title enters fullscreen |\n\n### Example\n\n\\`\\`\\`html\n<dbn-dashboard\n token=\"eyJhbGciOi...\"\n dashboard-id=\"dash-abc-123\"\n is-hide-table-preview\n is-hide-chart-settings\n disable-fullscreen\n></dbn-dashboard>\n\\`\\`\\`\n\n---\n\n## Download and Export Attributes\n\nControl data export capabilities for end users.\n\n| Attribute | Component | Description |\n|--------------------------------|-------------|--------------------------------------------------|\n| \\`enable-download-csv\\` | both | Enables CSV download for individual metrics |\n| \\`enable-email-csv\\` | both | Enables emailing metric data as CSV |\n| \\`enable-download-all-metrics\\` | dashboard | Enables bulk download of all metrics as CSV |\n| \\`enable-download-all-pdf\\` | dashboard | Enables downloading entire dashboard as PDF |\n\n### Example\n\n\\`\\`\\`html\n<dbn-dashboard\n token=\"eyJhbGciOi...\"\n dashboard-id=\"dash-abc-123\"\n enable-download-csv\n enable-email-csv\n enable-download-all-metrics\n enable-download-all-pdf\n></dbn-dashboard>\n\\`\\`\\`\n\n---\n\n## Advanced Attributes\n\n| Attribute | Component | Description |\n|----------------------------------|-------------|------------------------------------------------------|\n| \\`enable-multi-metric-filters\\` | dashboard | Enables cross-metric filter interactions |\n| \\`is-sticky-dashboard-filters\\` | dashboard | Makes the filter bar sticky at the top on scroll |\n| \\`options-icon\\` | both | Custom icon: \\`\"kebab-menu-vertical\"\\` or \\`\"download\"\\` |\n| \\`settings-icon\\` | dashboard | Custom settings icon (JSON: \\`{\"name\":\"...\",\"iconSvg\":\"...\"}\\`) |\n| \\`language\\` | dashboard | Locale code (e.g. \\`\"en\"\\`, \\`\"fr\"\\`, \\`\"de\"\\`) |\n| \\`calendar-type\\` | dashboard | Calendar format: \\`\"default\"\\` or \\`\"ind\"\\` (Indian FY) |\n| \\`no-data-img\\` | dashboard | URL to custom image shown when no data is found |\n| \\`no-data-found-svg\\` | dashboard | Inline SVG shown when no data is found |\n| \\`hide-dashboard-filters\\` | dashboard | JSON array of filter names to hide (e.g. \\`'[\"Region\"]'\\`) |\n| \\`long-description-config\\` | dashboard | JSON: \\`{\"width\":\"300px\",\"fontColor\":\"#666\"}\\` |\n| \\`custom-chart-settings\\` | dashboard | JSON per-chart overrides (CustomChartSettingsType) |\n\n### Example\n\n\\`\\`\\`html\n<dbn-dashboard\n token=\"eyJhbGciOi...\"\n dashboard-id=\"dash-abc-123\"\n enable-multi-metric-filters\n is-sticky-dashboard-filters\n></dbn-dashboard>\n\\`\\`\\`\n\n---\n\n## The \\`options\\` Attribute\n\nThe \\`options\\` attribute accepts a JSON string with advanced configuration:\n\n\\`\\`\\`html\n<dbn-dashboard\n token=\"eyJhbGciOi...\"\n dashboard-id=\"dash-abc-123\"\n options='{ \"theme\": {...}, \"accessSettings\": {...}, \"customMessages\": {...} }'\n></dbn-dashboard>\n\\`\\`\\`\n\n### Options JSON Structure\n\n\\`\\`\\`json\n{\n \"theme\": {\n \"general\": { },\n \"chart\": { },\n \"dashboard\": { },\n \"cardTitle\": { },\n \"cardDescription\": { },\n \"cardCustomization\": { },\n \"chartCustomization\": { }\n },\n \"accessSettings\": {\n \"isAllowMetricCreation\": false,\n \"isAllowMetricDeletion\": false,\n \"isAllowMetricUpdate\": false,\n \"isAllowMetricLayoutChange\": false,\n \"isAllowAiPilot\": false\n },\n \"customMessages\": {\n \"noDataMessage\": \"No data available for the selected filters.\",\n \"errorMessage\": \"Something went wrong. Please try again.\"\n }\n}\n\\`\\`\\`\n\n### Setting Options in JavaScript\n\nFor dynamic configurations, set the \\`options\\` attribute via JavaScript:\n\n\\`\\`\\`javascript\nconst dashboard = document.querySelector('dbn-dashboard');\ndashboard.setAttribute('options', JSON.stringify({\n theme: {\n general: { primaryColor: '#4F46E5' }\n },\n accessSettings: {\n isAllowUnderlyingData: true,\n isAllowAiPilot: true\n }\n}));\n\\`\\`\\`\n\n---\n\n## Boolean Attribute Convention\n\nDatabrain web components follow the standard HTML boolean attribute convention:\n\n- **Presence** of the attribute means \\`true\\`\n- **Absence** of the attribute means \\`false\\`\n\n\\`\\`\\`html\n<!-- Downloads enabled -->\n<dbn-dashboard token=\"...\" dashboard-id=\"...\" enable-download-csv></dbn-dashboard>\n\n<!-- Downloads disabled (attribute omitted) -->\n<dbn-dashboard token=\"...\" dashboard-id=\"...\"></dbn-dashboard>\n\\`\\`\\`\n\nThe value of a boolean attribute does not matter. These are all equivalent:\n\\`\\`\\`html\n<dbn-dashboard enable-download-csv></dbn-dashboard>\n<dbn-dashboard enable-download-csv=\"\"></dbn-dashboard>\n<dbn-dashboard enable-download-csv=\"true\"></dbn-dashboard>\n\\`\\`\\`\n\nTo disable a boolean attribute, remove it entirely from the element. Setting it to\n\\`\"false\"\\` does **not** disable it (the attribute is still present).\n\n---\n\n## Responsive Behavior\n\nBoth components are responsive and adapt to their container size. Ensure the parent\ncontainer has defined dimensions:\n\n\\`\\`\\`html\n<div style=\"width: 100%; height: 600px;\">\n <dbn-dashboard token=\"...\" dashboard-id=\"...\"></dbn-dashboard>\n</div>\n\\`\\`\\`\n\nFor full-page dashboards:\n\n\\`\\`\\`html\n<div style=\"width: 100vw; height: 100vh;\">\n <dbn-dashboard token=\"...\" dashboard-id=\"...\"></dbn-dashboard>\n</div>\n\\`\\`\\`\n\n---\n\n## Events\n\nThe web components emit custom events that you can listen to:\n\n\\`\\`\\`javascript\nconst dashboard = document.querySelector('dbn-dashboard');\n\ndashboard.addEventListener('dbn-token-expired', (event) => {\n // Refresh the guest token and set the new one\n fetchNewGuestToken().then(newToken => {\n dashboard.setAttribute('token', newToken);\n });\n});\n\ndashboard.addEventListener('dbn-error', (event) => {\n console.error('Dashboard error:', event.detail);\n});\n\ndashboard.addEventListener('dbn-loaded', (event) => {\n console.log('Dashboard loaded successfully');\n});\n\\`\\`\\`\n\n---\n\n## Complete Example\n\n\\`\\`\\`html\n<!DOCTYPE html>\n<html>\n<head>\n <script type=\"module\">\n import '@databrainhq/plugin';\n </script>\n <style>\n #dashboard-container {\n width: 100%;\n max-width: 1200px;\n height: 800px;\n margin: 0 auto;\n }\n </style>\n</head>\n<body>\n <div id=\"dashboard-container\">\n <dbn-dashboard\n token=\"eyJhbGciOi...\"\n dashboard-id=\"dash-abc-123\"\n enable-download-csv\n enable-download-all-pdf\n enable-multi-metric-filters\n is-sticky-dashboard-filters\n is-hide-chart-settings\n options='{\n \"theme\": {\n \"general\": { \"primaryColor\": \"#4F46E5\" }\n }\n }'\n ></dbn-dashboard>\n </div>\n</body>\n</html>\n\\`\\`\\`\n`;\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { apiReferenceContent } from './content/api-reference.js';\nimport { embeddingGuideContent } from './content/embedding-guide.js';\nimport { filterReferenceContent } from './content/filter-reference.js';\nimport { gettingStartedContent } from './content/getting-started.js';\nimport { multiTenancyGuideContent } from './content/multi-tenancy-guide.js';\nimport { permissionSchemaContent } from './content/permission-schema.js';\nimport { selfServeReferenceContent } from './content/self-serve-reference.js';\nimport { semanticLayerGuideContent } from './content/semantic-layer-guide.js';\nimport { themeReferenceContent } from './content/theme-reference.js';\nimport { useCaseGuidesContent } from './content/use-case-guides.js';\nimport { webComponentReferenceContent } from './content/web-component-reference.js';\n\ninterface ResourceDef {\n uri: string;\n name: string;\n description: string;\n content: string;\n}\n\nconst resources: ResourceDef[] = [\n {\n uri: 'databrain://getting-started',\n name: 'Getting Started',\n description:\n 'Entity model, onboarding funnel, quick-start checklist, and common pitfalls',\n content: gettingStartedContent,\n },\n {\n uri: 'databrain://api-reference',\n name: 'API Reference',\n description:\n 'Summarized API reference covering key endpoints, parameters, and examples',\n content: apiReferenceContent,\n },\n {\n uri: 'databrain://embedding-guide',\n name: 'Embedding Guide',\n description:\n 'Framework-specific embedding instructions for React, Next.js, Vue, Angular, Svelte, SolidJS, and vanilla JS',\n content: embeddingGuideContent,\n },\n {\n uri: 'databrain://filter-reference',\n name: 'Filter Reference',\n description:\n 'Filter types, operators, and usage patterns for guest tokens, runtime, and dashboard-level filters',\n content: filterReferenceContent,\n },\n {\n uri: 'databrain://theme-reference',\n name: 'Theme Reference',\n description:\n 'Theme properties, predefined vs custom themes, color and branding customization',\n content: themeReferenceContent,\n },\n {\n uri: 'databrain://web-component-reference',\n name: 'Web Component Reference',\n description:\n 'Complete property reference for dbn-dashboard and dbn-metric web components',\n content: webComponentReferenceContent,\n },\n {\n uri: 'databrain://self-serve-reference',\n name: 'Self-Serve Reference',\n description:\n 'Access settings, metric creation modes, runtime permission overrides',\n content: selfServeReferenceContent,\n },\n {\n uri: 'databrain://semantic-layer-guide',\n name: 'Semantic Layer Guide',\n description:\n 'Semantic layer configuration for AI chat mode, auto-generation workflow',\n content: semanticLayerGuideContent,\n },\n {\n uri: 'databrain://multi-tenancy-guide',\n name: 'Multi-Tenancy Guide',\n description:\n 'Multi-tenant embedding with row-level security using clientId and clientColumn',\n content: multiTenancyGuideContent,\n },\n {\n uri: 'databrain://use-case-guides',\n name: 'Use Case Guides',\n description:\n 'Summary of 3 core use cases with tool sequences, prompt names, and decision guide',\n content: useCaseGuidesContent,\n },\n {\n uri: 'databrain://permission-schema',\n name: 'Permission Schema',\n description:\n 'Machine-readable permission/capability schema for embed accessSettings, guest token permissions, precedence rules, and known limitations',\n content: permissionSchemaContent,\n },\n];\n\nexport function registerAllResources(server: McpServer): void {\n for (const res of resources) {\n server.resource(\n res.name,\n res.uri,\n { description: res.description },\n async () => ({\n contents: [\n {\n uri: res.uri,\n mimeType: 'text/markdown',\n text: res.content,\n },\n ],\n })\n );\n }\n}\n","import { z } from 'zod';\nimport {\n MAX_BUNDLE_CSS_BYTES,\n MAX_BUNDLE_JS_BYTES,\n MAX_ICON_BYTES,\n MAX_MANIFEST_BYTES,\n} from '../custom-chart/types.js';\n\nexport const CHART_URI = 'ui://databrain/chart-tile';\nexport const KPI_URI = 'ui://databrain/kpi-tile';\nexport const APP_MIME = 'text/html;profile=mcp-app';\n// The deprecated flat pointer key. The official apps SDK exports the same constant and\n// still reads it, so it is published next to the nested `ui.resourceUri`, never instead of it.\nexport const RESOURCE_URI_META_KEY = 'ui/resourceUri';\nexport const PAGE_SIZE = 50;\n// Leave room for the inline HTML and hosted workspace metadata below the 150k host ceiling.\nexport const MAX_RESULT_CHARS = 124_000;\n// JSON strings can expand one source byte to six characters (e.g. NUL -> \\u0000).\n// The manifest is already bounded as serialized JSON; reserve the outer field syntax.\nexport const MAX_CUSTOM_BUNDLE_CHARS =\n 6 * (MAX_BUNDLE_JS_BYTES + MAX_BUNDLE_CSS_BYTES + MAX_ICON_BYTES) +\n MAX_MANIFEST_BYTES +\n 128;\nexport const CUSTOM_BUNDLE_CHUNK_CHARS = 32_000;\nconst id = z.string().trim().min(1).max(256);\nconst cell = z.union([\n z.string().max(2000),\n z.number().finite(),\n z.boolean(),\n z.null(),\n]);\nexport const rowsSchema = z.array(z.record(z.string(), cell)).max(PAGE_SIZE);\nexport const referenceSchema = z.union([\n z\n .object({\n embedId: id,\n clientId: id,\n widgetId: id,\n dataAppName: id.optional(),\n })\n .strict(),\n z\n .object({\n dashboardId: id,\n widgetId: id,\n clientId: id.optional(),\n display: z.enum(['chart', 'kpi']).optional(),\n })\n .strict(),\n]);\nexport type ChartReference = z.infer<typeof referenceSchema>;\nconst point = z\n .object({\n key: id,\n label: z.string().max(2000),\n value: cell,\n x: z.number().min(0),\n y: z.number().min(0),\n width: z.number().positive(),\n height: z.number().positive(),\n drillId: id.optional(),\n })\n .strict();\nexport const dateRangeSchema = z\n .object({\n from: z.string().date(),\n to: z.string().date(),\n })\n .strict()\n .refine((value) => value.from <= value.to, 'Date range must be ordered');\nexport const viewSchema = z\n .object({\n cursor: z.string().min(1).max(2048).optional(),\n dateRange: dateRangeSchema.optional(),\n drillId: id.optional(),\n })\n .strict();\nexport const pageSchema = z\n .object({\n kind: z.enum(['chart', 'kpi', 'table']),\n title: z.string().max(500),\n description: z.string().max(2000).optional(),\n rowsTotal: z.number().int().nonnegative().optional(),\n chartSpec: z.object({ type: z.string().max(80) }).strict(),\n rows: rowsSchema,\n columns: z.array(z.string().max(128)).max(20),\n svg: z.string().max(100_000).optional(),\n customChart: z\n .object({\n key: z.string().regex(/^[a-z][a-z0-9_-]{0,63}$/),\n bindings: z.record(z.string(), z.array(z.string().max(128)).max(20)),\n options: z.record(\n z.string(),\n z.union([z.string().max(2000), z.number().finite(), z.boolean()])\n ),\n })\n .strict()\n .optional(),\n fallback: z.string().max(1000).optional(),\n width: z.number().int().min(240).max(1200),\n height: z.number().int().min(120).max(800),\n points: z.array(point).max(PAGE_SIZE),\n value: cell.optional(),\n nextCursor: z.string().min(1).max(2048).optional(),\n })\n .strict()\n .superRefine((page, ctx) => {\n if (page.kind === 'chart' && !page.svg && !page.customChart)\n ctx.addIssue({ code: 'custom', message: 'SVG required' });\n if (\n page.kind === 'kpi' &&\n (page.svg || page.points.length || page.value === undefined)\n ) {\n ctx.addIssue({\n code: 'custom',\n message: 'KPI requires a value and no SVG/points',\n });\n }\n if (\n page.kind === 'table' &&\n (page.svg || page.points.length || page.value !== undefined)\n ) {\n ctx.addIssue({\n code: 'custom',\n message: 'Table requires rows without SVG/points/value',\n });\n }\n if (\n new Set(page.points.map((p) => p.key)).size !== page.points.length ||\n page.points.some(\n (p) => p.x + p.width > page.width || p.y + p.height > page.height\n )\n ) {\n ctx.addIssue({ code: 'custom', message: 'Invalid point geometry' });\n }\n });\nexport type ChartPage = z.infer<typeof pageSchema>;\nexport type ChartView = z.infer<typeof viewSchema>;\n\n/** Bound the entire serialized result, not just the number of rows. */\nexport function bounded<T>(value: T): T {\n if (JSON.stringify(value).length > MAX_RESULT_CHARS)\n throw new Error('Chart page exceeds payload budget');\n return value;\n}\n\n/** Project primitive first-viewport values without allowing arbitrary object graphs. */\nexport function firstRows(value: unknown): z.infer<typeof rowsSchema> {\n if (!Array.isArray(value)) return [];\n return value.slice(0, PAGE_SIZE).map((row) => {\n if (!row || typeof row !== 'object' || Array.isArray(row)) return {};\n return Object.fromEntries(\n Object.entries(row)\n .slice(0, 20)\n .map(([key, value]) => {\n const parsed = cell.safeParse(value);\n return [\n key.slice(0, 128),\n parsed.success ? parsed.data : String(value ?? '').slice(0, 2000),\n ];\n })\n );\n });\n}\n","import type {\n McpServer,\n RegisteredTool,\n} from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport {\n bounded,\n CHART_URI,\n KPI_URI,\n RESOURCE_URI_META_KEY,\n} from './contract.js';\n\n/** Hosts disagree on where the app pointer lives, so publish every form the ecosystem reads.\n * `_meta.ui.resourceUri` is the current spec shape; `_meta['ui/resourceUri']` is the\n * deprecated flat key that the official apps SDK still emits alongside it and that\n * `getToolUiResourceUri` still accepts. Emitting one and not the other means a host that\n * reads only the other renders no widget at all, with nothing in the payload to explain why. */\nexport function appMeta(\n visibility: Array<'model' | 'app'>,\n uri = CHART_URI\n): Record<string, unknown> {\n return { ui: { resourceUri: uri, visibility }, [RESOURCE_URI_META_KEY]: uri };\n}\n\nconst enabled = new WeakSet<McpServer>();\nexport function enableChartApps(server: McpServer): void {\n enabled.add(server);\n}\nexport function hasChartApps(server: McpServer): boolean {\n return enabled.has(server);\n}\nexport function tagChartTool(server: McpServer, tool: RegisteredTool): void {\n if (hasChartApps(server)) tool.update({ _meta: appMeta(['model', 'app']) });\n}\n/** The pointer also rides on the result. A tool definition carries it for hosts that read\n * `tools/list`, but the AG-UI and OpenAI-convention paths only ever see the result, so a\n * definition-only pointer leaves those hosts rendering plain text. `_meta` stays out of\n * model context, so this costs the model nothing. */\nexport function chartResult(\n summary: string,\n payload: Record<string, unknown>\n): CallToolResult {\n return bounded({\n content: [{ type: 'text' as const, text: summary }],\n structuredContent: payload,\n _meta: appMeta(\n ['model', 'app'],\n payload.kind === 'kpi' ? KPI_URI : CHART_URI\n ),\n });\n}\n\n/** Text the model reads after a dashboard picker: one line per chart it can pass to\n * render_metric_tile. The App tile is invisible to the model, so without this the\n * model has a picker for the person and nothing it can call itself. */\nexport function chartIndex(\n dashboardId: string,\n charts: Array<{ widgetId: string; name?: string; chartType?: string | null }>\n): string {\n return (\n `To draw one, call render_metric_tile with dashboardId ${JSON.stringify(dashboardId)} and metricId set to a widgetId below.\\n` +\n JSON.stringify(\n charts.slice(0, 50).map((c) => ({\n widgetId: c.widgetId,\n name: (c.name || 'Untitled widget').slice(0, 200),\n chartType: c.chartType || null,\n }))\n ) +\n (charts.length > 50 ? `\\nShowing the first 50 of ${charts.length}.` : '')\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport {\n DatabrainApiError,\n toolError,\n toolSuccess,\n} from '../../utils/errors.js';\nimport { READ_ONLY } from '../annotations.js';\n\nexport function registerListDashboards(\n server: McpServer,\n client: DatabrainClient\n): void {\n const services = createServiceBundle(client);\n server.tool(\n 'list_dashboards',\n 'List dashboards globally or for a specific data app.',\n {\n scope: z\n .enum(['auto', 'global', 'data_app'])\n .optional()\n .describe(\n 'Dashboard listing scope. auto: use data_app when dataAppName + API token are available, otherwise global.'\n ),\n dataAppName: z\n .string()\n .optional()\n .describe(\n 'Data app name for data_app scope. Ignored for global scope.'\n ),\n },\n READ_ONLY,\n async (params) => {\n try {\n const scope = params.scope || 'auto';\n const useDataAppScope =\n scope === 'data_app' ||\n (scope === 'auto' &&\n !!params.dataAppName &&\n params.dataAppName.trim().length > 0 &&\n client.hasApiToken());\n\n const result = useDataAppScope\n ? await services.dashboardsApi.listDashboards(params.dataAppName)\n : await services.dashboardsApi.listDashboardsAcrossWorkspaces();\n\n if (!Array.isArray(result) || result.length === 0) {\n return toolSuccess(\n useDataAppScope\n ? `No dashboards found for data app \"${params.dataAppName || 'unknown'}\".`\n : 'No dashboards found in available workspaces.'\n );\n }\n\n return toolSuccess(\n JSON.stringify({\n count: result.length,\n scope: useDataAppScope ? 'data_app' : 'global',\n dashboards: result.map((d: any) => {\n const {\n name,\n dashboardId,\n externalDashboardId,\n workspaceName,\n metricCount,\n } = services.discoveryService.normalizeDashboard(\n d as Record<string, unknown>\n );\n return {\n id: dashboardId || null,\n dashboardId,\n externalDashboardId,\n name,\n workspace: workspaceName || null,\n metricCount: metricCount ?? null,\n };\n }),\n })\n );\n } catch (err) {\n if (err instanceof DatabrainApiError) return err.toToolResponse();\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n}\n","import type { DatabrainClient } from '../client/databrain-client.js';\n\nexport interface DashboardRecord {\n dashboardId?: string;\n externalDashboardId?: string;\n id?: string;\n _id?: string;\n uid?: string;\n name?: string;\n dashboardName?: string;\n workspaceName?: string;\n workspace?: string;\n workspaceId?: string;\n metricCount?: number;\n [key: string]: unknown;\n}\n\ninterface WorkspaceRecord {\n name?: string;\n [key: string]: unknown;\n}\n\nexport class DashboardsApi {\n constructor(private readonly client: DatabrainClient) {}\n\n async listDashboardsAcrossWorkspaces(): Promise<DashboardRecord[]> {\n const workspaces = await this.client.request<WorkspaceRecord[]>({\n method: 'GET',\n path: '/api/v2/workspace',\n auth: 'service',\n cacheKey: 'list_workspaces',\n cacheTtlMs: 5 * 60 * 1000,\n });\n\n const workspaceNames = (Array.isArray(workspaces) ? workspaces : [])\n .map((w) => (typeof w.name === 'string' ? w.name.trim() : ''))\n .filter((v) => v.length > 0);\n\n if (workspaceNames.length === 0) return [];\n\n const dashboardsPerWorkspace = await Promise.all(\n workspaceNames.map((workspaceName) =>\n this.client\n .request<DashboardRecord[]>({\n method: 'POST',\n path: '/api/v2/workspace/dashboards',\n auth: 'service',\n body: { workspaceName },\n })\n .then((dashboards) =>\n (Array.isArray(dashboards) ? dashboards : []).map((d) => ({\n ...d,\n workspaceName:\n typeof d.workspaceName === 'string' &&\n d.workspaceName.trim().length > 0\n ? d.workspaceName\n : workspaceName,\n }))\n )\n )\n );\n\n return dashboardsPerWorkspace.flat();\n }\n\n async listDashboardsForWorkspace(\n workspaceName: string\n ): Promise<DashboardRecord[]> {\n const dashboards = await this.client.request<DashboardRecord[]>({\n method: 'POST',\n path: '/api/v2/workspace/dashboards',\n auth: 'service',\n body: { workspaceName },\n });\n return (Array.isArray(dashboards) ? dashboards : []).map((d) => ({\n ...d,\n workspaceName:\n typeof d.workspaceName === 'string' && d.workspaceName.trim().length > 0\n ? d.workspaceName\n : workspaceName,\n }));\n }\n\n // Data-app scoped dashboard listing for API-token flows.\n async listDashboards(dataAppName?: string): Promise<DashboardRecord[]> {\n const query =\n dataAppName && dataAppName.trim().length > 0\n ? { dataAppName }\n : undefined;\n return this.client.request<DashboardRecord[]>({\n method: 'GET',\n path: '/api/v2/data-app/dashboards',\n auth: 'api',\n query,\n cacheKey: 'list_dashboards',\n cacheTtlMs: 5 * 60 * 1000,\n });\n }\n}\n","import type { DatabrainClient } from '../client/databrain-client.js';\n\nexport interface DataAppRecord {\n dataAppId?: string;\n id?: string;\n _id?: string;\n uid?: string;\n name?: string;\n dataAppName?: string;\n workspaceName?: string;\n workspace?: string;\n workspaceId?: string;\n [key: string]: unknown;\n}\n\nexport class DataAppsApi {\n constructor(private readonly client: DatabrainClient) {}\n\n async listDataApps(workspaceName?: string): Promise<DataAppRecord[]> {\n const query =\n workspaceName && workspaceName.trim().length > 0\n ? { workspaceName }\n : undefined;\n return this.client.request<DataAppRecord[]>({\n method: 'GET',\n path: '/api/v2/data-app/',\n auth: 'service',\n query,\n cacheKey: `list_data_apps:${workspaceName?.trim() || '*'}`,\n cacheTtlMs: 10 * 60 * 1000,\n });\n }\n}\n","import type { DatabrainClient } from '../client/databrain-client.js';\n\nexport interface DatamartRecord {\n name?: string;\n datamartName?: string;\n [key: string]: unknown;\n}\n\nexport class DatamartsApi {\n constructor(private readonly client: DatabrainClient) {}\n\n async createDatamart(\n body: Record<string, unknown>\n ): Promise<Record<string, unknown>> {\n return this.client.request<Record<string, unknown>>({\n method: 'POST',\n path: '/api/v2/data-app/datamarts',\n body,\n auth: 'service',\n invalidateCache: ['list_datamarts'],\n });\n }\n\n async listDatamarts(\n query?: Record<string, string>\n ): Promise<DatamartRecord[]> {\n return this.client.request<DatamartRecord[]>({\n method: 'GET',\n path: '/api/v2/data-app/datamarts',\n auth: 'service',\n query,\n cacheKey: 'list_datamarts',\n cacheTtlMs: 5 * 60 * 1000,\n });\n }\n\n async listDatamartsByDataAppId(dataAppId: string): Promise<DatamartRecord[]> {\n return this.client.request<DatamartRecord[]>({\n method: 'GET',\n path: '/api/v2/data-app/datamarts',\n auth: 'service',\n query: { dataAppId },\n cacheKey: `list_datamarts_${dataAppId}`,\n cacheTtlMs: 5 * 60 * 1000,\n });\n }\n}\n","import type { DatabrainClient } from '../client/databrain-client.js';\n\nexport interface DatasourceRecord {\n name?: string;\n dbName?: string;\n datasourceType?: string;\n id?: string;\n _id?: string;\n [key: string]: unknown;\n}\n\nexport interface DatasourceSchemaColumn {\n name: string;\n dataType: string;\n}\n\nexport interface DatasourceSchemaTable {\n name: string;\n schema: string;\n columns: DatasourceSchemaColumn[];\n}\n\nexport interface DatasourceSchemaResult {\n datasourceName: string;\n datasourceId: string;\n tables: DatasourceSchemaTable[];\n tableCount: number;\n columnCount: number;\n}\n\nexport class DatasourcesApi {\n constructor(private readonly client: DatabrainClient) {}\n\n async createDatasource(\n body: Record<string, unknown>\n ): Promise<Record<string, unknown>> {\n return this.client.request<Record<string, unknown>>({\n method: 'POST',\n path: '/api/v2/datasource/',\n body,\n auth: 'service',\n invalidateCache: ['list_datasources'],\n });\n }\n\n async listDatasources(): Promise<DatasourceRecord[]> {\n return this.client.request<DatasourceRecord[]>({\n method: 'GET',\n path: '/api/v2/datasource/',\n auth: 'service',\n cacheKey: 'list_datasources',\n cacheTtlMs: 10 * 60 * 1000,\n });\n }\n\n async syncDatasource(\n datasourceName: string\n ): Promise<Record<string, unknown>> {\n const datasources = await this.listDatasources();\n const match = datasources.find(\n (ds) => ds.name?.toLowerCase() === datasourceName.toLowerCase()\n );\n if (!match) {\n throw new Error(\n `Datasource \"${datasourceName}\" not found. ` +\n `Available: ${datasources.map((ds) => ds.name).join(', ')}`\n );\n }\n\n const datasourceId = match._id || match.id;\n if (!datasourceId) {\n throw new Error(`Datasource \"${datasourceName}\" has no ID`);\n }\n\n return this.client.request<Record<string, unknown>>({\n method: 'POST',\n path: '/api/v2/datasource/sync',\n body: { input: { datasourceId } },\n auth: 'service',\n invalidateCache: [`datasource_schema_${datasourceName}`],\n });\n }\n\n async getDatasourceSchema(\n datasourceName: string\n ): Promise<DatasourceSchemaResult> {\n return this.client.request<DatasourceSchemaResult>({\n method: 'GET',\n path: '/api/v2/datasource/schema',\n auth: 'service',\n query: { datasourceName },\n cacheKey: `datasource_schema_${datasourceName}`,\n cacheTtlMs: 5 * 60 * 1000,\n });\n }\n\n async resolveIdByName(datasourceName: string): Promise<string | null> {\n try {\n const schema = await this.getDatasourceSchema(datasourceName);\n return schema?.datasourceId || null;\n } catch {\n return null;\n }\n }\n}\n","import type { DatabrainClient } from '../client/databrain-client.js';\n\nexport interface EmbedRecord {\n id?: string;\n _id?: string;\n embedId?: string | null;\n dashboardId?: string;\n externalDashboardId?: string;\n dataAppId?: string;\n clientId?: string;\n createdBy?: string;\n name?: string | null;\n embedType?: string;\n accessSettings?: Record<string, unknown>;\n embedMetadata?: Record<string, unknown>;\n externalDashboard?: Record<string, unknown>;\n [key: string]: unknown;\n}\n\nexport class EmbedsApi {\n constructor(private readonly client: DatabrainClient) {}\n\n async createEmbed(\n body: Record<string, unknown>\n ): Promise<Record<string, unknown>> {\n const { dataAppName, ...payload } = body;\n return this.client.request<Record<string, unknown>>({\n method: 'POST',\n path: '/api/v2/data-app/embeds',\n query: typeof dataAppName === 'string' ? { dataAppName } : undefined,\n body: payload,\n auth: 'api',\n invalidateCache: ['list_embeds'],\n });\n }\n\n async listEmbeds(\n dataAppName?: string,\n clientId?: string\n ): Promise<EmbedRecord[]> {\n const query: Record<string, string> = {};\n if (dataAppName && dataAppName.trim().length > 0) {\n query.dataAppName = dataAppName.trim();\n }\n if (clientId && clientId.trim().length > 0) {\n query.clientId = clientId.trim();\n }\n return this.client.request<EmbedRecord[]>({\n method: 'GET',\n path: '/api/v2/data-app/embeds',\n auth: 'api',\n query: Object.keys(query).length > 0 ? query : undefined,\n cacheKey: `list_embeds:${query.dataAppName || '*'}:${query.clientId || '*'}`,\n cacheTtlMs: 5 * 60 * 1000,\n });\n }\n\n async getByEmbedId(embedId: string, dataAppName?: string): Promise<unknown> {\n return this.client.request<unknown>({\n method: 'GET',\n path: '/api/v2/data-app/embeds',\n auth: 'api',\n query: { embedId, ...(dataAppName ? { dataAppName } : {}) },\n });\n }\n\n async updateEmbed(\n body: Record<string, unknown>\n ): Promise<Record<string, unknown>> {\n return this.client.request<Record<string, unknown>>({\n method: 'PUT',\n path: '/api/v2/data-app/embeds',\n body,\n auth: 'api',\n invalidateCache: ['list_embeds'],\n });\n }\n}\n","import type { DatabrainClient } from '../client/databrain-client.js';\n\nexport interface CreateGuestTokenBody {\n clientId: string;\n dataAppName: string;\n params?: Record<string, unknown>;\n permissions?: Record<string, unknown>;\n theme?: Record<string, unknown>;\n expiryTime?: number;\n datasourceName?: string;\n}\n\nexport class GuestTokenApi {\n constructor(private readonly client: DatabrainClient) {}\n\n async createGuestToken(\n body: CreateGuestTokenBody\n ): Promise<{ token: string }> {\n return this.client.request<{ token: string }>({\n method: 'POST',\n path: '/api/v2/guest-token/create',\n body,\n auth: 'api',\n });\n }\n}\n","import type { DatabrainClient } from '../client/databrain-client.js';\n\nexport interface AskQuestionParams {\n question: string;\n datamartName?: string;\n workspaceName?: string;\n sessionId?: string;\n config?: {\n followUp?: {\n isEnable: boolean;\n previousQuestion?: string;\n previousSql?: string;\n };\n };\n timezone?: string;\n}\n\nexport interface QueryResult {\n data: unknown[];\n columns: { dimensions: string[]; measures: string[] };\n suggestedChartType: string;\n /** A string or, as the backend sends it today, an array of sentences. */\n reasoning: string | string[] | null;\n /** 0-1 per the original contract; the backend sends 0-100 today. */\n confidence: number | null;\n timeTaken: number;\n sessionId: string | null;\n summary: string | string[] | null;\n query: string | null;\n isTimeSeries: boolean;\n isCountryDimension: boolean;\n questionType: string | null;\n}\n\nexport interface SemanticLayerTable {\n name: string;\n schemaName?: string | null;\n description?: string | null;\n synonyms?: string[];\n miscellaneousInfo?: string | null;\n columns?: SemanticLayerColumn[];\n}\n\nexport interface SemanticLayerColumn {\n name: string;\n datatype?: string | null;\n description?: string | null;\n synonyms?: string[];\n miscellaneousInfo?: string | null;\n columnType?: string | null;\n columnTypeConfig?: unknown;\n isIdentifier?: boolean;\n isNotIndexed?: boolean;\n}\n\nexport interface SemanticLayerResult {\n datamartName: string;\n tables: SemanticLayerTable[];\n feedback: string | null;\n completionScore: number;\n lastUpdated: string | null;\n}\n\nexport interface SemanticGenerationStartResult {\n jobId: string;\n status: string;\n message?: string;\n}\n\nexport interface SemanticGenerationStatusResult {\n jobId: string;\n status: string;\n progress?: number;\n tablesProcessed?: number;\n totalTables?: number;\n error?: string | null;\n startedAt?: string | null;\n completedAt?: string | null;\n}\n\nexport interface SemanticLayerUpdateBody {\n datamartName: string;\n tables?: Array<{\n name: string;\n schemaName?: string;\n description?: string;\n synonyms?: string[];\n miscellaneousInfo?: string;\n columns?: Array<{\n name: string;\n description?: string;\n synonyms?: string[];\n miscellaneousInfo?: string;\n columnType?: string;\n columnTypeConfig?: unknown;\n isIdentifier?: boolean;\n isNotIndexed?: boolean;\n }>;\n }>;\n feedback?: string;\n}\n\nexport class QueryApi {\n constructor(private readonly client: DatabrainClient) {}\n\n async askQuestion(params: AskQuestionParams): Promise<QueryResult> {\n return this.client.request<QueryResult>({\n method: 'POST',\n path: '/api/v2/data-app/ask',\n body: params,\n auth: 'service',\n timeoutMs: 300_000,\n noRetryOnTimeout: true,\n });\n }\n\n async getSemanticLayer(datamartName: string): Promise<SemanticLayerResult> {\n return this.client.request<SemanticLayerResult>({\n method: 'GET',\n path: '/api/v2/data-app/datamarts/semantic-layer',\n auth: 'service',\n query: { datamartName },\n cacheKey: `semantic_layer_${datamartName}`,\n cacheTtlMs: 2 * 60 * 1000,\n });\n }\n\n async updateSemanticLayer(\n body: SemanticLayerUpdateBody\n ): Promise<{ id: string }> {\n try {\n return await this.client.request<{ id: string }>({\n method: 'PUT',\n path: '/api/v2/data-app/datamarts/semantic-layer',\n body,\n auth: 'service',\n invalidateCache: [`semantic_layer_${body.datamartName}`],\n });\n } catch (err: unknown) {\n const status = (err as { status?: number }).status;\n if (status === 404) {\n return this.client.request<{ id: string }>({\n method: 'POST',\n path: '/api/v2/data-app/datamarts/semantic-layer',\n body,\n auth: 'service',\n invalidateCache: [`semantic_layer_${body.datamartName}`],\n });\n }\n throw err;\n }\n }\n\n async startSemanticLayerGeneration(\n datamartId: string\n ): Promise<SemanticGenerationStartResult> {\n return this.client.request<SemanticGenerationStartResult>({\n method: 'POST',\n path: `/schema/datamart/${encodeURIComponent(datamartId)}/semantic-layer/auto-generate`,\n auth: 'service',\n invalidateCache: ['semantic_layer_'],\n });\n }\n\n async getSemanticLayerGenerationStatus(\n datamartId: string\n ): Promise<SemanticGenerationStatusResult> {\n return this.client.request<SemanticGenerationStatusResult>({\n method: 'GET',\n path: `/schema/datamart/${encodeURIComponent(datamartId)}/semantic-layer/generation-status`,\n auth: 'service',\n });\n }\n}\n","import type { DatabrainClient } from '../client/databrain-client.js';\n\nexport interface ScheduledReportRecord {\n id?: string;\n subject?: string;\n nextScheduledAt?: string | null;\n embedId?: string | null;\n clientId?: string | null;\n emails?: unknown[];\n timeConfigurations?: Record<string, unknown>;\n scheduleEmailReportCharts?: unknown[];\n isDownloadFile?: boolean;\n downloadFileFormat?: string | null;\n [key: string]: unknown;\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | null {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return null;\n return value as Record<string, unknown>;\n}\n\nfunction normalizeRecords(value: unknown): ScheduledReportRecord[] {\n if (Array.isArray(value)) {\n return value.filter(\n (item): item is ScheduledReportRecord => asRecord(item) !== null\n );\n }\n\n const record = asRecord(value);\n if (!record) return [];\n\n const candidates = [\n record.scheduleEmailReports,\n record.reports,\n record.items,\n record.data,\n ];\n\n for (const candidate of candidates) {\n if (Array.isArray(candidate)) {\n return candidate.filter(\n (item): item is ScheduledReportRecord => asRecord(item) !== null\n );\n }\n }\n\n return [];\n}\n\nexport class ScheduledReportsApi {\n constructor(private readonly client: DatabrainClient) {}\n\n async listByEmbed(params: {\n embedId: string;\n dataAppName?: string;\n clientId: string;\n userIdentifier?: string;\n pageNumber?: number;\n isPagination?: boolean;\n }): Promise<ScheduledReportRecord[]> {\n const query: Record<string, string> = {\n embedId: params.embedId,\n clientId: params.clientId,\n };\n if (params.dataAppName) query.dataAppName = params.dataAppName;\n if (params.userIdentifier) query.userIdentifier = params.userIdentifier;\n if (params.pageNumber !== undefined)\n query.pageNumber = String(params.pageNumber);\n if (params.isPagination !== undefined) {\n query.isPagination = params.isPagination ? 'true' : 'false';\n }\n\n const response = await this.client.request<unknown>({\n method: 'GET',\n path: '/api/v2/data-app/embeds/reports',\n auth: 'api',\n query,\n });\n\n return normalizeRecords(response);\n }\n}\n","import type { DatabrainClient } from '../client/databrain-client.js';\n\nexport interface StoredSemanticModel {\n source: string;\n content_hash: string;\n updated_at?: string;\n}\n\nexport interface SemanticValidation {\n ok: boolean;\n content_hash: string;\n errors: unknown[];\n}\n\n/** Semantic reads are uncached so proposals and authorization use current state. */\nexport class SemanticModelApi {\n constructor(private readonly client: DatabrainClient) {}\n\n private path(id: string, verb: string): string {\n return `/api/v2/semantic/${encodeURIComponent(id)}/${verb}`;\n }\n\n pull(id: string, mode?: 'combined'): Promise<StoredSemanticModel> {\n return this.client.request({\n method: 'GET',\n path: this.path(id, 'pull'),\n auth: 'service',\n ...(mode ? { query: { mode } } : {}),\n });\n }\n\n retrieve(id: string, q: string, k: number): Promise<unknown> {\n return this.client.request({\n method: 'POST',\n path: this.path(id, 'retrieve'),\n auth: 'service',\n body: { q, k },\n });\n }\n\n validate(id: string, source: string): Promise<SemanticValidation> {\n return this.client.request({\n method: 'POST',\n path: this.path(id, 'validate'),\n auth: 'service',\n body: { source },\n });\n }\n\n plan(\n id: string,\n source: string,\n expected_content_hash: string | null\n ): Promise<unknown> {\n return this.client.request({\n method: 'POST',\n path: this.path(id, 'plan'),\n auth: 'service',\n body: { source, expected_content_hash },\n });\n }\n\n apply(\n id: string,\n source: string,\n expected_content_hash: string | null\n ): Promise<unknown> {\n return this.client.request({\n method: 'POST',\n path: this.path(id, 'apply'),\n auth: 'service',\n body: { source, expected_content_hash },\n noRetryOnTimeout: true,\n });\n }\n\n evaluate(\n id: string,\n body: { source?: string; questions?: unknown[] }\n ): Promise<unknown> {\n return this.client.request({\n method: 'POST',\n path: this.path(id, 'eval'),\n auth: 'service',\n body,\n timeoutMs: 300_000,\n noRetryOnTimeout: true,\n });\n }\n}\n","import type { DatabrainClient } from '../client/databrain-client.js';\n\nexport interface TenantRecord {\n value?: string;\n label?: string;\n [key: string]: unknown;\n}\n\nexport interface TenantListResponse {\n data?: TenantRecord[];\n clientColumnType?: string;\n error?: unknown;\n message?: unknown;\n [key: string]: unknown;\n}\n\nexport type TenantListResult = TenantRecord[] | TenantListResponse;\n\nexport interface ListTenantsParams {\n workspaceId: string;\n limit?: number;\n searchValue?: string;\n datasourceId?: string;\n datamartId?: string;\n}\n\nexport class TenantsApi {\n constructor(private readonly client: DatabrainClient) {}\n\n async listTenants(params: ListTenantsParams): Promise<TenantListResult> {\n const input: Record<string, string> = {\n workspaceId: params.workspaceId,\n };\n if (params.limit !== undefined) input.limit = String(params.limit);\n if (params.searchValue && params.searchValue.trim().length > 0) {\n input.searchValue = params.searchValue.trim();\n }\n if (params.datasourceId && params.datasourceId.trim().length > 0) {\n input.datasourceId = params.datasourceId.trim();\n }\n if (params.datamartId && params.datamartId.trim().length > 0) {\n input.datamartId = params.datamartId.trim();\n }\n\n return this.client.request<TenantListResult>({\n method: 'POST',\n path: '/api/mcp/getClientData',\n auth: 'service',\n body: { input: { input } },\n skipDataUnwrap: true,\n cacheKey: `list_tenants:${JSON.stringify(input)}`,\n cacheTtlMs: 5 * 60 * 1000,\n });\n }\n}\n","import type { DatabrainClient } from '../client/databrain-client.js';\n\nexport interface WidgetSummary {\n id?: string | null;\n _id?: string | null;\n externalMetricId?: string | null;\n metricId?: string | null;\n name?: string | null;\n isPublished?: boolean;\n createdByUser?: string | null;\n [key: string]: unknown;\n}\n\nexport interface CreateMetricBody {\n name: string;\n metricId: string;\n query?: string;\n metricQuery?: string;\n description?: string;\n chartOptions?: Record<string, unknown>;\n companyId?: string;\n companyIntegrationId?: string;\n integrationName?: string;\n outputColumns?: string;\n inputFields?: unknown;\n isLive?: boolean;\n isCreatedByClient?: boolean;\n createdBy?: string;\n timeGrain?: string;\n selectedGroupBy?: unknown;\n isEnableGroupBy?: boolean;\n datasetMetricSettings?: unknown;\n groupBy?: unknown;\n drillDownSettings?: unknown;\n isPublished?: boolean;\n limit?: number;\n externalDashboardIds?: Array<{ externalDashboardId: string }>;\n [key: string]: unknown;\n}\n\nexport interface UpdateMetricBody {\n externalMetricId: string;\n set: Record<string, unknown>;\n}\n\nexport interface MarkArchivedBody {\n id: string;\n clientId: string;\n}\n\nexport interface GenerateMetricBody {\n integrationId: string;\n integrationName: string;\n userInputs: Record<string, unknown>;\n}\n\nexport interface GenerateMetricResponse {\n result?: Array<Record<string, unknown>>;\n error?: unknown;\n query?: string;\n timeTaken?: number;\n metaData?: unknown;\n chartType?: string | null;\n chartTypeReason?: unknown;\n}\n\nexport interface EmbeddedMetricResponse {\n externalMetric?: Record<string, unknown>;\n [key: string]: unknown;\n}\n\nexport class WidgetsApi {\n constructor(private readonly client: DatabrainClient) {}\n\n async listWidgets(\n embedId: string,\n clientId: string,\n dataAppName?: string\n ): Promise<WidgetSummary[]> {\n return this.client.request<WidgetSummary[]>({\n method: 'GET',\n path: '/api/v2/data-app/metrics',\n auth: 'api',\n query: { embedId, clientId, ...(dataAppName ? { dataAppName } : {}) },\n });\n }\n\n async createMetric(\n guestToken: string,\n body: CreateMetricBody\n ): Promise<Record<string, unknown>> {\n return this.client.request<Record<string, unknown>>({\n method: 'POST',\n path: '/api/v2/dashboard/createMetric',\n auth: 'none',\n token: guestToken,\n body: { ...body, isLive: body.isLive ?? false },\n });\n }\n\n async updateMetric(\n guestToken: string,\n body: UpdateMetricBody\n ): Promise<Record<string, unknown>> {\n return this.client.request<Record<string, unknown>>({\n method: 'POST',\n path: '/api/v2/dashboard/updateMetric',\n auth: 'none',\n token: guestToken,\n body,\n });\n }\n\n async markArchived(\n guestToken: string,\n body: MarkArchivedBody\n ): Promise<Record<string, unknown>> {\n return this.client.request<Record<string, unknown>>({\n method: 'POST',\n path: '/api/v3/metric/markArchived',\n auth: 'none',\n token: guestToken,\n body,\n });\n }\n\n async generateMetric(\n guestToken: string,\n body: GenerateMetricBody\n ): Promise<GenerateMetricResponse> {\n return this.client.request<GenerateMetricResponse>({\n method: 'POST',\n path: '/api/v2/dashboard/generateMetric',\n auth: 'none',\n token: guestToken,\n body,\n timeoutMs: 120_000,\n noRetryOnTimeout: true,\n });\n }\n\n async fetchEmbeddedMetric(\n guestToken: string,\n metricId: string\n ): Promise<EmbeddedMetricResponse> {\n return this.client.request<EmbeddedMetricResponse>({\n method: 'GET',\n path: '/api/v2/dashboard/embeddedMetric',\n auth: 'none',\n token: guestToken,\n query: { metricId },\n });\n }\n}\n","import type { DatabrainClient } from '../client/databrain-client.js';\n\nexport interface WorkspaceRecord {\n name?: string;\n id?: string;\n _id?: string;\n [key: string]: unknown;\n}\n\nexport class WorkspacesApi {\n constructor(private readonly client: DatabrainClient) {}\n\n async createWorkspace(\n body: Record<string, unknown>\n ): Promise<Record<string, unknown>> {\n return this.client.request<Record<string, unknown>>({\n method: 'POST',\n path: '/api/v2/workspace',\n body,\n auth: 'service',\n invalidateCache: ['list_workspaces'],\n });\n }\n\n async listWorkspaces(): Promise<WorkspaceRecord[]> {\n return this.client.request<WorkspaceRecord[]>({\n method: 'GET',\n path: '/api/v2/workspace',\n auth: 'service',\n cacheKey: 'list_workspaces',\n cacheTtlMs: 5 * 60 * 1000,\n });\n }\n}\n","import type { DashboardRecord } from '../api/dashboards-api.js';\nimport type { DataAppRecord } from '../api/data-apps-api.js';\nimport type { EmbedRecord } from '../api/embeds-api.js';\n\nconst isNonEmptyString = (v: unknown): v is string =>\n typeof v === 'string' && v.trim().length > 0;\n\nexport interface NormalizedDataApp {\n name: string;\n dataAppId: string | null;\n workspaceName: string | null;\n}\n\nexport interface NormalizedDashboard {\n name: string;\n dashboardId: string | null;\n externalDashboardId: string | null;\n workspaceName: string | null;\n metricCount: number | null;\n}\n\nexport interface NormalizedEmbed {\n name: string;\n embedId: string | null;\n internalId: string | null;\n dashboardId: string | null;\n externalDashboardId: string | null;\n dataAppName: string | null;\n embedType: string | null;\n}\n\nexport class DiscoveryService {\n normalizeDataApp(app: DataAppRecord): NormalizedDataApp {\n return {\n name:\n (isNonEmptyString(app.name) && app.name) ||\n (isNonEmptyString(app.dataAppName) && app.dataAppName) ||\n 'Unnamed Data App',\n dataAppId:\n (isNonEmptyString(app.dataAppId) && app.dataAppId) ||\n (isNonEmptyString(app._id) && app._id) ||\n (isNonEmptyString(app.id) && app.id) ||\n (isNonEmptyString(app.uid) && app.uid) ||\n null,\n workspaceName:\n (isNonEmptyString(app.workspaceName) && app.workspaceName) ||\n (isNonEmptyString(app.workspace) && app.workspace) ||\n (isNonEmptyString(app.workspaceId) && app.workspaceId) ||\n null,\n };\n }\n\n normalizeDashboard(dashboard: DashboardRecord): NormalizedDashboard {\n return {\n name:\n (isNonEmptyString(dashboard.name) && dashboard.name) ||\n (isNonEmptyString(dashboard.dashboardName) &&\n dashboard.dashboardName) ||\n 'Unnamed Dashboard',\n dashboardId:\n (isNonEmptyString(dashboard.dashboardId) && dashboard.dashboardId) ||\n (isNonEmptyString(dashboard._id) && dashboard._id) ||\n (isNonEmptyString(dashboard.id) && dashboard.id) ||\n (isNonEmptyString(dashboard.uid) && dashboard.uid) ||\n (isNonEmptyString(dashboard.externalDashboardId) &&\n dashboard.externalDashboardId) ||\n null,\n externalDashboardId:\n (isNonEmptyString(dashboard.externalDashboardId) &&\n dashboard.externalDashboardId) ||\n null,\n workspaceName:\n (isNonEmptyString(dashboard.workspaceName) &&\n dashboard.workspaceName) ||\n (isNonEmptyString(dashboard.workspace) && dashboard.workspace) ||\n (isNonEmptyString(dashboard.workspaceId) && dashboard.workspaceId) ||\n null,\n metricCount:\n typeof dashboard.metricCount === 'number'\n ? dashboard.metricCount\n : null,\n };\n }\n\n normalizeEmbed(embed: EmbedRecord): NormalizedEmbed {\n const metadata = embed.embedMetadata as Record<string, unknown> | undefined;\n const externalDashboard = embed.externalDashboard as\n | Record<string, unknown>\n | undefined;\n\n return {\n name:\n (isNonEmptyString(embed.name) && embed.name) ||\n (externalDashboard &&\n isNonEmptyString(externalDashboard.name) &&\n externalDashboard.name) ||\n 'Unnamed',\n embedId: isNonEmptyString(embed.embedId) ? embed.embedId : null,\n internalId:\n (isNonEmptyString(embed._id) && embed._id) ||\n (isNonEmptyString(embed.id) && embed.id) ||\n null,\n dashboardId:\n (metadata &&\n isNonEmptyString(metadata.dashboardId) &&\n (metadata.dashboardId as string)) ||\n (isNonEmptyString(embed.dashboardId) && embed.dashboardId) ||\n null,\n externalDashboardId:\n (isNonEmptyString(embed.externalDashboardId) &&\n embed.externalDashboardId) ||\n (externalDashboard &&\n isNonEmptyString(externalDashboard.externalDashboardId) &&\n (externalDashboard.externalDashboardId as string)) ||\n (metadata &&\n isNonEmptyString(metadata.externalDashboardId) &&\n (metadata.externalDashboardId as string)) ||\n null,\n dataAppName:\n (metadata &&\n isNonEmptyString(metadata.dataAppName) &&\n (metadata.dataAppName as string)) ||\n null,\n embedType: isNonEmptyString(embed.embedType) ? embed.embedType : null,\n };\n }\n}\n","import type { DatamartsApi } from '../api/datamarts-api.js';\nimport type { EmbedRecord, EmbedsApi } from '../api/embeds-api.js';\nimport { logger } from '../utils/logger.js';\n\nconst DEFAULT_ACCESS_SETTINGS = {\n isAllowMetricCreation: false,\n isAllowMetricDeletion: false,\n isAllowMetricUpdate: false,\n isAllowMetricLayoutChange: false,\n isAllowManageMetrics: false,\n isAllowUnderlyingData: false,\n isAllowAiPilot: false,\n isAllowEmailReports: false,\n isAllowCreateDashboardView: false,\n metricCreationMode: 'DRAG_DROP' as const,\n};\n\nfunction isNonEmptyString(value: unknown): value is string {\n return typeof value === 'string' && value.trim().length > 0;\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | null {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return null;\n return value as Record<string, unknown>;\n}\n\nfunction extractAccessSettings(\n embed: EmbedRecord\n): Record<string, unknown> | null {\n const metadata = asRecord(embed.embedMetadata);\n const metadataConfig = asRecord(metadata?.embedConfig);\n const options = asRecord(embed.options);\n const candidates = [\n asRecord(embed.accessSettings),\n asRecord(metadata?.accessSettings),\n asRecord(metadataConfig?.accessSettings),\n asRecord(options?.accessSettings),\n ].filter((c): c is Record<string, unknown> => !!c);\n\n for (const candidate of candidates) {\n if (Object.keys(candidate).length > 0) return candidate;\n }\n return null;\n}\n\nfunction extractDatamartName(\n embed: EmbedRecord,\n existingAccess: Record<string, unknown> | null\n): string | null {\n const metadata = asRecord(embed.embedMetadata);\n const metadataConfig = asRecord(metadata?.embedConfig);\n const values = [\n existingAccess?.datamartName,\n existingAccess?.dataMartName,\n existingAccess?.datamart_name,\n embed.datamartName,\n metadata?.datamartName,\n metadata?.dataMartName,\n metadataConfig?.datamartName,\n ];\n for (const value of values) {\n if (isNonEmptyString(value)) return value;\n }\n return null;\n}\n\nfunction getEmbedIds(embed: EmbedRecord): string[] {\n return [embed.embedId, embed.id, embed._id].filter(isNonEmptyString);\n}\n\nfunction getDashboardIds(embed: EmbedRecord): string[] {\n const metadata = embed.embedMetadata as Record<string, unknown> | undefined;\n const extDash = embed.externalDashboard as\n | Record<string, unknown>\n | undefined;\n return [\n embed.dashboardId,\n embed.externalDashboardId,\n metadata?.dashboardId as string | undefined,\n extDash?.externalDashboardId as string | undefined,\n ].filter(isNonEmptyString);\n}\n\nexport class EmbedService {\n constructor(\n private readonly embedsApi: EmbedsApi,\n private readonly datamartsApi: DatamartsApi\n ) {}\n\n async listEmbeds(\n dataAppName?: string,\n clientId?: string\n ): Promise<EmbedRecord[]> {\n return this.embedsApi.listEmbeds(dataAppName, clientId);\n }\n\n async createEmbedStrict(\n body: Record<string, unknown>\n ): Promise<Record<string, unknown>> {\n const accessSettings = asRecord(body.accessSettings);\n if (!accessSettings || Object.keys(accessSettings).length === 0) {\n throw new Error(\n 'Embed creation requires `accessSettings` for future update compatibility.'\n );\n }\n const datamartName = extractDatamartName({} as EmbedRecord, accessSettings);\n if (!datamartName) {\n throw new Error(\n 'Embed creation requires `accessSettings.datamartName` to guarantee update compatibility.'\n );\n }\n\n // Merge caller-provided accessSettings onto defaults so the API gets all required fields.\n body.accessSettings = {\n ...DEFAULT_ACCESS_SETTINGS,\n ...accessSettings,\n };\n\n return this.embedsApi.createEmbed(body);\n }\n\n async resolveEmbedStrict(\n embedId: string,\n dataAppName?: string\n ): Promise<EmbedRecord> {\n const response = await this.embedsApi.getByEmbedId(embedId, dataAppName);\n const records = Array.isArray(response)\n ? response.filter((r): r is EmbedRecord => !!r && typeof r === 'object')\n : [response as EmbedRecord];\n\n const exact = records.filter((r) => r.embedId === embedId);\n if (exact.length === 1) return exact[0];\n\n const sample = records\n .slice(0, 10)\n .map((r) => {\n const ids = getEmbedIds(r).join(', ') || 'none';\n const dashboards = getDashboardIds(r).join(', ') || 'none';\n return `{embedIds:[${ids}], dashboardIds:[${dashboards}]}`;\n })\n .join(', ');\n\n throw new Error(\n `Embed \"${embedId}\" did not resolve to an exact match by embedId. ` +\n 'API may be ignoring query filtering or returning non-canonical records.\\n\\n' +\n `Received records (sample): ${sample || 'none'}`\n );\n }\n\n async buildUpdateBase(\n embedId: string,\n dataAppName?: string\n ): Promise<Record<string, unknown>> {\n const embed = await this.resolveEmbedStrict(embedId, dataAppName);\n const existingAccess = extractAccessSettings(embed);\n\n if (existingAccess) {\n return { embedId, accessSettings: existingAccess };\n }\n\n const datamartName = extractDatamartName(embed, existingAccess);\n\n let resolvedDatamartName = datamartName;\n\n if (!resolvedDatamartName && isNonEmptyString(embed.dataAppId)) {\n try {\n const datamarts = await this.datamartsApi.listDatamartsByDataAppId(\n embed.dataAppId\n );\n const names = Array.from(\n new Set(\n datamarts\n .map((d) => d.name || d.datamartName)\n .filter(isNonEmptyString)\n )\n );\n if (names.length === 1) {\n resolvedDatamartName = names[0];\n logger.warn(\n `[EmbedService] Resolved datamartName from dataAppId=${embed.dataAppId}: ${resolvedDatamartName}`\n );\n } else if (names.length > 1) {\n throw new Error(\n `multiple datamarts found (${names.join(', ')}) for dataAppId=${embed.dataAppId}`\n );\n }\n } catch (err) {\n logger.warn(\n `[EmbedService] Datamart resolution failed for embed \"${embedId}\": ${(err as Error).message}`\n );\n }\n }\n\n if (!resolvedDatamartName) {\n throw new Error(\n `Embed \"${embedId}\" is missing accessSettings and datamartName, and datamart could not be resolved deterministically.\\n\\n` +\n 'Run `update_embed` with explicit `accessSettings.datamartName`, or recreate the embed with explicit accessSettings.'\n );\n }\n\n return {\n embedId,\n accessSettings: {\n datamartName: resolvedDatamartName,\n ...DEFAULT_ACCESS_SETTINGS,\n },\n };\n }\n\n async updateEmbed(\n embedId: string,\n updatePatch: Record<string, unknown>,\n dataAppName?: string\n ): Promise<Record<string, unknown>> {\n const body = await this.buildUpdateBase(embedId, dataAppName);\n const baseAccessSettings = asRecord(body.accessSettings);\n const patchAccessSettings = asRecord(updatePatch.accessSettings);\n for (const [key, value] of Object.entries(updatePatch)) {\n if (key === 'accessSettings') continue;\n if (value !== undefined) body[key] = value;\n }\n // Never lose required datamartName when callers send partial accessSettings patches.\n if (baseAccessSettings && patchAccessSettings) {\n body.accessSettings = {\n ...baseAccessSettings,\n ...patchAccessSettings,\n };\n } else if (patchAccessSettings) {\n body.accessSettings = patchAccessSettings;\n }\n return this.embedsApi.updateEmbed({\n ...body,\n ...(dataAppName ? { dataAppName } : {}),\n });\n }\n}\n","import {\n type CreateGuestTokenBody,\n GuestTokenApi,\n} from '../api/guest-token-api.js';\n\nexport interface GenerateGuestTokenInput {\n clientId: string;\n dataAppName: string;\n params?: Record<string, unknown>;\n timezone?: string;\n allowedEmbeds?: string[];\n rlsSettings?: Array<{ metricId: string; values: Record<string, unknown> }>;\n appFilters?: Array<{ metricId: string; values: Record<string, unknown> }>;\n dashboardAppFilters?: Array<{\n dashboardId: string;\n values: Record<string, unknown>;\n isShowOnUrl?: boolean;\n }>;\n hideDashboardFilters?: string[];\n userIdentifier?: string;\n permissions?: Record<string, unknown>;\n theme?: Record<string, unknown>;\n expiryTime?: number;\n datasourceName?: string;\n}\n\nexport class GuestTokenService {\n constructor(private readonly guestTokenApi: GuestTokenApi) {}\n\n async generateToken(\n input: GenerateGuestTokenInput\n ): Promise<{ token: string }> {\n const mergedParams: Record<string, unknown> = { ...(input.params || {}) };\n\n if (input.timezone && mergedParams.timezone === undefined) {\n mergedParams.timezone = input.timezone;\n }\n if (input.allowedEmbeds && mergedParams.allowedEmbeds === undefined) {\n mergedParams.allowedEmbeds = input.allowedEmbeds;\n }\n if (input.rlsSettings && mergedParams.rlsSettings === undefined) {\n mergedParams.rlsSettings = input.rlsSettings;\n }\n if (input.appFilters && mergedParams.appFilters === undefined) {\n mergedParams.appFilters = input.appFilters;\n }\n if (\n input.dashboardAppFilters &&\n mergedParams.dashboardAppFilters === undefined\n ) {\n mergedParams.dashboardAppFilters = input.dashboardAppFilters;\n }\n if (\n input.hideDashboardFilters &&\n mergedParams.hideDashboardFilters === undefined\n ) {\n mergedParams.hideDashboardFilters = input.hideDashboardFilters;\n }\n if (input.userIdentifier && mergedParams.userIdentifier === undefined) {\n mergedParams.userIdentifier = input.userIdentifier;\n }\n\n const body: CreateGuestTokenBody = {\n clientId: input.clientId,\n dataAppName: input.dataAppName,\n };\n\n if (Object.keys(mergedParams).length > 0) body.params = mergedParams;\n if (input.permissions) body.permissions = input.permissions;\n if (input.theme) body.theme = input.theme;\n if (input.expiryTime !== undefined) body.expiryTime = input.expiryTime;\n if (input.datasourceName) body.datasourceName = input.datasourceName;\n\n return this.guestTokenApi.createGuestToken(body);\n }\n}\n","import type { DashboardsApi } from '../api/dashboards-api.js';\nimport type { DataAppsApi } from '../api/data-apps-api.js';\nimport type { DatasourcesApi } from '../api/datasources-api.js';\nimport type { EmbedRecord, EmbedsApi } from '../api/embeds-api.js';\nimport type { CreateMetricBody, WidgetsApi } from '../api/widgets-api.js';\nimport { DatabrainApiError } from '../utils/errors.js';\nimport type { DiscoveryService } from './discovery-service.js';\nimport type { GuestTokenService } from './guest-token-service.js';\n\nconst isNonEmptyString = (v: unknown): v is string =>\n typeof v === 'string' && v.trim().length > 0;\n\nconst asRecord = (v: unknown): Record<string, unknown> | null => {\n if (!v || typeof v !== 'object' || Array.isArray(v)) return null;\n return v as Record<string, unknown>;\n};\n\nexport interface EmbedContext {\n embedId: string;\n dataAppId: string | null;\n dataAppName: string | null;\n externalDashboardId: string | null;\n dashboardId: string | null;\n externalDashboardCreatedBy: string | null;\n /** The embed row's own tenant, when the embed was created for one. Null on a data-app embed. */\n embedClientId: string | null;\n}\n\nexport type Resolved<T> = { ok: true; value: T } | { ok: false; error: string };\n\nexport interface DatasourceResolution {\n integrationId: string;\n integrationName: string;\n}\n\ntype EmbedProbe =\n | { kind: 'ok'; value: DatasourceResolution }\n | { kind: 'no_widgets' }\n | { kind: 'no_metric_fields'; widgetsTried: number; fetchErrors: number };\n\nconst isActiveDatasource = (ds: Record<string, unknown>): boolean =>\n Boolean(ds.isAuthenticated) && !ds.isDisabled;\n\nexport interface EmbedFromDashboard {\n embedId: string;\n dashboardName: string;\n workspaceName: string | null;\n}\n\nexport interface TenantDashboardScope {\n embedId: string;\n clientId: string;\n dataAppName: string | null;\n}\n\nexport class WidgetService {\n constructor(\n private readonly widgetsApi: WidgetsApi,\n private readonly embedsApi: EmbedsApi,\n private readonly dataAppsApi: DataAppsApi,\n private readonly datasourcesApi: DatasourcesApi,\n private readonly dashboardsApi: DashboardsApi,\n private readonly guestTokenService: GuestTokenService,\n private readonly discoveryService: DiscoveryService\n ) {}\n\n /**\n * Resolve the target embedId from a non-technical dashboard name (optionally\n * scoped to a workspace). This is the preferred entry point for CS/CX flows\n * where the user only knows the dashboard + workspace, not the embedId or\n * data app name. Returns a business-user-friendly error on ambiguity.\n */\n async resolveEmbedFromDashboard(\n dashboardName: string,\n workspaceName?: string,\n dataAppName?: string\n ): Promise<Resolved<EmbedFromDashboard>> {\n const wsProvided =\n workspaceName && workspaceName.trim().length > 0\n ? workspaceName.trim()\n : undefined;\n\n let dashboards: Awaited<\n ReturnType<typeof this.dashboardsApi.listDashboardsForWorkspace>\n >;\n try {\n dashboards = wsProvided\n ? await this.dashboardsApi.listDashboardsForWorkspace(wsProvided)\n : await this.dashboardsApi.listDashboardsAcrossWorkspaces();\n } catch (err) {\n return {\n ok: false,\n error: `Could not list dashboards: ${(err as Error).message}`,\n };\n }\n\n const normalized = dashboards.map((d) =>\n this.discoveryService.normalizeDashboard(d)\n );\n const target = dashboardName.trim().toLowerCase();\n const matches = normalized.filter(\n (d) => d.name.trim().toLowerCase() === target\n );\n\n if (matches.length === 0) {\n const available = normalized\n .filter((d) => d.name && d.name !== 'Unnamed Dashboard')\n .map((d) =>\n d.workspaceName\n ? `\"${d.name}\" (workspace: ${d.workspaceName})`\n : `\"${d.name}\"`\n )\n .join(', ');\n return {\n ok: false,\n error:\n `No dashboard named \"${dashboardName}\"${wsProvided ? ` in workspace \"${wsProvided}\"` : ''}. ` +\n (available\n ? `Available dashboards: ${available}. Ask the user to pick by dashboard name.`\n : 'No dashboards exist in this organization.'),\n };\n }\n\n if (matches.length > 1) {\n const workspaces = matches\n .map((d) => d.workspaceName || '(unknown workspace)')\n .join(', ');\n return {\n ok: false,\n error:\n `Dashboard name \"${dashboardName}\" is ambiguous — it exists in multiple workspaces (${workspaces}). ` +\n 'Ask the user which workspace and retry with `workspaceName`.',\n };\n }\n\n const dashboard = matches[0];\n if (!dashboard.dashboardId) {\n return {\n ok: false,\n error: `Dashboard \"${dashboard.name}\" has no ID. This is unexpected — ask the user to verify the dashboard in the Databrain UI.`,\n };\n }\n\n let embeds: EmbedRecord[];\n let dataAppSelectionAvailable = false;\n try {\n try {\n embeds = await this.embedsApi.listEmbeds(dataAppName);\n } catch (error) {\n if (\n !(error instanceof DatabrainApiError) ||\n error.code !== 'DATA_APP_REQUIRED'\n )\n throw error;\n dataAppSelectionAvailable = true;\n const apps = await this.dataAppsApi.listDataApps(\n dashboard.workspaceName || wsProvided\n );\n embeds = [];\n for (const app of apps) {\n const name = app.name || app.dataAppName;\n if (typeof name === 'string' && name.trim()) {\n const scoped = await this.embedsApi.listEmbeds(name);\n embeds.push(\n ...scoped.map((e) => ({\n ...e,\n embedMetadata: { ...e.embedMetadata, dataAppName: name },\n }))\n );\n }\n }\n }\n } catch (err) {\n return {\n ok: false,\n error: `Could not list embeds: ${(err as Error).message}`,\n };\n }\n\n // Embeds and dashboards can carry either an internal `dashboardId` or an\n // `externalDashboardId` depending on how they were created. Match on any\n // overlap between the two sets so mixed-ID orgs still resolve correctly.\n const dashboardIds = new Set(\n [dashboard.dashboardId, dashboard.externalDashboardId].filter(\n (v): v is string => typeof v === 'string' && v.length > 0\n )\n );\n const embedMatches = embeds\n .map((e) => ({ raw: e, n: this.discoveryService.normalizeEmbed(e) }))\n .filter((x) => {\n if (!x.n.embedId) return false;\n const embedIds = [x.n.dashboardId, x.n.externalDashboardId].filter(\n (v): v is string => typeof v === 'string' && v.length > 0\n );\n return embedIds.some((id) => dashboardIds.has(id));\n });\n\n if (embedMatches.length === 0) {\n return {\n ok: false,\n error:\n `Dashboard \"${dashboard.name}\" has no embed configured. ` +\n 'An embed must be created in the Databrain UI before widgets can be managed for customers.',\n };\n }\n\n if (embedMatches.length > 1) {\n const names = embedMatches\n .map((x) => `\"${x.n.name}\" (embedId: ${x.n.embedId})`)\n .join(', ');\n const apps = [\n ...new Set(embedMatches.map((x) => x.n.dataAppName).filter(Boolean)),\n ];\n return {\n ok: false,\n error:\n `Dashboard \"${dashboard.name}\" has multiple embeds (${names}). ` +\n (dataAppSelectionAvailable && apps.length > 1\n ? `Pass dataAppName to choose one of: ${apps.join(', ')}, or select an embedId. (DATA_APP_REQUIRED)`\n : 'Select an embedId and retry.'),\n };\n }\n\n return {\n ok: true,\n value: {\n embedId: embedMatches[0].n.embedId as string,\n dashboardName: dashboard.name,\n workspaceName: dashboard.workspaceName,\n },\n };\n }\n\n /**\n * Normalize widget-tool input: callers may supply `embedId` directly (legacy\n * / technical callers) or `dashboardName` + optional `workspaceName`\n * (non-technical CS/CX flow). Returns a single embedId and the resolved\n * dashboard info if lookup happened. Pass `required: true` to enforce that\n * the user named a target dashboard (recommended for CS/CX flows).\n */\n async resolveEmbedId(params: {\n embedId?: string;\n dashboardName?: string;\n workspaceName?: string;\n dataAppName?: string;\n required?: boolean;\n }): Promise<\n Resolved<{ embedId: string | null; resolvedFrom?: EmbedFromDashboard }>\n > {\n if (params.embedId && params.embedId.trim().length > 0) {\n return { ok: true, value: { embedId: params.embedId.trim() } };\n }\n if (params.dashboardName && params.dashboardName.trim().length > 0) {\n const res = await this.resolveEmbedFromDashboard(\n params.dashboardName,\n params.workspaceName,\n params.dataAppName\n );\n if (!res.ok) return res;\n return {\n ok: true,\n value: { embedId: res.value.embedId, resolvedFrom: res.value },\n };\n }\n if (params.required) {\n return {\n ok: false,\n error:\n 'Missing dashboard. Ask the user which dashboard to customize (by name) and optionally which workspace, then pass `dashboardName` (and `workspaceName` if needed). Technical callers may pass `embedId` directly.',\n };\n }\n return { ok: true, value: { embedId: null } };\n }\n\n /**\n * Resolve the data app name from either a caller override, an embed's\n * metadata, or the sole data app in the workspace. Used by every widget\n * tool so business users never have to name the data app when it's\n * unambiguous.\n */\n async resolveDataAppName(\n provided: string | undefined,\n embedId: string | undefined\n ): Promise<Resolved<string>> {\n if (provided) return { ok: true, value: provided };\n\n if (embedId) {\n const ctx = await this.resolveEmbedContext(embedId);\n if (ctx.dataAppName) return { ok: true, value: ctx.dataAppName };\n }\n\n const apps = await this.dataAppsApi.listDataApps();\n const normalized = apps\n .map((a) => this.discoveryService.normalizeDataApp(a))\n .filter((a) => a.name && a.name !== 'Unnamed Data App');\n\n if (normalized.length === 1) return { ok: true, value: normalized[0].name };\n if (normalized.length === 0) {\n return {\n ok: false,\n error:\n 'No data apps found in this workspace. Create one in the Databrain UI first.',\n };\n }\n return {\n ok: false,\n error:\n `Multiple data apps exist (${normalized.map((a) => `\"${a.name}\"`).join(', ')}). ` +\n 'Pass `dataAppName` explicitly, or pass `embedId` to auto-resolve.',\n };\n }\n\n async ensureTenantDashboardScope(params: {\n embedId: string;\n clientId: string;\n dataAppName?: string;\n dashboardName?: string | null;\n }): Promise<Resolved<TenantDashboardScope>> {\n const clientId = params.clientId.trim();\n if (!clientId) {\n return {\n ok: false,\n error: '`clientId` cannot be empty. Pick a tenant/client first.',\n };\n }\n\n const ctx = await this.resolveEmbedContext(\n params.embedId,\n params.dataAppName\n );\n if (ctx.externalDashboardCreatedBy === clientId) {\n return {\n ok: true,\n value: {\n embedId: params.embedId,\n clientId,\n dataAppName: ctx.dataAppName,\n },\n };\n }\n\n let tenantEmbeds: EmbedRecord[];\n try {\n tenantEmbeds = await this.embedsApi.listEmbeds(\n params.dataAppName,\n clientId\n );\n } catch (err) {\n return {\n ok: false,\n error: `Could not verify tenant dashboard ownership for client \"${clientId}\": ${(err as Error).message}`,\n };\n }\n\n const target = params.embedId.trim();\n const matches = tenantEmbeds\n .map((embed) => ({\n raw: embed,\n normalized: this.discoveryService.normalizeEmbed(embed),\n }))\n .filter(({ raw, normalized }) => {\n const ids = [\n raw.embedId,\n raw.id,\n raw._id,\n raw.dashboardId,\n normalized.embedId,\n normalized.internalId,\n normalized.dashboardId,\n ].filter(isNonEmptyString);\n return ids.includes(target);\n });\n\n if (matches.length === 0) {\n const dashboardLabel = params.dashboardName || params.embedId;\n return {\n ok: false,\n error:\n `Refusing to touch dashboard \"${dashboardLabel}\" for client \"${clientId}\". ` +\n \"The tenant-scoped embed lookup did not return this dashboard, which means the resolved target is likely the production/data-app dashboard rather than this client's dashboard copy. \" +\n 'Create or select a multi-tenant dashboard embed for this client first (`create_embed` with `clientId`), then retry.',\n };\n }\n\n return {\n ok: true,\n value: {\n embedId: params.embedId,\n clientId,\n dataAppName: matches[0].normalized.dataAppName,\n },\n };\n }\n\n /**\n * Read-only sibling of `ensureTenantDashboardScope`.\n *\n * The tenant gate above exists to stop a WRITE landing on the data-app\n * dashboard when the caller meant a tenant's copy, so it insists the\n * tenant-scoped embed lookup returns the target. A data-app embed has no\n * tenant row, `listEmbeds(dataAppName, clientId)` answers with an empty list,\n * and the render path was denied before it ever reached the backend. That is\n * the wrong trade for a read: the chart route re-derives everything from the\n * guest token it is handed (embed inside the token's data app, `allowedEmbeds`,\n * the tenancy subset for the client, and per-metric client visibility), so the\n * only thing this check can usefully add is refusing another tenant's embed.\n */\n async ensureReadableDashboardScope(params: {\n embedId: string;\n clientId: string;\n dataAppName?: string;\n }): Promise<Resolved<TenantDashboardScope>> {\n const clientId = params.clientId.trim();\n if (!clientId) {\n return {\n ok: false,\n error: '`clientId` cannot be empty. Pick a tenant/client first.',\n };\n }\n\n let ctx: EmbedContext;\n try {\n ctx = await this.resolveEmbedContext(params.embedId, params.dataAppName);\n } catch (err) {\n return { ok: false, error: (err as Error).message };\n }\n\n if (ctx.embedClientId && ctx.embedClientId !== clientId) {\n return {\n ok: false,\n error:\n `Embed \"${params.embedId}\" belongs to another client. ` +\n 'Pass the `clientId` the embed was created for.',\n };\n }\n if (\n !ctx.embedClientId &&\n ctx.externalDashboardCreatedBy &&\n ctx.externalDashboardCreatedBy !== clientId\n ) {\n return {\n ok: false,\n error:\n `Dashboard behind embed \"${params.embedId}\" belongs to another client. ` +\n 'Pass the `clientId` the dashboard was created for.',\n };\n }\n\n return {\n ok: true,\n value: {\n embedId: params.embedId,\n clientId,\n dataAppName: ctx.dataAppName || params.dataAppName || null,\n },\n };\n }\n\n /**\n * Resolve a datasource for a widget. Priority:\n * 1. Explicit integrationId + integrationName (fast path).\n * 2. One of integrationId/integrationName supplied — look up the other.\n * 3. Probe existing widgets on the embed for inherited datasource metadata.\n * 4. Fall back to the sole active datasource in the workspace.\n * On failure, returns a business-user-friendly error listing the available\n * datasource names.\n */\n async resolveDatasource(\n guestToken: string,\n params: {\n embedId?: string;\n clientId: string;\n integrationId?: string;\n integrationName?: string;\n }\n ): Promise<Resolved<DatasourceResolution>> {\n // Fast path: both overrides supplied.\n if (params.integrationId && params.integrationName) {\n return {\n ok: true,\n value: {\n integrationId: params.integrationId,\n integrationName: params.integrationName,\n },\n };\n }\n\n // If one of integrationId/integrationName was supplied, resolve the other\n // from the datasource list so a single-field override still works. Return\n // the lookup error directly — falling through to embed/auto paths would\n // silently ignore the user's explicit choice or produce a mismatched pair.\n if (params.integrationId || params.integrationName) {\n return this.completeFromDatasources({\n integrationId: params.integrationId,\n integrationName: params.integrationName,\n });\n }\n\n // Prefer inheriting from the embed's existing widgets.\n let embedProbe: EmbedProbe | null = null;\n if (params.embedId) {\n embedProbe = await this.probeDatasourceFromEmbed(\n guestToken,\n params.embedId,\n params.clientId\n );\n if (embedProbe.kind === 'ok') {\n return { ok: true, value: embedProbe.value };\n }\n }\n\n // Fall back to sole datasource. Only consider active datasources — other\n // tools (list_datasources, etc.) treat unauthenticated/disabled ones as\n // unusable, so resolving to one here would cause an avoidable failure.\n const datasources = await this.datasourcesApi.listDatasources();\n const named = datasources\n .filter(isActiveDatasource)\n .filter(\n (ds) =>\n typeof ds.name === 'string' && (ds.name as string).trim().length > 0\n );\n if (named.length === 1) {\n const ds = named[0];\n const name = ds.name as string;\n const id =\n (ds._id as string) ||\n (ds.id as string) ||\n (await this.datasourcesApi.resolveIdByName(name)) ||\n '';\n if (id && name) {\n return {\n ok: true,\n value: { integrationId: id, integrationName: name },\n };\n }\n }\n if (named.length === 0) {\n return {\n ok: false,\n error:\n 'No datasources found in this workspace. Connect one in the Databrain UI first (technical setup).',\n };\n }\n\n // Build a business-user-friendly error. The agent MUST stop and ask the\n // user — present two options in plain language so the user can pick.\n const nameList = named.map((d) => `\"${d.name}\"`).join(', ');\n\n let embedReason = '';\n if (params.embedId && embedProbe) {\n if (embedProbe.kind === 'no_widgets') {\n embedReason =\n ` This dashboard has no widgets for client \"${params.clientId}\" yet, ` +\n `so there's no existing widget to inherit the datasource from.`;\n } else if (embedProbe.kind === 'no_metric_fields') {\n embedReason =\n ` Checked ${embedProbe.widgetsTried} existing widget(s) on this dashboard` +\n (embedProbe.fetchErrors > 0\n ? ` (${embedProbe.fetchErrors} could not be fetched)`\n : '') +\n `, but none had datasource metadata to inherit from.`;\n }\n }\n\n return {\n ok: false,\n error:\n `Could not auto-detect the datasource for this dashboard.${embedReason} ` +\n 'STOP and ASK the user to choose one of these two options:\\n' +\n ' (1) Pick an existing chart to copy from — call `list_widgets` and present the widgets by name, then retry via `add_widget` with `templateMetricId` (datasource inherited automatically). This is the recommended path for non-technical users.\\n' +\n ` (2) Pick a datasource by name from: ${nameList}. Retry with \\`integrationName: \"<chosen name>\"\\`. Only use this if the user already knows their datasource.\\n` +\n 'Do not guess between the two — wait for the user to choose.',\n };\n }\n\n private async completeFromDatasources(provided: {\n integrationId?: string;\n integrationName?: string;\n }): Promise<Resolved<DatasourceResolution>> {\n const allDatasources = await this.datasourcesApi.listDatasources();\n // Only match against active datasources. An inactive match would point\n // the widget at a connection other tools reject as unusable.\n const datasources = allDatasources.filter(isActiveDatasource);\n const matchPredicate = (ds: (typeof allDatasources)[number]) => {\n const id = (ds._id as string) || (ds.id as string) || '';\n const name = typeof ds.name === 'string' ? ds.name : '';\n if (provided.integrationId && id === provided.integrationId) return true;\n if (\n provided.integrationName &&\n name.toLowerCase() === provided.integrationName.toLowerCase()\n ) {\n return true;\n }\n return false;\n };\n let target = datasources.find(matchPredicate);\n // The list response may contain names only. Hydrate missing IDs through\n // the authorized schema endpoint before rejecting an explicit UUID.\n if (!target && provided.integrationId) {\n for (const datasource of datasources) {\n if (\n datasource._id ||\n datasource.id ||\n typeof datasource.name !== 'string'\n )\n continue;\n const id = await this.datasourcesApi.resolveIdByName(datasource.name);\n if (id === provided.integrationId) {\n target = { ...datasource, id };\n break;\n }\n }\n }\n\n if (!target) {\n const available = datasources\n .filter(\n (ds) =>\n typeof ds.name === 'string' && (ds.name as string).trim().length > 0\n )\n .map((ds) => `\"${ds.name}\"`)\n .join(', ');\n // If the user's pick matched an inactive datasource, say so explicitly —\n // otherwise they'll keep retrying the same name.\n const inactiveMatch = allDatasources.find(\n (ds) => !isActiveDatasource(ds) && matchPredicate(ds)\n );\n if (inactiveMatch) {\n const reason = (inactiveMatch as { isDisabled?: boolean }).isDisabled\n ? 'disabled'\n : 'not authenticated';\n return {\n ok: false,\n error:\n `Datasource \"${inactiveMatch.name ?? provided.integrationName ?? provided.integrationId}\" is ${reason}. ` +\n `Fix the connection in the Databrain UI, or pick another datasource. Active options: ${available || '(none)'}.`,\n };\n }\n const hint = provided.integrationId\n ? `No active datasource matches integrationId \"${provided.integrationId}\". Available datasources: ${available || '(none)'}.`\n : `No active datasource matches integrationName \"${provided.integrationName}\". Available datasources: ${available || '(none)'}. Match is case-insensitive — double-check the name with the user.`;\n return { ok: false, error: hint };\n }\n\n const name = typeof target.name === 'string' ? target.name : '';\n // The /api/v2/datasource/ list endpoint omits IDs, so hydrate via the\n // schema endpoint (which returns { datasourceId, ... } for a given name).\n const id =\n (target._id as string) ||\n (target.id as string) ||\n (name ? await this.datasourcesApi.resolveIdByName(name) : null) ||\n '';\n if (!id || !name) {\n return {\n ok: false,\n error:\n `Could not resolve datasource \"${name || provided.integrationName || provided.integrationId}\" to a UUID. ` +\n 'The datasource list API does not return IDs; the schema lookup also failed — the datasource may need to be synced in the Databrain UI.',\n };\n }\n return { ok: true, value: { integrationId: id, integrationName: name } };\n }\n\n private async probeDatasourceFromEmbed(\n guestToken: string,\n embedId: string,\n clientId: string\n ): Promise<EmbedProbe> {\n const widgets = await this.widgetsApi.listWidgets(embedId, clientId);\n const candidates = widgets.filter(\n (w) => typeof w.metricId === 'string' && (w.metricId as string).length > 0\n );\n if (candidates.length === 0) return { kind: 'no_widgets' };\n\n // Cap the number of widgets we probe — a healthy embed resolves on the\n // first one, and we don't want to burn minutes on a broken dashboard.\n const MAX_PROBES = 5;\n const toProbe = candidates.slice(0, MAX_PROBES);\n\n let fetchErrors = 0;\n let datasourcesCache: Awaited<\n ReturnType<typeof this.datasourcesApi.listDatasources>\n > | null = null;\n\n for (const widget of toProbe) {\n let response: Awaited<\n ReturnType<typeof this.widgetsApi.fetchEmbeddedMetric>\n >;\n try {\n response = await this.widgetsApi.fetchEmbeddedMetric(\n guestToken,\n widget.metricId as string\n );\n } catch {\n fetchErrors += 1;\n continue;\n }\n const metric = response?.externalMetric;\n if (!metric || typeof metric !== 'object') continue;\n\n const rec = metric as Record<string, unknown>;\n const integrationId =\n typeof rec.companyIntegrationId === 'string' && rec.companyIntegrationId\n ? rec.companyIntegrationId\n : null;\n let integrationName =\n typeof rec.integrationName === 'string' && rec.integrationName\n ? rec.integrationName\n : null;\n\n if (integrationId && !integrationName) {\n // Legacy widgets populate companyIntegrationId but not integrationName.\n // Look the name up from the datasource list.\n if (!datasourcesCache) {\n datasourcesCache = await this.datasourcesApi.listDatasources();\n }\n const match = datasourcesCache.find((ds) => {\n const id = (ds._id as string) || (ds.id as string) || '';\n return id === integrationId;\n });\n if (match && typeof match.name === 'string' && match.name) {\n integrationName = match.name;\n }\n }\n\n if (integrationId && integrationName) {\n return { kind: 'ok', value: { integrationId, integrationName } };\n }\n }\n\n return {\n kind: 'no_metric_fields',\n widgetsTried: toProbe.length,\n fetchErrors,\n };\n }\n\n async resolveEmbedContext(\n embedId: string,\n dataAppNameHint?: string\n ): Promise<EmbedContext> {\n const response = await this.embedsApi.getByEmbedId(\n embedId,\n dataAppNameHint\n );\n const records = Array.isArray(response)\n ? (response as EmbedRecord[])\n : response\n ? [response as EmbedRecord]\n : [];\n\n const exact = records.find((r) => r && r.embedId === embedId) || records[0];\n if (!exact) {\n throw new Error(\n `Embed \"${embedId}\" not found. Run \\`list_embeds\\` to verify.`\n );\n }\n\n const metadata = asRecord(exact.embedMetadata);\n const externalDashboard = asRecord(exact.externalDashboard);\n\n const dataAppId = isNonEmptyString(exact.dataAppId)\n ? exact.dataAppId\n : null;\n const externalDashboardId =\n (isNonEmptyString(exact.externalDashboardId) &&\n exact.externalDashboardId) ||\n (externalDashboard &&\n isNonEmptyString(externalDashboard.externalDashboardId)\n ? (externalDashboard.externalDashboardId as string)\n : null) ||\n (metadata && isNonEmptyString(metadata.externalDashboardId)\n ? (metadata.externalDashboardId as string)\n : null);\n const dashboardId =\n (isNonEmptyString(exact.dashboardId) && exact.dashboardId) ||\n (metadata && isNonEmptyString(metadata.dashboardId)\n ? (metadata.dashboardId as string)\n : null);\n\n let dataAppName: string | null =\n metadata && isNonEmptyString(metadata.dataAppName)\n ? (metadata.dataAppName as string)\n : null;\n\n if (!dataAppName && dataAppId) {\n try {\n const apps = await this.dataAppsApi.listDataApps();\n const match = apps.find((a) => {\n const n = this.discoveryService.normalizeDataApp(a);\n return n.dataAppId === dataAppId;\n });\n if (match) {\n dataAppName = this.discoveryService.normalizeDataApp(match).name;\n }\n } catch {\n // Non-fatal — caller can pass dataAppName explicitly.\n }\n }\n\n return {\n embedId,\n dataAppId,\n dataAppName,\n externalDashboardId,\n dashboardId,\n embedClientId:\n (isNonEmptyString(exact.clientId) && exact.clientId) ||\n (metadata && isNonEmptyString(metadata.clientId)\n ? (metadata.clientId as string)\n : null),\n externalDashboardCreatedBy:\n (externalDashboard && isNonEmptyString(externalDashboard.createdBy)\n ? (externalDashboard.createdBy as string)\n : null) ||\n (isNonEmptyString(exact.createdBy) ? exact.createdBy : null) ||\n (metadata && isNonEmptyString(metadata.createdBy)\n ? (metadata.createdBy as string)\n : null) ||\n (isNonEmptyString(exact.clientId) ? exact.clientId : null),\n };\n }\n\n async mintGuestToken(\n clientId: string,\n dataAppName: string,\n allowedEmbeds?: string[]\n ): Promise<string> {\n // Widget tools (add/update/remove/generate) need metric write permissions.\n // Embed-level accessSettings alone aren't sufficient — the guest token must\n // opt in to management/creation or the create-metric API returns UNAUTHORISED.\n const { token } = await this.guestTokenService.generateToken({\n clientId,\n dataAppName,\n ...(allowedEmbeds && allowedEmbeds.length > 0 ? { allowedEmbeds } : {}),\n permissions: {\n isDisableMetricCreation: false,\n isEnableManageMetrics: true,\n isEnableMetricUpdation: true,\n isEnableArchiveMetrics: true,\n },\n });\n return token;\n }\n\n /**\n * Build a create body by cloning a template metric. Fetches the full metric\n * via the embeddedMetric endpoint and copies structural fields, then lets the\n * caller override `name`/`metricId`/etc.\n */\n async buildCloneBody(\n guestToken: string,\n templateMetricId: string,\n overrides: Partial<CreateMetricBody>,\n externalDashboardId: string\n ): Promise<CreateMetricBody> {\n const response = await this.widgetsApi.fetchEmbeddedMetric(\n guestToken,\n templateMetricId\n );\n const metric = asRecord(response.externalMetric);\n if (!metric) {\n throw new Error(\n `Template metric \"${templateMetricId}\" not found or could not be loaded. Response keys: ${Object.keys(\n response || {}\n ).join(\n ', '\n )}. Error: ${JSON.stringify((response as Record<string, unknown>)?.error ?? null)}`\n );\n }\n\n const clone: CreateMetricBody = {\n // Required identity — caller must override or we derive.\n name:\n overrides.name ||\n (isNonEmptyString(metric.name) ? `${metric.name} (copy)` : 'Widget'),\n metricId:\n overrides.metricId ||\n `${(isNonEmptyString(metric.metricId) && metric.metricId) || 'widget'}-${Date.now()}`,\n\n // Structural fields copied from template.\n query: (metric.query as string) || undefined,\n metricQuery: (metric.metricQuery as string) || undefined,\n description: (metric.description as string) || '',\n chartOptions: asRecord(metric.chartOptions) || {},\n companyId: (metric.companyId as string) || undefined,\n companyIntegrationId:\n (metric.companyIntegrationId as string) || undefined,\n integrationName: (metric.integrationName as string) || undefined,\n outputColumns: (metric.outputColumns as string) || undefined,\n inputFields: metric.inputFields,\n isLive: (metric.isLive as boolean) ?? undefined,\n timeGrain: (metric.timeGrain as string) || undefined,\n selectedGroupBy: metric.selectedGroupBy,\n isEnableGroupBy: (metric.isEnableGroupBy as boolean) ?? undefined,\n datasetMetricSettings: metric.datasetMetricSettings,\n groupBy: metric.groupBy,\n drillDownSettings: metric.drillDownSettings,\n limit: (metric.limit as number) ?? undefined,\n\n // Dashboard attachment — always for the target embed's dashboard.\n externalDashboardIds: [{ externalDashboardId }],\n\n // Defaults that shouldn't be inherited from the template.\n isCreatedByClient: false,\n isPublished: true,\n };\n\n // Apply caller overrides.\n for (const [key, value] of Object.entries(overrides)) {\n if (value !== undefined) {\n (clone as Record<string, unknown>)[key] = value;\n }\n }\n\n // Always re-assert dashboard attachment (overrides can't drop it silently).\n if (\n !clone.externalDashboardIds ||\n clone.externalDashboardIds.length === 0\n ) {\n clone.externalDashboardIds = [{ externalDashboardId }];\n }\n\n return clone;\n }\n}\n","import { CustomChartsApi } from '../api/custom-charts-api.js';\nimport { DashboardsApi } from '../api/dashboards-api.js';\nimport { DataAppsApi } from '../api/data-apps-api.js';\nimport { DatamartsApi } from '../api/datamarts-api.js';\nimport { DatasourcesApi } from '../api/datasources-api.js';\nimport { EmbedsApi } from '../api/embeds-api.js';\nimport { GuestTokenApi } from '../api/guest-token-api.js';\nimport { QueryApi } from '../api/query-api.js';\nimport { ScheduledReportsApi } from '../api/scheduled-reports-api.js';\nimport { SemanticModelApi } from '../api/semantic-model-api.js';\nimport { TenantsApi } from '../api/tenants-api.js';\nimport { WidgetsApi } from '../api/widgets-api.js';\nimport { WorkspacesApi } from '../api/workspaces-api.js';\nimport type { DatabrainClient } from '../client/databrain-client.js';\nimport { DiscoveryService } from './discovery-service.js';\nimport { EmbedService } from './embed-service.js';\nimport { GuestTokenService } from './guest-token-service.js';\nimport { WidgetService } from './widget-service.js';\n\nexport interface ServiceBundle {\n embedsApi: EmbedsApi;\n dashboardsApi: DashboardsApi;\n dataAppsApi: DataAppsApi;\n datamartsApi: DatamartsApi;\n datasourcesApi: DatasourcesApi;\n workspacesApi: WorkspacesApi;\n queryApi: QueryApi;\n scheduledReportsApi: ScheduledReportsApi;\n semanticModelApi: SemanticModelApi;\n customChartsApi: CustomChartsApi;\n tenantsApi: TenantsApi;\n widgetsApi: WidgetsApi;\n embedService: EmbedService;\n discoveryService: DiscoveryService;\n guestTokenService: GuestTokenService;\n widgetService: WidgetService;\n}\n\nexport function createServiceBundle(client: DatabrainClient): ServiceBundle {\n const embedsApi = new EmbedsApi(client);\n const dashboardsApi = new DashboardsApi(client);\n const dataAppsApi = new DataAppsApi(client);\n const datamartsApi = new DatamartsApi(client);\n const datasourcesApi = new DatasourcesApi(client);\n const guestTokenApi = new GuestTokenApi(client);\n const queryApi = new QueryApi(client);\n const scheduledReportsApi = new ScheduledReportsApi(client);\n const semanticModelApi = new SemanticModelApi(client);\n const customChartsApi = new CustomChartsApi(client);\n const tenantsApi = new TenantsApi(client);\n const widgetsApi = new WidgetsApi(client);\n const workspacesApi = new WorkspacesApi(client);\n\n const discoveryService = new DiscoveryService();\n const guestTokenService = new GuestTokenService(guestTokenApi);\n\n return {\n embedsApi,\n dashboardsApi,\n dataAppsApi,\n datamartsApi,\n datasourcesApi,\n workspacesApi,\n queryApi,\n scheduledReportsApi,\n semanticModelApi,\n customChartsApi,\n tenantsApi,\n widgetsApi,\n embedService: new EmbedService(embedsApi, datamartsApi),\n discoveryService,\n guestTokenService,\n widgetService: new WidgetService(\n widgetsApi,\n embedsApi,\n dataAppsApi,\n datasourcesApi,\n dashboardsApi,\n guestTokenService,\n discoveryService\n ),\n };\n}\n","import type { ToolAnnotations } from '@modelcontextprotocol/sdk/types.js';\n\nexport const READ_ONLY: ToolAnnotations = {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n};\n\nexport const WRITE_IDEMPOTENT: ToolAnnotations = {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n};\n\nexport const WRITE_CREATE: ToolAnnotations = {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: false,\n};\n\nexport const DESTRUCTIVE: ToolAnnotations = {\n readOnlyHint: false,\n destructiveHint: true,\n idempotentHint: false,\n openWorldHint: false,\n};\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { toolSuccess } from '../../utils/errors.js';\nimport { READ_ONLY } from '../annotations.js';\n\nexport function registerWhoami(\n server: McpServer,\n client: DatabrainClient\n): void {\n server.tool(\n 'whoami',\n 'Return the credential currently used for API calls. Use to confirm which auth mode this MCP session is operating under before mutating actions.',\n {},\n READ_ONLY,\n async () => {\n const auth = client.getActiveAuth();\n\n if (auth.source === 'oauth-client-credentials') {\n return toolSuccess(\n JSON.stringify(\n {\n status:\n auth.status === 'ready' ? 'credential_acquired' : auth.status,\n activeBearer: 'oauth-client-credentials',\n note: 'OAuth client credentials identify a service application, not a human. The backend must validate and authorize the token. This local status does not verify backend acceptance or resolve an operator identity.',\n },\n null,\n 2\n )\n );\n }\n\n if (auth.source === 'service-token') {\n return toolSuccess(\n JSON.stringify(\n {\n status: 'authenticated',\n activeBearer: 'service-token',\n ...(auth.oauthFallback ? { oauthFallback: true } : {}),\n note: auth.oauthFallback\n ? 'OAuth token acquisition failed; the configured static service token is in use. Mutations use the static org-level principal, with actor=system. OAuth will be retried after a short cooldown.'\n : 'Org-level service token (DATABRAIN_SERVICE_TOKEN). Per-user identity is NOT bound — mutations are audit-logged as actor=system. For per-user access, connect an AI app to the hosted server (it signs in with your Databrain account).',\n },\n null,\n 2\n )\n );\n }\n\n if (auth.source === 'api-token') {\n return toolSuccess(\n JSON.stringify(\n {\n status: 'authenticated',\n activeBearer: 'api-token',\n note: 'Per-data-app API token. Limited to embedding operations on that data app. Org-level setup tools require DATABRAIN_SERVICE_TOKEN.',\n },\n null,\n 2\n )\n );\n }\n\n return toolSuccess(\n JSON.stringify(\n {\n status: 'not_authenticated',\n activeBearer: 'none',\n note: 'No usable credential is configured. Set DATABRAIN_SERVICE_TOKEN or DATABRAIN_API_TOKEN in the MCP config.',\n },\n null,\n 2\n )\n );\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { MAX_RESULT_CHARS, rowsSchema } from '../../apps/contract.js';\nimport { chartResult, hasChartApps, tagChartTool } from '../../apps/feature.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { editWithBryn, studioDraftSchema } from '../../custom-chart/studio.js';\nimport {\n DatabrainApiError,\n toolError,\n toolSuccess,\n} from '../../utils/errors.js';\nimport { READ_ONLY, WRITE_CREATE } from '../annotations.js';\nimport {\n bundleInputShape,\n formatProblems,\n isCompleteBundle,\n resolveBundleInput,\n} from './shared.js';\n\nexport function registerCustomChartAuthor(\n server: McpServer,\n client: DatabrainClient\n): void {\n server.tool(\n 'custom_chart_edit',\n 'Iterate a custom chart draft with Chart studio Bryn in a granted workspace. Never saves a version or publishes. ' +\n 'Feature-detects the backend route. If absent, returns the draft for the calling agent to edit and validate with chartTs, without a local build.',\n {\n key: z.string().regex(/^[a-z][a-z0-9_-]{0,63}$/),\n workspaceId: z.string().uuid(),\n message: z.string().trim().min(1).max(8000),\n draft: studioDraftSchema,\n sessionId: z.string().uuid().optional(),\n },\n WRITE_CREATE,\n async (input) => {\n try {\n if (input.draft.manifest.id !== input.key)\n return toolError('The draft manifest id must match key.');\n const result = await editWithBryn(client, input);\n return toolSuccess(\n JSON.stringify({\n ...result,\n nextStep: result.available\n ? 'Check the returned draft. Validate and preview before saving. Publishing still requires the author to confirm.'\n : '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.',\n })\n );\n } catch (error) {\n return error instanceof DatabrainApiError\n ? error.toToolResponse()\n : toolError('Bryn could not edit the draft. No version was saved.');\n }\n }\n );\n\n const preview = server.tool(\n 'custom_chart_preview',\n 'Validate and preview a draft custom chart as an MCP App tile using bounded sample query rows. No version is saved. ' +\n '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.',\n {\n ...bundleInputShape,\n rows: rowsSchema,\n bindings: z.record(z.string(), z.array(z.string().max(128)).max(20)),\n options: z\n .record(\n z.string(),\n z.union([z.string().max(2000), z.number().finite(), z.boolean()])\n )\n .default({}),\n },\n READ_ONLY,\n async (input) => {\n try {\n const resolved = await resolveBundleInput(input, { build: true });\n if (resolved.error) return toolError(resolved.error);\n if (!resolved.bundle || !isCompleteBundle(resolved.bundle))\n return toolError(formatProblems(resolved.problems));\n const { validateBundle } = await import('../../custom-chart/bundle.js');\n const problems = validateBundle(resolved.bundle);\n if (problems.length) return toolError(formatProblems(problems));\n const manifest = resolved.bundle.manifest;\n const columns = Object.keys(input.rows[0] ?? {});\n const missing = manifest.slots.filter(\n (slot) =>\n slot.required &&\n !(input.bindings[slot.id] ?? []).some((column) =>\n columns.includes(column)\n )\n );\n if (input.rows.length && missing.length)\n return toolError(\n `Bind required slots ${missing.map((slot) => slot.id).join(', ')} to sample columns: ${columns.join(', ') || '(none)'}.`\n );\n const customChart = {\n key: manifest.id,\n bindings: input.bindings,\n options: input.options,\n };\n const payload = {\n kind: 'chart',\n title: manifest.name,\n chartSpec: { type: `custom:${manifest.id}` },\n rows: input.rows,\n columns: Object.keys(input.rows[0] ?? {}),\n width: 600,\n height: 320,\n points: [],\n customChart,\n fallback:\n 'Draft validated. An MCP Apps host can preview it. These are sample rows, not a saved metric.',\n };\n if (!hasChartApps(server))\n return toolSuccess(JSON.stringify({ ...payload, ok: true }));\n const result = chartResult(\n 'Custom chart draft validated. Preview uses sample rows. Nothing was saved or published.',\n payload\n );\n // Bundle source is app-only metadata, never executable server code or model context.\n result._meta = {\n ...result._meta,\n 'databrain/custom-chart-bundle': resolved.bundle,\n };\n if (JSON.stringify(result).length > MAX_RESULT_CHARS)\n return toolError(\n 'Draft preview exceeds the MCP host result budget. Reduce the source, CSS or sample rows before previewing.'\n );\n return result;\n } catch (error) {\n return error instanceof DatabrainApiError\n ? error.toToolResponse()\n : toolError(\n error instanceof Error &&\n error.message === 'Chart page exceeds payload budget'\n ? 'Draft preview exceeds the MCP host result budget. Reduce the source, CSS or sample rows before previewing.'\n : 'Custom chart preview could not be prepared. Check the manifest, source and bindings.'\n );\n }\n }\n );\n tagChartTool(server, preview);\n}\n","import { z } from 'zod';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport {\n apiProblems,\n createCustomChartsApi,\n type ValidateResponse,\n} from '../../custom-chart/api.js';\nimport {\n buildProject,\n buildSource,\n readDist,\n} from '../../custom-chart/bundle.js';\nimport {\n manifestOptionSchema,\n manifestSlotSchema,\n} from '../../custom-chart/manifest.js';\nimport type { CustomChartBundle, Problem } from '../../custom-chart/types.js';\nimport { DatabrainApiError } from '../../utils/errors.js';\n\nexport const slotInputSchema = manifestSlotSchema;\nexport const optionInputSchema = manifestOptionSchema;\n\nexport const manifestInputSchema = z\n .record(z.string(), z.unknown())\n .describe(\n 'manifest.json as an object (schemaVersion 2). Validated with the same rules as the server.'\n );\n\nexport const bundleInputShape = {\n manifest: manifestInputSchema.optional(),\n chartTs: z\n .string()\n .max(64_000)\n .optional()\n .describe(\n 'Hosted source: export render(ctx) in TypeScript or JavaScript. Compiled in memory without filesystem or imports. Pass instead of bundleJs/projectDir.'\n ),\n bundleJs: z\n .string()\n .optional()\n .describe(\n 'dist/index.js from `databrain custom-chart build` (the shim plus the chart module).'\n ),\n bundleCss: z\n .string()\n .optional()\n .describe('The raw chart.css, kept for provenance.'),\n iconSvg: z\n .string()\n .optional()\n .describe(\n 'icon.svg, at most 16 KiB, no script, no foreignObject, no external href.'\n ),\n projectDir: z\n .string()\n .optional()\n .describe(\n 'Local only: a chart project folder. The tool reads it instead of manifest/bundleJs/iconSvg.'\n ),\n};\n\n/** Problems as the CLI prints them: path, code, message. */\nexport function formatProblems(problems: Problem[]): string {\n if (problems.length === 0) return 'No problems.';\n return problems\n .map((p) => `${p.path || '/'} ${p.code} ${p.message}`)\n .join('\\n');\n}\n\n/**\n * Reading a folder is a local-process convenience. Over the hosted HTTP\n * transport the process serves many principals and must never read its own\n * disk on request, so projectDir is refused there.\n */\nexport function projectDirRefusal(): string | null {\n if (process.env.DATABRAIN_HOSTED_PUBLIC_URL) {\n 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.';\n }\n return null;\n}\n\n/** A bundle before validation: the manifest is still untrusted JSON. */\nexport type LooseBundle = Omit<Partial<CustomChartBundle>, 'manifest'> & {\n manifest: unknown;\n};\n\nexport interface ResolvedBundleInput {\n bundle?: LooseBundle;\n problems: Problem[];\n error?: string;\n source: 'arguments' | 'projectDir';\n}\n\n/**\n * Turn tool arguments into a bundle. With projectDir the project is built in\n * memory (or dist/ is read when build is false). With arguments the values\n * are used as given.\n */\nexport async function resolveBundleInput(\n params: {\n manifest?: Record<string, unknown>;\n chartTs?: string;\n bundleJs?: string;\n bundleCss?: string;\n iconSvg?: string;\n projectDir?: string;\n },\n options: { build: boolean }\n): Promise<ResolvedBundleInput> {\n if (params.chartTs !== undefined) {\n if (\n params.projectDir ||\n params.bundleJs ||\n !params.manifest ||\n !params.iconSvg\n ) {\n return {\n problems: [],\n error:\n 'chartTs needs manifest and iconSvg, and cannot be combined with bundleJs or projectDir.',\n source: 'arguments',\n };\n }\n const result = await buildSource({\n manifest: params.manifest,\n chartTs: params.chartTs,\n bundleCss: params.bundleCss,\n iconSvg: params.iconSvg,\n });\n return {\n bundle: result.outputs,\n problems: result.problems,\n source: 'arguments',\n };\n }\n if (params.projectDir) {\n const refusal = projectDirRefusal();\n if (refusal) return { problems: [], error: refusal, source: 'projectDir' };\n if (params.manifest || params.bundleJs || params.iconSvg) {\n return {\n problems: [],\n error: 'Pass either projectDir or manifest/bundleJs/iconSvg, not both.',\n source: 'projectDir',\n };\n }\n if (options.build) {\n const result = await buildProject(params.projectDir, { write: false });\n if (!result.ok || !result.outputs)\n return { problems: result.problems, source: 'projectDir' };\n const { manifest, bundleJs, bundleCss, iconSvg } = result.outputs;\n return {\n bundle: { manifest, bundleJs, bundleCss, iconSvg },\n problems: [],\n source: 'projectDir',\n };\n }\n const dist = readDist(params.projectDir);\n if (!dist.bundle) return { problems: dist.problems, source: 'projectDir' };\n return { bundle: dist.bundle, problems: [], source: 'projectDir' };\n }\n if (!params.manifest) {\n return {\n problems: [],\n error: 'manifest is required (or pass projectDir when running locally).',\n source: 'arguments',\n };\n }\n return {\n bundle: {\n manifest: params.manifest as unknown,\n bundleJs: params.bundleJs,\n bundleCss: params.bundleCss,\n iconSvg: params.iconSvg,\n },\n problems: [],\n source: 'arguments',\n };\n}\n\nexport type RemoteValidation =\n | { status: 'ok'; result: ValidateResponse }\n | { status: 'skipped'; reason: string }\n | { status: 'failed'; reason: string; problems: Problem[] };\n\n/** POST /validate when a service credential is configured; otherwise say so. */\nexport async function remoteValidate(\n client: DatabrainClient,\n bundle: CustomChartBundle\n): Promise<RemoteValidation> {\n try {\n const result = await createCustomChartsApi(client).validate(bundle);\n return { status: 'ok', result };\n } catch (err) {\n if (err instanceof DatabrainApiError) {\n if (err.code === 'MISSING_SERVICE_TOKEN') {\n return {\n status: 'skipped',\n reason:\n 'No service token is configured, so only the local validator ran.',\n };\n }\n return {\n status: 'failed',\n reason: err.message,\n problems: apiProblems(err),\n };\n }\n return { status: 'failed', reason: (err as Error).message, problems: [] };\n }\n}\n\nexport function isCompleteBundle(\n bundle: LooseBundle\n): bundle is CustomChartBundle {\n return (\n typeof bundle.bundleJs === 'string' && typeof bundle.iconSvg === 'string'\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { createCustomChartsApi } from '../../custom-chart/api.js';\nimport {\n DatabrainApiError,\n toolError,\n toolSuccess,\n} from '../../utils/errors.js';\nimport { READ_ONLY } from '../annotations.js';\n\nexport function registerListCustomCharts(\n server: McpServer,\n client: DatabrainClient\n): void {\n server.tool(\n 'list_custom_charts',\n 'List the custom chart types of the company (key, name, status, published and preview versions). Uses the service token.',\n {},\n READ_ONLY,\n async () => {\n try {\n const charts = await createCustomChartsApi(client).list();\n const rows = charts.map((chart) => ({\n key: chart.key,\n chartType: `custom:${chart.key}`,\n name: chart.name,\n status: chart.status,\n publishedVersionId: chart.publishedVersionId ?? null,\n publishedVersionNumber:\n typeof chart.publishedVersionNumber === 'number'\n ? chart.publishedVersionNumber\n : undefined,\n previewVersionId: chart.previewVersionId ?? null,\n previewVersionNumber:\n typeof chart.previewVersionNumber === 'number'\n ? chart.previewVersionNumber\n : undefined,\n versionsCount:\n typeof chart.versionsCount === 'number'\n ? chart.versionsCount\n : undefined,\n updatedAt: chart.updatedAt,\n createdBy: chart.createdBy ?? null,\n }));\n if (rows.length === 0) {\n return toolSuccess(\n 'No custom charts yet. Scaffold one with custom_chart_scaffold, build it with `databrain custom-chart build`, then upload with custom_chart_upload.'\n );\n }\n return toolSuccess(\n JSON.stringify({ count: rows.length, charts: rows }, null, 2)\n );\n } catch (err) {\n if (err instanceof DatabrainApiError) return err.toToolResponse();\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { createCustomChartsApi } from '../../custom-chart/api.js';\nimport {\n DatabrainApiError,\n toolError,\n toolSuccess,\n} from '../../utils/errors.js';\nimport { WRITE_IDEMPOTENT } from '../annotations.js';\nimport {\n APPLY_TO_PRODUCTION_CONFIRMATION,\n genericProductionSafetyNote,\n validateProductionApply,\n} from '../widgets/production-guards.js';\n\nexport function registerPublishCustomChart(\n server: McpServer,\n client: DatabrainClient\n): void {\n const api = createCustomChartsApi(client);\n\n server.tool(\n 'publish_custom_chart',\n '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.',\n {\n key: z\n .string()\n .describe('The chart key (manifest.id), for example revenue-bars.'),\n versionId: z\n .string()\n .optional()\n .describe(\n 'A specific version id to publish. Defaults to the preview version.'\n ),\n mode: z\n .enum(['dry_run', 'apply'])\n .default('dry_run')\n .describe('dry_run shows what would be published; apply publishes.'),\n confirm: z\n .string()\n .optional()\n .describe(`Required for apply: ${APPLY_TO_PRODUCTION_CONFIRMATION}`),\n },\n WRITE_IDEMPOTENT,\n async (params) => {\n try {\n const mode = params.mode || 'dry_run';\n const detail = await api.get(params.key);\n const versions = Array.isArray(detail.versions) ? detail.versions : [];\n const targetId = params.versionId ?? detail.previewVersionId ?? null;\n const target = versions.find((version) => version.id === targetId);\n\n if (!targetId) {\n return toolError(\n `custom:${params.key} has no preview version to publish${detail.publishedVersionId ? ` (v published: ${detail.publishedVersionId})` : ''}. Upload a new version first, or pass versionId.`\n );\n }\n if (params.versionId && versions.length > 0 && !target) {\n return toolError(\n `custom:${params.key} has no version with id ${params.versionId}. Versions: ${versions.map((v) => `${v.id} (v${v.versionNumber})`).join(', ')}.`\n );\n }\n if (detail.publishedVersionId === targetId) {\n return toolSuccess(\n `custom:${params.key} already has ${target ? `v${target.versionNumber}` : targetId} published. Nothing to do.`\n );\n }\n\n if (mode === 'dry_run') {\n return toolSuccess(\n JSON.stringify(\n {\n status: 'dry_run_only',\n safety: genericProductionSafetyNote(),\n key: params.key,\n chartType: `custom:${params.key}`,\n name: detail.name,\n currentStatus: detail.status,\n currentPublishedVersionId: detail.publishedVersionId ?? null,\n willPublish: {\n versionId: targetId,\n versionNumber: target?.versionNumber,\n contentHash: target?.contentHash,\n },\n impact: `Every dashboard using custom:${params.key} will render this version.`,\n requiredApplyConfirmation: APPLY_TO_PRODUCTION_CONFIRMATION,\n nextStep: `Ask the user to confirm, then call again with mode=\"apply\" and confirm=\"${APPLY_TO_PRODUCTION_CONFIRMATION}\".`,\n },\n null,\n 2\n )\n );\n }\n\n const guardError = validateProductionApply({ confirm: params.confirm });\n if (guardError) return toolError(guardError);\n\n // Publish the version this call resolved and (in dry run) showed, not\n // \"whatever the preview is by now\": an upload landing between the two\n // calls must not change what goes live.\n const result = await api.publish(params.key, targetId);\n return toolSuccess(\n `Published ${target ? `v${target.versionNumber}` : targetId} of custom:${params.key} (${result.chart?.name ?? detail.name}). ` +\n `Status: ${result.chart?.status ?? 'published'}. Every dashboard using custom:${params.key} now renders this version.`\n );\n } catch (err) {\n if (err instanceof DatabrainApiError) return err.toToolResponse();\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n}\n","export const APPLY_TO_PRODUCTION_CONFIRMATION = 'APPLY_TO_PRODUCTION';\n\nexport function validateProductionApply(params: {\n workspaceName?: string;\n confirm?: string;\n}): string | null {\n if (params.confirm !== APPLY_TO_PRODUCTION_CONFIRMATION) {\n return (\n `Applying to production requires confirm: \"${APPLY_TO_PRODUCTION_CONFIRMATION}\". ` +\n 'Run dry-run first, review the plan, then retry with that confirmation string.'\n );\n }\n return null;\n}\n\nexport function productionSafetyNote(workspaceName: string): string {\n return (\n `This workspace is production-backed. Dry-run is the default; apply requires explicit production confirmation. ` +\n `Resolved workspace: \"${workspaceName.trim()}\".`\n );\n}\n\nexport function genericProductionSafetyNote(): string {\n return 'This operation targets production-backed Databrain resources. Dry-run is the default; apply requires explicit production confirmation.';\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { transformSync } from 'esbuild';\nimport { z } from 'zod';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { scaffoldProject } from '../../custom-chart/scaffold.js';\nimport { toolError, toolSuccess } from '../../utils/errors.js';\nimport { READ_ONLY } from '../annotations.js';\nimport {\n formatProblems,\n optionInputSchema,\n slotInputSchema,\n} from './shared.js';\n\nexport function registerCustomChartScaffold(\n server: McpServer,\n _client: DatabrainClient\n): void {\n server.tool(\n 'custom_chart_scaffold',\n '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.',\n {\n key: z\n .string()\n .describe(\n 'Chart key, becomes chart type custom:<key>. Lowercase letters, digits, _ and -, 64 max.'\n ),\n name: z\n .string()\n .describe(\n 'Display name shown in the chart picker, 1 to 256 characters.'\n ),\n description: z\n .string()\n .optional()\n .describe('Optional description, up to 500 characters.'),\n slots: z\n .array(slotInputSchema)\n .optional()\n .describe(\n 'Data slots. Defaults to category (dimension), value (measure), target (optional measure).'\n ),\n options: z\n .array(optionInputSchema)\n .optional()\n .describe(\n 'Chart options. Defaults to the template options (labels, subtitle, radius, colour, sort).'\n ),\n },\n READ_ONLY,\n async (params) => {\n try {\n const result = scaffoldProject({\n key: params.key,\n name: params.name,\n description: params.description,\n slots: params.slots as Parameters<typeof scaffoldProject>[0]['slots'],\n options: params.options as Parameters<\n typeof scaffoldProject\n >[0]['options'],\n });\n if (!result.ok) {\n return toolError(\n `The requested manifest is not valid:\\n${formatProblems(result.problems)}`\n );\n }\n return toolSuccess(\n JSON.stringify(\n {\n status: 'scaffold_only',\n key: params.key,\n chartType: `custom:${params.key}`,\n files: result.files,\n draft: {\n code: transformSync(result.files['chart.ts'], {\n loader: 'ts',\n format: 'esm',\n }).code.replace(/export\\s*\\{[^}]*\\};?\\s*$/, ''),\n css: result.files['chart.css'],\n manifest: JSON.parse(result.files['manifest.json']),\n sampleData: (() => {\n const sample = JSON.parse(result.files['sample-data.json']);\n return {\n columns: sample.columns.map(\n ({\n id,\n label,\n type,\n slotId,\n }: {\n id: string;\n label: string;\n type: string;\n slotId?: string;\n }) => ({ id, label, type, ...(slotId ? { slotId } : {}) })\n ),\n rows: sample.rows,\n };\n })(),\n name: params.name,\n description: params.description ?? '',\n iconSvg: result.files['icon.svg'],\n },\n nextStep:\n '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: ' +\n result.nextStep,\n },\n null,\n 2\n )\n );\n } catch (err) {\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport {\n apiProblems,\n createCustomChartsApi,\n planUpload,\n type UploadBody,\n} from '../../custom-chart/api.js';\nimport {\n bundleSizeBytes,\n contentHash,\n validateBundle,\n} from '../../custom-chart/bundle.js';\nimport type { CustomChartManifest } from '../../custom-chart/types.js';\nimport {\n DatabrainApiError,\n toolError,\n toolSuccess,\n} from '../../utils/errors.js';\nimport { WRITE_CREATE } from '../annotations.js';\nimport {\n APPLY_TO_PRODUCTION_CONFIRMATION,\n genericProductionSafetyNote,\n validateProductionApply,\n} from '../widgets/production-guards.js';\nimport {\n bundleInputShape,\n formatProblems,\n isCompleteBundle,\n remoteValidate,\n resolveBundleInput,\n} from './shared.js';\n\nexport function registerCustomChartUpload(\n server: McpServer,\n client: DatabrainClient\n): void {\n const api = createCustomChartsApi(client);\n\n server.tool(\n 'custom_chart_upload',\n '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.',\n {\n mode: z\n .enum(['dry_run', 'apply'])\n .default('dry_run')\n .describe('dry_run validates and returns the plan; apply uploads.'),\n confirm: z\n .string()\n .optional()\n .describe(`Required for apply: ${APPLY_TO_PRODUCTION_CONFIRMATION}`),\n publish: z\n .boolean()\n .default(false)\n .describe(\n 'After a successful apply, publish the uploaded version so every builder can use it.'\n ),\n name: z\n .string()\n .optional()\n .describe('Display name override. Defaults to manifest.name.'),\n description: z\n .string()\n .optional()\n .describe('Description override. Defaults to manifest.description.'),\n ...bundleInputShape,\n },\n WRITE_CREATE,\n async (params) => {\n try {\n const mode = params.mode || 'dry_run';\n const resolved = await resolveBundleInput(params, { build: false });\n if (resolved.error) return toolError(resolved.error);\n if (!resolved.bundle) {\n return toolError(\n `The project could not be read:\\n${formatProblems(resolved.problems)}`\n );\n }\n const { bundle } = resolved;\n if (!isCompleteBundle(bundle)) {\n return toolError(\n 'manifest, bundleJs and iconSvg are all required to upload. Run `databrain custom-chart build` and pass dist/index.js, dist/manifest.json and dist/icon.svg (or projectDir when local).'\n );\n }\n const problems = validateBundle(bundle);\n if (problems.length > 0) {\n return toolError(\n `The bundle is not valid. Fix these and try again:\\n${formatProblems(problems)}`\n );\n }\n const manifest = bundle.manifest as CustomChartManifest;\n const key = manifest.id;\n const body: UploadBody = {\n manifest,\n bundleJs: bundle.bundleJs,\n bundleCss: bundle.bundleCss,\n iconSvg: bundle.iconSvg,\n ...(params.name ? { name: params.name } : {}),\n ...(params.description ? { description: params.description } : {}),\n };\n const localHash = contentHash(bundle);\n const localSize = bundleSizeBytes(bundle);\n\n if (mode === 'dry_run') {\n const remote = await remoteValidate(client, bundle);\n let existing:\n | Awaited<ReturnType<typeof api.list>>[number]\n | undefined;\n let planNote: string | undefined;\n try {\n existing = (await api.list()).find((chart) => chart.key === key);\n } catch (err) {\n planNote =\n err instanceof DatabrainApiError &&\n err.code === 'MISSING_SERVICE_TOKEN'\n ? 'No service token is configured, so the plan could not check whether the chart exists.'\n : `Could not list custom charts: ${(err as Error).message}`;\n }\n const plan = planUpload(key, existing);\n const remoteOk = remote.status !== 'ok' || remote.result.ok;\n return toolSuccess(\n JSON.stringify(\n {\n status: 'dry_run_only',\n safety: genericProductionSafetyNote(),\n ok: remoteOk,\n key,\n chartType: `custom:${key}`,\n contentHash:\n remote.status === 'ok' && remote.result.contentHash\n ? remote.result.contentHash\n : localHash,\n sizeBytes:\n remote.status === 'ok' &&\n typeof remote.result.sizeBytes === 'number'\n ? remote.result.sizeBytes\n : localSize,\n problems:\n remote.status === 'ok'\n ? remote.result.problems\n : remote.status === 'failed'\n ? remote.problems\n : [],\n remote:\n remote.status === 'ok'\n ? 'validated by the server'\n : remote.reason,\n plan: plan.summary,\n ...(planNote ? { planNote } : {}),\n publishAfterUpload: params.publish === true,\n requiredApplyConfirmation: APPLY_TO_PRODUCTION_CONFIRMATION,\n nextStep: remoteOk\n ? `Review this plan. To execute, call again with mode=\"apply\" and confirm=\"${APPLY_TO_PRODUCTION_CONFIRMATION}\"${params.publish ? ' (publish=true will publish the new version right away)' : ''}.`\n : 'Fix every problem, rebuild, then run dry_run again.',\n },\n null,\n 2\n )\n );\n }\n\n const guardError = validateProductionApply({ confirm: params.confirm });\n if (guardError) return toolError(guardError);\n\n const uploaded = await api.upload(body);\n const versionNumber = uploaded.version?.versionNumber;\n const lines: string[] = [];\n if (uploaded.created === 'none') {\n lines.push(\n `This exact bundle is already v${versionNumber ?? '?'} of custom:${key}. Nothing was created.`\n );\n } else if (uploaded.created === 'chart') {\n lines.push(\n `Created custom chart custom:${key} (v${versionNumber ?? 1}, status private).`\n );\n } else {\n lines.push(\n `Uploaded v${versionNumber ?? '?'} of custom:${key}. It is in preview until you publish it.`\n );\n }\n lines.push(\n `contentHash: ${uploaded.version?.contentHash ?? localHash}`\n );\n\n if (params.publish) {\n const published = await api.publish(key, uploaded.version?.id);\n lines.push(\n `Published v${versionNumber ?? '?'} of custom:${key}. Status: ${published.chart?.status ?? 'published'}. Every dashboard using custom:${key} now renders this version.`\n );\n } else if (\n uploaded.created !== 'none' ||\n uploaded.chart?.status !== 'published'\n ) {\n lines.push(\n `To make it available to builders: publish_custom_chart with key \"${key}\" and confirm=\"${APPLY_TO_PRODUCTION_CONFIRMATION}\", or Settings > Developers > Custom charts.`\n );\n }\n return toolSuccess(lines.join('\\n'));\n } catch (err) {\n if (err instanceof DatabrainApiError) {\n const problems = apiProblems(err);\n if (problems.length > 0) {\n return toolError(\n `The server refused the bundle: ${err.message}\\n${formatProblems(problems)}`\n );\n }\n return err.toToolResponse();\n }\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport {\n bundleSizeBytes,\n contentHash,\n validateBundle,\n} from '../../custom-chart/bundle.js';\nimport { toolError, toolSuccess } from '../../utils/errors.js';\nimport { READ_ONLY } from '../annotations.js';\nimport {\n bundleInputShape,\n isCompleteBundle,\n remoteValidate,\n resolveBundleInput,\n} from './shared.js';\n\nexport function registerCustomChartValidate(\n server: McpServer,\n client: DatabrainClient\n): void {\n server.tool(\n 'custom_chart_validate',\n 'Validate a custom chart manifest and bundle with the local rules and, when a service token is configured, the server rules. Never persists anything.',\n bundleInputShape,\n READ_ONLY,\n async (params) => {\n try {\n const resolved = await resolveBundleInput(params, { build: true });\n if (resolved.error) return toolError(resolved.error);\n if (!resolved.bundle) {\n return toolSuccess(\n JSON.stringify(\n {\n ok: false,\n problems: resolved.problems,\n source: resolved.source,\n },\n null,\n 2\n )\n );\n }\n const { bundle } = resolved;\n const problems = validateBundle(bundle);\n const complete = isCompleteBundle(bundle);\n const result: Record<string, unknown> = {\n ok: problems.length === 0,\n problems,\n source: resolved.source,\n contentHash:\n complete && problems.length === 0 ? contentHash(bundle) : undefined,\n sizeBytes:\n complete && problems.length === 0\n ? bundleSizeBytes(bundle)\n : undefined,\n };\n if (!complete) {\n result.note =\n 'Only the manifest was checked. Pass bundleJs and iconSvg (or projectDir) to check the whole package.';\n } else if (problems.length === 0) {\n const remote = await remoteValidate(client, bundle);\n if (remote.status === 'ok') {\n result.remote = remote.result;\n if (!remote.result.ok) {\n result.ok = false;\n result.problems = remote.result.problems;\n }\n if (remote.result.contentHash)\n result.contentHash = remote.result.contentHash;\n if (typeof remote.result.sizeBytes === 'number')\n result.sizeBytes = remote.result.sizeBytes;\n } else if (remote.status === 'skipped') {\n result.remote = { status: 'skipped', reason: remote.reason };\n } else {\n result.remote = { status: 'failed', reason: remote.reason };\n if (remote.problems.length > 0) {\n result.ok = false;\n result.problems = remote.problems;\n }\n }\n }\n result.nextStep = result.ok\n ? 'Upload with custom_chart_upload (mode dry_run first) or `databrain custom-chart upload`.'\n : 'Fix every problem (path, code, message), then validate again.';\n return toolSuccess(JSON.stringify(result, null, 2));\n } catch (err) {\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n}\n","import { z } from 'zod';\n\nexport const dashboardPositionSchema = z\n .object({\n x: z.number().int().min(0).max(23),\n y: z.number().int().min(0),\n w: z.number().int().min(1).max(24),\n h: z.number().int().min(1).max(40),\n })\n .strict();\n\nexport const dashboardChartSchema = z\n .object({\n type: z.string(),\n metricRef: z.string().optional(),\n query: z.string().optional(),\n companyIntegrationId: z.string().optional(),\n chartOptions: z.record(z.string(), z.unknown()).optional(),\n })\n .passthrough();\n\nexport const dashboardTileSchema = z\n .object({\n id: z.string().regex(/^[a-z0-9][a-z0-9-]{0,62}$/),\n kind: z.literal('databrain-chart'),\n position: dashboardPositionSchema,\n title: z.string().min(1).max(200),\n chart: dashboardChartSchema.optional(),\n })\n .strict();\n\nexport const dashboardDocumentShape = {\n schemaVersion: z.literal(1),\n title: z.string().min(1).max(200),\n description: z.string().max(2000).optional(),\n layout: z\n .object({ columns: z.union([z.literal(12), z.literal(24)]).default(24) })\n .strict()\n .optional(),\n tiles: z.array(dashboardTileSchema).min(1).max(50),\n};\n\nexport const workspaceNameSchema = z\n .string()\n .min(1)\n .describe('Target workspace name');\n\nexport const idempotencyKeySchema = z\n .string()\n .regex(\n /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,\n 'idempotencyKey must be a UUID v4'\n )\n .describe('UUID v4 unique to this workspace dashboard create request');\n\nexport type DashboardTile = z.infer<typeof dashboardTileSchema>;\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport {\n DatabrainApiError,\n stringify,\n toolError,\n toolSuccess,\n} from '../../utils/errors.js';\nimport { WRITE_IDEMPOTENT } from '../annotations.js';\nimport {\n dashboardDocumentShape,\n idempotencyKeySchema,\n workspaceNameSchema,\n} from './schema.js';\n\nexport function registerCreateDashboard(\n server: McpServer,\n client: DatabrainClient\n): void {\n server.tool(\n 'create_dashboard',\n 'Create a workspace dashboard from a versioned tile list with retry-safe idempotency.',\n {\n workspaceName: workspaceNameSchema,\n idempotencyKey: idempotencyKeySchema,\n ...dashboardDocumentShape,\n },\n WRITE_IDEMPOTENT,\n async (params) => {\n try {\n const body = {\n schemaVersion: params.schemaVersion,\n title: params.title,\n ...(params.description === undefined\n ? {}\n : { description: params.description }),\n ...(params.layout === undefined ? {} : { layout: params.layout }),\n tiles: params.tiles,\n };\n const result = await client.request<Record<string, unknown>>({\n method: 'POST',\n path: '/api/v2/workspace/dashboard',\n auth: 'service',\n query: { workspaceName: params.workspaceName },\n headers: { 'Idempotency-Key': params.idempotencyKey },\n body,\n invalidateCache: ['list_dashboards'],\n });\n const validation = result.validation;\n if (\n Array.isArray(validation) &&\n validation.some(\n (verdict) =>\n verdict &&\n typeof verdict === 'object' &&\n (verdict as Record<string, unknown>).valid === false\n )\n ) {\n return toolError(\n `Dashboard creation blocked by tile validation:\\n${stringify(validation)}`\n );\n }\n return toolSuccess(stringify(result));\n } catch (err) {\n if (err instanceof DatabrainApiError) return err.toToolResponse();\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { DatabrainApiError, toolError } from '../../utils/errors.js';\nimport { READ_ONLY } from '../annotations.js';\nimport { workspaceNameSchema } from './schema.js';\n\ninterface SnapshotAnswer {\n mimeType?: string;\n image?: string;\n width?: number;\n height?: number;\n theme?: string;\n summary?: string;\n workspace?: { name?: string };\n dashboard?: { id?: string; name?: string };\n metric?: { id?: string; name?: string };\n}\n\n/** The render runs up to 30 s on the server; wait a little longer for its own timeout answer. */\nconst SNAPSHOT_REQUEST_MS = 45_000;\n\nexport function registerDashboardSnapshot(\n server: McpServer,\n client: DatabrainClient\n): void {\n server.tool(\n 'dashboard_snapshot',\n 'Get a PNG picture of a dashboard, or of one chart on it (metricId), as the signed-in user sees it in Databrain. ' +\n 'Light or dark, 480 to 1600 px wide. Needs a Databrain sign-in (OAuth), not a service token.',\n {\n workspaceName: workspaceNameSchema.optional(),\n dashboardId: z\n .string()\n .min(1)\n .max(200)\n .optional()\n .describe(\n 'Dashboard id from list_dashboards. Needed unless metricId is given.'\n ),\n metricId: z\n .string()\n .min(1)\n .max(200)\n .optional()\n .describe(\n 'One chart (metric) id: draw only that chart, from a dashboard it is on.'\n ),\n theme: z\n .enum(['light', 'dark'])\n .default('light')\n .describe('Picture colours'),\n width: z\n .number()\n .int()\n .min(480)\n .max(1600)\n .default(1200)\n .describe('Picture width in pixels'),\n },\n READ_ONLY,\n async (params) => {\n if (!params.dashboardId && !params.metricId) {\n return toolError(\n 'Name a dashboardId (from list_dashboards), or a metricId for one chart.'\n );\n }\n try {\n const result = await client.request<SnapshotAnswer>({\n method: 'POST',\n path: '/api/v2/workspace/dashboard/snapshot',\n auth: 'service',\n timeoutMs: SNAPSHOT_REQUEST_MS,\n body: {\n ...(params.workspaceName\n ? { workspaceName: params.workspaceName }\n : {}),\n ...(params.dashboardId ? { dashboardId: params.dashboardId } : {}),\n ...(params.metricId ? { metricId: params.metricId } : {}),\n theme: params.theme,\n width: params.width,\n },\n });\n if (\n result?.mimeType !== 'image/png' ||\n typeof result.image !== 'string' ||\n !result.image\n ) {\n return toolError('The snapshot answer had no picture. Try again.');\n }\n const what = result.metric?.name\n ? `Chart \"${result.metric.name}\" on dashboard \"${result.dashboard?.name ?? ''}\"`\n : `Dashboard \"${result.dashboard?.name ?? ''}\"`;\n const text = [\n `${what} in workspace \"${result.workspace?.name ?? ''}\", ${result.theme ?? params.theme}, ${result.width}x${result.height} px.`,\n result.summary ?? '',\n ]\n .filter(Boolean)\n .join('\\n');\n return {\n content: [\n { type: 'text' as const, text },\n {\n type: 'image' as const,\n data: result.image,\n mimeType: 'image/png',\n },\n ],\n };\n } catch (err) {\n if (err instanceof DatabrainApiError) return err.toToolResponse();\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport {\n DatabrainApiError,\n stringify,\n toolError,\n toolSuccess,\n} from '../../utils/errors.js';\nimport {\n formatDataApp,\n resolveResource,\n} from '../../utils/resolve-resource.js';\nimport { READ_ONLY } from '../annotations.js';\nimport { dashboardPositionSchema, workspaceNameSchema } from './schema.js';\n\nexport function registerGenerateDashboardTiles(\n server: McpServer,\n client: DatabrainClient\n): void {\n const services = createServiceBundle(client);\n server.tool(\n 'generate_dashboard_tiles',\n 'Generate multiple workspace dashboard tile drafts without persisting them.',\n {\n workspaceName: workspaceNameSchema,\n clientId: z\n .string()\n .trim()\n .min(1)\n .describe(\n 'Tenant client identifier in this data app; use list_tenants to choose it'\n ),\n dataAppName: z\n .string()\n .optional()\n .describe('Data app in the workspace; auto-resolved when unique'),\n integrationId: z.string().optional().describe('Datasource UUID override'),\n integrationName: z\n .string()\n .optional()\n .describe('Datasource name override'),\n tiles: z\n .array(\n z\n .object({\n id: z.string().regex(/^[a-z0-9][a-z0-9-]{0,62}$/),\n title: z.string().min(1).max(200),\n position: dashboardPositionSchema,\n userInputs: z.record(z.string(), z.unknown()),\n })\n .strict()\n )\n .min(1)\n .max(50),\n },\n READ_ONLY,\n async (params) => {\n try {\n const dataApps = await services.dataAppsApi.listDataApps(\n params.workspaceName\n );\n const resolution = resolveResource({\n items: dataApps,\n name: params.dataAppName,\n getName: (app) => app.name || app.dataAppName,\n formatItem: formatDataApp,\n resourceType: 'dataApp',\n toolName: 'generate_dashboard_tiles',\n });\n if (resolution.kind !== 'resolved') return resolution.response;\n\n const guest = await client.request<{ token: string }>({\n method: 'POST',\n path: '/api/v2/guest-token/create',\n auth: 'service',\n body: { clientId: params.clientId, dataAppName: resolution.name },\n });\n const datasource = await services.widgetService.resolveDatasource(\n guest.token,\n {\n clientId: params.clientId,\n integrationId: params.integrationId,\n integrationName: params.integrationName,\n }\n );\n if (!datasource.ok) return toolError(datasource.error);\n\n const generated = await Promise.all(\n params.tiles.map(async (tile) => ({\n input: tile,\n result: await services.widgetsApi.generateMetric(guest.token, {\n integrationId: datasource.value.integrationId,\n integrationName: datasource.value.integrationName,\n userInputs: tile.userInputs,\n }),\n }))\n );\n\n for (const item of generated) {\n if (item.result.error) {\n return toolError(\n `Tile \"${item.input.id}\" generation failed: ${stringify(item.result.error)}`\n );\n }\n }\n\n return toolSuccess(\n stringify({\n schemaVersion: 1,\n workspaceName: params.workspaceName,\n tiles: generated.map(({ input, result }) => ({\n id: input.id,\n kind: 'databrain-chart',\n position: input.position,\n title: input.title,\n chart: {\n type: result.chartType || 'table',\n query: result.query,\n companyIntegrationId: datasource.value.integrationId,\n },\n })),\n generation: generated.map(({ input, result }) => ({\n id: input.id,\n chartTypeReason: result.chartTypeReason ?? null,\n metaData: result.metaData ?? null,\n timeTaken: result.timeTaken ?? null,\n previewRows: result.result ?? [],\n })),\n })\n );\n } catch (err) {\n if (err instanceof DatabrainApiError) return err.toToolResponse();\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n}\n","import { toolError, toolSuccess } from './errors.js';\n\nexport interface ResolveResult<T> {\n selected: T;\n name: string;\n}\n\nexport interface ResolveOptions<T> {\n items: T[];\n name?: string;\n getName: (item: T) => string | undefined;\n formatItem: (item: T) => string;\n resourceType: string;\n toolName: string;\n}\n\ntype Resolution<T> =\n | { kind: 'resolved'; selected: T; name: string }\n | { kind: 'prompt'; response: ReturnType<typeof toolSuccess> }\n | { kind: 'error'; response: ReturnType<typeof toolError> };\n\n/**\n * Resolve a named resource from a list.\n * - If `name` is provided, finds the match (case-insensitive) or returns an error with available options.\n * - If `name` is omitted and there's exactly one item, auto-selects it.\n * - If `name` is omitted and there are multiple items, returns a prompt listing them.\n * - If the list is empty, returns an error.\n */\nexport function resolveResource<T>(options: ResolveOptions<T>): Resolution<T> {\n const { items, name, getName, formatItem, resourceType, toolName } = options;\n\n if (!Array.isArray(items) || items.length === 0) {\n return {\n kind: 'error',\n response: toolError(`No ${resourceType}s found.`),\n };\n }\n\n if (!name) {\n if (items.length === 1) {\n const selected = items[0];\n return { kind: 'resolved', selected, name: getName(selected) || '' };\n }\n const list = items.map(formatItem).join('\\n');\n return {\n kind: 'prompt',\n response: toolSuccess(\n `Found ${items.length} ${resourceType}s. Please specify which one to use:\\n\\n` +\n `${list}\\n\\n` +\n `Call \\`${toolName}\\` again with the \\`${resourceType}Name\\` of your choice.`\n ),\n };\n }\n\n const match = items.find(\n (item) => getName(item)?.toLowerCase() === name.toLowerCase()\n );\n if (!match) {\n const list = items.map(formatItem).join('\\n');\n return {\n kind: 'error',\n response: toolError(\n `${resourceType.charAt(0).toUpperCase() + resourceType.slice(1)} \"${name}\" not found. Available ${resourceType}s:\\n\\n${list}`\n ),\n };\n }\n\n return { kind: 'resolved', selected: match, name: getName(match) || name };\n}\n\nexport function formatDatasource(ds: Record<string, unknown>): string {\n return `- **${ds.name}** (${ds.dbName || ds.datasourceType || 'unknown'}) — ID: ${ds._id || ds.id}`;\n}\n\nexport function formatDatamart(dm: Record<string, unknown>): string {\n const rawTables = (dm.datamartTables || dm.tableList || []) as any[];\n const tables =\n Array.isArray(rawTables) && rawTables.length > 0\n ? rawTables.map((t: any) => t.tableName || t.name).join(', ')\n : 'N/A';\n return `- **${dm.name}** — Tables: ${tables}`;\n}\n\nexport function formatDataApp(app: Record<string, unknown>): string {\n const name = app.name || app.dataAppName || 'unnamed';\n const id = app.dataAppId || app._id || app.id || 'unknown';\n const ws = app.workspaceName || app.workspace || '';\n return `- **${name}** (ID: ${id})${ws ? ` | Workspace: ${ws}` : ''}`;\n}\n\nexport function formatWorkspace(ws: Record<string, unknown>): string {\n return `- **${ws.name}** — ID: ${ws._id || ws.id}`;\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport {\n chartIndex,\n chartResult,\n hasChartApps,\n tagChartTool,\n} from '../../apps/feature.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport {\n DatabrainApiError,\n stringify,\n toolError,\n toolSuccess,\n} from '../../utils/errors.js';\nimport { READ_ONLY } from '../annotations.js';\nimport { workspaceNameSchema } from './schema.js';\n\nexport function registerGetDashboard(\n server: McpServer,\n client: DatabrainClient\n): void {\n const tool = server.tool(\n 'get_dashboard',\n 'Retrieve a workspace dashboard projected back into the versioned tile-list contract.',\n {\n workspaceName: workspaceNameSchema.optional(),\n workspaceId: z\n .string()\n .min(1)\n .optional()\n .describe('Workspace UUID from a dashboard link wid parameter'),\n dashboardId: z\n .string()\n .min(1)\n .describe(\n 'Dashboard UUID or externalDashboardId slug returned by list_dashboards or create_dashboard'\n ),\n },\n READ_ONLY,\n async (params) => {\n try {\n const result = await client.request<Record<string, unknown>>({\n method: 'GET',\n path: '/api/v2/workspace/dashboard',\n auth: 'service',\n query: {\n ...(params.workspaceName\n ? { workspaceName: params.workspaceName }\n : {}),\n ...(params.workspaceId ? { workspaceId: params.workspaceId } : {}),\n dashboardId: params.dashboardId,\n },\n });\n if (hasChartApps(server) && client.isHosted()) {\n const tiles = Array.isArray(result.tiles)\n ? (result.tiles as Array<{\n title?: string;\n chart?: { metricRef?: string; type?: string };\n unavailable?: boolean;\n }>)\n : [];\n const charts = tiles.filter(\n (t) => !t.unavailable && t.chart?.metricRef\n );\n const dashboardId = String(result.dashboardId || params.dashboardId);\n const picker = {\n kind: 'dashboard',\n title: result.title || 'Dashboard',\n rows: [],\n widgets: charts.map((t) => ({\n name: t.title || 'Widget',\n chartType: t.chart!.type || null,\n reference: { dashboardId, widgetId: t.chart!.metricRef! },\n })),\n dashboardId: result.dashboardId,\n };\n try {\n return chartResult(stringify(result), picker);\n } catch (error) {\n if (\n !(error instanceof Error) ||\n error.message !== 'Chart page exceeds payload budget'\n )\n throw error;\n // The tool is advertised as an App even for a large dashboard. Keep its\n // picker structured; a text-only fallback gives the host an empty tile.\n // The model cannot read the App tile. Give it every chart id it can render.\n return chartResult(\n `Dashboard ready. ${picker.widgets.length} saved charts. The tile shows a compact picker because the full dashboard document exceeds the App payload budget. ` +\n chartIndex(\n dashboardId,\n picker.widgets.map((w) => ({\n widgetId: w.reference.widgetId,\n name: w.name,\n chartType: w.chartType,\n }))\n ),\n picker\n );\n }\n }\n return toolSuccess(stringify(result));\n } catch (err) {\n if (err instanceof DatabrainApiError) return err.toToolResponse();\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n tagChartTool(server, tool);\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport {\n DatabrainApiError,\n stringify,\n toolError,\n toolSuccess,\n} from '../../utils/errors.js';\nimport {\n formatDataApp,\n resolveResource,\n} from '../../utils/resolve-resource.js';\nimport { WRITE_CREATE } from '../annotations.js';\n\nexport function registerCreateApiToken(\n server: McpServer,\n client: DatabrainClient\n): void {\n const services = createServiceBundle(client);\n\n server.tool(\n 'create_api_token',\n 'Create an API token for a data app and activate it for this session. Omit dataAppName to auto-resolve.',\n {\n dataAppName: z\n .string()\n .optional()\n .describe('Data app name. Omit to list available data apps.'),\n name: z.string().optional().describe('Optional token name'),\n body: z\n .record(z.string(), z.unknown())\n .optional()\n .describe(\n 'Raw API body passthrough for POST /api/v2/data-app/api-tokens'\n ),\n },\n WRITE_CREATE,\n async (params) => {\n try {\n const dataApps = await services.dataAppsApi.listDataApps();\n\n const resolution = resolveResource({\n items: dataApps,\n name: params.dataAppName,\n getName: (app) => app.name || app.dataAppName,\n formatItem: formatDataApp,\n resourceType: 'dataApp',\n toolName: 'create_api_token',\n });\n\n if (resolution.kind !== 'resolved') return resolution.response;\n\n const dataAppName = resolution.name;\n\n const body = params.body\n ? { ...params.body }\n : {\n dataAppName,\n name: params.name || `${dataAppName}-api-token`,\n };\n\n const result = await client.request<Record<string, unknown>>({\n method: 'POST',\n path: '/api/v2/data-app/api-tokens',\n auth: 'service',\n body,\n });\n\n if (result.error) {\n return toolError(\n `API token creation failed: ${stringify(result.error)}`\n );\n }\n\n const key =\n (result.key as string | undefined) ||\n (result.token as string | undefined) ||\n (result.apiToken as string | undefined);\n\n if (!key) {\n return toolError(\n `Token created, but no token value returned. Response: ${stringify(result)}`\n );\n }\n\n client.setRuntimeApiToken(key);\n // A hosted session ignores the new key and keeps acting as the signed-in user.\n const used = client.hasApiToken()\n ? 'API token created and set for this MCP session.'\n : 'API token created. This session keeps acting as the signed-in user; the token is for your backend.';\n\n return toolSuccess(\n `${used}\\n\\n` +\n `**Token:** \\`${key}\\`\\n\\n` +\n 'Save this in backend secrets immediately. This value may not be returned again.'\n );\n } catch (err) {\n if (err instanceof DatabrainApiError) return err.toToolResponse();\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport {\n DatabrainApiError,\n stringify,\n toolError,\n toolSuccess,\n} from '../../utils/errors.js';\nimport { WRITE_CREATE } from '../annotations.js';\n\nexport function registerCreateDataApp(\n server: McpServer,\n client: DatabrainClient\n): void {\n server.tool(\n 'create_data_app',\n 'Create a new data app.',\n {\n name: z.string().describe('Data app name'),\n workspaceName: z\n .string()\n .optional()\n .describe('Optional workspace name if required by backend'),\n body: z\n .record(z.string(), z.unknown())\n .optional()\n .describe('Raw API body passthrough for POST /api/v2/data-app/'),\n },\n WRITE_CREATE,\n async (params) => {\n try {\n const body = params.body\n ? { ...params.body }\n : {\n name: params.name,\n workspaceName: params.workspaceName,\n };\n\n const result = await client.request<Record<string, unknown>>({\n method: 'POST',\n path: '/api/v2/data-app/',\n body,\n auth: 'service',\n invalidateCache: ['list_data_apps'],\n });\n\n if (result.error) {\n return toolError(\n `Data app creation failed: ${stringify(result.error)}`\n );\n }\n\n return toolSuccess(\n `Data app created successfully.\\n\\n` +\n `- Name: ${params.name}\\n` +\n `- ID: \\`${(result.id as string | undefined) || (result._id as string | undefined) || 'UNKNOWN_ID'}\\``\n );\n } catch (err) {\n if (err instanceof DatabrainApiError) return err.toToolResponse();\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport {\n DatabrainApiError,\n toolError,\n toolSuccess,\n} from '../../utils/errors.js';\nimport {\n formatDataApp,\n resolveResource,\n} from '../../utils/resolve-resource.js';\nimport { READ_ONLY } from '../annotations.js';\n\nexport function registerListApiTokens(\n server: McpServer,\n client: DatabrainClient\n): void {\n const services = createServiceBundle(client);\n\n server.tool(\n 'list_api_tokens',\n 'List API tokens for a data app. Omit dataAppName to auto-resolve.',\n {\n dataAppName: z\n .string()\n .optional()\n .describe('Data app name. Omit to list available data apps.'),\n },\n READ_ONLY,\n async (params) => {\n try {\n const dataApps = await services.dataAppsApi.listDataApps();\n\n const resolution = resolveResource({\n items: dataApps,\n name: params.dataAppName,\n getName: (app) => app.name || app.dataAppName,\n formatItem: formatDataApp,\n resourceType: 'dataApp',\n toolName: 'list_api_tokens',\n });\n\n if (resolution.kind !== 'resolved') return resolution.response;\n\n const dataAppName = resolution.name;\n\n const result = await client.request<unknown[]>({\n method: 'GET',\n path: '/api/v2/data-app/api-tokens',\n auth: 'service',\n query: { dataAppName },\n });\n\n if (!Array.isArray(result) || result.length === 0) {\n return toolSuccess(\n `No API tokens found for data app \"${dataAppName}\".`\n );\n }\n\n return toolSuccess(\n JSON.stringify({\n count: result.length,\n dataAppName,\n tokens: result.map((t: any, i) => ({\n name: t.name || t.tokenName || `token-${i + 1}`,\n id: t.id || t._id || null,\n createdAt: t.createdAt || null,\n })),\n })\n );\n } catch (err) {\n if (err instanceof DatabrainApiError) return err.toToolResponse();\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport {\n DatabrainApiError,\n toolError,\n toolSuccess,\n} from '../../utils/errors.js';\nimport { READ_ONLY } from '../annotations.js';\n\nexport function registerListDataApps(\n server: McpServer,\n client: DatabrainClient\n): void {\n const services = createServiceBundle(client);\n server.tool(\n 'list_data_apps',\n 'List data apps in your organization. Start here for embed setup.',\n {\n workspaceName: z.string().optional().describe('Filter by workspace name'),\n },\n READ_ONLY,\n async (params) => {\n try {\n const result = await services.dataAppsApi.listDataApps(\n params.workspaceName\n );\n\n if (!Array.isArray(result) || result.length === 0) {\n return toolSuccess('No data apps found for this account/workspace.');\n }\n\n return toolSuccess(\n JSON.stringify({\n count: result.length,\n dataApps: result.map((app: any) => {\n const { name, dataAppId, workspaceName } =\n services.discoveryService.normalizeDataApp(app);\n return {\n name,\n id: dataAppId || null,\n workspace: workspaceName || null,\n };\n }),\n })\n );\n } catch (err) {\n if (err instanceof DatabrainApiError) return err.toToolResponse();\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type { TenantListResult, TenantRecord } from '../../api/tenants-api.js';\nimport type { WorkspaceRecord } from '../../api/workspaces-api.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport {\n DatabrainApiError,\n toolError,\n toolSuccess,\n} from '../../utils/errors.js';\nimport { READ_ONLY } from '../annotations.js';\n\nconst isNonEmptyString = (value: unknown): value is string =>\n typeof value === 'string' && value.trim().length > 0;\n\nfunction workspaceIdFrom(workspace: WorkspaceRecord): string | null {\n return (\n (isNonEmptyString(workspace.id) && workspace.id) ||\n (isNonEmptyString(workspace._id) && workspace._id) ||\n (isNonEmptyString(workspace.workspaceId) && workspace.workspaceId) ||\n null\n );\n}\n\nfunction tenantErrorMessage(result: Record<string, unknown>): string | null {\n const message = result.message;\n if (isNonEmptyString(message)) return message;\n\n const error = result.error;\n if (isNonEmptyString(error)) return error;\n if (error !== null && error !== undefined) {\n try {\n return JSON.stringify(error);\n } catch {\n return String(error);\n }\n }\n\n return null;\n}\n\nfunction normalizeTenantList(result: TenantListResult): {\n tenants: TenantRecord[];\n clientColumnType?: string;\n errorMessage?: string;\n} {\n if (Array.isArray(result)) {\n return { tenants: result };\n }\n\n const errorMessage = tenantErrorMessage(result);\n if (errorMessage) {\n return { tenants: [], errorMessage };\n }\n\n return {\n tenants: Array.isArray(result.data) ? result.data : [],\n clientColumnType: isNonEmptyString(result.clientColumnType)\n ? result.clientColumnType\n : undefined,\n };\n}\n\nexport function registerListTenants(\n server: McpServer,\n client: DatabrainClient\n): void {\n const services = createServiceBundle(client);\n\n server.tool(\n 'list_tenants',\n 'List available tenants/clients from the workspace tenancy database. Use this to pick a valid clientId before creating guest tokens or editing customer dashboards.',\n {\n workspaceName: z\n .string()\n .optional()\n .describe(\n 'Workspace name. Preferred for non-technical callers; the tool resolves it to a workspaceId.'\n ),\n workspaceId: z\n .string()\n .optional()\n .describe(\n 'Technical workspace UUID. Provide this instead of workspaceName if already known.'\n ),\n searchValue: z\n .string()\n .optional()\n .describe(\n 'Optional case-insensitive search string for tenant/client labels.'\n ),\n limit: z\n .number()\n .int()\n .positive()\n .max(500)\n .optional()\n .describe(\n 'Maximum number of tenants to return. Backend may apply connector-specific limits.'\n ),\n datasourceId: z\n .string()\n .optional()\n .describe(\n 'Optional datasource UUID override when the workspace has multiple datasource contexts.'\n ),\n datamartId: z\n .string()\n .optional()\n .describe(\n 'Optional datamart UUID override when tenant lookup should use a specific datamart.'\n ),\n },\n READ_ONLY,\n async (params) => {\n try {\n let workspaceId = params.workspaceId?.trim() || '';\n let workspaceName = params.workspaceName?.trim() || '';\n\n if (!workspaceId && !workspaceName) {\n return toolError(\n 'Provide `workspaceName` or `workspaceId` so the tenancy lookup can resolve the client table.'\n );\n }\n\n if (!workspaceId) {\n const workspaces = await services.workspacesApi.listWorkspaces();\n const matches = workspaces.filter(\n (workspace) =>\n isNonEmptyString(workspace.name) &&\n workspace.name.trim().toLowerCase() ===\n workspaceName.toLowerCase()\n );\n\n if (matches.length === 0) {\n const available = workspaces\n .map((workspace) => workspace.name)\n .filter(isNonEmptyString)\n .map((name) => `\"${name}\"`)\n .join(', ');\n return toolError(\n `No workspace named \"${workspaceName}\". ` +\n (available\n ? `Available workspaces: ${available}.`\n : 'No workspaces were returned by list_workspaces.')\n );\n }\n\n if (matches.length > 1) {\n return toolError(\n `Workspace name \"${workspaceName}\" is ambiguous. Retry with \\`workspaceId\\`.`\n );\n }\n\n workspaceId = workspaceIdFrom(matches[0]) || '';\n if (!workspaceId) {\n return toolError(\n `Workspace \"${workspaceName}\" did not include an id in the backend response. Retry with \\`workspaceId\\`.`\n );\n }\n workspaceName = matches[0].name || workspaceName;\n }\n\n if (!workspaceName) {\n try {\n const workspaces = await services.workspacesApi.listWorkspaces();\n const match = workspaces.find(\n (workspace) => workspaceIdFrom(workspace) === workspaceId\n );\n if (match?.name) workspaceName = match.name;\n } catch {\n // Non-fatal; workspaceId is enough for the tenancy lookup.\n }\n }\n\n const result = await services.tenantsApi.listTenants({\n workspaceId,\n limit: params.limit,\n searchValue: params.searchValue,\n datasourceId: params.datasourceId,\n datamartId: params.datamartId,\n });\n\n const { tenants, clientColumnType, errorMessage } =\n normalizeTenantList(result);\n if (errorMessage) {\n return toolError(`Failed to list tenants: ${errorMessage}`);\n }\n\n if (tenants.length === 0) {\n return toolSuccess(\n `No tenants found for workspace \"${workspaceName || workspaceId}\".`\n );\n }\n\n return toolSuccess(\n JSON.stringify(\n {\n count: tenants.length,\n source: 'tenancy_database',\n workspace: {\n id: workspaceId,\n name: workspaceName || null,\n },\n clientColumnType: clientColumnType || 'STRING',\n tenants: tenants.map((tenant) => {\n const clientId = isNonEmptyString(tenant.value)\n ? tenant.value\n : null;\n const label = isNonEmptyString(tenant.label)\n ? tenant.label\n : clientId;\n return {\n clientId,\n label,\n };\n }),\n },\n null,\n 2\n )\n );\n } catch (err) {\n if (err instanceof DatabrainApiError) return err.toToolResponse();\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n}\n","import { randomUUID } from 'node:crypto';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport {\n DatabrainApiError,\n stringify,\n toolError,\n toolSuccess,\n} from '../../utils/errors.js';\nimport {\n formatDataApp,\n resolveResource,\n} from '../../utils/resolve-resource.js';\nimport { DESTRUCTIVE } from '../annotations.js';\n\nexport function registerRotateApiToken(\n server: McpServer,\n client: DatabrainClient\n): void {\n const services = createServiceBundle(client);\n\n server.tool(\n 'rotate_api_token',\n 'Rotate through the raw token-authenticated endpoint, or issue a replacement token for a data app. The replacement fallback does not revoke existing tokens.',\n {\n dataAppName: z\n .string()\n .optional()\n .describe('Data app name. Omit to list available data apps.'),\n tokenId: z.string().optional().describe('Optional token ID to rotate'),\n body: z\n .record(z.string(), z.unknown())\n .optional()\n .describe('Raw API body passthrough for rotate endpoint'),\n },\n DESTRUCTIVE,\n async (params) => {\n try {\n const dataApps = await services.dataAppsApi.listDataApps();\n\n const resolution = resolveResource({\n items: dataApps,\n name: params.dataAppName,\n getName: (app) => app.name || app.dataAppName,\n formatItem: formatDataApp,\n resourceType: 'dataApp',\n toolName: 'rotate_api_token',\n });\n\n if (resolution.kind !== 'resolved') return resolution.response;\n\n const dataAppName = resolution.name;\n\n if (params.body) {\n const rotateRes = await client.request<Record<string, unknown>>({\n method: 'POST',\n path: '/api/v2/data-app/api-tokens/rotate',\n auth: 'service',\n body: params.body,\n });\n if (rotateRes.error) {\n return toolError(\n `Token rotation failed: ${stringify(rotateRes.error)}`\n );\n }\n const key =\n (rotateRes.key as string | undefined) ||\n (rotateRes.token as string | undefined) ||\n (rotateRes.apiToken as string | undefined);\n if (key) client.setRuntimeApiToken(key);\n return toolSuccess(\n `API token rotated successfully.\\n\\n` +\n (key ? `**New Token:** \\`${key}\\`\\n\\n` : '') +\n 'Update backend secrets immediately.'\n );\n }\n\n if (params.tokenId)\n return toolError(\n 'Rotating a named token requires the token-authenticated raw body endpoint. No replacement was issued. Use the API token settings to retire a specific token.'\n );\n\n const createRes = await client.request<Record<string, unknown>>({\n method: 'POST',\n path: '/api/v2/data-app/api-tokens',\n auth: 'service',\n body: {\n dataAppName,\n name: `${dataAppName}-rotated-${randomUUID()}`,\n },\n });\n if (createRes.error) {\n return toolError(\n `Token rotation fallback failed: ${stringify(createRes.error)}`\n );\n }\n const key =\n (createRes.key as string | undefined) ||\n (createRes.token as string | undefined) ||\n (createRes.apiToken as string | undefined);\n if (key) client.setRuntimeApiToken(key);\n\n return toolSuccess(\n `Issued a new API token for \"${dataAppName}\" (rotation fallback).\\n\\n` +\n (key ? `**New Token:** \\`${key}\\`\\n\\n` : '') +\n 'Existing tokens remain active. Update backend secrets, then retire the old token in API token settings.'\n );\n } catch (err) {\n if (err instanceof DatabrainApiError) return err.toToolResponse();\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport {\n DatabrainApiError,\n stringify,\n toolError,\n toolSuccess,\n} from '../../utils/errors.js';\nimport {\n formatWorkspace,\n resolveResource,\n} from '../../utils/resolve-resource.js';\nimport { WRITE_CREATE } from '../annotations.js';\n\nconst DEFAULT_ACCESS_SETTINGS: Record<string, unknown> = {\n isAllowMetricCreation: false,\n isAllowMetricDeletion: false,\n isAllowMetricUpdate: false,\n isAllowMetricLayoutChange: false,\n isAllowManageMetrics: false,\n isAllowUnderlyingData: false,\n isAllowAiPilot: false,\n isAllowEmailReports: false,\n isAllowCreateDashboardView: false,\n metricCreationMode: 'DRAG_DROP',\n};\n\nconst accessSettingsSchema = z\n .object({\n datamartName: z.string().describe('Name of the datamart (required)'),\n isAllowMetricCreation: z\n .boolean()\n .optional()\n .describe('Allow end-users to create metrics'),\n metricCreationMode: z\n .enum(['DRAG_DROP', 'CHAT'])\n .optional()\n .describe('Metric creation mode'),\n isAllowMetricDeletion: z\n .boolean()\n .optional()\n .describe('Allow metric deletion'),\n isAllowMetricUpdate: z\n .boolean()\n .optional()\n .describe('Allow metric editing'),\n isAllowMetricLayoutChange: z\n .boolean()\n .optional()\n .describe('Allow layout changes'),\n isAllowManageMetrics: z\n .boolean()\n .optional()\n .describe('Show manage metrics UI'),\n isAllowUnderlyingData: z\n .boolean()\n .optional()\n .describe('Allow viewing underlying data'),\n isAllowAiPilot: z.boolean().optional().describe('Enable AI pilot features'),\n isAllowEmailReports: z\n .boolean()\n .optional()\n .describe('Allow email report scheduling'),\n isAllowCreateDashboardView: z\n .boolean()\n .optional()\n .describe('Allow creating dashboard views'),\n })\n .describe(\n 'Embed access settings. Only datamartName is required — all flags default to false.'\n );\n\n// ---------------------------------------------------------------------------\n// Consolidated tool: create_embed\n// Replaces: create_embed + create_dashboard_embed\n// When clientId is provided → multi-tenant dashboard embed (POST /dashboard-embeds)\n// Otherwise → standard embed (POST /embeds)\n// ---------------------------------------------------------------------------\nexport function registerCreateEmbed(\n server: McpServer,\n client: DatabrainClient\n): void {\n const services = createServiceBundle(client);\n server.tool(\n 'create_embed',\n 'Create an embed. Provide dashboardId, workspaceName, accessSettings.datamartName. Add clientId for multi-tenant per-client dashboards. All isAllow* flags default to false.',\n {\n body: z\n .record(z.string(), z.unknown())\n .optional()\n .describe(\n 'Raw API body passthrough. If provided, all other fields are ignored.'\n ),\n dataAppName: z\n .string()\n .optional()\n .describe(\n 'Data app name; required when the workspace has more than one'\n ),\n dashboardId: z\n .string()\n .optional()\n .describe(\n 'Existing dashboard UUID or externalDashboardId slug for a standard embed; a new unique slug for a client dashboard copy'\n ),\n workspaceName: z\n .string()\n .optional()\n .describe('Workspace name. Omit to auto-resolve if only one exists.'),\n embedType: z\n .enum(['dashboard', 'metric'])\n .optional()\n .describe('Embed type'),\n metricId: z\n .string()\n .optional()\n .describe('Required for metric embed type'),\n name: z.string().optional().describe('Human-readable embed config name'),\n accessSettings: accessSettingsSchema.optional(),\n\n // Multi-tenant (dashboard embed) params\n clientId: z\n .string()\n .optional()\n .describe(\n 'Client identifier for multi-tenant isolation. When provided, creates a dashboard embed (each client gets their own dashboard copy).'\n ),\n templateDashboardId: z\n .string()\n .optional()\n .describe(\n 'Template dashboard UUID or externalDashboardId slug to clone metrics from'\n ),\n isImportMetrics: z\n .boolean()\n .optional()\n .describe('Import metrics from template dashboard'),\n metricImportMode: z\n .enum(['GALLERY', 'METRIC'])\n .optional()\n .describe(\n 'GALLERY imports dashboard gallery metrics; METRIC imports selected metrics'\n ),\n isRenameDashboard: z\n .boolean()\n .optional()\n .describe('Rename the dashboard for this client'),\n },\n WRITE_CREATE,\n async (params) => {\n try {\n const isMultiTenant = !!params.clientId;\n // These public embed handlers take business slugs. Resolve a listed UUID through\n // the authorized dashboard listing; never send an unverified UUID as a slug.\n const dashboardSlug = async (\n value: unknown,\n workspace: unknown\n ): Promise<unknown> => {\n if (\n typeof value !== 'string' ||\n !z.string().uuid().safeParse(value).success\n )\n return value;\n if (typeof workspace !== 'string' || !workspace)\n throw new Error(\n 'workspaceName is required to resolve a dashboard UUID.'\n );\n const boards =\n await services.dashboardsApi.listDashboardsForWorkspace(workspace);\n const board = boards.find(\n (item) => item.id === value || item.dashboardId === value\n );\n if (!board?.externalDashboardId)\n throw new Error(\n 'Dashboard not found in this workspace. Use list_dashboards to choose one.'\n );\n return board.externalDashboardId;\n };\n\n // --- Workspace resolution for multi-tenant embeds ---\n let resolvedWorkspaceName = params.workspaceName;\n if (!params.body && isMultiTenant && !resolvedWorkspaceName) {\n const workspaces = await services.workspacesApi.listWorkspaces();\n const resolution = resolveResource({\n items: workspaces,\n name: undefined,\n getName: (ws) => ws.name,\n formatItem: formatWorkspace,\n resourceType: 'workspace',\n toolName: 'create_embed',\n });\n if (resolution.kind !== 'resolved') return resolution.response;\n resolvedWorkspaceName = resolution.name;\n }\n\n if (isMultiTenant) {\n // --- Multi-tenant dashboard embed ---\n const body: Record<string, unknown> = params.body\n ? { ...params.body }\n : {\n dashboardId: params.dashboardId,\n dataAppName: params.dataAppName,\n workspaceName: resolvedWorkspaceName,\n clientId: params.clientId,\n name: params.name,\n templateDashboardId: params.templateDashboardId,\n isImportMetrics: params.isImportMetrics,\n metricImportMode: params.metricImportMode,\n isRenameDashboard: params.isRenameDashboard,\n accessSettings: params.accessSettings,\n };\n\n const callerAccess =\n body.accessSettings && typeof body.accessSettings === 'object'\n ? (body.accessSettings as Record<string, unknown>)\n : {};\n body.accessSettings = { ...DEFAULT_ACCESS_SETTINGS, ...callerAccess };\n\n if (body.templateDashboardId)\n body.templateDashboardId = await dashboardSlug(\n body.templateDashboardId,\n body.workspaceName\n );\n const { dataAppName, ...payload } = body;\n const result = await client.request<Record<string, unknown>>({\n method: 'POST',\n path: '/api/v2/data-app/dashboard-embeds',\n query:\n typeof dataAppName === 'string' ? { dataAppName } : undefined,\n body: payload,\n auth: 'api',\n invalidateCache: ['list_embeds'],\n });\n\n if (result.error) {\n return toolError(\n `Dashboard embed creation failed: ${stringify(result.error)}`\n );\n }\n\n const embedId =\n (result.embedId as string) ||\n (result.id as string) ||\n (result._id as string) ||\n 'UNKNOWN_ID';\n\n return toolSuccess(\n `Dashboard embed created successfully.\\n\\n` +\n `- Embed ID: \\`${embedId}\\`\\n` +\n `- Client ID: \\`${params.clientId}\\`\\n` +\n `- Dashboard: \\`${params.dashboardId}\\`\\n` +\n `- Workspace: \\`${resolvedWorkspaceName || params.workspaceName}\\`\\n\\n` +\n 'Next: use `generate_guest_token` with the clientId and `generate_embed_code` for frontend integration.'\n );\n }\n\n // --- Standard embed ---\n const body: Record<string, unknown> = params.body\n ? { ...params.body }\n : {\n dashboardId: params.dashboardId,\n dataAppName: params.dataAppName,\n workspaceName: params.workspaceName,\n embedType: params.embedType || 'dashboard',\n metricId: params.metricId,\n name: params.name,\n accessSettings: params.accessSettings,\n };\n\n if (!body.dashboardId || typeof body.dashboardId !== 'string') {\n return toolError(\n 'create_embed requires `dashboardId` (or provide full raw `body`).'\n );\n }\n if (!body.workspaceName || typeof body.workspaceName !== 'string') {\n return toolError(\n 'create_embed requires `workspaceName` (or provide full raw `body`).'\n );\n }\n const accessSettings = body.accessSettings as\n | Record<string, unknown>\n | undefined;\n if (!accessSettings || typeof accessSettings !== 'object') {\n return toolError(\n 'create_embed requires `accessSettings` and must include `datamartName`.'\n );\n }\n const datamartName = accessSettings.datamartName;\n if (!datamartName || typeof datamartName !== 'string') {\n return toolError(\n 'create_embed requires `accessSettings.datamartName`.'\n );\n }\n\n body.dashboardId = await dashboardSlug(\n body.dashboardId,\n body.workspaceName\n );\n const result = await services.embedService.createEmbedStrict(body);\n if (result.error) {\n return toolError(`Embed creation failed: ${stringify(result.error)}`);\n }\n\n const embedId =\n (result.embedId as string) || (result.id as string) || 'UNKNOWN_ID';\n\n return toolSuccess(\n `Embed created successfully.\\n\\n` +\n `- Embed ID: \\`${embedId}\\`\\n` +\n `- dashboardId: \\`${body.dashboardId as string}\\`\\n` +\n `- workspaceName: \\`${body.workspaceName as string}\\`\\n` +\n `- accessSettings.datamartName: \\`${datamartName}\\`\\n\\n` +\n 'Next: run `get_embed_details` to verify the embed configuration.'\n );\n } catch (err) {\n if (err instanceof DatabrainApiError) return err.toToolResponse();\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport {\n DatabrainApiError,\n stringify,\n toolError,\n toolSuccess,\n} from '../../utils/errors.js';\nimport { WRITE_IDEMPOTENT } from '../annotations.js';\nimport {\n GUEST_TOKEN_REMINDER,\n maybeBuildCorruptedEmbedGuardrail,\n} from './helpers.js';\n\n// ---------------------------------------------------------------------------\n// Theme & access presets (merged from apply-theme-preset)\n// ---------------------------------------------------------------------------\nconst THEME_PRESETS: Record<string, Record<string, unknown>> = {\n light: {\n general: {\n fontFamily: 'Inter, sans-serif',\n backgroundColor: '#ffffff',\n primaryColor: '#4F46E5',\n secondaryColor: '#10B981',\n textColor: '#1F2937',\n borderColor: '#E5E7EB',\n borderRadius: '8px',\n },\n dashboard: { backgroundColor: '#F9FAFB', padding: '24px', gap: '16px' },\n chart: {\n colorPalette: [\n '#4F46E5',\n '#10B981',\n '#F59E0B',\n '#EF4444',\n '#8B5CF6',\n '#06B6D4',\n ],\n axisColor: '#9CA3AF',\n gridColor: '#F3F4F6',\n },\n cardCustomization: {\n backgroundColor: '#FFFFFF',\n borderColor: '#E5E7EB',\n borderRadius: '12px',\n shadow: '0 1px 3px rgba(0,0,0,0.1)',\n },\n },\n dark: {\n general: {\n fontFamily: 'Inter, sans-serif',\n backgroundColor: '#111827',\n primaryColor: '#818CF8',\n secondaryColor: '#34D399',\n textColor: '#F9FAFB',\n borderColor: '#374151',\n borderRadius: '8px',\n },\n dashboard: { backgroundColor: '#0F172A', padding: '24px', gap: '16px' },\n chart: {\n colorPalette: [\n '#818CF8',\n '#34D399',\n '#FBBF24',\n '#F87171',\n '#A78BFA',\n '#22D3EE',\n ],\n axisColor: '#6B7280',\n gridColor: '#1F2937',\n tooltipBackground: '#F9FAFB',\n tooltipTextColor: '#111827',\n },\n cardTitle: { color: '#F9FAFB' },\n cardDescription: { color: '#9CA3AF' },\n cardCustomization: {\n backgroundColor: '#1F2937',\n borderColor: '#374151',\n borderRadius: '12px',\n shadow: '0 1px 3px rgba(0,0,0,0.3)',\n },\n },\n corporate: {\n general: {\n fontFamily: '\"IBM Plex Sans\", sans-serif',\n backgroundColor: '#FAFAFA',\n primaryColor: '#1E40AF',\n secondaryColor: '#059669',\n textColor: '#1E293B',\n borderColor: '#CBD5E1',\n borderRadius: '4px',\n },\n dashboard: { backgroundColor: '#F1F5F9', padding: '20px', gap: '12px' },\n chart: {\n colorPalette: [\n '#1E40AF',\n '#059669',\n '#D97706',\n '#DC2626',\n '#7C3AED',\n '#0891B2',\n ],\n axisColor: '#94A3B8',\n gridColor: '#E2E8F0',\n },\n cardCustomization: {\n backgroundColor: '#FFFFFF',\n borderColor: '#CBD5E1',\n borderRadius: '4px',\n shadow: 'none',\n },\n },\n minimal: {\n general: {\n fontFamily: 'system-ui, sans-serif',\n backgroundColor: '#FFFFFF',\n primaryColor: '#171717',\n secondaryColor: '#525252',\n textColor: '#171717',\n borderColor: '#E5E5E5',\n borderRadius: '0px',\n },\n dashboard: { backgroundColor: '#FFFFFF', padding: '16px', gap: '8px' },\n chart: {\n colorPalette: ['#171717', '#525252', '#737373', '#A3A3A3', '#D4D4D4'],\n axisColor: '#D4D4D4',\n gridColor: '#F5F5F5',\n },\n cardCustomization: {\n backgroundColor: '#FFFFFF',\n borderColor: '#E5E5E5',\n borderRadius: '0px',\n shadow: 'none',\n },\n },\n};\n\nconst ACCESS_PRESETS: Record<string, Record<string, unknown>> = {\n 'view-only': {\n isAllowMetricCreation: false,\n isAllowMetricDeletion: false,\n isAllowMetricUpdate: false,\n isAllowMetricLayoutChange: false,\n isAllowManageMetrics: false,\n isAllowAiPilot: false,\n isAllowEmailReports: false,\n },\n 'power-user': {\n isAllowMetricCreation: true,\n isAllowMetricDeletion: true,\n isAllowMetricUpdate: true,\n isAllowMetricLayoutChange: true,\n isAllowManageMetrics: true,\n isAllowUnderlyingData: true,\n isAllowAiPilot: true,\n isAllowEmailReports: true,\n isAllowCreateDashboardView: true,\n metricCreationMode: 'CHAT',\n },\n 'export-only': {\n isAllowMetricCreation: false,\n isAllowMetricUpdate: false,\n isAllowUnderlyingData: true,\n isAllowEmailReports: true,\n },\n 'ai-enabled': {\n isAllowMetricCreation: true,\n isAllowAiPilot: true,\n isAllowManageMetrics: true,\n metricCreationMode: 'CHAT',\n },\n};\n\n// ---------------------------------------------------------------------------\n// Zod helpers\n// ---------------------------------------------------------------------------\nconst fontFamilyEnum = z\n .enum([\n 'Inter',\n 'Roboto',\n 'Open Sans',\n 'Lato',\n 'Poppins',\n 'Montserrat',\n 'IBM Plex Sans',\n 'Source Sans Pro',\n 'Nunito',\n 'system-ui',\n ])\n .describe('Font family');\n\nconst tooltipFontSchema = z\n .object({\n fontFamily: z.string().optional(),\n fontSize: z.number().optional(),\n fontWeight: z.number().optional(),\n fontColor: z.string().optional(),\n })\n .optional();\n\nconst fontConfigInputSchema = z\n .object({\n fontSize: z.number().optional(),\n fontFamily: z.string().optional(),\n fontWeight: z.number().optional(),\n color: z.string().optional(),\n })\n .optional();\n\nfunction mapToFrontendFontConfig(\n input:\n | {\n fontSize?: number;\n fontFamily?: string;\n fontWeight?: number;\n color?: string;\n }\n | undefined\n): Record<string, unknown> | undefined {\n if (!input) return undefined;\n return {\n ...(input.fontSize !== undefined && { size: input.fontSize }),\n ...(input.fontFamily && { family: input.fontFamily }),\n ...(input.fontWeight !== undefined && { weight: input.fontWeight }),\n ...(input.color && { color: input.color }),\n };\n}\n\nconst axisSchema = z\n .object({\n hideAxisLines: z.boolean().optional().describe('Hide axis lines'),\n hideSplitLines: z.boolean().optional().describe('Hide grid/split lines'),\n hideAxisLabels: z.boolean().optional().describe('Hide axis labels'),\n hideAxisTicks: z.boolean().optional().describe('Hide axis tick marks'),\n axisName: z.string().optional().describe('Axis title text'),\n axisNameOffset: z\n .number()\n .optional()\n .describe('Axis title offset from axis'),\n axisLabelMargin: z\n .number()\n .optional()\n .describe('Margin between axis labels and chart area in pixels'),\n fontSize: z.number().optional().describe('Axis label font size'),\n fontFamily: z.string().optional().describe('Axis label font family'),\n fontWeight: z.number().optional().describe('Axis label font weight'),\n color: z.string().optional().describe('Axis label color (hex)'),\n axisColor: z.string().optional().describe('Axis line color (hex)'),\n axisNameFontConfig: z\n .object({\n fontFamily: z.string().optional(),\n fontSize: z.number().optional(),\n fontWeight: z.number().optional(),\n })\n .optional()\n .describe('Axis title font configuration'),\n })\n .optional();\n\n// ---------------------------------------------------------------------------\n// Patch builders\n// ---------------------------------------------------------------------------\nfunction buildAdminTheme(\n p: Record<string, unknown>,\n presetBase?: Record<string, unknown>\n): Record<string, unknown> {\n const adminTheme: Record<string, unknown> = presetBase\n ? { ...presetBase }\n : {};\n\n const general: Record<string, unknown> = {\n ...((adminTheme.general as Record<string, unknown>) ?? {}),\n };\n if (p.fontFamily) general.fontFamily = p.fontFamily;\n if (p.datePickerFormat) general.datePickerFormat = p.datePickerFormat;\n if (p.primaryColor) general.primaryColor = p.primaryColor;\n if (p.backgroundColor) general.backgroundColor = p.backgroundColor;\n if (p.textColor) general.textColor = p.textColor;\n if (Object.keys(general).length) adminTheme.general = general;\n\n const dashboard: Record<string, unknown> = {\n ...((adminTheme.dashboard as Record<string, unknown>) ?? {}),\n };\n if (p.dashboardBackgroundColor)\n dashboard.backgroundColor = p.dashboardBackgroundColor;\n if (p.ctaColor) dashboard.ctaColor = p.ctaColor;\n if (p.ctaTextColor) dashboard.ctaTextColor = p.ctaTextColor;\n if (p.selectBoxSize) dashboard.selectBoxSize = p.selectBoxSize;\n if (p.selectBoxVariant) dashboard.selectBoxVariant = p.selectBoxVariant;\n if (p.selectBoxBorderRadius)\n dashboard.selectBoxBorderRadius = p.selectBoxBorderRadius;\n if (p.selectBoxTextColor) dashboard.selectBoxTextColor = p.selectBoxTextColor;\n if (p.metricCardColor) dashboard.metricCardColor = p.metricCardColor;\n if (Object.keys(dashboard).length) adminTheme.dashboard = dashboard;\n\n const cardTitle: Record<string, unknown> = {\n ...((adminTheme.cardTitle as Record<string, unknown>) ?? {}),\n };\n if (p.cardTitleFontSize) cardTitle.fontSize = p.cardTitleFontSize;\n if (p.cardTitleFontWeight) cardTitle.fontWeight = p.cardTitleFontWeight;\n if (p.cardTitleColor) cardTitle.color = p.cardTitleColor;\n if (Object.keys(cardTitle).length) adminTheme.cardTitle = cardTitle;\n\n const cardDescription: Record<string, unknown> = {\n ...((adminTheme.cardDescription as Record<string, unknown>) ?? {}),\n };\n if (p.cardDescriptionFontSize)\n cardDescription.fontSize = p.cardDescriptionFontSize;\n if (p.cardDescriptionFontWeight)\n cardDescription.fontWeight = p.cardDescriptionFontWeight;\n if (p.cardDescriptionColor) cardDescription.color = p.cardDescriptionColor;\n if (Object.keys(cardDescription).length)\n adminTheme.cardDescription = cardDescription;\n\n const cardCustomization: Record<string, unknown> = {\n ...((adminTheme.cardCustomization as Record<string, unknown>) ?? {}),\n };\n if (p.cardPadding) cardCustomization.padding = p.cardPadding;\n if (p.cardBorderRadius) cardCustomization.borderRadius = p.cardBorderRadius;\n if (p.cardShadow) cardCustomization.shadow = p.cardShadow;\n if (p.disableShadowOnHover !== undefined)\n cardCustomization.disableShadowOnHover = p.disableShadowOnHover;\n if (p.disableCardStroke !== undefined)\n cardCustomization.disableStroke = p.disableCardStroke;\n if (p.cardStrokeColor)\n cardCustomization.metricStrokeColor = p.cardStrokeColor;\n if (Object.keys(cardCustomization).length)\n adminTheme.cardCustomization = cardCustomization;\n\n const chart: Record<string, unknown> = {\n ...((adminTheme.chart as Record<string, unknown>) ?? {}),\n };\n if (p.chartFontFamily) chart.chartFontFamily = p.chartFontFamily;\n if (p.chartFontColor) chart.chartFontColor = p.chartFontColor;\n if (p.chartColors) chart.paletteOptions = p.chartColors;\n if (p.chartPaletteName && p.chartPaletteColors) {\n chart.palettes = [\n { name: p.chartPaletteName, colors: p.chartPaletteColors },\n ];\n chart.selected = p.chartPaletteName;\n }\n const tooltip: Record<string, unknown> = {};\n if (p.tooltipHeader) tooltip.header = p.tooltipHeader;\n if (p.tooltipLabel) tooltip.label = p.tooltipLabel;\n if (p.tooltipValue) tooltip.value = p.tooltipValue;\n if (Object.keys(tooltip).length) chart.tooltip = tooltip;\n if (Object.keys(chart).length) adminTheme.chart = chart;\n\n return adminTheme;\n}\n\nfunction buildComponentTheme(\n p: Record<string, unknown>\n): Record<string, unknown> {\n const componentTheme: Record<string, unknown> = {};\n\n if (\n p.buttonPrimaryColor ||\n p.buttonPrimaryTextColor ||\n p.buttonSecondaryColor ||\n p.buttonSecondaryTextColor\n ) {\n const button: Record<string, unknown> = {};\n if (p.buttonPrimaryColor) button.primary = p.buttonPrimaryColor;\n if (p.buttonPrimaryTextColor) button.primaryText = p.buttonPrimaryTextColor;\n if (p.buttonSecondaryColor) button.secondary = p.buttonSecondaryColor;\n if (p.buttonSecondaryTextColor)\n button.secondaryText = p.buttonSecondaryTextColor;\n componentTheme.button = button;\n }\n if (p.checkboxCheckedColor || p.checkboxUncheckedColor) {\n const checkbox: Record<string, unknown> = {};\n if (p.checkboxCheckedColor) checkbox.checked = p.checkboxCheckedColor;\n if (p.checkboxUncheckedColor) checkbox.unChecked = p.checkboxUncheckedColor;\n componentTheme.checkbox = checkbox;\n }\n if (p.switchEnabledColor || p.switchDisabledColor) {\n const switchTheme: Record<string, unknown> = {};\n if (p.switchEnabledColor) switchTheme.enabled = p.switchEnabledColor;\n if (p.switchDisabledColor) switchTheme.disabled = p.switchDisabledColor;\n componentTheme.switch = switchTheme;\n }\n if (\n p.breadcrumbFontFamily ||\n p.breadcrumbFontColor ||\n p.breadcrumbActiveColor\n ) {\n const drillBreadCrumbs: Record<string, unknown> = {};\n if (p.breadcrumbFontFamily)\n drillBreadCrumbs.fontFamily = p.breadcrumbFontFamily;\n if (p.breadcrumbFontColor)\n drillBreadCrumbs.fontColor = p.breadcrumbFontColor;\n if (p.breadcrumbActiveColor)\n drillBreadCrumbs.activeColor = p.breadcrumbActiveColor;\n componentTheme.drillBreadCrumbs = drillBreadCrumbs;\n }\n if (p.filterBadgeColor || p.filterBadgeTextColor) {\n const multiSelectFilterDropdown: Record<string, unknown> = {};\n if (p.filterBadgeColor)\n multiSelectFilterDropdown.badgeColor = p.filterBadgeColor;\n if (p.filterBadgeTextColor)\n multiSelectFilterDropdown.badgeTextColor = p.filterBadgeTextColor;\n componentTheme.multiSelectFilterDropdown = multiSelectFilterDropdown;\n }\n if (p.datePickerColor) componentTheme.datePickerColor = p.datePickerColor;\n\n const breakpoint: Record<string, unknown> = {};\n if (p.breakpointXl !== undefined) breakpoint.xl = p.breakpointXl;\n if (p.breakpointLg !== undefined) breakpoint.lg = p.breakpointLg;\n if (p.breakpointMd !== undefined) breakpoint.md = p.breakpointMd;\n if (p.breakpointSm !== undefined) breakpoint.sm = p.breakpointSm;\n if (p.breakpointXs !== undefined) breakpoint.xs = p.breakpointXs;\n if (Object.keys(breakpoint).length) componentTheme.breakpoint = breakpoint;\n\n const metricLayoutCols: Record<string, unknown> = {};\n if (p.layoutColsXl !== undefined) metricLayoutCols.xl = p.layoutColsXl;\n if (p.layoutColsLg !== undefined) metricLayoutCols.lg = p.layoutColsLg;\n if (p.layoutColsMd !== undefined) metricLayoutCols.md = p.layoutColsMd;\n if (p.layoutColsSm !== undefined) metricLayoutCols.sm = p.layoutColsSm;\n if (p.layoutColsXs !== undefined) metricLayoutCols.xs = p.layoutColsXs;\n if (p.layoutColsXxs !== undefined) metricLayoutCols.xxs = p.layoutColsXxs;\n if (Object.keys(metricLayoutCols).length)\n componentTheme.metricLayoutCols = metricLayoutCols;\n\n return componentTheme;\n}\n\nfunction buildChartAppearance(\n p: Record<string, unknown>\n): Record<string, unknown> {\n const chartAppearance: Record<string, unknown> = {};\n\n const chartTooltip: Record<string, unknown> = {};\n const mappedHeader = mapToFrontendFontConfig(p.tooltipHeaderStyle as any);\n const mappedLabel = mapToFrontendFontConfig(p.tooltipLabelStyle as any);\n const mappedValue = mapToFrontendFontConfig(p.tooltipValueStyle as any);\n if (mappedHeader) chartTooltip.tooltipHeader = mappedHeader;\n if (mappedLabel) chartTooltip.labelStyle = mappedLabel;\n if (mappedValue) chartTooltip.valueStyle = mappedValue;\n if (Object.keys(chartTooltip).length)\n chartAppearance.chartTooltip = chartTooltip;\n\n const chartLabel: Record<string, unknown> = {};\n if (p.labelPosition) chartLabel.position = p.labelPosition;\n if (p.radialLabelPosition)\n chartLabel.radialChartposition = p.radialLabelPosition;\n if (Object.keys(chartLabel).length) chartAppearance.chartLabel = chartLabel;\n\n if (\n p.marginTop !== undefined ||\n p.marginLeft !== undefined ||\n p.marginRight !== undefined ||\n p.marginBottom !== undefined\n ) {\n chartAppearance.chartMargin = {\n ...(p.marginTop !== undefined && { marginTop: p.marginTop }),\n ...(p.marginLeft !== undefined && { marginLeft: p.marginLeft }),\n ...(p.marginRight !== undefined && { marginRight: p.marginRight }),\n ...(p.marginBottom !== undefined && { marginBottom: p.marginBottom }),\n };\n }\n\n const chartLegend: Record<string, unknown> = {};\n if (p.legendShow !== undefined) chartLegend.show = p.legendShow;\n if (p.legendPosition) chartLegend.fixedPosition = p.legendPosition;\n if (p.legendLayout) chartLegend.legendAppearance = p.legendLayout;\n if (p.legendShape) chartLegend.legendShape = p.legendShape;\n if (p.legendFontSize !== undefined) chartLegend.fontSize = p.legendFontSize;\n if (p.legendFontWeight !== undefined)\n chartLegend.fontWeight = p.legendFontWeight;\n if (p.legendFontFamily) chartLegend.fontFamily = p.legendFontFamily;\n if (p.legendColor) chartLegend.color = p.legendColor;\n if (p.legendTruncateLength !== undefined)\n chartLegend.truncateLegend = p.legendTruncateLength;\n if (p.disableLegendScrolling !== undefined)\n chartLegend.disableLegendScrolling = p.disableLegendScrolling;\n if (p.enableVariableLegendPosition !== undefined)\n chartLegend.enableVariablePosition = p.enableVariableLegendPosition;\n if (p.legendTop !== undefined) chartLegend.top = p.legendTop;\n if (p.legendLeft !== undefined) chartLegend.left = p.legendLeft;\n if (Object.keys(chartLegend).length)\n chartAppearance.chartLegend = chartLegend;\n\n if (p.verticalAxis) chartAppearance.verticalAxis = p.verticalAxis;\n if (p.horizontalAxis) chartAppearance.horizontalAxis = p.horizontalAxis;\n\n return chartAppearance;\n}\n\n// ---------------------------------------------------------------------------\n// Consolidated tool: customize_embed_theme\n// Replaces: apply_embed_preset + customize_embed_theme + configure_chart_appearance\n// ---------------------------------------------------------------------------\nexport function registerCustomizeTheme(\n server: McpServer,\n client: DatabrainClient\n): void {\n const services = createServiceBundle(client);\n server.tool(\n 'customize_embed_theme',\n `Theme an embed: presets (${Object.keys(THEME_PRESETS).join('/')}), colors, fonts, cards, chart appearance, responsive layout, or access presets (${Object.keys(ACCESS_PRESETS).join('/')}).`,\n {\n embedId: z.string().describe('ID of the embed to theme'),\n dataAppName: z\n .string()\n .trim()\n .min(1)\n .optional()\n .describe('Data app when this embed ID belongs to several apps'),\n body: z\n .record(z.string(), z.unknown())\n .optional()\n .describe(\n 'Raw API body for PUT /api/v2/data-app/embeds. If provided, sent directly and all convenience fields are ignored.'\n ),\n\n // --- Presets ---\n themePreset: z\n .enum(['light', 'dark', 'corporate', 'minimal'])\n .optional()\n .describe(\n 'Apply a theme preset as the base. Granular params below override preset values.'\n ),\n accessPreset: z\n .enum(['view-only', 'power-user', 'export-only', 'ai-enabled'])\n .optional()\n .describe('Apply an access settings preset'),\n\n // --- General ---\n fontFamily: fontFamilyEnum.optional().describe('Global font family'),\n datePickerFormat: z\n .string()\n .optional()\n .describe('Date picker display format'),\n\n // --- Colors ---\n primaryColor: z\n .string()\n .optional()\n .describe('Primary accent color (hex)'),\n backgroundColor: z\n .string()\n .optional()\n .describe('Overall background color (hex)'),\n textColor: z.string().optional().describe('Default text color (hex)'),\n ctaColor: z\n .string()\n .optional()\n .describe('Call-to-action button color (hex)'),\n ctaTextColor: z\n .string()\n .optional()\n .describe('CTA button text color (hex)'),\n\n // --- Dashboard ---\n dashboardBackgroundColor: z\n .string()\n .optional()\n .describe('Dashboard container background (hex)'),\n selectBoxSize: z\n .enum(['small', 'medium', 'large'])\n .optional()\n .describe('Filter select box size'),\n selectBoxVariant: z\n .enum(['floating', 'outlined', 'standard'])\n .optional()\n .describe('Filter select box style'),\n selectBoxBorderRadius: z\n .string()\n .optional()\n .describe('Select box border radius (e.g. \"20px\")'),\n selectBoxTextColor: z\n .string()\n .optional()\n .describe('Select box text color (hex)'),\n metricCardColor: z\n .string()\n .optional()\n .describe('Metric card background color (hex)'),\n\n // --- Card Title ---\n cardTitleFontSize: z\n .string()\n .optional()\n .describe('Card title font size (e.g. \"16px\")'),\n cardTitleFontWeight: z\n .string()\n .optional()\n .describe('Card title font weight (e.g. \"600\")'),\n cardTitleColor: z\n .string()\n .optional()\n .describe('Card title text color (hex)'),\n\n // --- Card Description ---\n cardDescriptionFontSize: z\n .string()\n .optional()\n .describe('Card description font size'),\n cardDescriptionFontWeight: z\n .string()\n .optional()\n .describe('Card description font weight'),\n cardDescriptionColor: z\n .string()\n .optional()\n .describe('Card description text color (hex)'),\n\n // --- Card Customization ---\n cardPadding: z.string().optional().describe('Card internal padding'),\n cardBorderRadius: z.string().optional().describe('Card border radius'),\n cardShadow: z.string().optional().describe('Card box-shadow CSS value'),\n disableShadowOnHover: z\n .boolean()\n .optional()\n .describe('Disable shadow on card hover'),\n disableCardStroke: z\n .boolean()\n .optional()\n .describe('Remove card border stroke'),\n cardStrokeColor: z\n .string()\n .optional()\n .describe('Card border stroke color (hex)'),\n\n // --- Chart Colors (admin theme level) ---\n chartFontFamily: z\n .string()\n .optional()\n .describe('Font family for chart text'),\n chartFontColor: z\n .string()\n .optional()\n .describe('Font color for chart text (hex)'),\n chartColors: z\n .array(z.string())\n .optional()\n .describe('Array of chart series colors (hex)'),\n chartPaletteName: z\n .string()\n .optional()\n .describe('Name for a custom palette'),\n chartPaletteColors: z\n .array(z.string())\n .optional()\n .describe('9 colors for a custom palette'),\n\n // --- Chart Tooltip (admin theme level) ---\n tooltipHeader: tooltipFontSchema.describe('Tooltip header font config'),\n tooltipLabel: tooltipFontSchema.describe('Tooltip label font config'),\n tooltipValue: tooltipFontSchema.describe('Tooltip value font config'),\n\n // --- Component Theme ---\n buttonPrimaryColor: z\n .string()\n .optional()\n .describe('Primary button background (hex)'),\n buttonPrimaryTextColor: z\n .string()\n .optional()\n .describe('Primary button text (hex)'),\n buttonSecondaryColor: z\n .string()\n .optional()\n .describe('Secondary button background (hex)'),\n buttonSecondaryTextColor: z\n .string()\n .optional()\n .describe('Secondary button text (hex)'),\n checkboxCheckedColor: z\n .string()\n .optional()\n .describe('Checked checkbox color (hex)'),\n checkboxUncheckedColor: z\n .string()\n .optional()\n .describe('Unchecked checkbox color (hex)'),\n switchEnabledColor: z\n .string()\n .optional()\n .describe('Enabled switch color (hex)'),\n switchDisabledColor: z\n .string()\n .optional()\n .describe('Disabled switch color (hex)'),\n breadcrumbFontFamily: z\n .string()\n .optional()\n .describe('Drill breadcrumb font family'),\n breadcrumbFontColor: z\n .string()\n .optional()\n .describe('Drill breadcrumb font color (hex)'),\n breadcrumbActiveColor: z\n .string()\n .optional()\n .describe('Active breadcrumb color (hex)'),\n filterBadgeColor: z\n .string()\n .optional()\n .describe('Multi-select filter badge color (hex)'),\n filterBadgeTextColor: z\n .string()\n .optional()\n .describe('Filter badge text color (hex)'),\n datePickerColor: z\n .string()\n .optional()\n .describe('Date picker accent color (hex)'),\n\n // --- Responsive Breakpoints ---\n breakpointXl: z.number().optional().describe('XL breakpoint width in px'),\n breakpointLg: z.number().optional().describe('LG breakpoint width in px'),\n breakpointMd: z.number().optional().describe('MD breakpoint width in px'),\n breakpointSm: z.number().optional().describe('SM breakpoint width in px'),\n breakpointXs: z.number().optional().describe('XS breakpoint width in px'),\n\n // --- Metric Layout Columns ---\n layoutColsXl: z\n .number()\n .optional()\n .describe('Grid columns at XL breakpoint'),\n layoutColsLg: z\n .number()\n .optional()\n .describe('Grid columns at LG breakpoint'),\n layoutColsMd: z\n .number()\n .optional()\n .describe('Grid columns at MD breakpoint'),\n layoutColsSm: z\n .number()\n .optional()\n .describe('Grid columns at SM breakpoint'),\n layoutColsXs: z\n .number()\n .optional()\n .describe('Grid columns at XS breakpoint'),\n layoutColsXxs: z\n .number()\n .optional()\n .describe('Grid columns at XXS breakpoint'),\n\n // --- Chart Appearance (detailed) ---\n tooltipHeaderStyle: fontConfigInputSchema.describe(\n 'Tooltip header: fontSize, fontFamily, fontWeight, color'\n ),\n tooltipLabelStyle: fontConfigInputSchema.describe(\n 'Tooltip label: fontSize, fontFamily, fontWeight, color'\n ),\n tooltipValueStyle: fontConfigInputSchema.describe(\n 'Tooltip value: fontSize, fontFamily, fontWeight, color'\n ),\n labelPosition: z\n .enum(['hidden', 'top', 'left', 'right', 'bottom', 'inside'])\n .optional()\n .describe('Data label position on charts'),\n radialLabelPosition: z\n .enum(['outside', 'inside'])\n .optional()\n .describe('Label position for radial/pie charts'),\n marginTop: z.number().optional().describe('Chart top margin in pixels'),\n marginLeft: z.number().optional().describe('Chart left margin in pixels'),\n marginRight: z\n .number()\n .optional()\n .describe('Chart right margin in pixels'),\n marginBottom: z\n .number()\n .optional()\n .describe('Chart bottom margin in pixels'),\n legendShow: z.boolean().optional().describe('Show or hide chart legend'),\n legendPosition: z\n .enum([\n 'top-left',\n 'top-center',\n 'top-right',\n 'left-center',\n 'right-center',\n 'bottom-left',\n 'bottom-center',\n 'bottom-right',\n ])\n .optional()\n .describe('Legend position'),\n legendLayout: z\n .enum(['horizontal', 'vertical'])\n .optional()\n .describe('Legend layout direction'),\n legendShape: z\n .enum([\n 'circle',\n 'rect',\n 'roundRect',\n 'triangle',\n 'diamond',\n 'arrow',\n 'none',\n ])\n .optional()\n .describe('Legend icon shape'),\n legendFontSize: z.number().optional().describe('Legend font size'),\n legendFontWeight: z.number().optional().describe('Legend font weight'),\n legendFontFamily: z.string().optional().describe('Legend font family'),\n legendColor: z.string().optional().describe('Legend text color (hex)'),\n legendTruncateLength: z\n .number()\n .optional()\n .describe('Max characters before truncating legend'),\n disableLegendScrolling: z\n .boolean()\n .optional()\n .describe('Disable scrolling in legend'),\n enableVariableLegendPosition: z\n .boolean()\n .optional()\n .describe('Allow user to drag legend'),\n legendTop: z.number().optional().describe('Custom legend top offset'),\n legendLeft: z.number().optional().describe('Custom legend left offset'),\n verticalAxis: axisSchema.describe('Vertical (Y) axis configuration'),\n horizontalAxis: axisSchema.describe('Horizontal (X) axis configuration'),\n },\n WRITE_IDEMPOTENT,\n async (params) => {\n const {\n embedId,\n dataAppName,\n body,\n themePreset,\n accessPreset,\n ...themeParams\n } = params;\n\n // --- Raw passthrough ---\n if (body) {\n try {\n const rawBody: Record<string, unknown> = { ...body };\n if (!rawBody.embedId) rawBody.embedId = embedId;\n if (dataAppName) rawBody.dataAppName = dataAppName;\n const result = await services.embedsApi.updateEmbed(rawBody);\n if (result.error) {\n return toolError(`Theme update failed: ${stringify(result.error)}`);\n }\n return toolSuccess(\n `Theme updated for embed \"${embedId}\" (raw passthrough mode).` +\n GUEST_TOKEN_REMINDER\n );\n } catch (err) {\n const guardrail = await maybeBuildCorruptedEmbedGuardrail(\n client,\n embedId,\n 'customize theme',\n err\n );\n if (guardrail) return guardrail;\n if (err instanceof DatabrainApiError) return err.toToolResponse();\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n\n const patch: Record<string, unknown> = {};\n const presetBase = themePreset ? THEME_PRESETS[themePreset] : undefined;\n\n // Admin theme (colors, cards, chart palette, tooltips)\n const adminTheme = buildAdminTheme(\n themeParams as Record<string, unknown>,\n presetBase\n );\n if (Object.keys(adminTheme).length) patch.adminThemeOptions = adminTheme;\n\n // Component theme (buttons, checkboxes, breakpoints, layout)\n const componentTheme = buildComponentTheme(\n themeParams as Record<string, unknown>\n );\n if (Object.keys(componentTheme).length) patch.theme = componentTheme;\n\n // Chart appearance (tooltip styles, legend, axes, labels, margins)\n const chartAppearance = buildChartAppearance(\n themeParams as Record<string, unknown>\n );\n const options: Record<string, unknown> = {};\n if (Object.keys(chartAppearance).length)\n options.chartAppearance = chartAppearance;\n if (themeParams.chartColors)\n options.chartColors = themeParams.chartColors;\n if (Object.keys(options).length) patch.options = options;\n\n // Access preset\n if (accessPreset) {\n patch.accessSettings = ACCESS_PRESETS[accessPreset];\n }\n\n if (Object.keys(patch).length === 0) {\n return toolError(\n 'No theme properties provided. Specify at least one property, or use a themePreset.'\n );\n }\n\n try {\n const result = await services.embedService.updateEmbed(\n embedId,\n patch,\n dataAppName\n );\n if (result.error) {\n return toolError(`Theme update failed: ${stringify(result.error)}`);\n }\n\n const applied: string[] = [];\n if (themePreset) applied.push(`preset: **${themePreset}**`);\n if (accessPreset) applied.push(`access: **${accessPreset}**`);\n if (patch.adminThemeOptions)\n applied.push(`admin theme (${Object.keys(adminTheme).join(', ')})`);\n if (patch.theme)\n applied.push(\n `component theme (${Object.keys(componentTheme).join(', ')})`\n );\n if (options.chartAppearance) {\n const parts = Object.keys(chartAppearance);\n if (themeParams.chartColors) parts.push('chart colors');\n applied.push(`chart appearance (${parts.join(', ')})`);\n }\n\n return toolSuccess(\n `Theme updated for embed \"${embedId}\".\\n\\n` +\n `**Applied:** ${applied.join(', ')}\\n\\n` +\n 'Use `get_embed_details` to view the full current theme configuration.' +\n GUEST_TOKEN_REMINDER\n );\n } catch (err) {\n const guardrail = await maybeBuildCorruptedEmbedGuardrail(\n client,\n embedId,\n 'customize theme',\n err\n );\n if (guardrail) return guardrail;\n if (err instanceof DatabrainApiError) return err.toToolResponse();\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n}\n","import type { DatabrainClient } from '../../client/databrain-client.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport { DatabrainApiError, toolError } from '../../utils/errors.js';\n\n/**\n * Reminder to include in success messages for any tool that modifies embed settings.\n * Guest tokens bake in the embed config at creation time, so they must be regenerated\n * after any embed update for changes to take effect.\n */\nexport const GUEST_TOKEN_REMINDER =\n '\\n\\n⚠️ **Guest tokens must be regenerated** for these changes to take effect. ' +\n 'Existing guest tokens still carry the old settings. ' +\n 'Call `generate_guest_token` to create a new token with the updated configuration.';\n\ntype ToolErrorResponse = {\n content: Array<{ type: 'text'; text: string }>;\n isError: true;\n};\n\nasync function probeEmbedExists(\n client: DatabrainClient,\n embedId: string\n): Promise<boolean> {\n try {\n const services = createServiceBundle(client);\n const embed = await services.embedService.resolveEmbedStrict(embedId);\n return embed.embedId === embedId;\n } catch {\n return false;\n }\n}\n\nexport async function maybeBuildCorruptedEmbedGuardrail(\n client: DatabrainClient,\n embedId: string,\n action: string,\n err: unknown\n): Promise<ToolErrorResponse | null> {\n if (!(err instanceof DatabrainApiError)) return null;\n if (err.status !== 404 && err.status < 500) return null;\n\n const embedExists = await probeEmbedExists(client, embedId);\n if (!embedExists) return null;\n\n return toolError(\n `Failed to ${action} for embed \"${embedId}\". The Databrain API returned ` +\n `${err.status === 404 ? 'NOT_FOUND' : 'INTERNAL_SERVER_ERROR'} even though the embed record is still discoverable.\\n\\n` +\n 'This usually indicates the embed is in an inconsistent backend state.\\n\\n' +\n 'Recommended recovery:\\n' +\n '1. Use `get_embed_details` to snapshot current config for reference.\\n' +\n '2. Delete the broken embed from the Databrain UI.\\n' +\n '3. Recreate the embed from the Databrain UI with explicit access settings.\\n' +\n '4. Re-apply branding changes and regenerate guest tokens.'\n );\n}\n\n/**\n * Fetch existing embed and return the current state for merging into a PUT update.\n * The Databrain API requires `accessSettings` on every PUT.\n */\nexport async function getEmbedForUpdate(\n client: DatabrainClient,\n embedId: string\n): Promise<Record<string, unknown>> {\n const services = createServiceBundle(client);\n return services.embedService.buildUpdateBase(embedId);\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport {\n DatabrainApiError,\n toolError,\n toolSuccess,\n} from '../../utils/errors.js';\nimport { WRITE_CREATE } from '../annotations.js';\n\nconst HOUR_MS = 60 * 60 * 1000;\nconst DEFAULT_EXPIRY_HOURS = 24;\nconst MAX_EXPIRY_HOURS = 24 * 30;\n\nexport function registerGetDemoLink(\n server: McpServer,\n client: DatabrainClient\n): void {\n const services = createServiceBundle(client);\n server.tool(\n 'get_demo_link',\n 'Get a shareable demo URL for a dashboard embed scoped to a specific clientId — 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.',\n {\n clientId: z\n .string()\n .describe('End-customer identifier to scope the preview to.'),\n dashboardName: z\n .string()\n .optional()\n .describe(\n 'Dashboard name (non-technical). Preferred — pass with optional `workspaceName`.'\n ),\n workspaceName: z\n .string()\n .optional()\n .describe(\n 'Workspace name. Only needed if `dashboardName` is ambiguous.'\n ),\n dataAppName: z\n .string()\n .trim()\n .min(1)\n .optional()\n .describe('Data app name when dashboard embeds span several apps'),\n embedId: z\n .string()\n .optional()\n .describe('Technical alternative to `dashboardName`.'),\n expiryHours: z\n .number()\n .min(1)\n .max(MAX_EXPIRY_HOURS)\n .optional()\n .describe(\n `Token TTL in hours. Defaults to ${DEFAULT_EXPIRY_HOURS}. Max ${MAX_EXPIRY_HOURS} (30 days).`\n ),\n },\n WRITE_CREATE,\n async (params) => {\n try {\n const embed = await services.widgetService.resolveEmbedId({\n embedId: params.embedId,\n dashboardName: params.dashboardName,\n workspaceName: params.workspaceName,\n dataAppName: params.dataAppName,\n required: true,\n });\n if (!embed.ok) return toolError(embed.error);\n const embedId = embed.value.embedId as string;\n const dashboardName = embed.value.resolvedFrom?.dashboardName || null;\n\n const ctx = await services.widgetService.resolveEmbedContext(\n embedId,\n params.dataAppName\n );\n if (!ctx.dataAppName) {\n return toolError(\n `Could not resolve the data app for embed \"${embedId}\". The demo link needs a data app to mint a guest token against. Run \\`list_data_apps\\` to confirm one exists, or pass \\`embedId\\` for an embed with metadata.dataAppName populated.`\n );\n }\n const dashboardSlug = ctx.externalDashboardId || ctx.dashboardId;\n if (!dashboardSlug) {\n return toolError(\n `Embed \"${embedId}\" has no dashboardId/externalDashboardId — the demo URL requires one to load the dashboard. This is unexpected; verify the embed in the Databrain UI.`\n );\n }\n\n const expiryHours = params.expiryHours ?? DEFAULT_EXPIRY_HOURS;\n const { token } = await services.guestTokenService.generateToken({\n clientId: params.clientId,\n dataAppName: ctx.dataAppName,\n allowedEmbeds: [embedId],\n expiryTime: expiryHours * HOUR_MS,\n });\n\n const baseUrl = client.getDemoDomain().replace(/\\/+$/, '');\n const demoUrl = `${baseUrl}/?token=${encodeURIComponent(token)}&dashboardId=${encodeURIComponent(dashboardSlug)}`;\n\n return toolSuccess(\n JSON.stringify({\n demoUrl,\n clientId: params.clientId,\n dashboardName,\n embedId,\n dashboardId: dashboardSlug,\n dataAppName: ctx.dataAppName,\n expiresInHours: expiryHours,\n note: 'Open this URL in a browser to preview the dashboard exactly as the end-customer sees it. This matches the UI\\'s \"Share Demo Link\" flow. Override the host with DATABRAIN_DEMO_DOMAIN for self-hosted / custom preview domains.',\n })\n );\n } catch (err) {\n if (err instanceof DatabrainApiError) return err.toToolResponse();\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport {\n DatabrainApiError,\n toolError,\n toolSuccess,\n} from '../../utils/errors.js';\nimport { READ_ONLY } from '../annotations.js';\n\nexport function registerGetEmbedDetails(\n server: McpServer,\n client: DatabrainClient\n): void {\n const services = createServiceBundle(client);\n server.tool(\n 'get_embed_details',\n 'Get full embed configuration including access settings and theme.',\n {\n embedId: z.string().describe('ID of the embed'),\n dataAppName: z\n .string()\n .trim()\n .min(1)\n .optional()\n .describe('Data app when this embed ID belongs to several apps'),\n },\n READ_ONLY,\n async (params) => {\n try {\n const embed = await services.embedService.resolveEmbedStrict(\n params.embedId,\n params.dataAppName\n );\n\n return toolSuccess(\n JSON.stringify({ embedId: params.embedId, ...embed })\n );\n } catch (err) {\n if (err instanceof DatabrainApiError) return err.toToolResponse();\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport {\n DatabrainApiError,\n toolError,\n toolSuccess,\n} from '../../utils/errors.js';\nimport { READ_ONLY } from '../annotations.js';\n\nexport function registerListEmbeds(\n server: McpServer,\n client: DatabrainClient\n): void {\n const services = createServiceBundle(client);\n server.tool(\n 'list_embeds',\n 'List embed configurations. Requires an API token (use create_api_token first). Use `list_tenants` for authoritative client discovery from the tenancy database.',\n {\n dataAppName: z.string().optional().describe('Filter by data app name'),\n },\n READ_ONLY,\n async (params) => {\n try {\n const result = await services.embedService.listEmbeds(\n params.dataAppName\n );\n\n if (!Array.isArray(result) || result.length === 0) {\n return toolSuccess(\n 'No embeds found. Create an embed in the Databrain UI, then run `list_embeds` again.'\n );\n }\n\n const embeds = result.map((e: any) => {\n const n = services.discoveryService.normalizeEmbed(e);\n const externalDashboard =\n e.externalDashboard && typeof e.externalDashboard === 'object'\n ? e.externalDashboard\n : {};\n let clientId: string | null = null;\n if (typeof e.clientId === 'string' && e.clientId.trim().length > 0) {\n clientId = e.clientId;\n } else if (\n typeof e.createdBy === 'string' &&\n e.createdBy.trim().length > 0\n ) {\n clientId = e.createdBy;\n } else if (\n typeof externalDashboard.createdBy === 'string' &&\n externalDashboard.createdBy.trim().length > 0\n ) {\n clientId = externalDashboard.createdBy;\n }\n return {\n embedId: n.embedId || null,\n internalId: !n.embedId && n.internalId ? n.internalId : undefined,\n name: n.name,\n type: n.embedType || 'dashboard',\n dashboardId: n.dashboardId || null,\n dataApp: n.dataAppName || null,\n clientId,\n };\n });\n\n const distinctClientIds = Array.from(\n new Set(\n embeds\n .map((e) => e.clientId)\n .filter(\n (id): id is string => typeof id === 'string' && id.length > 0\n )\n )\n ).sort();\n\n return toolSuccess(\n JSON.stringify({\n count: embeds.length,\n distinctClientIds,\n embeds,\n })\n );\n } catch (err) {\n if (err instanceof DatabrainApiError) return err.toToolResponse();\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport {\n DatabrainApiError,\n stringify,\n toolError,\n toolSuccess,\n} from '../../utils/errors.js';\nimport { WRITE_IDEMPOTENT } from '../annotations.js';\nimport {\n GUEST_TOKEN_REMINDER,\n maybeBuildCorruptedEmbedGuardrail,\n} from './helpers.js';\n\nexport function registerUpdateEmbed(\n server: McpServer,\n client: DatabrainClient\n): void {\n const services = createServiceBundle(client);\n server.tool(\n 'update_embed',\n 'Update embed access settings, permissions, theme, or name.',\n {\n embedId: z.string().describe('ID of the embed to update'),\n dataAppName: z\n .string()\n .trim()\n .min(1)\n .optional()\n .describe('Data app when this embed ID belongs to several apps'),\n body: z\n .record(z.string(), z.unknown())\n .optional()\n .describe(\n 'Raw API body for PUT /api/v2/data-app/embeds. If provided, it is sent directly (passthrough mode).'\n ),\n name: z.string().optional().describe('New name for the embed'),\n accessSettings: z\n .record(z.string(), z.unknown())\n .optional()\n .describe(\n 'Partial update of access settings. See `get_embed_details` for current settings.'\n ),\n theme: z\n .record(z.string(), z.unknown())\n .optional()\n .describe(\n 'Theme configuration object. See databrain://theme-reference for the full schema.'\n ),\n },\n WRITE_IDEMPOTENT,\n async (params) => {\n try {\n if (params.body) {\n const rawBody: Record<string, unknown> = { ...params.body };\n if (!rawBody.embedId) rawBody.embedId = params.embedId;\n if (params.dataAppName) rawBody.dataAppName = params.dataAppName;\n const result = await services.embedsApi.updateEmbed(rawBody);\n if (result.error) {\n return toolError(`Embed update failed: ${stringify(result.error)}`);\n }\n return toolSuccess(\n `Embed \"${params.embedId}\" updated successfully (raw passthrough mode).` +\n GUEST_TOKEN_REMINDER\n );\n }\n\n const patch: Record<string, unknown> = {};\n if (params.name) patch.name = params.name;\n if (params.accessSettings) patch.accessSettings = params.accessSettings;\n if (params.theme) patch.theme = params.theme;\n const result = await services.embedService.updateEmbed(\n params.embedId,\n patch,\n params.dataAppName\n );\n\n if (result.error) {\n return toolError(`Embed update failed: ${stringify(result.error)}`);\n }\n\n return toolSuccess(\n `Embed \"${params.embedId}\" updated successfully.` +\n GUEST_TOKEN_REMINDER\n );\n } catch (err) {\n const guardrail = await maybeBuildCorruptedEmbedGuardrail(\n client,\n params.embedId,\n 'update embed',\n err\n );\n if (guardrail) return guardrail;\n if (err instanceof DatabrainApiError) return err.toToolResponse();\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { getTemplate } from '../../templates/index.js';\nimport type { TemplateContext } from '../../templates/types.js';\nimport { toolSuccess } from '../../utils/errors.js';\nimport { READ_ONLY } from '../annotations.js';\n\nconst FRAMEWORKS = [\n 'react',\n 'nextjs',\n 'vue',\n 'angular',\n 'svelte',\n 'solidjs',\n 'vanilla',\n] as const;\n\nexport function registerGenerateEmbedCode(\n server: McpServer,\n _client: DatabrainClient\n): void {\n server.tool(\n 'generate_embed_code',\n 'Generate framework-specific embed code (React, Next.js, Vue, Angular, Svelte, SolidJS, vanilla HTML).',\n {\n embedId: z.string().describe('The embed ID to generate code for'),\n framework: z.enum(FRAMEWORKS).describe('Frontend framework'),\n embedType: z\n .enum(['dashboard', 'metric'])\n .optional()\n .default('dashboard'),\n options: z\n .object({\n enableDownloadCsv: z.boolean().optional(),\n enableEmailCsv: z.boolean().optional(),\n enableDownloadAllMetrics: z.boolean().optional(),\n enableDownloadAllPdf: z.boolean().optional(),\n disableFullscreen: z.boolean().optional(),\n isHideTablePreview: z.boolean().optional(),\n isHideChartSettings: z.boolean().optional(),\n isStickyDashboardFilters: z.boolean().optional(),\n enableMultiMetricFilters: z.boolean().optional(),\n themeName: z.string().optional(),\n customTheme: z.record(z.string(), z.unknown()).optional(),\n optionsIcon: z.enum(['kebab-menu-vertical', 'download']).optional(),\n })\n .optional(),\n },\n READ_ONLY,\n async (params) => {\n const ctx: TemplateContext = {\n embedId: params.embedId,\n embedType: params.embedType || 'dashboard',\n options: params.options || {},\n };\n\n const generated = getTemplate(params.framework, ctx);\n\n let output = `## ${params.framework.charAt(0).toUpperCase() + params.framework.slice(1)} Embed Code\\n\\n`;\n\n output += `### 1. Install Dependencies\\n\\`\\`\\`bash\\n${generated.installCommand}\\n\\`\\`\\`\\n\\n`;\n\n output += `### 2. Backend — Guest Token API Route\\n\\`\\`\\`${generated.backendLanguage || 'typescript'}\\n${generated.backendCode}\\n\\`\\`\\`\\n\\n`;\n\n output += `### 3. Frontend Component\\n\\`\\`\\`${generated.frontendLanguage || 'tsx'}\\n${generated.frontendCode}\\n\\`\\`\\`\\n\\n`;\n\n output += `### 4. Setup Instructions\\n${generated.instructions}`;\n\n return toolSuccess(output);\n }\n );\n}\n","import type { GeneratedCode, TemplateContext } from './types.js';\n\nfunction kebabCase(str: string): string {\n return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();\n}\n\nfunction buildAttributes(ctx: TemplateContext) {\n const tag = ctx.embedType === 'dashboard' ? 'dbn-dashboard' : 'dbn-metric';\n const idAttr = ctx.embedType === 'dashboard' ? 'dashboard-id' : 'metric-id';\n const boolAttrs = Object.entries(ctx.options)\n .filter(([_, v]) => v === true)\n .map(([k]) => kebabCase(k))\n .join(' ');\n return { tag, idAttr, boolAttrs };\n}\n\nexport function angularTemplate(ctx: TemplateContext): GeneratedCode {\n const { tag, idAttr, boolAttrs } = buildAttributes(ctx);\n const boolAttrString = boolAttrs ? ` ${boolAttrs}` : '';\n\n const installCommand = 'npm install @databrainhq/plugin';\n\n const backendCode = `// server.ts - Express backend\nimport express from 'express';\nimport cors from 'cors';\n\nconst app = express();\napp.use(cors());\napp.use(express.json());\n\nconst DEFAULT_PERMISSIONS = {\n isEnableManageMetrics: true,\n isEnableMetricUpdation: true,\n isEnableCustomizeLayout: true,\n isEnableCreateDashboardView: true,\n isDisableMetricCreation: false,\n};\n\napp.post('/api/guest-token', async (req, res) => {\n const { clientId, dataAppName } = req.body;\n const resolvedDataAppName = dataAppName || process.env.DATABRAIN_DATA_APP_NAME;\n\n if (!resolvedDataAppName) {\n return res.status(400).json({\n error: 'Missing dataAppName. Provide it in request body or set DATABRAIN_DATA_APP_NAME.',\n });\n }\n\n try {\n const response = await fetch(\n \\`\\${process.env.DATABRAIN_API_URL}/api/v2/guest-token/create\\`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: \\`Bearer \\${process.env.DATABRAIN_API_TOKEN}\\`,\n },\n body: JSON.stringify({\n clientId,\n dataAppName: resolvedDataAppName,\n permissions: DEFAULT_PERMISSIONS,\n }),\n }\n );\n\n const data = await response.json();\n res.json(data);\n } catch (error) {\n console.error('Error creating guest token:', error);\n res.status(500).json({ error: 'Failed to create guest token' });\n }\n});\n\napp.listen(3001, () => {\n console.log('Server running on http://localhost:3001');\n});`;\n\n const frontendCode = `// databrain-embed.component.ts - Angular component\nimport { Component, OnInit, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';\nimport { HttpClient } from '@angular/common/http';\nimport '@databrainhq/plugin';\n\n@Component({\n selector: 'app-databrain-embed',\n standalone: true,\n schemas: [CUSTOM_ELEMENTS_SCHEMA],\n template: \\`\n <div *ngIf=\"!token\">Loading...</div>\n <${tag}\n *ngIf=\"token\"\n [attr.token]=\"token\"\n ${idAttr}=\"${ctx.embedId}\"${boolAttrString}\n />\n \\`,\n})\nexport class DatabrainEmbedComponent implements OnInit {\n token: string | null = null;\n\n constructor(private http: HttpClient) {}\n\n ngOnInit(): void {\n this.http\n .post<{ token: string }>('/api/guest-token', {\n clientId: 'your-client-id',\n })\n .subscribe({\n next: (data) => {\n this.token = data.token;\n },\n error: (error) => {\n console.error('Failed to fetch guest token:', error);\n },\n });\n }\n}`;\n\n const instructions = `## Angular + Express Setup\n\n### Environment Variables\nSet the following environment variables on your backend server:\n- \\`DATABRAIN_API_TOKEN\\` - Your Databrain API token\n- \\`DATABRAIN_API_URL\\` - Your Databrain API base URL (e.g. https://api.usedatabrain.com)\n- \\`DATABRAIN_DATA_APP_NAME\\` - Default data app name for guest token generation\n\n### Security\nThe guest token must be generated server-side. Never expose your DATABRAIN_API_TOKEN to the client.\n\n### Steps\n1. Install the plugin: \\`${installCommand}\\`\n2. Set up the Express backend (server.ts) and start it\n3. Add \\`HttpClientModule\\` to your app's imports (or use \\`provideHttpClient()\\` in standalone apps)\n4. Add the \\`DatabrainEmbedComponent\\` to your Angular app\n5. The component uses \\`CUSTOM_ELEMENTS_SCHEMA\\` to allow the custom web component elements\n6. Replace 'your-client-id' with the actual client identifier for the logged-in user\n7. Configure a proxy for /api requests to the Express backend during development:\n \\`\\`\\`json\n // proxy.conf.json\n {\n \"/api\": {\n \"target\": \"http://localhost:3001\",\n \"secure\": false\n }\n }\n \\`\\`\\`\n\n### Runtime Verification Checklist\n- Call your backend \\`/api/guest-token\\` route and verify the returned token works for the target data app\n- In browser network response for \\`/api/v2/dashboard\\`, confirm \\`isAllowedToCreateMetrics=true\\` and \\`metricCreationMode=DRAG_DROP\\`\n- Ensure embed options do not include \\`disableMetricCreation=true\\`\n- Regenerate guest tokens after changing embed permissions/access settings`;\n\n return {\n installCommand,\n backendCode,\n backendLanguage: 'typescript',\n frontendCode,\n frontendLanguage: 'typescript',\n instructions,\n };\n}\n","import type { GeneratedCode, TemplateContext } from './types.js';\n\nfunction kebabCase(str: string): string {\n return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();\n}\n\nfunction buildAttributes(ctx: TemplateContext) {\n const tag = ctx.embedType === 'dashboard' ? 'dbn-dashboard' : 'dbn-metric';\n const idAttr = ctx.embedType === 'dashboard' ? 'dashboard-id' : 'metric-id';\n const boolAttrs = Object.entries(ctx.options)\n .filter(([_, v]) => v === true)\n .map(([k]) => kebabCase(k))\n .join(' ');\n return { tag, idAttr, boolAttrs };\n}\n\nexport function nextjsTemplate(ctx: TemplateContext): GeneratedCode {\n const { tag, idAttr, boolAttrs } = buildAttributes(ctx);\n const boolAttrString = boolAttrs ? ` ${boolAttrs}` : '';\n\n const installCommand = 'npm install @databrainhq/plugin';\n\n const backendCode = `// app/api/guest-token/route.ts - Next.js App Router API route\nimport { NextRequest, NextResponse } from 'next/server';\n\nexport async function POST(request: NextRequest) {\n const { clientId, dataAppName } = await request.json();\n const resolvedDataAppName = dataAppName || process.env.DATABRAIN_DATA_APP_NAME;\n const defaultPermissions = {\n isEnableManageMetrics: true,\n isEnableMetricUpdation: true,\n isEnableCustomizeLayout: true,\n isEnableCreateDashboardView: true,\n isDisableMetricCreation: false,\n };\n\n if (!resolvedDataAppName) {\n return NextResponse.json(\n {\n error: 'Missing dataAppName. Provide it in request body or set DATABRAIN_DATA_APP_NAME.',\n },\n { status: 400 }\n );\n }\n\n try {\n const response = await fetch(\n \\`\\${process.env.DATABRAIN_API_URL}/api/v2/guest-token/create\\`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: \\`Bearer \\${process.env.DATABRAIN_API_TOKEN}\\`,\n },\n body: JSON.stringify({\n clientId,\n dataAppName: resolvedDataAppName,\n permissions: defaultPermissions,\n }),\n }\n );\n\n const data = await response.json();\n return NextResponse.json(data);\n } catch (error) {\n console.error('Error creating guest token:', error);\n return NextResponse.json(\n { error: 'Failed to create guest token' },\n { status: 500 }\n );\n }\n}`;\n\n const frontendCode = `// app/components/DatabrainEmbed.tsx - Next.js Client Component\n'use client';\n\nimport { useEffect, useState } from 'react';\nimport '@databrainhq/plugin';\n\nexport default function DatabrainEmbed() {\n const [token, setToken] = useState<string | null>(null);\n\n useEffect(() => {\n async function fetchToken() {\n try {\n const response = await fetch('/api/guest-token', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ clientId: 'your-client-id' }),\n });\n const data = await response.json();\n setToken(data.token);\n } catch (error) {\n console.error('Failed to fetch guest token:', error);\n }\n }\n\n fetchToken();\n }, []);\n\n if (!token) return <div>Loading...</div>;\n\n return (\n <${tag}\n token={token}\n ${idAttr}=\"${ctx.embedId}\"${boolAttrString}\n />\n );\n}`;\n\n const instructions = `## Next.js (App Router) Setup\n\n### Environment Variables\nAdd the following to your \\`.env.local\\` file:\n- \\`DATABRAIN_API_TOKEN\\` - Your Databrain API token\n- \\`DATABRAIN_API_URL\\` - Your Databrain API base URL (e.g. https://api.usedatabrain.com)\n- \\`DATABRAIN_DATA_APP_NAME\\` - Default data app name for guest token generation\n\n### Security\nThe guest token is generated in the API route (server-side). Never expose your DATABRAIN_API_TOKEN to the client.\n\n### Steps\n1. Install the plugin: \\`${installCommand}\\`\n2. Create the API route at \\`app/api/guest-token/route.ts\\`\n3. Create the client component at \\`app/components/DatabrainEmbed.tsx\\`\n4. Import and use the component in your page (it must be used within a client component boundary due to the 'use client' directive)\n5. Replace 'your-client-id' with the actual client identifier for the logged-in user\n6. The \\`@databrainhq/plugin\\` import registers custom elements, so it must run on the client side\n\n### Runtime Verification Checklist\n- Call your backend \\`/api/guest-token\\` route and verify the returned token works for the target data app\n- In browser network response for \\`/api/v2/dashboard\\`, confirm \\`isAllowedToCreateMetrics=true\\` and \\`metricCreationMode=DRAG_DROP\\`\n- Ensure embed options do not include \\`disableMetricCreation=true\\`\n- Regenerate guest tokens after changing embed permissions/access settings`;\n\n return {\n installCommand,\n backendCode,\n backendLanguage: 'typescript',\n frontendCode,\n frontendLanguage: 'tsx',\n instructions,\n };\n}\n","import type { GeneratedCode, TemplateContext } from './types.js';\n\nfunction kebabCase(str: string): string {\n return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();\n}\n\nfunction buildAttributes(ctx: TemplateContext) {\n const tag = ctx.embedType === 'dashboard' ? 'dbn-dashboard' : 'dbn-metric';\n const idAttr = ctx.embedType === 'dashboard' ? 'dashboard-id' : 'metric-id';\n const boolAttrs = Object.entries(ctx.options)\n .filter(([_, v]) => v === true)\n .map(([k]) => kebabCase(k))\n .join(' ');\n return { tag, idAttr, boolAttrs };\n}\n\nexport function reactTemplate(ctx: TemplateContext): GeneratedCode {\n const { tag, idAttr, boolAttrs } = buildAttributes(ctx);\n const boolAttrString = boolAttrs ? ` ${boolAttrs}` : '';\n\n const installCommand = 'npm install @databrainhq/plugin';\n\n const backendCode = `// server.ts - Express backend\nimport express from 'express';\nimport cors from 'cors';\n\nconst app = express();\napp.use(cors());\napp.use(express.json());\n\nconst DEFAULT_PERMISSIONS = {\n isEnableManageMetrics: true,\n isEnableMetricUpdation: true,\n isEnableCustomizeLayout: true,\n isEnableCreateDashboardView: true,\n isDisableMetricCreation: false,\n};\n\napp.post('/api/guest-token', async (req, res) => {\n const { clientId, dataAppName } = req.body;\n const resolvedDataAppName = dataAppName || process.env.DATABRAIN_DATA_APP_NAME;\n\n if (!resolvedDataAppName) {\n return res.status(400).json({\n error: 'Missing dataAppName. Provide it in request body or set DATABRAIN_DATA_APP_NAME.',\n });\n }\n\n try {\n const response = await fetch(\n \\`\\${process.env.DATABRAIN_API_URL}/api/v2/guest-token/create\\`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: \\`Bearer \\${process.env.DATABRAIN_API_TOKEN}\\`,\n },\n body: JSON.stringify({\n clientId,\n dataAppName: resolvedDataAppName,\n permissions: DEFAULT_PERMISSIONS,\n }),\n }\n );\n\n const data = await response.json();\n res.json(data);\n } catch (error) {\n console.error('Error creating guest token:', error);\n res.status(500).json({ error: 'Failed to create guest token' });\n }\n});\n\napp.listen(3001, () => {\n console.log('Server running on http://localhost:3001');\n});`;\n\n const frontendCode = `// DatabrainEmbed.tsx - React component\nimport { useEffect, useState } from 'react';\nimport '@databrainhq/plugin';\n\nexport default function DatabrainEmbed() {\n const [token, setToken] = useState<string | null>(null);\n\n useEffect(() => {\n async function fetchToken() {\n try {\n const response = await fetch('/api/guest-token', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ clientId: 'your-client-id' }),\n });\n const data = await response.json();\n setToken(data.token);\n } catch (error) {\n console.error('Failed to fetch guest token:', error);\n }\n }\n\n fetchToken();\n }, []);\n\n if (!token) return <div>Loading...</div>;\n\n return (\n <${tag}\n token={token}\n ${idAttr}=\"${ctx.embedId}\"${boolAttrString}\n />\n );\n}`;\n\n const instructions = `## React + Express Setup\n\n### Environment Variables\nSet the following environment variables on your backend server:\n- \\`DATABRAIN_API_TOKEN\\` - Your Databrain API token\n- \\`DATABRAIN_API_URL\\` - Your Databrain API base URL (e.g. https://api.usedatabrain.com)\n- \\`DATABRAIN_DATA_APP_NAME\\` - Default data app name for guest token generation\n\n### Security\nThe guest token must be generated server-side. Never expose your DATABRAIN_API_TOKEN to the client.\n\n### Steps\n1. Install the plugin: \\`${installCommand}\\`\n2. Set up the Express backend (server.ts) and start it\n3. Use the DatabrainEmbed component in your React app\n4. Replace 'your-client-id' with the actual client identifier for the logged-in user\n5. If using Create React App or Vite, proxy /api requests to the Express backend\n\n### Runtime Verification Checklist\n- Call your backend \\`/api/guest-token\\` route and verify the returned token works for the target data app\n- In browser network response for \\`/api/v2/dashboard\\`, confirm \\`isAllowedToCreateMetrics=true\\` and \\`metricCreationMode=DRAG_DROP\\`\n- Ensure embed options do not include \\`disableMetricCreation=true\\`\n- Regenerate guest tokens after changing embed permissions/access settings`;\n\n return {\n installCommand,\n backendCode,\n backendLanguage: 'typescript',\n frontendCode,\n frontendLanguage: 'tsx',\n instructions,\n };\n}\n","import type { GeneratedCode, TemplateContext } from './types.js';\n\nfunction kebabCase(str: string): string {\n return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();\n}\n\nfunction buildAttributes(ctx: TemplateContext) {\n const tag = ctx.embedType === 'dashboard' ? 'dbn-dashboard' : 'dbn-metric';\n const idAttr = ctx.embedType === 'dashboard' ? 'dashboard-id' : 'metric-id';\n const boolAttrs = Object.entries(ctx.options)\n .filter(([_, v]) => v === true)\n .map(([k]) => kebabCase(k))\n .join(' ');\n return { tag, idAttr, boolAttrs };\n}\n\nexport function solidjsTemplate(ctx: TemplateContext): GeneratedCode {\n const { tag, idAttr, boolAttrs } = buildAttributes(ctx);\n const boolAttrString = boolAttrs ? ` ${boolAttrs}` : '';\n\n const installCommand = 'npm install @databrainhq/plugin';\n\n const backendCode = `// server.ts - Express backend\nimport express from 'express';\nimport cors from 'cors';\n\nconst app = express();\napp.use(cors());\napp.use(express.json());\n\nconst DEFAULT_PERMISSIONS = {\n isEnableManageMetrics: true,\n isEnableMetricUpdation: true,\n isEnableCustomizeLayout: true,\n isEnableCreateDashboardView: true,\n isDisableMetricCreation: false,\n};\n\napp.post('/api/guest-token', async (req, res) => {\n const { clientId, dataAppName } = req.body;\n const resolvedDataAppName = dataAppName || process.env.DATABRAIN_DATA_APP_NAME;\n\n if (!resolvedDataAppName) {\n return res.status(400).json({\n error: 'Missing dataAppName. Provide it in request body or set DATABRAIN_DATA_APP_NAME.',\n });\n }\n\n try {\n const response = await fetch(\n \\`\\${process.env.DATABRAIN_API_URL}/api/v2/guest-token/create\\`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: \\`Bearer \\${process.env.DATABRAIN_API_TOKEN}\\`,\n },\n body: JSON.stringify({\n clientId,\n dataAppName: resolvedDataAppName,\n permissions: DEFAULT_PERMISSIONS,\n }),\n }\n );\n\n const data = await response.json();\n res.json(data);\n } catch (error) {\n console.error('Error creating guest token:', error);\n res.status(500).json({ error: 'Failed to create guest token' });\n }\n});\n\napp.listen(3001, () => {\n console.log('Server running on http://localhost:3001');\n});`;\n\n const frontendCode = `// DatabrainEmbed.tsx - SolidJS component\nimport { createSignal, onMount, Show } from 'solid-js';\nimport '@databrainhq/plugin';\n\nexport default function DatabrainEmbed() {\n const [token, setToken] = createSignal<string | null>(null);\n\n onMount(async () => {\n try {\n const response = await fetch('/api/guest-token', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ clientId: 'your-client-id' }),\n });\n const data = await response.json();\n setToken(data.token);\n } catch (error) {\n console.error('Failed to fetch guest token:', error);\n }\n });\n\n return (\n <Show when={token()} fallback={<div>Loading...</div>}>\n <${tag}\n token={token()}\n ${idAttr}=\"${ctx.embedId}\"${boolAttrString}\n />\n </Show>\n );\n}`;\n\n const instructions = `## SolidJS + Express Setup\n\n### Environment Variables\nSet the following environment variables on your backend server:\n- \\`DATABRAIN_API_TOKEN\\` - Your Databrain API token\n- \\`DATABRAIN_API_URL\\` - Your Databrain API base URL (e.g. https://api.usedatabrain.com)\n- \\`DATABRAIN_DATA_APP_NAME\\` - Default data app name for guest token generation\n\n### Security\nThe guest token must be generated server-side. Never expose your DATABRAIN_API_TOKEN to the client.\n\n### Steps\n1. Install the plugin: \\`${installCommand}\\`\n2. Set up the Express backend (server.ts) and start it\n3. Add the DatabrainEmbed component to your SolidJS app\n4. Replace 'your-client-id' with the actual client identifier for the logged-in user\n5. If using SolidStart, you can create a server function or API route instead of a separate Express server\n6. Proxy /api requests to the Express backend in your Vite config during development\n\n### Runtime Verification Checklist\n- Call your backend \\`/api/guest-token\\` route and verify the returned token works for the target data app\n- In browser network response for \\`/api/v2/dashboard\\`, confirm \\`isAllowedToCreateMetrics=true\\` and \\`metricCreationMode=DRAG_DROP\\`\n- Ensure embed options do not include \\`disableMetricCreation=true\\`\n- Regenerate guest tokens after changing embed permissions/access settings`;\n\n return {\n installCommand,\n backendCode,\n backendLanguage: 'typescript',\n frontendCode,\n frontendLanguage: 'tsx',\n instructions,\n };\n}\n","import type { GeneratedCode, TemplateContext } from './types.js';\n\nfunction kebabCase(str: string): string {\n return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();\n}\n\nfunction buildAttributes(ctx: TemplateContext) {\n const tag = ctx.embedType === 'dashboard' ? 'dbn-dashboard' : 'dbn-metric';\n const idAttr = ctx.embedType === 'dashboard' ? 'dashboard-id' : 'metric-id';\n const boolAttrs = Object.entries(ctx.options)\n .filter(([_, v]) => v === true)\n .map(([k]) => kebabCase(k))\n .join(' ');\n return { tag, idAttr, boolAttrs };\n}\n\nexport function svelteTemplate(ctx: TemplateContext): GeneratedCode {\n const { tag, idAttr, boolAttrs } = buildAttributes(ctx);\n const boolAttrString = boolAttrs ? ` ${boolAttrs}` : '';\n\n const installCommand = 'npm install @databrainhq/plugin';\n\n const backendCode = `// server.ts - Express backend\nimport express from 'express';\nimport cors from 'cors';\n\nconst app = express();\napp.use(cors());\napp.use(express.json());\n\nconst DEFAULT_PERMISSIONS = {\n isEnableManageMetrics: true,\n isEnableMetricUpdation: true,\n isEnableCustomizeLayout: true,\n isEnableCreateDashboardView: true,\n isDisableMetricCreation: false,\n};\n\napp.post('/api/guest-token', async (req, res) => {\n const { clientId, dataAppName } = req.body;\n const resolvedDataAppName = dataAppName || process.env.DATABRAIN_DATA_APP_NAME;\n\n if (!resolvedDataAppName) {\n return res.status(400).json({\n error: 'Missing dataAppName. Provide it in request body or set DATABRAIN_DATA_APP_NAME.',\n });\n }\n\n try {\n const response = await fetch(\n \\`\\${process.env.DATABRAIN_API_URL}/api/v2/guest-token/create\\`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: \\`Bearer \\${process.env.DATABRAIN_API_TOKEN}\\`,\n },\n body: JSON.stringify({\n clientId,\n dataAppName: resolvedDataAppName,\n permissions: DEFAULT_PERMISSIONS,\n }),\n }\n );\n\n const data = await response.json();\n res.json(data);\n } catch (error) {\n console.error('Error creating guest token:', error);\n res.status(500).json({ error: 'Failed to create guest token' });\n }\n});\n\napp.listen(3001, () => {\n console.log('Server running on http://localhost:3001');\n});`;\n\n const frontendCode = `<!-- DatabrainEmbed.svelte - Svelte component -->\n<script lang=\"ts\">\n import { onMount } from 'svelte';\n import '@databrainhq/plugin';\n\n let token: string | null = null;\n\n onMount(async () => {\n try {\n const response = await fetch('/api/guest-token', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ clientId: 'your-client-id' }),\n });\n const data = await response.json();\n token = data.token;\n } catch (error) {\n console.error('Failed to fetch guest token:', error);\n }\n });\n</script>\n\n{#if !token}\n <div>Loading...</div>\n{:else}\n <${tag}\n token={token}\n ${idAttr}=\"${ctx.embedId}\"${boolAttrString}\n />\n{/if}`;\n\n const instructions = `## Svelte + Express Setup\n\n### Environment Variables\nSet the following environment variables on your backend server:\n- \\`DATABRAIN_API_TOKEN\\` - Your Databrain API token\n- \\`DATABRAIN_API_URL\\` - Your Databrain API base URL (e.g. https://api.usedatabrain.com)\n- \\`DATABRAIN_DATA_APP_NAME\\` - Default data app name for guest token generation\n\n### Security\nThe guest token must be generated server-side. Never expose your DATABRAIN_API_TOKEN to the client.\n\n### Steps\n1. Install the plugin: \\`${installCommand}\\`\n2. Set up the Express backend (server.ts) and start it\n3. Add the DatabrainEmbed.svelte component to your Svelte app\n4. Replace 'your-client-id' with the actual client identifier for the logged-in user\n5. If using SvelteKit, you can create a server route at \\`src/routes/api/guest-token/+server.ts\\` instead of a separate Express server\n6. Proxy /api requests to the Express backend in your Vite config during development\n\n### Runtime Verification Checklist\n- Call your backend \\`/api/guest-token\\` route and verify the returned token works for the target data app\n- In browser network response for \\`/api/v2/dashboard\\`, confirm \\`isAllowedToCreateMetrics=true\\` and \\`metricCreationMode=DRAG_DROP\\`\n- Ensure embed options do not include \\`disableMetricCreation=true\\`\n- Regenerate guest tokens after changing embed permissions/access settings`;\n\n return {\n installCommand,\n backendCode,\n backendLanguage: 'typescript',\n frontendCode,\n frontendLanguage: 'svelte',\n instructions,\n };\n}\n","import type { GeneratedCode, TemplateContext } from './types.js';\n\nfunction kebabCase(str: string): string {\n return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();\n}\n\nfunction buildAttributes(ctx: TemplateContext) {\n const tag = ctx.embedType === 'dashboard' ? 'dbn-dashboard' : 'dbn-metric';\n const idAttr = ctx.embedType === 'dashboard' ? 'dashboard-id' : 'metric-id';\n const boolAttrs = Object.entries(ctx.options)\n .filter(([_, v]) => v === true)\n .map(([k]) => kebabCase(k))\n .join(' ');\n return { tag, idAttr, boolAttrs };\n}\n\nexport function vanillaTemplate(ctx: TemplateContext): GeneratedCode {\n const { tag, idAttr, boolAttrs } = buildAttributes(ctx);\n const boolAttrString = boolAttrs ? ` ${boolAttrs}` : '';\n\n const installCommand = 'npm install @databrainhq/plugin';\n\n const backendCode = `// server.ts - Express backend\nimport express from 'express';\nimport cors from 'cors';\nimport path from 'path';\n\nconst app = express();\napp.use(cors());\napp.use(express.json());\napp.use(express.static('public'));\n\nconst DEFAULT_PERMISSIONS = {\n isEnableManageMetrics: true,\n isEnableMetricUpdation: true,\n isEnableCustomizeLayout: true,\n isEnableCreateDashboardView: true,\n isDisableMetricCreation: false,\n};\n\napp.post('/api/guest-token', async (req, res) => {\n const { clientId, dataAppName } = req.body;\n const resolvedDataAppName = dataAppName || process.env.DATABRAIN_DATA_APP_NAME;\n\n if (!resolvedDataAppName) {\n return res.status(400).json({\n error: 'Missing dataAppName. Provide it in request body or set DATABRAIN_DATA_APP_NAME.',\n });\n }\n\n try {\n const response = await fetch(\n \\`\\${process.env.DATABRAIN_API_URL}/api/v2/guest-token/create\\`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: \\`Bearer \\${process.env.DATABRAIN_API_TOKEN}\\`,\n },\n body: JSON.stringify({\n clientId,\n dataAppName: resolvedDataAppName,\n permissions: DEFAULT_PERMISSIONS,\n }),\n }\n );\n\n const data = await response.json();\n res.json(data);\n } catch (error) {\n console.error('Error creating guest token:', error);\n res.status(500).json({ error: 'Failed to create guest token' });\n }\n});\n\napp.listen(3001, () => {\n console.log('Server running on http://localhost:3001');\n});`;\n\n const frontendCode = `<!-- index.html - Vanilla HTML/JS -->\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <title>Databrain Embed</title>\n <script type=\"module\">\n import '@databrainhq/plugin';\n </script>\n</head>\n<body>\n <div id=\"loading\">Loading...</div>\n <${tag}\n id=\"dbn-embed\"\n ${idAttr}=\"${ctx.embedId}\"${boolAttrString}\n style=\"display: none;\"\n ></${tag}>\n\n <script>\n async function init() {\n try {\n const response = await fetch('/api/guest-token', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ clientId: 'your-client-id' }),\n });\n const data = await response.json();\n\n const embed = document.getElementById('dbn-embed');\n embed.setAttribute('token', data.token);\n embed.style.display = '';\n document.getElementById('loading').style.display = 'none';\n } catch (error) {\n console.error('Failed to fetch guest token:', error);\n document.getElementById('loading').textContent = 'Failed to load.';\n }\n }\n\n init();\n </script>\n</body>\n</html>`;\n\n const instructions = `## Vanilla JS + Express Setup\n\n### Environment Variables\nSet the following environment variables on your backend server:\n- \\`DATABRAIN_API_TOKEN\\` - Your Databrain API token\n- \\`DATABRAIN_API_URL\\` - Your Databrain API base URL (e.g. https://api.usedatabrain.com)\n- \\`DATABRAIN_DATA_APP_NAME\\` - Default data app name for guest token generation\n\n### Security\nThe guest token must be generated server-side. Never expose your DATABRAIN_API_TOKEN to the client.\n\n### Steps\n1. Install the plugin: \\`${installCommand}\\`\n Alternatively, you can use a CDN script tag instead of the npm import:\n \\`<script type=\"module\" src=\"https://cdn.jsdelivr.net/npm/@databrainhq/plugin\"></script>\\`\n2. Set up the Express backend (server.ts) which also serves the static HTML\n3. Place index.html in a \\`public/\\` directory\n4. Replace 'your-client-id' with the actual client identifier for the logged-in user\n5. Start the Express server and navigate to http://localhost:3001\n\n### Runtime Verification Checklist\n- Call your backend \\`/api/guest-token\\` route and verify the returned token works for the target data app\n- In browser network response for \\`/api/v2/dashboard\\`, confirm \\`isAllowedToCreateMetrics=true\\` and \\`metricCreationMode=DRAG_DROP\\`\n- Ensure embed options do not include \\`disableMetricCreation=true\\`\n- Regenerate guest tokens after changing embed permissions/access settings`;\n\n return {\n installCommand,\n backendCode,\n backendLanguage: 'typescript',\n frontendCode,\n frontendLanguage: 'html',\n instructions,\n };\n}\n","import type { GeneratedCode, TemplateContext } from './types.js';\n\nfunction kebabCase(str: string): string {\n return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();\n}\n\nfunction buildAttributes(ctx: TemplateContext) {\n const tag = ctx.embedType === 'dashboard' ? 'dbn-dashboard' : 'dbn-metric';\n const idAttr = ctx.embedType === 'dashboard' ? 'dashboard-id' : 'metric-id';\n const boolAttrs = Object.entries(ctx.options)\n .filter(([_, v]) => v === true)\n .map(([k]) => kebabCase(k))\n .join(' ');\n return { tag, idAttr, boolAttrs };\n}\n\nexport function vueTemplate(ctx: TemplateContext): GeneratedCode {\n const { tag, idAttr, boolAttrs } = buildAttributes(ctx);\n const boolAttrString = boolAttrs ? ` ${boolAttrs}` : '';\n\n const installCommand = 'npm install @databrainhq/plugin';\n\n const backendCode = `// server.ts - Express backend\nimport express from 'express';\nimport cors from 'cors';\n\nconst app = express();\napp.use(cors());\napp.use(express.json());\n\nconst DEFAULT_PERMISSIONS = {\n isEnableManageMetrics: true,\n isEnableMetricUpdation: true,\n isEnableCustomizeLayout: true,\n isEnableCreateDashboardView: true,\n isDisableMetricCreation: false,\n};\n\napp.post('/api/guest-token', async (req, res) => {\n const { clientId, dataAppName } = req.body;\n const resolvedDataAppName = dataAppName || process.env.DATABRAIN_DATA_APP_NAME;\n\n if (!resolvedDataAppName) {\n return res.status(400).json({\n error: 'Missing dataAppName. Provide it in request body or set DATABRAIN_DATA_APP_NAME.',\n });\n }\n\n try {\n const response = await fetch(\n \\`\\${process.env.DATABRAIN_API_URL}/api/v2/guest-token/create\\`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: \\`Bearer \\${process.env.DATABRAIN_API_TOKEN}\\`,\n },\n body: JSON.stringify({\n clientId,\n dataAppName: resolvedDataAppName,\n permissions: DEFAULT_PERMISSIONS,\n }),\n }\n );\n\n const data = await response.json();\n res.json(data);\n } catch (error) {\n console.error('Error creating guest token:', error);\n res.status(500).json({ error: 'Failed to create guest token' });\n }\n});\n\napp.listen(3001, () => {\n console.log('Server running on http://localhost:3001');\n});`;\n\n const frontendCode = `<!-- DatabrainEmbed.vue - Vue 3 SFC -->\n<script setup lang=\"ts\">\nimport { ref, onMounted } from 'vue';\nimport '@databrainhq/plugin';\n\nconst token = ref<string | null>(null);\n\nonMounted(async () => {\n try {\n const response = await fetch('/api/guest-token', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ clientId: 'your-client-id' }),\n });\n const data = await response.json();\n token.value = data.token;\n } catch (error) {\n console.error('Failed to fetch guest token:', error);\n }\n});\n</script>\n\n<template>\n <div v-if=\"!token\">Loading...</div>\n <${tag}\n v-else\n :token=\"token\"\n ${idAttr}=\"${ctx.embedId}\"${boolAttrString}\n />\n</template>`;\n\n const instructions = `## Vue 3 + Express Setup\n\n### Environment Variables\nSet the following environment variables on your backend server:\n- \\`DATABRAIN_API_TOKEN\\` - Your Databrain API token\n- \\`DATABRAIN_API_URL\\` - Your Databrain API base URL (e.g. https://api.usedatabrain.com)\n- \\`DATABRAIN_DATA_APP_NAME\\` - Default data app name for guest token generation\n\n### Security\nThe guest token must be generated server-side. Never expose your DATABRAIN_API_TOKEN to the client.\n\n### Steps\n1. Install the plugin: \\`${installCommand}\\`\n2. Set up the Express backend (server.ts) and start it\n3. Add the DatabrainEmbed.vue component to your Vue 3 app\n4. Replace 'your-client-id' with the actual client identifier for the logged-in user\n5. Configure your Vue app to recognize custom elements by adding \\`compilerOptions.isCustomElement\\` in your Vue config:\n \\`\\`\\`ts\n // vite.config.ts\n vue({\n template: {\n compilerOptions: {\n isCustomElement: (tag) => tag.startsWith('dbn-'),\n },\n },\n })\n \\`\\`\\`\n6. Proxy /api requests to the Express backend in your dev server config\n\n### Runtime Verification Checklist\n- Call your backend \\`/api/guest-token\\` route and verify the returned token works for the target data app\n- In browser network response for \\`/api/v2/dashboard\\`, confirm \\`isAllowedToCreateMetrics=true\\` and \\`metricCreationMode=DRAG_DROP\\`\n- Ensure embed options do not include \\`disableMetricCreation=true\\`\n- Regenerate guest tokens after changing embed permissions/access settings`;\n\n return {\n installCommand,\n backendCode,\n backendLanguage: 'typescript',\n frontendCode,\n frontendLanguage: 'vue',\n instructions,\n };\n}\n","import { angularTemplate } from './angular.js';\nimport { nextjsTemplate } from './nextjs.js';\nimport { reactTemplate } from './react.js';\nimport { solidjsTemplate } from './solidjs.js';\nimport { svelteTemplate } from './svelte.js';\nimport type { GeneratedCode, TemplateContext } from './types.js';\nimport { vanillaTemplate } from './vanilla.js';\nimport { vueTemplate } from './vue.js';\n\ntype Framework =\n | 'react'\n | 'nextjs'\n | 'vue'\n | 'angular'\n | 'svelte'\n | 'solidjs'\n | 'vanilla';\n\nconst templates: Record<Framework, (ctx: TemplateContext) => GeneratedCode> = {\n react: reactTemplate,\n nextjs: nextjsTemplate,\n vue: vueTemplate,\n angular: angularTemplate,\n svelte: svelteTemplate,\n solidjs: solidjsTemplate,\n vanilla: vanillaTemplate,\n};\n\nexport function getTemplate(\n framework: Framework,\n ctx: TemplateContext\n): GeneratedCode {\n return templates[framework](ctx);\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport {\n DatabrainApiError,\n toolError,\n toolSuccess,\n} from '../../utils/errors.js';\nimport {\n formatDataApp,\n resolveResource,\n} from '../../utils/resolve-resource.js';\nimport { WRITE_CREATE } from '../annotations.js';\n\nexport function registerGenerateGuestToken(\n server: McpServer,\n client: DatabrainClient\n): void {\n const services = createServiceBundle(client);\n server.tool(\n 'generate_guest_token',\n 'Generate a guest token for frontend embedding. Requires clientId. Omit dataAppName to auto-resolve.',\n {\n clientId: z\n .string()\n .describe(\n 'Unique end-user identifier for multi-tenant filtering. Use \"None\" if no tenancy.'\n ),\n dataAppName: z\n .string()\n .optional()\n .describe('Name of the data app. Omit to list available data apps.'),\n body: z\n .record(z.string(), z.unknown())\n .optional()\n .describe(\n 'Raw API body for POST /api/v2/guest-token/create. If provided, sent directly and convenience fields are ignored.'\n ),\n params: z\n .object({\n allowedEmbeds: z\n .array(z.string())\n .optional()\n .describe('Restrict token to specific embed IDs'),\n rlsSettings: z\n .array(\n z.object({\n metricId: z.string().describe('Metric ID'),\n values: z\n .record(z.string(), z.unknown())\n .describe('RLS values by column name'),\n })\n )\n .optional()\n .describe(\n 'Legacy alias used in docs/examples; forwarded as params.rlsSettings'\n ),\n appFilters: z\n .array(\n z.object({\n metricId: z.string().describe('Metric ID'),\n values: z\n .record(z.string(), z.unknown())\n .describe('Filter values by column name'),\n })\n )\n .optional()\n .describe('Metric-level app filters'),\n dashboardAppFilters: z\n .array(\n z.object({\n dashboardId: z.string().describe('Dashboard ID'),\n values: z\n .record(z.string(), z.unknown())\n .describe('Filter values by dashboard filter name'),\n isShowOnUrl: z\n .boolean()\n .optional()\n .describe('Whether filters are shown in URL params'),\n })\n )\n .optional()\n .describe('Dashboard-level app filters'),\n hideDashboardFilters: z\n .array(z.string())\n .optional()\n .describe('Dashboard filter names to hide'),\n userIdentifier: z\n .string()\n .optional()\n .describe('End-user identifier for private metrics support'),\n timezone: z\n .string()\n .optional()\n .describe('IANA timezone, e.g. \"America/New_York\"'),\n })\n .optional()\n .describe('Advanced token params'),\n\n // Legacy convenience fields (auto-mapped into params for backward compatibility)\n timezone: z\n .string()\n .optional()\n .describe('Legacy: moved under params.timezone'),\n allowedEmbeds: z\n .array(z.string())\n .optional()\n .describe('Legacy: moved under params.allowedEmbeds'),\n rlsSettings: z\n .array(\n z.object({\n metricId: z.string().describe('Metric ID'),\n values: z\n .record(z.string(), z.unknown())\n .describe('RLS values by column name'),\n })\n )\n .optional()\n .describe('Legacy: moved under params.rlsSettings'),\n appFilters: z\n .array(\n z.object({\n metricId: z.string().describe('Metric ID'),\n values: z\n .record(z.string(), z.unknown())\n .describe('Filter values by column name'),\n })\n )\n .optional()\n .describe('Legacy: moved under params.appFilters'),\n dashboardAppFilters: z\n .array(\n z.object({\n dashboardId: z\n .string()\n .describe('Dashboard ID to apply filters to'),\n values: z\n .record(z.string(), z.unknown())\n .describe('Filter values for this dashboard'),\n isShowOnUrl: z\n .boolean()\n .optional()\n .describe('Whether filters are shown in URL params'),\n })\n )\n .optional()\n .describe('Legacy: moved under params.dashboardAppFilters'),\n permissions: z\n .object({\n isEnableArchiveMetrics: z.boolean().optional(),\n isEnableManageMetrics: z.boolean().optional(),\n isEnableCreateDashboardView: z.boolean().optional(),\n isEnableMetricUpdation: z.boolean().optional(),\n isEnableCustomizeLayout: z.boolean().optional(),\n isEnableUnderlyingData: z.boolean().optional(),\n isEnableDownloadMetrics: z.boolean().optional(),\n isShowSideBar: z.boolean().optional(),\n isShowDashboardName: z.boolean().optional(),\n isDisableMetricCreation: z.boolean().optional(),\n })\n .optional()\n .describe(\n 'Runtime permission overrides (merge with and override embed-level settings)'\n ),\n theme: z\n .record(z.string(), z.unknown())\n .optional()\n .describe('Runtime theme overrides (overrides embed-level theme)'),\n hideDashboardFilters: z\n .array(z.string())\n .optional()\n .describe('Legacy: moved under params.hideDashboardFilters'),\n userIdentifier: z\n .string()\n .optional()\n .describe('Legacy: moved under params.userIdentifier'),\n expiryTime: z.number().optional().describe('Token TTL in milliseconds'),\n datasourceName: z\n .string()\n .optional()\n .describe('Datasource name for multi-datasource routing'),\n },\n WRITE_CREATE,\n async (params) => {\n try {\n const dataApps = await services.dataAppsApi.listDataApps();\n\n const resolution = resolveResource({\n items: dataApps,\n name: params.dataAppName,\n getName: (app) => app.name || app.dataAppName,\n formatItem: formatDataApp,\n resourceType: 'dataApp',\n toolName: 'generate_guest_token',\n });\n\n if (resolution.kind !== 'resolved') return resolution.response;\n\n const dataAppName = resolution.name;\n\n if (params.body) {\n const rawBody: Record<string, unknown> = { ...params.body };\n if (!rawBody.clientId) rawBody.clientId = params.clientId;\n if (!rawBody.dataAppName) rawBody.dataAppName = dataAppName;\n const result = await services.guestTokenService.generateToken(\n rawBody as any\n );\n return toolSuccess(\n `Guest token generated successfully (raw passthrough mode).\\n\\n` +\n `**Token:** \\`${result.token}\\`\\n\\n` +\n \"Use this token in the frontend `<dbn-dashboard>` or `<dbn-metric>` web component's `token` attribute.\\n\\n\" +\n 'Next step: Use `generate_embed_code` to get copy-paste-ready frontend code.'\n );\n }\n\n const resolvedParams = { ...params, dataAppName };\n const result =\n await services.guestTokenService.generateToken(resolvedParams);\n\n return toolSuccess(\n `Guest token generated successfully.\\n\\n` +\n `**Token:** \\`${result.token}\\`\\n\\n` +\n \"Use this token in the frontend `<dbn-dashboard>` or `<dbn-metric>` web component's `token` attribute.\\n\\n\" +\n 'Next step: Use `generate_embed_code` to get copy-paste-ready frontend code.'\n );\n } catch (err) {\n if (err instanceof DatabrainApiError) return err.toToolResponse();\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport {\n DatabrainApiError,\n stringify,\n toolError,\n toolSuccess,\n} from '../../utils/errors.js';\nimport {\n formatDatasource,\n resolveResource,\n} from '../../utils/resolve-resource.js';\nimport { WRITE_CREATE } from '../annotations.js';\nimport {\n APPLY_TO_PRODUCTION_CONFIRMATION,\n genericProductionSafetyNote,\n validateProductionApply,\n} from '../widgets/production-guards.js';\n\nconst columnSchema = z.object({\n name: z.string(),\n alias: z.string().optional(),\n label: z.string().optional(),\n isHide: z.boolean().optional(),\n isCustomColumn: z.boolean().optional(),\n sql: z.string().optional(),\n});\n\nconst tableSchema = z.object({\n name: z.string(),\n schemaName: z.string().optional(),\n clientColumn: z.string().optional(),\n label: z.string().optional(),\n columns: z.array(columnSchema),\n});\n\nconst relationshipSchema = z.object({\n parentTableName: z.string(),\n parentColumnName: z.string(),\n childTableName: z.string(),\n childColumnName: z.string(),\n cardinality: z.enum(['OneToOne', 'OneToMany', 'ManyToOne', 'ManyToMany']),\n join: z.enum(['INNER JOIN', 'LEFT JOIN', 'RIGHT JOIN', 'FULL JOIN']),\n relationshipName: z.string(),\n});\n\nfunction datamartSuccessMessage(\n name: string,\n result: { id?: string; _id?: string }\n): string {\n return (\n `Datamart \"${name}\" created successfully (ID: ${result.id || result._id || 'UNKNOWN'}).\\n\\n` +\n '**To query data**, complete the semantic layer first:\\n' +\n `1. \\`get_semantic_layer\\` with \\`datamartName: \"${name}\"\\` — check if table descriptions exist\\n` +\n `2. \\`update_semantic_layer\\` — add table/column descriptions and synonyms so the AI can generate accurate SQL\\n` +\n `3. \\`ask_question\\` with \\`datamartName: \"${name}\"\\` — ask natural language questions\\n\\n` +\n '**To embed dashboards** (optional):\\n' +\n '1. Connect this datamart to a workspace outside MCP\\n' +\n '2. Create a dashboard in the Databrain UI\\n' +\n '3. Use `create_embed` to embed the dashboard'\n );\n}\n\nexport function registerCreateDatamart(\n server: McpServer,\n client: DatabrainClient\n): void {\n const services = createServiceBundle(client);\n\n server.tool(\n 'create_datamart',\n 'Create a production datamart from selected tables and relationships. Defaults to dry-run; apply requires explicit confirmation.',\n {\n mode: z\n .enum(['dry_run', 'apply'])\n .default('dry_run')\n .describe('dry_run returns the plan only; apply creates the datamart'),\n confirm: z\n .string()\n .optional()\n .describe(`Required for apply: ${APPLY_TO_PRODUCTION_CONFIRMATION}`),\n name: z.string().describe('Unique datamart name'),\n datasourceName: z\n .string()\n .optional()\n .describe(\n 'Name of the datasource to use. Omit to list available datasources.'\n ),\n tableList: z\n .array(tableSchema)\n .optional()\n .describe('Array of tables with their columns'),\n relationships: z\n .array(relationshipSchema)\n .optional()\n .describe('Join definitions between tables'),\n tenancySettings: z\n .object({\n tenancyLevel: z.enum(['TABLE', 'DATABASE']).optional(),\n clientColumnType: z.string().optional(),\n schemaName: z.string().optional(),\n tableName: z.string().optional(),\n tableClientNameColumn: z.string().optional(),\n tablePrimaryKeyColumn: z.string().optional(),\n })\n .optional()\n .describe('Multi-tenant configuration'),\n body: z\n .record(z.string(), z.unknown())\n .optional()\n .describe(\n 'Raw API body passthrough for POST /api/v2/data-app/datamarts'\n ),\n },\n WRITE_CREATE,\n async (params) => {\n try {\n const mode = params.mode || 'dry_run';\n if (!params.body) {\n const datasources = await services.datasourcesApi.listDatasources();\n\n const resolution = resolveResource({\n items: datasources,\n name: params.datasourceName,\n getName: (ds) => ds.name,\n formatItem: formatDatasource,\n resourceType: 'datasource',\n toolName: 'create_datamart',\n });\n\n if (resolution.kind !== 'resolved') return resolution.response;\n\n if (!params.tableList || params.tableList.length === 0) {\n return toolError(\n 'tableList is required. Use `discover_datasource_schema` to see available tables first.'\n );\n }\n\n const body: Record<string, unknown> = {\n name: params.name,\n datasourceName: resolution.name,\n tableList: params.tableList,\n relationships: params.relationships,\n tenancySettings: params.tenancySettings,\n };\n\n if (mode === 'dry_run') {\n return toolSuccess(\n JSON.stringify(\n {\n status: 'dry_run_only',\n safety: genericProductionSafetyNote(),\n requiredApplyConfirmation: APPLY_TO_PRODUCTION_CONFIRMATION,\n body,\n nextStep: `Review this plan. To execute, call again with mode=\"apply\" and confirm=\"${APPLY_TO_PRODUCTION_CONFIRMATION}\".`,\n },\n null,\n 2\n )\n );\n }\n\n const guardError = validateProductionApply({\n confirm: params.confirm,\n });\n if (guardError) return toolError(guardError);\n\n const result = await client.request<{\n id?: string;\n _id?: string;\n error?: unknown;\n }>({\n method: 'POST',\n path: '/api/v2/data-app/datamarts',\n body,\n auth: 'service',\n invalidateCache: ['list_datamarts'],\n });\n\n if (result.error) {\n return toolError(\n `Datamart creation failed: ${stringify(result.error)}`\n );\n }\n\n return toolSuccess(datamartSuccessMessage(params.name, result));\n }\n\n if (mode === 'dry_run') {\n return toolSuccess(\n JSON.stringify(\n {\n status: 'dry_run_only',\n safety: genericProductionSafetyNote(),\n requiredApplyConfirmation: APPLY_TO_PRODUCTION_CONFIRMATION,\n body: params.body,\n nextStep: `Review this raw datamart body. To execute, call again with mode=\"apply\" and confirm=\"${APPLY_TO_PRODUCTION_CONFIRMATION}\".`,\n },\n null,\n 2\n )\n );\n }\n\n const guardError = validateProductionApply({ confirm: params.confirm });\n if (guardError) return toolError(guardError);\n\n const result = await client.request<{\n id?: string;\n _id?: string;\n error?: unknown;\n }>({\n method: 'POST',\n path: '/api/v2/data-app/datamarts',\n body: params.body,\n auth: 'service',\n invalidateCache: ['list_datamarts'],\n });\n\n if (result.error) {\n return toolError(\n `Datamart creation failed: ${stringify(result.error)}`\n );\n }\n\n return toolSuccess(datamartSuccessMessage(params.name, result));\n } catch (err) {\n if (err instanceof DatabrainApiError) return err.toToolResponse();\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport {\n DatabrainApiError,\n toolError,\n toolSuccess,\n} from '../../utils/errors.js';\nimport {\n formatDatasource,\n resolveResource,\n} from '../../utils/resolve-resource.js';\nimport { READ_ONLY } from '../annotations.js';\n\nexport function registerDiscoverDatasourceSchema(\n server: McpServer,\n client: DatabrainClient\n): void {\n const services = createServiceBundle(client);\n\n server.tool(\n 'discover_datasource_schema',\n 'Inspect tables and columns in a datasource. Omit datasourceName to list available datasources.',\n {\n datasourceName: z\n .string()\n .optional()\n .describe(\n 'Name of the datasource to inspect. Omit to list available datasources.'\n ),\n },\n READ_ONLY,\n async (params) => {\n try {\n const allDatasources = await services.datasourcesApi.listDatasources();\n const datasources = allDatasources.filter(\n (ds: any) => ds.isAuthenticated && !ds.isDisabled\n );\n\n if (datasources.length === 0 && allDatasources.length > 0) {\n const inactive = allDatasources\n .map((ds: any) => {\n const reason = (ds as any).isDisabled\n ? 'disabled'\n : 'not authenticated';\n return `- **${ds.name}** (${reason})`;\n })\n .join('\\n');\n return toolError(\n `No active datasources found. ${allDatasources.length} datasource(s) exist but are not usable:\\n\\n${inactive}\\n\\n` +\n 'Fix the connection or add a new database in the **Databrain UI**.'\n );\n }\n\n const resolution = resolveResource({\n items: datasources,\n name: params.datasourceName,\n getName: (ds) => ds.name,\n formatItem: formatDatasource,\n resourceType: 'datasource',\n toolName: 'discover_datasource_schema',\n });\n\n if (resolution.kind !== 'resolved') return resolution.response;\n\n const datasourceName = resolution.name;\n const result =\n await services.datasourcesApi.getDatasourceSchema(datasourceName);\n\n if (!result.tables || result.tables.length === 0) {\n return toolSuccess(\n `Datasource **${datasourceName}** returned no tables. ` +\n 'The datasource may need syncing — sync it in the **Databrain UI** and try again.'\n );\n }\n\n const parts: string[] = [];\n parts.push(`## Datasource Schema: ${result.datasourceName}\\n`);\n parts.push(\n `**Tables:** ${result.tableCount} | **Total columns:** ${result.columnCount}\\n`\n );\n\n const bySchema = new Map<string, typeof result.tables>();\n for (const table of result.tables) {\n const key = table.schema || 'default';\n if (!bySchema.has(key)) bySchema.set(key, []);\n bySchema.get(key)!.push(table);\n }\n\n for (const [schemaName, tables] of bySchema) {\n parts.push(`### Schema: \\`${schemaName}\\`\\n`);\n for (const table of tables) {\n parts.push(`#### ${table.name} (${table.columns.length} columns)`);\n parts.push('| Column | Type |');\n parts.push('| --- | --- |');\n for (const col of table.columns) {\n parts.push(`| ${col.name} | ${col.dataType} |`);\n }\n parts.push('');\n }\n }\n\n parts.push(\n '---\\n' +\n '**Next step:** To query these tables, a **datamart** is needed.\\n\\n' +\n '- Use `list_datamarts` to check if one already exists for this datasource\\n' +\n '- If no datamart exists, the user needs to create one in the **Databrain UI** using the tables listed above\\n' +\n '- Once a datamart exists, use `get_semantic_layer` to check its documentation, ' +\n 'then `ask_question` to query the data'\n );\n\n return toolSuccess(parts.join('\\n'));\n } catch (err) {\n if (err instanceof DatabrainApiError) return err.toToolResponse();\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport {\n DatabrainApiError,\n toolError,\n toolSuccess,\n} from '../../utils/errors.js';\nimport { READ_ONLY } from '../annotations.js';\n\nexport function registerListDatamarts(\n server: McpServer,\n client: DatabrainClient\n): void {\n server.tool(\n 'list_datamarts',\n 'List datamarts with table counts and semantic layer scores.',\n {\n dataAppName: z.string().optional().describe('Filter by data app name'),\n },\n READ_ONLY,\n async (params) => {\n try {\n const query: Record<string, string> = {};\n if (params.dataAppName) query.dataAppName = params.dataAppName;\n\n const result = await client.request<unknown[]>({\n method: 'GET',\n path: '/api/v2/data-app/datamarts',\n auth: 'service',\n query: Object.keys(query).length > 0 ? query : undefined,\n cacheKey: 'list_datamarts',\n cacheTtlMs: 10 * 60 * 1000,\n });\n\n if (!Array.isArray(result) || result.length === 0) {\n return toolError(\n 'No datamarts found. A datamart is **required** before you can query data with `ask_question`.\\n\\n' +\n 'The user needs to set this up in the **Databrain UI**:\\n' +\n '1. Connect a datasource (database) in the Databrain platform\\n' +\n '2. Create a datamart by selecting tables from the datasource\\n' +\n '3. Come back here and use `ask_question` with the `datamartName`\\n\\n' +\n 'You can use `list_datasources` and `discover_datasource_schema` to explore existing connections.'\n );\n }\n\n return toolSuccess(\n JSON.stringify({\n count: result.length,\n datamarts: result.map((dm: any) => {\n const tables = dm.datamartTables || dm.tableList || [];\n return {\n name: dm.name,\n id: dm._id || dm.id,\n tables: tables.map((t: any) => t.tableName || t.name),\n tableCount: tables.length,\n semanticScore: dm.semanticLayerCompletionScore,\n };\n }),\n })\n );\n } catch (err) {\n if (err instanceof DatabrainApiError) return err.toToolResponse();\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport {\n DatabrainApiError,\n toolError,\n toolSuccess,\n} from '../../utils/errors.js';\nimport { READ_ONLY } from '../annotations.js';\n\nexport function registerListDatasources(\n server: McpServer,\n client: DatabrainClient\n): void {\n server.tool(\n 'list_datasources',\n 'List active datasources in your organization.',\n {},\n READ_ONLY,\n async () => {\n try {\n const result = await client.request<unknown[]>({\n method: 'GET',\n path: '/api/v2/datasource/',\n auth: 'service',\n cacheKey: 'list_datasources',\n cacheTtlMs: 10 * 60 * 1000,\n });\n\n if (!Array.isArray(result) || result.length === 0) {\n return toolSuccess(\n 'No datasources found. Connect a database in the **Databrain UI** first.'\n );\n }\n\n const active = result.filter(\n (ds: any) => ds.isAuthenticated && !ds.isDisabled\n );\n const inactive = result.filter(\n (ds: any) => !ds.isAuthenticated || ds.isDisabled\n );\n\n if (active.length === 0) {\n return toolSuccess(\n JSON.stringify({\n count: 0,\n datasources: [],\n inactive: inactive.map((ds: any) => ({\n name: ds.name,\n reason: ds.isDisabled ? 'disabled' : 'not authenticated',\n })),\n hint: 'No active datasources. Fix connections or add a database in the Databrain UI.',\n })\n );\n }\n\n // The /api/v2/datasource/ list endpoint only returns\n // { name, isAuthenticated, isDisabled } — IDs are resolved lazily via\n // the schema endpoint when a tool actually needs one, so there's no\n // `id` field to surface here.\n return toolSuccess(\n JSON.stringify({\n count: active.length,\n datasources: active.map((ds: any) => ({\n name: ds.name,\n })),\n inactive:\n inactive.length > 0\n ? inactive.map((ds: any) => ({ name: ds.name }))\n : undefined,\n })\n );\n } catch (err) {\n if (err instanceof DatabrainApiError) return err.toToolResponse();\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport {\n DatabrainApiError,\n toolError,\n toolSuccess,\n} from '../../utils/errors.js';\nimport { READ_ONLY } from '../annotations.js';\n\nfunction describeConnection(ws: any): string {\n if (ws.datamart?.name) {\n return `datamart: ${ws.datamart.name}`;\n }\n if (ws.companyIntegration?.name) {\n return `datasource: ${ws.companyIntegration.name} (no datamart linked)`;\n }\n if (ws.isMultiDatasource) return 'multi-datasource mode';\n if (ws.isMultiDatamart) return 'multi-datamart mode';\n return 'no connection';\n}\n\nexport function registerListWorkspaces(\n server: McpServer,\n client: DatabrainClient\n): void {\n server.tool(\n 'list_workspaces',\n 'List workspaces with their datamart/datasource connections.',\n {},\n READ_ONLY,\n async () => {\n try {\n const result = await client.request<unknown[]>({\n method: 'GET',\n path: '/api/v2/workspace',\n auth: 'service',\n cacheKey: 'list_workspaces',\n cacheTtlMs: 5 * 60 * 1000,\n });\n\n if (!Array.isArray(result) || result.length === 0) {\n return toolSuccess(\n 'No workspaces found. Create a workspace in the **Databrain UI** first.'\n );\n }\n\n return toolSuccess(\n JSON.stringify({\n count: result.length,\n workspaces: result.map((ws: any) => ({\n name: ws.name,\n connection: describeConnection(ws),\n })),\n })\n );\n } catch (err) {\n if (err instanceof DatabrainApiError) return err.toToolResponse();\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport {\n type DatasourceRecord,\n DatasourcesApi,\n} from '../../api/datasources-api.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport {\n DatabrainApiError,\n toolError,\n toolSuccess,\n} from '../../utils/errors.js';\nimport {\n formatDatasource,\n resolveResource,\n} from '../../utils/resolve-resource.js';\nimport { WRITE_IDEMPOTENT } from '../annotations.js';\n\nexport function registerSyncDatasource(\n server: McpServer,\n client: DatabrainClient\n): void {\n const datasourcesApi = new DatasourcesApi(client);\n server.tool(\n 'sync_datasource',\n '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.',\n {\n datasourceName: z\n .string()\n .optional()\n .describe(\n 'Name of the datasource to sync. Omit to list available datasources.'\n ),\n },\n WRITE_IDEMPOTENT,\n async (params) => {\n try {\n const datasources = await client.request<DatasourceRecord[]>({\n method: 'GET',\n path: '/api/v2/datasource/',\n auth: 'service',\n cacheKey: 'list_datasources',\n cacheTtlMs: 10 * 60 * 1000,\n });\n\n const resolution = resolveResource({\n items: datasources,\n name: params.datasourceName,\n getName: (ds) => ds.name,\n formatItem: formatDatasource,\n resourceType: 'datasource',\n toolName: 'sync_datasource',\n });\n\n if (resolution.kind !== 'resolved') return resolution.response;\n\n const { selected } = resolution;\n // The list endpoint omits IDs; fall back to schema lookup by name.\n const datasourceId =\n selected._id ||\n selected.id ||\n (selected.name\n ? await datasourcesApi.resolveIdByName(selected.name)\n : null);\n if (!datasourceId) {\n return toolError(\n `Datasource \"${selected.name}\" found but has no ID. This is unexpected.`\n );\n }\n\n const result = await client.request<{\n data?: { message?: string; error?: unknown };\n }>({\n method: 'POST',\n path: '/api/v2/datasource/sync',\n body: { input: { datasourceId } },\n auth: 'service',\n invalidateCache: [`datasource_schema_${selected.name}`],\n });\n\n const message = result?.data?.message || 'Sync completed';\n return toolSuccess(\n `Datasource \"${selected.name}\" sync triggered (ID: ${datasourceId}).\\n` +\n `Status: ${message}\\n` +\n '\\nThe schema metadata will be refreshed. You can now use `discover_datasource_schema` or `create_datamart` to select tables.'\n );\n } catch (err) {\n if (err instanceof DatabrainApiError) return err.toToolResponse();\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n}\n","import { createHash } from 'node:crypto';\nimport { z } from 'zod';\nimport type { DatabrainClient } from '../client/databrain-client.js';\nimport { DatabrainApiError } from '../utils/errors.js';\nimport {\n type ChartPage,\n firstRows,\n pageSchema,\n rowsSchema,\n} from './contract.js';\n\n/** A question that became rows but is not a widget yet. Everything the tile needs to\n * redraw it as another chart type or to save it, and nothing that lets it query. */\nexport const draftSchema = z\n .object({\n question: z.string().min(1).max(2000),\n sql: z.string().min(1).max(20_000),\n datamartName: z.string().min(1).max(256),\n dimensions: z.array(z.string().max(128)).max(20).default([]),\n measures: z.array(z.string().max(128)).max(20).default([]),\n chartType: z.string().min(1).max(80),\n title: z.string().min(1).max(200),\n sessionId: z.string().max(256).optional(),\n /** Workspaces built on this datamart. One means Save needs no choice. */\n workspaces: z.array(z.string().max(256)).max(50).default([]),\n })\n .strict();\nexport type ChartDraft = z.infer<typeof draftSchema>;\n\nexport const PREVIEW_PATH = '/api/v2/data-app/chart-preview';\nexport const METRIC_PATH = '/api/mcp/metrics/create';\nexport const DASHBOARD_PATH = '/api/v2/workspace/dashboard';\n\n/** What the tile may offer as \"show as\". Mirrors the renderer's CARTESIAN + RADIAL sets,\n * minus the ones that need a series split or a date axis to mean anything. */\nexport const PREVIEW_TYPES = [\n 'bar',\n 'row',\n 'line',\n 'area',\n 'pie',\n 'doughnut',\n 'table',\n] as const;\n/** Everything the tile may ask to draw: the chips, plus a KPI when the engine chose one. */\nexport const RENDER_TYPES = [...PREVIEW_TYPES, 'single value'] as const;\n\n/** Render rows the server already holds as `chartType`. Throws DatabrainApiError with the\n * renderer's own code (UNSUPPORTED_CHART_TYPE, INVALID_CHART_CONFIG, ...) when it cannot. */\nexport async function previewPage(\n client: DatabrainClient,\n draft: ChartDraft,\n rows: unknown,\n chartType: string\n): Promise<ChartPage> {\n const page = await client.request<unknown>({\n method: 'POST',\n path: PREVIEW_PATH,\n auth: 'service',\n skipDataUnwrap: true,\n body: {\n rows: firstRows(rows),\n chartType,\n title: draft.title,\n dimensions: draft.dimensions,\n measures: draft.measures,\n width: 600,\n height: 320,\n },\n });\n return pageSchema.parse(page);\n}\n\n/** The honest fallback when nothing can be drawn: the rows, as a table. */\nexport function tablePage(\n draft: ChartDraft,\n rows: unknown\n): Record<string, unknown> {\n const page = firstRows(rows);\n return {\n kind: 'table',\n title: draft.title,\n chartSpec: { type: 'table' },\n rows: page,\n columns: Object.keys(page[0] ?? {}),\n };\n}\n\n/** Draw the draft as `chartType`, or as a table when the renderer cannot: a refusal, an\n * outage, a bad page. The rows are the answer; a preview failure must not cost them. The\n * result always carries the draft, so the tile can offer \"show as\" and \"save\" either way. */\nexport async function draftPage(\n client: DatabrainClient,\n draft: ChartDraft,\n rows: unknown,\n chartType: string\n): Promise<Record<string, unknown>> {\n const data = rowsSchema.parse(firstRows(rows));\n const carry = { draft: { ...draft, chartType }, previewTypes: PREVIEW_TYPES };\n if (chartType === 'table' || !data.length)\n return { ...tablePage(draft, data), ...carry };\n try {\n return { ...(await previewPage(client, draft, data, chartType)), ...carry };\n } catch (error) {\n const previewError =\n error instanceof DatabrainApiError ? error.code : 'PREVIEW_UNAVAILABLE';\n return {\n ...tablePage(draft, data),\n ...carry,\n draft: { ...draft, chartType: 'table' },\n previewError,\n };\n }\n}\n\ntype Ref = { id?: string; name?: string } | null | undefined;\ntype WorkspaceRecord = {\n name?: string;\n datamart?: Ref;\n datamartName?: string;\n companyIntegration?: Ref;\n};\ntype DatamartRecord = {\n name?: string;\n datamartName?: string;\n companyIntegration?: Ref;\n};\n/** Datamart names compare case-insensitively and trimmed, the way every resolver here does. */\nconst sameName = (a: unknown, b: string) =>\n typeof a === 'string' && a.trim().toLowerCase() === b.trim().toLowerCase();\n/** Workspaces that can run the draft's SQL: those built on this datamart, and those built\n * directly on the datamart's datasource (the SQL names that datasource's tables). Matched\n * by datasource id, never name — one company can own two datasources called \"Postgres\".\n * Datamart workspaces first, so a single obvious home needs no choice. */\nexport async function workspacesForDatamart(\n client: DatabrainClient,\n datamartName: string,\n mode: 'hint' | 'authorize' = 'hint'\n): Promise<string[]> {\n // The picker may read a five-minute cache. A save may not: it decides where a production\n // write lands, so membership is read live every time.\n const cached = (key: string) =>\n mode === 'hint' ? { cacheKey: key, cacheTtlMs: 5 * 60 * 1000 } : {};\n try {\n const [workspaces, datamarts] = await Promise.all([\n client.request<WorkspaceRecord[]>({\n method: 'GET',\n path: '/api/v2/workspace',\n auth: 'service',\n ...cached('list_workspaces'),\n }),\n client.request<DatamartRecord[]>({\n method: 'GET',\n path: '/api/v2/data-app/datamarts',\n auth: 'service',\n ...cached('list_datamarts'),\n }),\n ]);\n const datasource = (Array.isArray(datamarts) ? datamarts : []).find((d) =>\n sameName(d?.name ?? d?.datamartName, datamartName)\n )?.companyIntegration?.id;\n const all = (Array.isArray(workspaces) ? workspaces : []).filter(\n (w) => typeof w?.name === 'string'\n );\n const onDatamart = all.filter((w) =>\n sameName(w.datamart?.name ?? w.datamartName, datamartName)\n );\n const onDatasource = datasource\n ? all.filter(\n (w) => !w.datamart && w.companyIntegration?.id === datasource\n )\n : [];\n return [\n ...new Set([...onDatamart, ...onDatasource].map((w) => w.name as string)),\n ];\n } catch {\n return [];\n }\n}\n\nexport type SavedChart = {\n dashboardId: string;\n metricId: string;\n workspaceName: string;\n title: string;\n};\nexport type SaveInput = {\n chartType: string;\n dashboardTitle: string;\n workspaceName: string;\n attemptId?: string;\n};\n\n/** The Idempotency-Key for a save, derived from what the save writes. An identical retry\n * (a host that re-sends after a timeout, a person who presses Save twice) replays the\n * first response instead of inserting a second dashboard. Shaped as a UUID v4 because\n * the backend accepts nothing else. */\nexport function saveKey(draft: ChartDraft, input: SaveInput): string {\n const h = createHash('sha256')\n .update(\n JSON.stringify({\n sql: draft.sql,\n datamartName: draft.datamartName,\n workspaceName: input.workspaceName,\n dashboardTitle: input.dashboardTitle,\n chartType: input.chartType,\n // One attempt, many retries: the tile mints an id when the form opens and re-sends it on\n // retry, so a retry replays and a fresh Save is a fresh key. Without one, content is the key.\n attemptId: input.attemptId ?? null,\n })\n )\n .digest();\n h[6] = (h[6] & 0x0f) | 0x40;\n h[8] = (h[8] & 0x3f) | 0x80;\n const x = h.subarray(0, 16).toString('hex');\n return `${x.slice(0, 8)}-${x.slice(8, 12)}-${x.slice(12, 16)}-${x.slice(16, 20)}-${x.slice(20, 32)}`;\n}\n\n/** Two existing writes, in order: a workspace metric from the draft's SQL, then a\n * dashboard holding one tile that references it. The backend resolves the datasource\n * from the workspace, and derives axes from the query, so nothing is guessed here. */\nexport async function saveDraftAsDashboard(\n client: DatabrainClient,\n draft: ChartDraft,\n input: SaveInput\n): Promise<SavedChart> {\n const metric = await client.request<{ id?: string; metricId?: string }>({\n method: 'POST',\n path: METRIC_PATH,\n auth: 'service',\n body: {\n workspaceName: input.workspaceName,\n name: input.dashboardTitle,\n query: draft.sql,\n description: draft.question,\n isPublished: false,\n validateOnly: false,\n },\n });\n const metricId = metric?.metricId || metric?.id;\n if (!metricId)\n throw new DatabrainApiError(\n 502,\n 'METRIC_ID_MISSING',\n 'The metric was created but returned no id.'\n );\n const slug =\n input.dashboardTitle\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, 63) || 'chart';\n const body = {\n schemaVersion: 1,\n title: input.dashboardTitle,\n description: draft.question,\n layout: { columns: 24 },\n tiles: [\n {\n id: slug,\n kind: 'databrain-chart',\n title: input.dashboardTitle,\n position: { x: 0, y: 0, w: 12, h: 8 },\n chart: { type: input.chartType, metricRef: metricId },\n },\n ],\n };\n const dashboard = await client.request<{ dashboardId?: string }>({\n method: 'POST',\n path: DASHBOARD_PATH,\n auth: 'service',\n query: { workspaceName: input.workspaceName },\n headers: { 'Idempotency-Key': saveKey(draft, input) },\n body,\n invalidateCache: ['list_dashboards'],\n // A metadata insert: 15s keeps the attempt and its retries inside the host's 60s window.\n timeoutMs: 15_000,\n });\n if (!dashboard?.dashboardId) {\n throw new DatabrainApiError(\n 502,\n 'DASHBOARD_ID_MISSING',\n `Metric ${metricId} was saved but the dashboard returned no id.`\n );\n }\n return {\n dashboardId: dashboard.dashboardId,\n metricId,\n workspaceName: input.workspaceName,\n title: input.dashboardTitle,\n };\n}\n","import { firstRows } from '../../apps/contract.js';\nimport { chartResult, hasChartApps, tagChartTool } from '../../apps/feature.js';\nimport {\n draftPage,\n RENDER_TYPES,\n tablePage,\n workspacesForDatamart,\n} from '../../apps/preview.js';\n\n/** The defaults engine names types the renderer knows; map the rest to the nearest\n * drawable one, and anything else to a table. Never guess a type from the data here. */\nfunction normalizePreviewType(\n type: string | undefined\n): (typeof RENDER_TYPES)[number] {\n const t = (type || '').toLowerCase().trim();\n if ((RENDER_TYPES as readonly string[]).includes(t))\n return t as (typeof RENDER_TYPES)[number];\n if (t === 'single value' || t === 'kpi' || t === 'number')\n return 'single value';\n if (t === 'time series' || t === 'stepped') return 'line';\n if (t === 'stack' || t === 'column') return 'bar';\n if (t === 'horizontal stack' || t === 'horizontal bar') return 'row';\n if (t === 'stacked area') return 'area';\n return 'table';\n}\n\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport {\n DatabrainApiError,\n toolError,\n toolSuccess,\n} from '../../utils/errors.js';\nimport { logger } from '../../utils/logger.js';\nimport { formatDatamart } from '../../utils/resolve-resource.js';\nimport { WRITE_CREATE } from '../annotations.js';\nimport { formatConfidence, formatProse } from './answer-format.js';\n\nconst MAX_DISPLAY_ROWS = 50;\n\nfunction formatDataTable(\n data: unknown[],\n columns: { dimensions: string[]; measures: string[] }\n): string {\n if (!Array.isArray(data) || data.length === 0) return '_No data returned._';\n\n const allCols = [...(columns.dimensions || []), ...(columns.measures || [])];\n if (allCols.length === 0) {\n const first = data[0] as Record<string, unknown>;\n if (first && typeof first === 'object') allCols.push(...Object.keys(first));\n }\n if (allCols.length === 0) return '_No columns identified._';\n\n const header = `| ${allCols.join(' | ')} |`;\n const separator = `| ${allCols.map(() => '---').join(' | ')} |`;\n\n const displayRows = data.slice(0, MAX_DISPLAY_ROWS);\n const rows = displayRows.map((row) => {\n const r = row as Record<string, unknown>;\n return `| ${allCols.map((c) => String(r[c] ?? '')).join(' | ')} |`;\n });\n\n const truncation =\n data.length > MAX_DISPLAY_ROWS\n ? `\\n\\n_Showing ${MAX_DISPLAY_ROWS} of ${data.length} rows._`\n : '';\n\n return `${header}\\n${separator}\\n${rows.join('\\n')}${truncation}`;\n}\n\nexport function registerAskQuestion(\n server: McpServer,\n client: DatabrainClient\n): void {\n const services = createServiceBundle(client);\n\n const tool = server.tool(\n 'ask_question',\n 'Ask a natural language question — converts to SQL, returns data + chart suggestion. Requires datamartName with a populated semantic layer.',\n {\n question: z\n .string()\n .describe(\n 'The natural language question to ask (e.g. \"What was total revenue last month?\")'\n ),\n datamartName: z\n .string()\n .optional()\n .describe(\n '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.'\n ),\n sessionId: z\n .string()\n .optional()\n .describe(\n 'Session ID from a previous ask_question response, for follow-up questions.'\n ),\n timezone: z\n .string()\n .optional()\n .describe('IANA timezone (e.g. \"America/New_York\"). Defaults to UTC.'),\n },\n WRITE_CREATE,\n async (params) => {\n try {\n let datamartName = params.datamartName;\n\n // --- Pre-requisite 1: Must resolve to a datamartName ---\n {\n const datamarts = await services.datamartsApi.listDatamarts();\n if (!Array.isArray(datamarts) || datamarts.length === 0) {\n return toolError(\n 'No datamarts are available in this workspace. A datamart is **required** before you can query data.\\n\\n' +\n 'Tell the user they need to create a datamart in the **Databrain UI** first:\\n' +\n '1. Go to the Databrain platform and connect a datasource\\n' +\n '2. Create a datamart by selecting tables from the datasource\\n' +\n '3. Come back here and use `ask_question` with the `datamartName`\\n\\n' +\n \"You can use `list_datasources` and `discover_datasource_schema` to explore what's available.\"\n );\n }\n if (!datamartName && datamarts.length === 1) {\n const resolvedName = datamarts[0].name || datamarts[0].datamartName;\n if (!resolvedName) {\n return toolError(\n 'Found one datamart, but the API did not return a usable name. Use `list_datamarts` to inspect the response and pass `datamartName` explicitly.'\n );\n }\n datamartName = resolvedName;\n } else if (!datamartName) {\n const list = datamarts.map(formatDatamart).join('\\n');\n return toolSuccess(\n `Found ${datamarts.length} datamarts. Please specify which one to query:\\n\\n` +\n `${list}\\n\\n` +\n 'Call `ask_question` again with the `datamartName` parameter.'\n );\n }\n }\n if (!datamartName) {\n return toolError(\n 'Could not resolve a datamart name. Use `list_datamarts`, then call `ask_question` again with `datamartName`.'\n );\n }\n\n // --- Pre-requisite 2: Semantic layer must be populated ---\n // The semantic layer is metadata (descriptions, synonyms) on the\n // datamart's tables/columns. Tables always exist if the datamart does,\n // but if no descriptions exist the AI can't generate accurate SQL.\n try {\n const semanticLayer =\n await services.queryApi.getSemanticLayer(datamartName);\n const hasTables =\n semanticLayer.tables && semanticLayer.tables.length > 0;\n\n if (!hasTables) {\n return toolError(\n `The datamart \"${datamartName}\" has no tables. It may not be set up correctly.\\n\\n` +\n 'The user should check the datamart in the **Databrain UI** and ensure tables are added.'\n );\n }\n\n const hasAnyDescription = semanticLayer.tables.some(\n (t) =>\n t.description ||\n (t.columns ?? []).some((c) => c.description || c.columnType)\n );\n\n if (!hasAnyDescription) {\n const totalCols = semanticLayer.tables.reduce(\n (sum, t) => sum + (t.columns?.length ?? 0),\n 0\n );\n const tableNames = semanticLayer.tables\n .map((t) => t.name)\n .join(', ');\n return toolError(\n `TABLES ARE ALREADY SYNCED — do NOT tell the user to add tables or go to the UI.\\n\\n` +\n `The datamart \"${datamartName}\" has ${semanticLayer.tables.length} table(s) and ${totalCols} column(s): ${tableNames}.\\n` +\n `The data is there, but none of the tables or columns have descriptions or synonyms yet.\\n` +\n `Without descriptions the AI cannot map natural language to SQL, so queries will fail.\\n\\n` +\n `YOU (the assistant) should populate the semantic layer right now:\\n` +\n `1. Call \\`get_semantic_layer\\` with datamartName \"${datamartName}\" to see all tables and columns\\n` +\n `2. Auto-generate business-friendly descriptions from the table/column names (you're an LLM — infer what each represents)\\n` +\n `3. Call \\`update_semantic_layer\\` with datamartName \"${datamartName}\" to push those descriptions\\n` +\n `4. Then call \\`ask_question\\` again — it will work once descriptions exist\\n\\n` +\n `Use the \\`populate-semantic-layer\\` prompt for a detailed step-by-step workflow.\\n` +\n `Do NOT send the user to the Databrain UI for this.\\n` +\n `Do NOT call \\`ask_question\\` again until you have added descriptions.`\n );\n }\n } catch (slErr) {\n if (\n slErr instanceof DatabrainApiError &&\n (slErr.status === 404 || slErr.status === 400)\n ) {\n return toolError(\n `Could not retrieve semantic layer for \"${datamartName}\" (${slErr.message}).\\n\\n` +\n 'Check that the datamart exists and is correctly set up in the **Databrain UI**.\\n' +\n `You can verify with \\`get_semantic_layer\\` using datamartName \"${datamartName}\".`\n );\n }\n logger.warn('Semantic layer pre-check failed, proceeding anyway', {\n error: (slErr as Error).message,\n });\n }\n\n const config = params.sessionId\n ? {\n followUp: {\n isEnable: true,\n previousQuestion: '',\n previousSql: '',\n },\n }\n : undefined;\n\n const result = await services.queryApi.askQuestion({\n question: params.question,\n datamartName,\n sessionId: params.sessionId,\n config,\n timezone: params.timezone,\n });\n\n const data = Array.isArray(result.data) ? result.data : [];\n if (hasChartApps(server)) {\n // The answer draws as a chart the moment it exists. The chart type is the\n // defaults engine's call (suggestedChartType); the tile can redraw it as another\n // type from the same rows, and save it, without asking the model again.\n const chartType = normalizePreviewType(result.suggestedChartType);\n const draft = {\n question: params.question,\n sql: result.query || '',\n datamartName,\n dimensions: result.columns?.dimensions || [],\n measures: result.columns?.measures || [],\n chartType,\n title: params.question.slice(0, 200),\n sessionId: result.sessionId || undefined,\n workspaces: await workspacesForDatamart(client, datamartName),\n };\n const rows = firstRows(data);\n const page = draft.sql\n ? await draftPage(client, draft, rows, chartType)\n : { ...tablePage(draft, rows), previewTypes: [] };\n const shown =\n rows.length === data.length\n ? `${data.length} rows`\n : `first ${rows.length} of ${data.length} rows`;\n try {\n return chartResult(\n `${page.kind === 'table' ? 'Table' : 'Chart'} ready (${page.chartSpec && (page.chartSpec as { type: string }).type}): ${shown}.` +\n (result.summary ? ` ${result.summary}` : ''),\n { ...page, rowsTotal: data.length }\n );\n } catch (error) {\n // An optional chart must not discard an answer that the text path can return.\n if (\n !(error instanceof Error) ||\n error.message !== 'Chart page exceeds payload budget'\n )\n throw error;\n }\n }\n const table = formatDataTable(data, result.columns);\n\n const parts: string[] = [];\n parts.push(`## Query Results\\n`);\n parts.push(`**Question:** ${params.question}`);\n parts.push(`**Suggested chart type:** ${result.suggestedChartType}`);\n const confidence = formatConfidence(result.confidence);\n if (confidence) {\n parts.push(`**Confidence:** ${confidence}`);\n }\n parts.push(\n `**Rows returned:** ${data.length} | **Time:** ${result.timeTaken}ms`\n );\n const reasoning = formatProse(result.reasoning);\n if (reasoning) {\n parts.push(`\\n### Reasoning\\n${reasoning}`);\n }\n const summary = formatProse(result.summary);\n if (summary) {\n parts.push(`\\n### Summary\\n${summary}`);\n }\n parts.push(`\\n### Data\\n\\n${table}`);\n if (result.columns) {\n const dims = result.columns.dimensions?.join(', ') || 'none';\n const meas = result.columns.measures?.join(', ') || 'none';\n parts.push(`\\n**Dimensions:** ${dims}\\n**Measures:** ${meas}`);\n }\n if (result.sessionId) {\n parts.push(`\\n_Session ID for follow-up: \\`${result.sessionId}\\`_`);\n }\n\n return toolSuccess(parts.join('\\n'));\n } catch (err) {\n if (err instanceof DatabrainApiError) {\n const msg = err.message.toLowerCase();\n if (\n msg.includes('out of context') ||\n msg.includes('definition not found') ||\n msg.includes('not a data question')\n ) {\n return toolError(\n `The AI could not generate SQL for this question: ${err.message}\\n\\n` +\n 'This means the question does not match the tables/columns in the datamart. Do NOT retry the same question.\\n\\n' +\n 'To fix this:\\n' +\n '1. Use `get_semantic_layer` to check what tables and columns exist\\n' +\n '2. Rephrase the question using column/table names from the semantic layer\\n' +\n '3. If the semantic layer is sparse, use `update_semantic_layer` to add descriptions and synonyms'\n );\n }\n return err.toToolResponse();\n }\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n tagChartTool(server, tool);\n}\n","/*\n * The `/api/v2/data-app/ask` response is looser than the `QueryResult` type\n * says: `confidence` arrives on a 0-100 scale (90, not 0.9), and `reasoning`\n * and `summary` arrive as arrays of sentences. Rendered straight, the tool\n * printed \"Confidence: 9000%\" and a comma-glued paragraph. These keep both\n * shapes readable, whichever the backend sends.\n */\n\n/** \"90%\" for 90 or 0.9; null when the value is not a finite number. */\nexport function formatConfidence(value: unknown): string | null {\n if (typeof value !== 'number' || !Number.isFinite(value)) return null;\n const percent = value > 1 ? value : value * 100;\n return `${Math.round(Math.min(Math.max(percent, 0), 100))}%`;\n}\n\n/** One line for a string, one bullet per item for an array, null when empty. */\nexport function formatProse(value: unknown): string | null {\n if (Array.isArray(value)) {\n const items = value\n .filter(\n (item): item is string => typeof item === 'string' && item.trim() !== ''\n )\n .map((item) => `- ${item.trim()}`);\n return items.length ? items.join('\\n') : null;\n }\n if (typeof value === 'string' && value.trim() !== '') return value.trim();\n return null;\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport {\n DatabrainApiError,\n toolError,\n toolSuccess,\n} from '../../utils/errors.js';\nimport {\n formatDatamart,\n resolveResource,\n} from '../../utils/resolve-resource.js';\nimport { READ_ONLY } from '../annotations.js';\n\nexport function registerGetSemanticLayer(\n server: McpServer,\n client: DatabrainClient\n): void {\n const services = createServiceBundle(client);\n\n server.tool(\n 'get_semantic_layer',\n 'Get semantic layer metadata for a datamart: table/column descriptions, synonyms, completion score. Omit datamartName to auto-resolve.',\n {\n datamartName: z\n .string()\n .optional()\n .describe(\n 'Name of the datamart to inspect. Omit to list available datamarts.'\n ),\n },\n READ_ONLY,\n async (params) => {\n try {\n const datamarts = await services.datamartsApi.listDatamarts();\n\n const resolution = resolveResource({\n items: datamarts,\n name: params.datamartName,\n getName: (dm) => dm.name || dm.datamartName,\n formatItem: formatDatamart,\n resourceType: 'datamart',\n toolName: 'get_semantic_layer',\n });\n\n if (resolution.kind !== 'resolved') return resolution.response;\n\n const datamartName = resolution.name;\n const result = await services.queryApi.getSemanticLayer(datamartName);\n\n const parts: string[] = [];\n const hasTables = result.tables && result.tables.length > 0;\n const hasAnyDescription =\n hasTables &&\n result.tables.some(\n (t: any) =>\n t.description ||\n (t.columns ?? []).some((c: any) => c.description || c.columnType)\n );\n\n if (hasTables && !hasAnyDescription) {\n const totalCols = result.tables.reduce(\n (sum: number, t: any) => sum + (t.columns?.length ?? 0),\n 0\n );\n parts.push(\n '**SEMANTIC LAYER IS EMPTY — ACTION REQUIRED**\\n\\n' +\n `The datamart \"${result.datamartName}\" has ${result.tables.length} table(s) and ${totalCols} column(s) synced, but NONE have descriptions or synonyms.\\n` +\n 'Without descriptions, `ask_question` will fail.\\n\\n' +\n '**You (the assistant) should populate the semantic layer now:**\\n' +\n '1. Review the tables and columns listed below\\n' +\n '2. Auto-generate business-friendly descriptions from the table/column names\\n' +\n `3. Call \\`update_semantic_layer\\` with datamartName \"${result.datamartName}\" and your generated descriptions\\n` +\n '4. Then `ask_question` will work\\n\\n' +\n 'Do NOT send the user to the UI for this. Do NOT use `list_datasources` or `discover_datasource_schema`. ' +\n 'Use the `populate-semantic-layer` prompt for a detailed step-by-step workflow.\\n\\n---\\n'\n );\n }\n\n parts.push(`## Semantic Layer: ${result.datamartName}\\n`);\n parts.push(`**Completion Score:** ${result.completionScore}%`);\n if (result.lastUpdated) {\n parts.push(`**Last Updated:** ${result.lastUpdated}`);\n }\n if (result.feedback) {\n parts.push(`\\n### General Feedback / Context\\n${result.feedback}`);\n }\n\n if (hasTables) {\n parts.push(`\\n### Tables (${result.tables.length})\\n`);\n for (const table of result.tables) {\n parts.push(`#### ${table.name}`);\n if (table.schemaName) {\n parts.push(`Schema: \\`${table.schemaName}\\``);\n }\n if (table.description) {\n parts.push(`Description: ${table.description}`);\n }\n if (table.synonyms && table.synonyms.length > 0) {\n parts.push(`Synonyms: ${table.synonyms.join(', ')}`);\n }\n\n if (table.columns && table.columns.length > 0) {\n parts.push('');\n parts.push('| Column | Type | Description | Synonyms |');\n parts.push('| --- | --- | --- | --- |');\n for (const col of table.columns) {\n const synonyms =\n col.synonyms && col.synonyms.length > 0\n ? col.synonyms.join(', ')\n : '';\n parts.push(\n `| ${col.name} | ${col.datatype || col.columnType || ''} | ${col.description || ''} | ${synonyms} |`\n );\n }\n }\n parts.push('');\n }\n } else {\n parts.push(\n '\\n_No tables found in the semantic layer. The datamart may need syncing or the semantic layer may not be configured yet._'\n );\n }\n\n if (hasTables && hasAnyDescription && result.completionScore < 50) {\n parts.push(\n '\\n> **Tip:** The completion score is below 50%. Consider using `update_semantic_layer` to add more descriptions, synonyms, and example questions for better AI query accuracy.'\n );\n }\n\n return toolSuccess(parts.join('\\n'));\n } catch (err) {\n if (err instanceof DatabrainApiError) return err.toToolResponse();\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport {\n DatabrainApiError,\n toolError,\n toolSuccess,\n} from '../../utils/errors.js';\nimport {\n formatDatamart,\n formatWorkspace,\n resolveResource,\n} from '../../utils/resolve-resource.js';\nimport { READ_ONLY, WRITE_CREATE } from '../annotations.js';\n\nfunction nonEmptyString(value: unknown): string | null {\n return typeof value === 'string' && value.trim().length > 0 ? value : null;\n}\n\nfunction datamartIdFrom(datamart: Record<string, unknown>): string | null {\n return (\n nonEmptyString(datamart.id) ||\n nonEmptyString(datamart._id) ||\n nonEmptyString(datamart.datamartId) ||\n nonEmptyString(datamart.dataMartId) ||\n null\n );\n}\n\nfunction nestedDatamartFromWorkspace(\n workspace: Record<string, unknown>\n): Record<string, unknown> | null {\n const nested = workspace.datamart;\n return nested && typeof nested === 'object' && !Array.isArray(nested)\n ? (nested as Record<string, unknown>)\n : null;\n}\n\nfunction workspaceDatamartIdFrom(\n workspace: Record<string, unknown>\n): string | null {\n const nested = nestedDatamartFromWorkspace(workspace);\n return (\n nonEmptyString(workspace.dataMartId) ||\n nonEmptyString(workspace.datamartId) ||\n (nested ? datamartIdFrom(nested) : null)\n );\n}\n\nfunction workspaceDatamartNameFrom(\n workspace: Record<string, unknown>\n): string | null {\n const nested = nestedDatamartFromWorkspace(workspace);\n return (\n (nested\n ? nonEmptyString(nested.name) || nonEmptyString(nested.datamartName)\n : null) ||\n nonEmptyString(workspace.datamartName) ||\n null\n );\n}\n\nasync function resolveDatamartFromWorkspace(params: {\n client: DatabrainClient;\n workspaceName: string;\n datamartName?: string;\n toolName: string;\n}): Promise<\n | {\n ok: true;\n datamartName: string;\n datamartId: string;\n workspaceName: string;\n }\n | {\n ok: false;\n response: ReturnType<typeof toolError> | ReturnType<typeof toolSuccess>;\n }\n> {\n const services = createServiceBundle(params.client);\n const workspaces = await services.workspacesApi.listWorkspaces();\n const resolution = resolveResource({\n items: workspaces,\n name: params.workspaceName,\n getName: (ws) => ws.name,\n formatItem: formatWorkspace,\n resourceType: 'workspace',\n toolName: params.toolName,\n });\n\n if (resolution.kind !== 'resolved')\n return { ok: false, response: resolution.response };\n\n const selected = resolution.selected as Record<string, unknown>;\n const datamartId = workspaceDatamartIdFrom(selected);\n const workspaceDatamartName = workspaceDatamartNameFrom(selected);\n\n if (!datamartId) {\n return {\n ok: false,\n response: toolError(\n `Workspace \"${resolution.name}\" does not expose a linked dataMartId/datamart.id. Pass datamartId directly or choose a workspace linked to a datamart.`\n ),\n };\n }\n\n if (\n params.datamartName &&\n workspaceDatamartName &&\n workspaceDatamartName.toLowerCase() !== params.datamartName.toLowerCase()\n ) {\n return {\n ok: false,\n response: toolError(\n `Workspace \"${resolution.name}\" is linked to datamart \"${workspaceDatamartName}\", not \"${params.datamartName}\". Use the linked datamart name or choose another workspace.`\n ),\n };\n }\n\n return {\n ok: true,\n datamartName: workspaceDatamartName || params.datamartName || datamartId,\n datamartId,\n workspaceName: resolution.name,\n };\n}\n\nasync function resolveDatamart(params: {\n client: DatabrainClient;\n datamartId?: string;\n datamartName?: string;\n workspaceName?: string;\n toolName: string;\n}): Promise<\n | {\n ok: true;\n datamartName: string;\n datamartId: string;\n workspaceName?: string;\n }\n | {\n ok: false;\n response: ReturnType<typeof toolError> | ReturnType<typeof toolSuccess>;\n }\n> {\n if (params.datamartId) {\n return {\n ok: true,\n datamartName: params.datamartName || params.datamartId,\n datamartId: params.datamartId,\n workspaceName: params.workspaceName,\n };\n }\n\n if (params.workspaceName) {\n return resolveDatamartFromWorkspace({\n client: params.client,\n workspaceName: params.workspaceName,\n datamartName: params.datamartName,\n toolName: params.toolName,\n });\n }\n\n const services = createServiceBundle(params.client);\n const datamarts = await services.datamartsApi.listDatamarts();\n const resolution = resolveResource({\n items: datamarts,\n name: params.datamartName,\n getName: (dm) => dm.name || dm.datamartName,\n formatItem: formatDatamart,\n resourceType: 'datamart',\n toolName: params.toolName,\n });\n\n if (resolution.kind !== 'resolved')\n return { ok: false, response: resolution.response };\n\n const datamartId = datamartIdFrom(\n resolution.selected as Record<string, unknown>\n );\n if (!datamartId) {\n return {\n ok: false,\n response: toolError(\n `Datamart \"${resolution.name}\" did not include an ID in the datamart list. Refresh the list and try again, or pass datamartId directly.`\n ),\n };\n }\n\n return {\n ok: true,\n datamartName: resolution.name,\n datamartId,\n };\n}\n\nexport function registerStartSemanticLayerGeneration(\n server: McpServer,\n client: DatabrainClient\n): void {\n const services = createServiceBundle(client);\n\n server.tool(\n 'start_semantic_layer_generation',\n 'Start backend semantic-layer auto-generation for a datamart through a hosted OAuth sign-in. Static service-token authentication is not supported by this backend route. Returns an async job id to poll.',\n {\n datamartName: z\n .string()\n .optional()\n .describe('Datamart name. Omit to list available datamarts'),\n workspaceName: z\n .string()\n .optional()\n .describe(\n 'Workspace linked to the datamart. Use when datamartName resolution needs a dataMartId bridge.'\n ),\n datamartId: z\n .string()\n .optional()\n .describe('Datamart UUID. Use only when already known.'),\n },\n WRITE_CREATE,\n async (params) => {\n try {\n const resolved = await resolveDatamart({\n client,\n datamartId: params.datamartId,\n datamartName: params.datamartName,\n workspaceName: params.workspaceName,\n toolName: 'start_semantic_layer_generation',\n });\n if (!resolved.ok) return resolved.response;\n\n const result = await services.queryApi.startSemanticLayerGeneration(\n resolved.datamartId\n );\n\n return toolSuccess(\n JSON.stringify(\n {\n datamartName: resolved.datamartName,\n datamartId: resolved.datamartId,\n workspaceName: resolved.workspaceName,\n ...result,\n nextStep:\n 'Call get_semantic_layer_generation_status with the same datamartName or workspaceName until status is complete or failed.',\n },\n null,\n 2\n )\n );\n } catch (err) {\n if (err instanceof DatabrainApiError) return err.toToolResponse();\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n}\n\nexport function registerGetSemanticLayerGenerationStatus(\n server: McpServer,\n client: DatabrainClient\n): void {\n const services = createServiceBundle(client);\n\n server.tool(\n 'get_semantic_layer_generation_status',\n 'Get semantic-layer auto-generation job status for a datamart through a hosted OAuth sign-in. Static service-token authentication is not supported by this backend route.',\n {\n datamartName: z\n .string()\n .optional()\n .describe('Datamart name. Omit to list available datamarts'),\n workspaceName: z\n .string()\n .optional()\n .describe(\n 'Workspace linked to the datamart. Use when datamartName resolution needs a dataMartId bridge.'\n ),\n datamartId: z\n .string()\n .optional()\n .describe('Datamart UUID. Use only when already known.'),\n },\n READ_ONLY,\n async (params) => {\n try {\n const resolved = await resolveDatamart({\n client,\n datamartId: params.datamartId,\n datamartName: params.datamartName,\n workspaceName: params.workspaceName,\n toolName: 'get_semantic_layer_generation_status',\n });\n if (!resolved.ok) return resolved.response;\n\n const result = await services.queryApi.getSemanticLayerGenerationStatus(\n resolved.datamartId\n );\n\n return toolSuccess(\n JSON.stringify(\n {\n datamartName: resolved.datamartName,\n datamartId: resolved.datamartId,\n workspaceName: resolved.workspaceName,\n ...result,\n },\n null,\n 2\n )\n );\n } catch (err) {\n if (err instanceof DatabrainApiError) return err.toToolResponse();\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type { SemanticModelApi } from '../../api/semantic-model-api.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport { retrieveSemanticSource } from '../../services/semantic-retrieval.js';\nimport {\n changeSemanticSource,\n isObject,\n parseSemanticSource,\n type StructuredSemanticChange,\n semanticEntities,\n} from '../../services/semantic-source.js';\nimport {\n DatabrainApiError,\n stringify,\n toolError,\n toolSuccess,\n} from '../../utils/errors.js';\nimport { DESTRUCTIVE, READ_ONLY } from '../annotations.js';\nimport { validateProductionApply } from '../widgets/production-guards.js';\n\nconst datamartId = z\n .string()\n .trim()\n .min(1)\n .max(256)\n .describe('Datamart ID from list_datamarts.');\nconst source = z\n .string()\n .min(1)\n .max(2_000_000)\n .describe('Complete proposed semantic model as YAML.');\nconst entityKind = z.enum([\n 'table',\n 'column',\n 'measure',\n 'metric',\n 'join',\n 'entity',\n 'glossary',\n 'saved_query',\n 'instruction',\n 'access_rule',\n]);\nconst changeInputs = {\n source: source.optional(),\n yaml_patch: z\n .string()\n .min(1)\n .max(2_000_000)\n .optional()\n .describe(\n 'YAML mapping merged into the pulled model. Named lists merge by name. Other lists replace. Null removes a field. An empty list clears it.'\n ),\n change: z\n .object({\n operation: z.enum(['upsert', 'remove']),\n kind: entityKind,\n name: z.string().trim().min(1),\n table: z\n .string()\n .trim()\n .min(1)\n .optional()\n .describe(\n 'Required for columns. Use the table name and an unqualified column name.'\n ),\n value: z\n .record(z.string(), z.unknown())\n .optional()\n .describe('Fields to merge for upsert. Omit for remove.'),\n })\n .strict()\n .optional()\n .describe(\n 'One named entity change. Supply exactly one of source, yaml_patch or change.'\n ),\n};\nconst expectedHash = z\n .string()\n .trim()\n .min(1)\n .nullable()\n .optional()\n .describe(\n 'Stored content_hash from the reviewed proposal. Null explicitly means the first apply. Required when dry_run is false.'\n );\n\nfunction errorCode(error: DatabrainApiError): string {\n const nested =\n isObject(error.details) && isObject(error.details.error)\n ? error.details.error\n : undefined;\n return typeof nested?.code === 'string' ? nested.code : error.code;\n}\n\nfunction failure(error: unknown) {\n if (error instanceof DatabrainApiError) {\n if (error.status === 409 || error.status === 422) {\n return toolError(\n stringify({\n status: error.status,\n code: errorCode(error),\n reason: error.message,\n details: error.details,\n recovery:\n error.status === 409\n ? 'Pull the current model and review a new proposal before applying.'\n : 'Correct the validation errors and propose the change again.',\n })\n );\n }\n return error.toToolResponse();\n }\n return toolError(\n `Semantic model error: ${error instanceof Error ? error.message : String(error)}`\n );\n}\n\ninterface ChangeInput {\n source?: string;\n yaml_patch?: string;\n change?: StructuredSemanticChange;\n expected_content_hash?: string | null;\n}\n\nasync function candidate(\n api: SemanticModelApi,\n id: string,\n input: ChangeInput\n) {\n if (\n [input.source, input.yaml_patch, input.change].filter(\n (value) => value !== undefined\n ).length !== 1\n ) {\n throw new Error('Supply exactly one of source, yaml_patch or change.');\n }\n let stored: Awaited<ReturnType<typeof api.pull>> | undefined;\n try {\n stored = await api.pull(id);\n } catch (error) {\n // A missing route or inaccessible datamart must never be treated as an empty model.\n if (\n !(\n error instanceof DatabrainApiError &&\n error.status === 404 &&\n errorCode(error) === 'layer_not_found' &&\n input.source !== undefined\n )\n )\n throw error;\n }\n const hash = stored?.content_hash ?? null;\n if (\n input.expected_content_hash !== undefined &&\n input.expected_content_hash !== hash\n ) {\n throw new DatabrainApiError(\n 409,\n 'content_hash_mismatch',\n 'The model changed since the proposal was reviewed.',\n { current_hash: hash }\n );\n }\n return {\n source: input.source ?? changeSemanticSource(stored!.source, input),\n expected_content_hash:\n input.expected_content_hash === undefined\n ? hash\n : input.expected_content_hash,\n };\n}\n\nasync function proposal(api: SemanticModelApi, id: string, input: ChangeInput) {\n const next = await candidate(api, id, input);\n const validation = await api.validate(id, next.source);\n let plan: unknown = null;\n let plan_note: string | undefined;\n if (validation.ok) {\n try {\n plan = await api.plan(id, next.source, next.expected_content_hash);\n } catch (error) {\n // The API has no plan step (no `/plan` route). The same datamart just validated, so a\n // 404/405/501 here is the missing route, not a missing datamart.\n if (\n !(\n error instanceof DatabrainApiError &&\n [404, 405, 501].includes(error.status)\n )\n )\n throw error;\n plan_note =\n 'This Databrain API has no plan step. The validation above is the server check; apply runs it again.';\n }\n }\n return {\n ...next,\n validation,\n errors: validation.errors,\n plan,\n ...(plan_note ? { plan_note } : {}),\n dry_run: true,\n };\n}\n\nexport function registerSearchSemanticModel(\n server: McpServer,\n client: DatabrainClient\n): void {\n const api = createServiceBundle(client).semanticModelApi;\n server.tool(\n 'search_semantic_model',\n '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.',\n {\n datamartId,\n question: z.string().trim().min(1).max(10_000),\n k: z.number().int().min(1).max(100).default(10),\n },\n READ_ONLY,\n async ({ datamartId, question, k }) => {\n try {\n try {\n return toolSuccess(\n stringify(await api.retrieve(datamartId, question, k))\n );\n } catch (error) {\n if (\n !(\n error instanceof DatabrainApiError &&\n [404, 405, 501].includes(error.status)\n )\n )\n throw error;\n if (\n [\n 'datamart_not_found',\n 'layer_not_found',\n 'forbidden',\n 'unauthorized',\n ].includes(errorCode(error))\n )\n throw error;\n }\n const stored = await api.pull(datamartId);\n return toolSuccess(\n stringify({\n ...retrieveSemanticSource(stored.source, question, k),\n content_hash: stored.content_hash,\n })\n );\n } catch (error) {\n return failure(error);\n }\n }\n );\n}\n\nexport function registerGetSemanticEntity(\n server: McpServer,\n client: DatabrainClient\n): void {\n const api = createServiceBundle(client).semanticModelApi;\n server.tool(\n 'get_semantic_entity',\n '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.',\n { datamartId, kind: entityKind, name: z.string().trim().min(1) },\n READ_ONLY,\n async ({ datamartId, kind, name }) => {\n try {\n const stored = await api.pull(datamartId);\n const found = semanticEntities(\n parseSemanticSource(stored.source)\n ).filter((entity) => entity.kind === kind && entity.name === name);\n if (found.length !== 1)\n return toolError(\n `Expected one ${kind} named ${name}; found ${found.length}. Use search_semantic_model to find its exact name.`\n );\n return toolSuccess(\n stringify({ ...found[0], content_hash: stored.content_hash })\n );\n } catch (error) {\n return failure(error);\n }\n }\n );\n}\n\nexport function registerProposeSemanticChange(\n server: McpServer,\n client: DatabrainClient\n): void {\n const api = createServiceBundle(client).semanticModelApi;\n server.tool(\n 'propose_semantic_change',\n 'Prepare a semantic model change from complete YAML, a YAML patch or one structured change. Returns validation errors, the server plan, candidate YAML and the stored hash. Never writes.',\n { datamartId, ...changeInputs },\n READ_ONLY,\n async (params) => {\n try {\n return toolSuccess(\n stringify(await proposal(api, params.datamartId, params))\n );\n } catch (error) {\n return failure(error);\n }\n }\n );\n}\n\nexport function registerApplySemanticChange(\n server: McpServer,\n client: DatabrainClient\n): void {\n const api = createServiceBundle(client).semanticModelApi;\n server.tool(\n 'apply_semantic_change',\n 'Preview a semantic change by default. Setting dry_run to false applies it live and can remove entities. Requires the reviewed content hash and confirm set to APPLY_TO_PRODUCTION supplied by the user.',\n {\n datamartId,\n ...changeInputs,\n dry_run: z.boolean().default(true),\n expected_content_hash: expectedHash,\n confirm: z\n .string()\n .optional()\n .describe(\n 'User supplied APPLY_TO_PRODUCTION after reviewing the plan. Never invent confirmation.'\n ),\n },\n DESTRUCTIVE,\n async (params) => {\n try {\n if (params.dry_run !== false)\n return toolSuccess(\n stringify(await proposal(api, params.datamartId, params))\n );\n const refusal = validateProductionApply(params);\n if (refusal) return toolError(refusal);\n if (params.expected_content_hash === undefined)\n return toolError(\n 'expected_content_hash is required. Use the stored hash from the reviewed proposal, or null for the first apply.'\n );\n const next = await candidate(api, params.datamartId, params);\n const validation = await api.validate(params.datamartId, next.source);\n if (!validation.ok)\n return failure(\n new DatabrainApiError(\n 422,\n 'validation_failed',\n 'Apply refused because the model does not validate.',\n { validation }\n )\n );\n return toolSuccess(\n stringify(\n await api.apply(\n params.datamartId,\n next.source,\n next.expected_content_hash\n )\n )\n );\n } catch (error) {\n return failure(error);\n }\n }\n );\n}\n\nexport function registerEvalSemanticModel(\n server: McpServer,\n client: DatabrainClient\n): void {\n const api = createServiceBundle(client).semanticModelApi;\n server.tool(\n 'eval_semantic_model',\n 'Evaluate closed world semantic assertions against proposed or stored YAML. Each question must name an id and the model entities it exercises. Does not execute warehouse SQL or write the model.',\n {\n datamartId,\n source: source.optional(),\n questions: z\n .array(\n z\n .object({\n id: z.string().trim().min(1),\n question: z.string().trim().min(1),\n exercises: z\n .array(z.string().trim().min(1))\n .describe(\n 'Exact model entity names asserted by this question; an empty list is reported as unscoreable.'\n ),\n })\n .strict()\n )\n .max(100)\n .default([]),\n },\n READ_ONLY,\n async ({ datamartId, source, questions }) => {\n try {\n const yaml = source ?? (await api.pull(datamartId, 'combined')).source;\n return toolSuccess(\n stringify(await api.evaluate(datamartId, { source: yaml, questions }))\n );\n } catch (error) {\n return failure(error);\n }\n }\n );\n}\n","import { parseDocument, stringify } from 'yaml';\n\nexport const ENTITY_COLLECTIONS = {\n table: ['tables'],\n column: ['columns'],\n measure: ['measures'],\n metric: ['metrics'],\n join: ['joins'],\n entity: ['entities'],\n glossary: ['glossary'],\n saved_query: ['saved_queries', 'verified_queries'],\n instruction: ['instructions', 'agent_instructions'],\n access_rule: ['access', 'policies'],\n} as const;\nexport type SemanticEntityKind = keyof typeof ENTITY_COLLECTIONS;\nexport type SemanticObject = Record<string, unknown>;\n\nexport function isObject(value: unknown): value is SemanticObject {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction assertSafe(value: unknown, seen = new Set<object>(), depth = 0): void {\n if (depth > 100)\n throw new Error('Semantic source nesting exceeds 100 levels.');\n if (!value || typeof value !== 'object') return;\n if (seen.has(value))\n throw new Error('Recursive YAML aliases are not supported.');\n seen.add(value);\n for (const [key, child] of Object.entries(value)) {\n if (['__proto__', 'constructor', 'prototype'].includes(key))\n throw new Error(`Unsupported source key: ${key}.`);\n assertSafe(child, seen, depth + 1);\n }\n seen.delete(value);\n}\n\nexport function parseSemanticSource(source: string): SemanticObject {\n const document = parseDocument(source, {\n prettyErrors: false,\n uniqueKeys: true,\n });\n if (document.errors.length || document.warnings.length) {\n throw new Error((document.errors[0] ?? document.warnings[0]).message);\n }\n const value: unknown = document.toJS({ maxAliasCount: 100 });\n if (!isObject(value))\n throw new Error('Semantic source must be a YAML mapping.');\n assertSafe(value);\n return value;\n}\n\nexport interface SemanticEntity {\n id: string;\n kind: SemanticEntityKind;\n name: string;\n entity: SemanticObject;\n}\n\nexport function semanticEntities(\n source: SemanticObject,\n visibleOnly = false\n): SemanticEntity[] {\n const out: SemanticEntity[] = [];\n for (const [kind, keys] of Object.entries(ENTITY_COLLECTIONS)) {\n if (kind === 'column') continue;\n const key = keys.find((key) => Array.isArray(source[key]));\n const entries = key ? (source[key] as unknown[]) : [];\n for (const entry of entries) {\n if (\n !isObject(entry) ||\n typeof entry.name !== 'string' ||\n (visibleOnly && entry.hidden === true)\n )\n continue;\n const columns = Array.isArray(entry.columns)\n ? entry.columns.filter(isObject)\n : [];\n const entity =\n visibleOnly && kind === 'table'\n ? {\n ...entry,\n columns: columns.filter((column) => column.hidden !== true),\n }\n : entry;\n out.push({\n id: `${kind}:${entry.name}`,\n kind: kind as SemanticEntityKind,\n name: entry.name,\n entity,\n });\n if (kind === 'table')\n for (const column of columns) {\n if (\n typeof column.name !== 'string' ||\n (visibleOnly && column.hidden === true)\n )\n continue;\n const name = `${entry.name}.${column.name}`;\n out.push({\n id: `column:${name}`,\n kind: 'column',\n name,\n entity: column,\n });\n }\n }\n }\n return out;\n}\n\n/** Mapping fields merge; named sequences merge by name; other sequences replace. */\nfunction mergePatch(base: unknown, patch: unknown): unknown {\n if (isObject(patch)) {\n const next: SemanticObject = isObject(base) ? { ...base } : {};\n for (const [key, value] of Object.entries(patch)) {\n if (value === null) delete next[key];\n else next[key] = mergePatch(next[key], value);\n }\n return next;\n }\n if (\n Array.isArray(patch) &&\n patch.length &&\n patch.every((item) => isObject(item) && typeof item.name === 'string')\n ) {\n const next = Array.isArray(base) ? [...base] : [];\n const names = new Set<string>();\n for (const item of patch as SemanticObject[]) {\n const name = item.name as string;\n if (names.has(name)) throw new Error(`Duplicate patch entity: ${name}.`);\n names.add(name);\n const index = next.findIndex(\n (entry) => isObject(entry) && entry.name === name\n );\n if (index < 0) next.push(mergePatch({}, item));\n else next[index] = mergePatch(next[index], item);\n }\n return next;\n }\n return patch;\n}\n\nexport interface StructuredSemanticChange {\n operation: 'upsert' | 'remove';\n kind: SemanticEntityKind;\n name: string;\n table?: string;\n value?: SemanticObject;\n}\n\nexport function changeSemanticSource(\n source: string,\n input: { yaml_patch?: string; change?: StructuredSemanticChange }\n): string {\n const model = parseSemanticSource(source);\n if (input.yaml_patch !== undefined)\n return stringify(mergePatch(model, parseSemanticSource(input.yaml_patch)));\n const change = input.change!;\n assertSafe(change);\n let parent = model;\n if (change.kind === 'column') {\n if (!change.table)\n throw new Error(\n 'A column change requires table and an unqualified column name.'\n );\n const table = (Array.isArray(model.tables) ? model.tables : []).find(\n (item) => isObject(item) && item.name === change.table\n );\n if (!isObject(table)) throw new Error(`Table not found: ${change.table}.`);\n parent = table;\n } else if (change.table)\n throw new Error('table is only valid for a column change.');\n const keys = ENTITY_COLLECTIONS[change.kind];\n const key = keys.find((key) => Array.isArray(parent[key])) ?? keys[0];\n const entries = Array.isArray(parent[key])\n ? ([...parent[key]] as unknown[])\n : [];\n const index = entries.findIndex(\n (entry) => isObject(entry) && entry.name === change.name\n );\n if (change.operation === 'remove') {\n if (change.value !== undefined)\n throw new Error('A remove change must not include value.');\n if (index < 0)\n throw new Error(`Entity not found: ${change.kind} ${change.name}.`);\n entries.splice(index, 1);\n } else {\n if (!change.value) throw new Error('An upsert change requires value.');\n if (change.value.name !== undefined && change.value.name !== change.name)\n throw new Error('value.name must match name.');\n const value = mergePatch(index < 0 ? {} : entries[index], {\n ...change.value,\n name: change.name,\n });\n if (index < 0) entries.push(value);\n else entries[index] = value;\n }\n parent[key] = entries;\n return stringify(model);\n}\n","import {\n isObject,\n parseSemanticSource,\n type SemanticEntity,\n semanticEntities,\n} from './semantic-source.js';\n\nfunction tokens(text: string): string[] {\n return text\n .toLowerCase()\n .split(/[^\\p{L}\\p{N}]+/u)\n .filter(Boolean);\n}\n\nfunction text(value: unknown): string {\n return typeof value === 'string'\n ? value\n : Array.isArray(value)\n ? value.map(text).join(' ')\n : '';\n}\n\n// The compatibility path uses lexical fields in priority order, then one hop\n// of references. It is used only when the server has no retrieve route.\nexport function retrieveSemanticSource(\n source: string,\n question: string,\n k: number\n) {\n const nodes = semanticEntities(parseSemanticSource(source), true);\n const query = new Set(tokens(question));\n const score = (node: SemanticEntity) => {\n const fields: [unknown, number][] = [\n [node.name, 8],\n [node.entity.alias ?? node.entity.term, 6],\n [node.entity.synonyms, 4],\n [\n node.entity.description ??\n node.entity.definition ??\n node.entity.question,\n 2,\n ],\n ];\n return fields.reduce((sum, [value, weight]) => {\n const words = new Set(tokens(text(value)));\n return sum + [...query].filter((word) => words.has(word)).length * weight;\n }, 0);\n };\n const ranked = nodes\n .map((node) => ({ ...node, score: score(node), match: 'lexical' as const }))\n .filter((node) => node.score > 0)\n .sort((a, b) => b.score - a.score || a.id.localeCompare(b.id))\n .slice(0, k);\n const edges = new Map(nodes.map((node) => [node.id, new Set<string>()]));\n const byName = new Map<string, string[]>();\n for (const node of nodes)\n byName.set(node.name, [...(byName.get(node.name) ?? []), node.id]);\n const link = (a: string, b: string) => {\n if (a === b || !edges.has(b)) return;\n edges.get(a)!.add(b);\n edges.get(b)!.add(a);\n };\n // Never create graph edges from prose, labels or display configuration.\n const refKeys = new Set([\n 'table',\n 'column',\n 'columns',\n 'references',\n 'measure',\n 'numerator',\n 'denominator',\n 'metrics',\n 'measures',\n 'glossary_refs',\n 'left',\n 'right',\n 'from',\n 'to',\n 'on',\n 'bindings',\n 'scope',\n 'targets',\n 'tables',\n 'grain',\n 'identifiers',\n 'default_time_dimension',\n 'expression',\n 'sql',\n 'on_sql',\n 'predicate',\n 'type_config',\n ]);\n const refs = (value: unknown): string[] => {\n if (typeof value === 'string')\n return (\n value.match(/[\\p{L}_][\\p{L}\\p{N}_]*(?:\\.[\\p{L}_][\\p{L}\\p{N}_]*)?/gu) ??\n []\n );\n if (Array.isArray(value)) return value.flatMap(refs);\n if (isObject(value))\n return Object.entries(value).flatMap(([key, child]) =>\n refKeys.has(key) ? refs(child) : []\n );\n return [];\n };\n for (const node of nodes) {\n if (node.kind === 'column')\n link(node.id, `table:${node.name.split('.')[0]}`);\n for (const ref of refs(node.entity))\n for (const id of byName.get(ref) ?? []) link(node.id, id);\n }\n const chosen = new Map<\n string,\n SemanticEntity & { score: number; match: string }\n >(ranked.map((node) => [node.id, node]));\n for (const node of ranked) {\n for (const id of [...edges.get(node.id)!].sort()) {\n if (!chosen.has(id)) {\n const adjacent = nodes.find((node) => node.id === id)!;\n chosen.set(id, { ...adjacent, score: 0, match: 'adjacency' });\n }\n }\n }\n return {\n results: [...chosen.values()],\n k,\n lexical_matches: ranked.length,\n retrieval: 'local_lexical',\n };\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type {\n SemanticLayerResult,\n SemanticLayerUpdateBody,\n} from '../../api/query-api.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport {\n DatabrainApiError,\n toolError,\n toolSuccess,\n} from '../../utils/errors.js';\nimport {\n formatDatamart,\n resolveResource,\n} from '../../utils/resolve-resource.js';\nimport { WRITE_IDEMPOTENT } from '../annotations.js';\n\nconst columnSchema = z.object({\n name: z.string().describe('Column name (must exist in the datamart)'),\n description: z\n .string()\n .optional()\n .describe('Business-friendly description of what this column represents'),\n synonyms: z\n .array(z.string())\n .optional()\n .describe(\n 'Alternative names users might use for this column (e.g. [\"revenue\", \"sales amount\"])'\n ),\n miscellaneousInfo: z\n .string()\n .optional()\n .describe('Additional context such as valid values, units, or caveats'),\n columnType: z\n .enum([\n 'String',\n 'Long String',\n 'String (Custom)',\n 'ENUM',\n 'Mapper',\n 'Range',\n 'Expression',\n 'Identifier',\n 'Number',\n 'JSON',\n ])\n .nullable()\n .optional()\n .describe(\n 'Semantic column type. Use \"Identifier\" for IDs/foreign keys, \"Number\" for numeric values, \"String\" for text. Omit for date and boolean columns.'\n ),\n // The public PUT accepts these three as well (docs: Update Semantic Layer).\n // They were missing here, and zod strips unknown keys, so a caller who set\n // `isIdentifier: true` got a success message and a row with `false`.\n columnTypeConfig: z\n .union([\n z.record(z.string(), z.string()),\n z.string(),\n z.object({ lowerLimit: z.number(), upperLimit: z.number() }),\n z.null(),\n ])\n .optional()\n .describe(\n '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.'\n ),\n isIdentifier: z\n .boolean()\n .optional()\n .describe('Mark the column as an identifier (primary or foreign key).'),\n isNotIndexed: z\n .boolean()\n .optional()\n .describe('Exclude the column from AI indexing.'),\n});\n\nconst tableSchema = z.object({\n name: z.string().describe('Table name (must exist in the datamart)'),\n schemaName: z\n .string()\n .optional()\n .describe(\n 'Schema the table lives in, when the datamart has the same table name in more than one schema.'\n ),\n description: z\n .string()\n .optional()\n .describe('Business-friendly description of what this table represents'),\n synonyms: z\n .array(z.string())\n .optional()\n .describe('Alternative names for this table'),\n miscellaneousInfo: z\n .string()\n .optional()\n .describe(\n 'Additional context such as how the table relates to other tables'\n ),\n columns: z\n .array(columnSchema)\n .optional()\n .describe('Column-level semantic definitions to update'),\n});\n\ntype SemanticTableInput = z.infer<typeof tableSchema>;\ntype SemanticUpdateTable = NonNullable<\n SemanticLayerUpdateBody['tables']\n>[number];\ntype SemanticUpdateColumn = NonNullable<SemanticUpdateTable['columns']>[number];\n\nfunction columnKey(tableName: string, columnName: string): string {\n return `${tableName.toLowerCase()}\\0${columnName.toLowerCase()}`;\n}\n\nfunction buildColumnDatatypeMap(\n semanticLayer: SemanticLayerResult\n): Map<string, string> {\n const datatypes = new Map<string, string>();\n for (const table of semanticLayer.tables ?? []) {\n for (const column of table.columns ?? []) {\n if (column.datatype) {\n datatypes.set(columnKey(table.name, column.name), column.datatype);\n }\n }\n }\n return datatypes;\n}\n\nfunction hasExplicitColumnType(\n tables: SemanticTableInput[] | undefined\n): boolean {\n return (\n tables?.some((table) =>\n table.columns?.some(\n (column) =>\n column.columnType !== undefined && column.columnType !== null\n )\n ) ?? false\n );\n}\n\nfunction shouldOmitColumnTypeForDatatype(\n datatype: string | undefined\n): boolean {\n if (!datatype) return false;\n const normalized = datatype.trim().toLowerCase();\n return (\n normalized === 'boolean' ||\n normalized === 'bool' ||\n normalized === 'date' ||\n normalized.startsWith('date(') ||\n normalized.startsWith('datetime') ||\n normalized.startsWith('timestamp') ||\n normalized === 'time' ||\n normalized.startsWith('time(') ||\n normalized.startsWith('time ')\n );\n}\n\nexport function normalizeTablesForApi(\n tables: SemanticTableInput[] | undefined,\n datatypesByColumn?: Map<string, string>\n): SemanticLayerUpdateBody['tables'] {\n if (!tables) return undefined;\n\n return tables.map((table) => {\n const normalized: SemanticUpdateTable = { name: table.name };\n if (table.schemaName !== undefined)\n normalized.schemaName = table.schemaName;\n if (table.description !== undefined)\n normalized.description = table.description;\n if (table.synonyms !== undefined) normalized.synonyms = table.synonyms;\n if (table.miscellaneousInfo !== undefined) {\n normalized.miscellaneousInfo = table.miscellaneousInfo;\n }\n if (table.columns !== undefined) {\n normalized.columns = table.columns.map((column) => {\n const normalizedColumn: SemanticUpdateColumn = { name: column.name };\n if (column.description !== undefined) {\n normalizedColumn.description = column.description;\n }\n if (column.synonyms !== undefined)\n normalizedColumn.synonyms = column.synonyms;\n if (column.miscellaneousInfo !== undefined) {\n normalizedColumn.miscellaneousInfo = column.miscellaneousInfo;\n }\n if (column.columnType !== undefined && column.columnType !== null) {\n const datatype = datatypesByColumn?.get(\n columnKey(table.name, column.name)\n );\n if (!shouldOmitColumnTypeForDatatype(datatype)) {\n normalizedColumn.columnType = column.columnType;\n }\n }\n if (column.columnTypeConfig !== undefined) {\n normalizedColumn.columnTypeConfig = column.columnTypeConfig;\n }\n if (column.isIdentifier !== undefined) {\n normalizedColumn.isIdentifier = column.isIdentifier;\n }\n if (column.isNotIndexed !== undefined) {\n normalizedColumn.isNotIndexed = column.isNotIndexed;\n }\n return normalizedColumn;\n });\n }\n return normalized;\n });\n}\n\nexport function registerUpdateSemanticLayer(\n server: McpServer,\n client: DatabrainClient\n): void {\n const services = createServiceBundle(client);\n\n server.tool(\n 'update_semantic_layer',\n '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.',\n {\n datamartName: z\n .string()\n .optional()\n .describe(\n 'Name of the datamart to update. Omit to list available datamarts.'\n ),\n tables: z\n .array(tableSchema)\n .optional()\n .describe(\n 'Table and column definitions to update. Only include tables/columns you want to change.'\n ),\n feedback: z\n .string()\n .optional()\n .describe(\n 'General feedback or context about the datamart (e.g. \"This datamart contains e-commerce data for the US market\").'\n ),\n },\n WRITE_IDEMPOTENT,\n async (params) => {\n try {\n if (!params.tables && !params.feedback) {\n return toolError(\n 'Provide either tables (with descriptions/synonyms) or feedback to update the semantic layer.'\n );\n }\n\n const datamarts = await services.datamartsApi.listDatamarts();\n\n const resolution = resolveResource({\n items: datamarts,\n name: params.datamartName,\n getName: (dm) => dm.name || dm.datamartName,\n formatItem: formatDatamart,\n resourceType: 'datamart',\n toolName: 'update_semantic_layer',\n });\n\n if (resolution.kind !== 'resolved') return resolution.response;\n\n const datamartName = resolution.name;\n const datatypesByColumn = hasExplicitColumnType(params.tables)\n ? buildColumnDatatypeMap(\n await services.queryApi.getSemanticLayer(datamartName)\n )\n : undefined;\n const tables = normalizeTablesForApi(params.tables, datatypesByColumn);\n\n await services.queryApi.updateSemanticLayer({\n datamartName,\n tables,\n feedback: params.feedback,\n });\n\n const updatedParts: string[] = [];\n if (params.tables) {\n const tableCount = params.tables.length;\n const colCount = params.tables.reduce(\n (sum, t) => sum + (t.columns?.length || 0),\n 0\n );\n updatedParts.push(\n `${tableCount} table(s) and ${colCount} column(s) updated`\n );\n }\n if (params.feedback) {\n updatedParts.push('general feedback updated');\n }\n\n return toolSuccess(\n `Semantic layer for **${datamartName}** updated successfully (${updatedParts.join(', ')}).\\n\\n` +\n 'You can now:\\n' +\n '- Use `get_semantic_layer` to verify the changes\\n' +\n '- Use `ask_question` to query data with natural language — it should work now that descriptions exist'\n );\n } catch (err) {\n if (err instanceof DatabrainApiError) return err.toToolResponse();\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport {\n DatabrainApiError,\n toolError,\n toolSuccess,\n} from '../../utils/errors.js';\nimport { READ_ONLY } from '../annotations.js';\n\nexport function registerListScheduledReports(\n server: McpServer,\n client: DatabrainClient\n): void {\n const services = createServiceBundle(client);\n\n server.tool(\n 'list_scheduled_reports',\n 'List configured scheduled reports for a specific client/dashboard embed. Shows schedule metadata, not delivery success history.',\n {\n clientId: z\n .string()\n .describe(\n 'Client/tenant identifier. Required by the current backend API for non-empty results'\n ),\n dashboardName: z\n .string()\n .optional()\n .describe('Dashboard name to inspect'),\n workspaceName: z\n .string()\n .optional()\n .describe('Workspace name if dashboardName is ambiguous'),\n dataAppName: z\n .string()\n .trim()\n .min(1)\n .optional()\n .describe('Data app name when dashboard embeds span several apps'),\n embedId: z\n .string()\n .optional()\n .describe('Technical embed id alternative to dashboardName'),\n userIdentifier: z\n .string()\n .optional()\n .describe('Optional creator/user filter'),\n pageNumber: z\n .number()\n .int()\n .positive()\n .optional()\n .describe('Page number when pagination is enabled'),\n isPagination: z\n .boolean()\n .optional()\n .describe('Enable backend pagination'),\n },\n READ_ONLY,\n async (params) => {\n try {\n const embed = await services.widgetService.resolveEmbedId({\n embedId: params.embedId,\n dashboardName: params.dashboardName,\n workspaceName: params.workspaceName,\n dataAppName: params.dataAppName,\n required: true,\n });\n if (!embed.ok) return toolError(embed.error);\n const embedId = embed.value.embedId as string;\n\n const app = client.isHosted()\n ? await services.widgetService.resolveDataAppName(\n params.dataAppName,\n embedId\n )\n : { ok: true as const, value: params.dataAppName };\n if (!app.ok) return toolError(app.error);\n const reports = await services.scheduledReportsApi.listByEmbed({\n embedId,\n dataAppName: app.value,\n clientId: params.clientId,\n userIdentifier: params.userIdentifier,\n pageNumber: params.pageNumber,\n isPagination: params.isPagination,\n });\n\n return toolSuccess(\n JSON.stringify(\n {\n count: Array.isArray(reports) ? reports.length : 0,\n dashboardName:\n embed.value.resolvedFrom?.dashboardName ||\n params.dashboardName ||\n null,\n embedId,\n clientId: params.clientId,\n note: 'This lists configured schedules only. Delivery success/failure history is not persisted in the current MCP/API surface yet.',\n reports: (Array.isArray(reports) ? reports : []).map(\n (report) => ({\n id: report.id || null,\n subject: report.subject || null,\n nextScheduledAt: report.nextScheduledAt || null,\n recipientCount: Array.isArray(report.emails)\n ? report.emails.length\n : null,\n chartCount: Array.isArray(report.scheduleEmailReportCharts)\n ? report.scheduleEmailReportCharts.length\n : null,\n isDownloadFile: report.isDownloadFile ?? null,\n downloadFileFormat: report.downloadFileFormat || null,\n timeConfigurations: report.timeConfigurations || null,\n })\n ),\n },\n null,\n 2\n )\n );\n } catch (err) {\n if (err instanceof DatabrainApiError) return err.toToolResponse();\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n}\n","/**\n * Per-tool intent metadata, used to tag outbound API calls (X-Databrain-MCP-*\n * headers) so backend telemetry can attribute usage to a tool and a workflow.\n * The two dimensions answer the question Nick raised: is a call part of an\n * EMBEDDING flow or an INTERNAL ANALYTICS flow?\n */\nexport type ToolCategory =\n | 'discovery'\n | 'infrastructure'\n | 'embedding'\n | 'internal_analytics'\n | 'semantic_layer'\n | 'reports'\n | 'custom_charts';\n\n/**\n * Backend mode gate vocabulary (frozen wire contract, shared with the REST API):\n * read returns data and changes nothing; view changes only what is on screen\n * and writes no row; commit creates, updates, deletes, or issues a credential\n * (including one minted internally and never returned to the caller — see\n * the tools below whose implementations mint a guest token for their own use).\n * read -> offered in ask, plan, build. view/commit -> offered in build only.\n */\nexport type ToolEffect = 'read' | 'view' | 'commit';\n\nexport interface ToolMeta {\n category: ToolCategory;\n /** Use-case bucket, aligned with the server's core use cases. */\n workflowIntent: string;\n effect: ToolEffect;\n}\n\nexport const DEFAULT_TOOL_META: ToolMeta = {\n category: 'discovery',\n workflowIntent: 'other',\n // Fail closed: an unregistered/unclassified tool is treated as a commit\n // until someone deliberately marks it read or view.\n effect: 'commit',\n};\n\nexport const TOOL_METADATA: Record<string, ToolMeta> = {\n // Identity / discovery\n whoami: {\n category: 'discovery',\n workflowIntent: 'discovery',\n effect: 'read',\n },\n\n // Infrastructure / data setup\n list_datasources: {\n category: 'infrastructure',\n workflowIntent: 'setup_data',\n effect: 'read',\n },\n discover_datasource_schema: {\n category: 'infrastructure',\n workflowIntent: 'setup_data',\n effect: 'read',\n },\n list_datamarts: {\n category: 'infrastructure',\n workflowIntent: 'setup_data',\n effect: 'read',\n },\n list_workspaces: {\n category: 'infrastructure',\n workflowIntent: 'setup_data',\n effect: 'read',\n },\n // Triggers a backend sync job that refreshes stored schema metadata — a real mutation, not a read.\n sync_datasource: {\n category: 'infrastructure',\n workflowIntent: 'setup_data',\n effect: 'commit',\n },\n // dry_run is the default, but mode:\"apply\" performs a real POST that creates the datamart.\n create_datamart: {\n category: 'infrastructure',\n workflowIntent: 'setup_data',\n effect: 'commit',\n },\n // Hosted only (an \"All workspaces\" sign-in); stdio does not register it.\n create_workspace: {\n category: 'infrastructure',\n workflowIntent: 'setup_data',\n effect: 'commit',\n },\n\n // Embedding — data apps & tokens\n list_data_apps: {\n category: 'embedding',\n workflowIntent: 'embed_dashboard',\n effect: 'read',\n },\n list_tenants: {\n category: 'embedding',\n workflowIntent: 'embed_dashboard',\n effect: 'read',\n },\n create_data_app: {\n category: 'embedding',\n workflowIntent: 'embed_dashboard',\n effect: 'commit',\n },\n list_api_tokens: {\n category: 'embedding',\n workflowIntent: 'embed_dashboard',\n effect: 'read',\n },\n create_api_token: {\n category: 'embedding',\n workflowIntent: 'embed_dashboard',\n effect: 'commit',\n },\n rotate_api_token: {\n category: 'embedding',\n workflowIntent: 'embed_dashboard',\n effect: 'commit',\n },\n\n // Embedding — embed management\n create_embed: {\n category: 'embedding',\n workflowIntent: 'embed_dashboard',\n effect: 'commit',\n },\n list_embeds: {\n category: 'embedding',\n workflowIntent: 'embed_dashboard',\n effect: 'read',\n },\n get_embed_details: {\n category: 'embedding',\n workflowIntent: 'embed_dashboard',\n effect: 'read',\n },\n update_embed: {\n category: 'embedding',\n workflowIntent: 'embed_dashboard',\n effect: 'commit',\n },\n // Persists theme/access config on the embed record — a real write, not a display-only tweak.\n customize_embed_theme: {\n category: 'embedding',\n workflowIntent: 'embed_dashboard',\n effect: 'commit',\n },\n // Mints and returns a live guest token embedded in the demo URL.\n get_demo_link: {\n category: 'embedding',\n workflowIntent: 'embed_dashboard',\n effect: 'commit',\n },\n\n // Embedding — frontend\n generate_guest_token: {\n category: 'embedding',\n workflowIntent: 'embed_dashboard',\n effect: 'commit',\n },\n generate_embed_code: {\n category: 'embedding',\n workflowIntent: 'embed_dashboard',\n effect: 'read',\n },\n\n // Embedding — customer dashboards & widgets\n list_dashboards: {\n category: 'embedding',\n workflowIntent: 'embedded_widget',\n effect: 'read',\n },\n create_dashboard: {\n category: 'embedding',\n workflowIntent: 'author_dashboard',\n effect: 'commit',\n },\n get_dashboard: {\n category: 'embedding',\n workflowIntent: 'author_dashboard',\n effect: 'read',\n },\n // Persists nothing the user sees, but the backend mints (and then deletes) an internal guest token to render it.\n dashboard_snapshot: {\n category: 'internal_analytics',\n workflowIntent: 'query_data',\n effect: 'commit',\n },\n // Does not persist a dashboard, but mints an internal guest token to render tile previews.\n generate_dashboard_tiles: {\n category: 'embedding',\n workflowIntent: 'author_dashboard',\n effect: 'commit',\n },\n list_widgets: {\n category: 'embedding',\n workflowIntent: 'embedded_widget',\n effect: 'read',\n },\n add_widget: {\n category: 'embedding',\n workflowIntent: 'embedded_widget',\n effect: 'commit',\n },\n update_widget: {\n category: 'embedding',\n workflowIntent: 'embedded_widget',\n effect: 'commit',\n },\n remove_widget: {\n category: 'embedding',\n workflowIntent: 'embedded_widget',\n effect: 'commit',\n },\n // Returns an unsaved draft, but mints an internal write-capable guest token to generate it.\n generate_widget: {\n category: 'embedding',\n workflowIntent: 'embedded_widget',\n effect: 'commit',\n },\n // Dry-run validation only, but mints an internal write-capable guest token to check conflicts.\n validate_metric_spec: {\n category: 'embedding',\n workflowIntent: 'sql_to_embedded_metric',\n effect: 'commit',\n },\n create_or_update_metric_from_query: {\n category: 'embedding',\n workflowIntent: 'sql_to_embedded_metric',\n effect: 'commit',\n },\n\n // Internal analytics\n create_workspace_metric: {\n category: 'internal_analytics',\n workflowIntent: 'sql_to_workspace_metric',\n effect: 'commit',\n },\n // Runs a query and returns rows; no dashboard/widget/row is persisted.\n ask_question: {\n category: 'internal_analytics',\n workflowIntent: 'query_data',\n effect: 'read',\n },\n preview_chart: {\n category: 'internal_analytics',\n workflowIntent: 'query_data',\n effect: 'view',\n },\n save_chart_as_dashboard: {\n category: 'internal_analytics',\n workflowIntent: 'author_dashboard',\n effect: 'commit',\n },\n // Read-only to the user, but each interaction mints an embed-scoped guest credential.\n render_metric_tile: {\n category: 'internal_analytics',\n workflowIntent: 'chart_app',\n effect: 'read',\n },\n render_chart: {\n category: 'embedding',\n workflowIntent: 'chart_app',\n effect: 'commit',\n },\n refresh_widget: {\n category: 'embedding',\n workflowIntent: 'chart_app',\n effect: 'commit',\n },\n drill_down: {\n category: 'embedding',\n workflowIntent: 'chart_app',\n effect: 'commit',\n },\n change_date_range: {\n category: 'embedding',\n workflowIntent: 'chart_app',\n effect: 'commit',\n },\n\n // Semantic layer\n search_semantic_model: {\n category: 'semantic_layer',\n workflowIntent: 'query_data',\n effect: 'read',\n },\n get_semantic_entity: {\n category: 'semantic_layer',\n workflowIntent: 'query_data',\n effect: 'read',\n },\n propose_semantic_change: {\n category: 'semantic_layer',\n workflowIntent: 'model_data',\n effect: 'read',\n },\n apply_semantic_change: {\n category: 'semantic_layer',\n workflowIntent: 'model_data',\n effect: 'commit',\n },\n eval_semantic_model: {\n category: 'semantic_layer',\n workflowIntent: 'query_data',\n effect: 'read',\n },\n get_semantic_layer: {\n category: 'semantic_layer',\n workflowIntent: 'query_data',\n effect: 'read',\n },\n update_semantic_layer: {\n category: 'semantic_layer',\n workflowIntent: 'query_data',\n effect: 'commit',\n },\n start_semantic_layer_generation: {\n category: 'semantic_layer',\n workflowIntent: 'query_data',\n effect: 'commit',\n },\n get_semantic_layer_generation_status: {\n category: 'semantic_layer',\n workflowIntent: 'query_data',\n effect: 'read',\n },\n\n // Reports\n list_scheduled_reports: {\n category: 'reports',\n workflowIntent: 'reports',\n effect: 'read',\n },\n\n // Custom chart types (DAT-925)\n // Returns template files; nothing is written or persisted.\n custom_chart_edit: {\n category: 'custom_charts',\n workflowIntent: 'custom_chart',\n effect: 'commit',\n },\n custom_chart_preview: {\n category: 'custom_charts',\n workflowIntent: 'custom_chart',\n effect: 'read',\n },\n load_custom_chart_bundle: {\n category: 'custom_charts',\n workflowIntent: 'custom_chart',\n effect: 'read',\n },\n load_custom_chart_runtime: {\n category: 'custom_charts',\n workflowIntent: 'custom_chart',\n effect: 'read',\n },\n custom_chart_scaffold: {\n category: 'custom_charts',\n workflowIntent: 'custom_chart',\n effect: 'read',\n },\n // Local rules plus POST /validate, which never persists.\n custom_chart_validate: {\n category: 'custom_charts',\n workflowIntent: 'custom_chart',\n effect: 'read',\n },\n // dry_run is the default, but mode:\"apply\" creates a chart or a version (and may publish).\n custom_chart_upload: {\n category: 'custom_charts',\n workflowIntent: 'custom_chart',\n effect: 'commit',\n },\n list_custom_charts: {\n category: 'custom_charts',\n workflowIntent: 'custom_chart',\n effect: 'read',\n },\n publish_custom_chart: {\n category: 'custom_charts',\n workflowIntent: 'custom_chart',\n effect: 'commit',\n },\n};\n","/**\n * Human titles for every tool (DEV-1195). The Claude Connectors Directory, the\n * ChatGPT directory and MCP hosts show these instead of the snake_case name, and\n * the Claude submission portal flags any tool without one. A tool missing from\n * this map still gets a title made from its name, so none ships without.\n */\nexport const TOOL_TITLES: Record<string, string> = {\n whoami: 'Show active credential',\n list_datasources: 'List data sources',\n discover_datasource_schema: 'Discover data source schema',\n list_datamarts: 'List datamarts',\n list_workspaces: 'List workspaces',\n sync_datasource: 'Sync data source',\n create_datamart: 'Create datamart',\n create_workspace: 'Create workspace',\n list_data_apps: 'List data apps',\n list_tenants: 'List tenants',\n create_data_app: 'Create data app',\n list_api_tokens: 'List API tokens',\n create_api_token: 'Create API token',\n rotate_api_token: 'Rotate API token',\n create_embed: 'Create embed',\n list_embeds: 'List embeds',\n get_embed_details: 'Get embed details',\n update_embed: 'Update embed',\n customize_embed_theme: 'Customize embed theme',\n get_demo_link: 'Get demo link',\n generate_guest_token: 'Generate guest token',\n generate_embed_code: 'Generate embed code',\n list_dashboards: 'List dashboards',\n create_dashboard: 'Create dashboard',\n get_dashboard: 'Get dashboard',\n dashboard_snapshot: 'Dashboard snapshot (picture)',\n generate_dashboard_tiles: 'Generate dashboard tiles',\n ask_question: 'Ask a data question',\n get_semantic_layer: 'Get semantic layer',\n update_semantic_layer: 'Update semantic layer',\n start_semantic_layer_generation: 'Start semantic layer generation',\n get_semantic_layer_generation_status: 'Get semantic layer generation status',\n search_semantic_model: 'Search semantic model',\n get_semantic_entity: 'Get semantic entity',\n propose_semantic_change: 'Propose semantic model change',\n apply_semantic_change: 'Apply semantic model change',\n eval_semantic_model: 'Evaluate semantic model',\n list_widgets: 'List widgets',\n render_metric_tile: 'Render a saved metric tile',\n validate_metric_spec: 'Validate metric spec',\n create_or_update_metric_from_query: 'Create or update metric from SQL',\n create_workspace_metric: 'Create workspace metric',\n add_widget: 'Add widget',\n update_widget: 'Update widget',\n remove_widget: 'Remove widget',\n generate_widget: 'Generate widget',\n list_scheduled_reports: 'List scheduled reports',\n custom_chart_scaffold: 'Scaffold custom chart',\n custom_chart_validate: 'Validate custom chart',\n custom_chart_upload: 'Upload custom chart',\n list_custom_charts: 'List custom charts',\n publish_custom_chart: 'Publish custom chart',\n};\n\nexport function toolTitle(name: string): string {\n if (TOOL_TITLES[name]) return TOOL_TITLES[name];\n const words = name.split('_').filter(Boolean);\n return words\n .map((word, index) =>\n index === 0 ? word[0].toUpperCase() + word.slice(1) : word\n )\n .join(' ');\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type { CreateMetricBody } from '../../api/widgets-api.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport {\n DatabrainApiError,\n stringify,\n toolError,\n toolSuccess,\n} from '../../utils/errors.js';\nimport { WRITE_CREATE } from '../annotations.js';\n\nexport function registerAddWidget(\n server: McpServer,\n client: DatabrainClient\n): void {\n const services = createServiceBundle(client);\n\n server.tool(\n 'add_widget',\n 'Add a widget to a customer dashboard. Non-technical flow: pass `clientId` + `dashboardName` (+ optional `workspaceName` if ambiguous). Cloning via `templateMetricId` is the recommended path — query, chart config, and datasource are all inherited. Data app and datasource auto-resolve; never ask the user for them.',\n {\n clientId: z\n .string()\n .describe(\n 'Client/tenant identifier (widget is created in their scope)'\n ),\n dashboardName: z\n .string()\n .optional()\n .describe(\n 'Dashboard name (non-technical). Preferred input — pass this with optional `workspaceName` instead of `embedId`.'\n ),\n workspaceName: z\n .string()\n .optional()\n .describe(\n 'Workspace name (non-technical). Only needed if `dashboardName` is ambiguous across workspaces.'\n ),\n embedId: z\n .string()\n .optional()\n .describe(\n 'Technical alternative to `dashboardName`. Pass only if you already have the embed identifier.'\n ),\n dataAppName: z\n .string()\n .optional()\n .describe(\n 'Technical override. Auto-resolved from the embed; non-technical callers should leave this blank.'\n ),\n templateMetricId: z\n .string()\n .optional()\n .describe(\n 'Source widget metricId to clone from. Copies query, chartOptions, and datasource fields; caller can override via other params.'\n ),\n name: z.string().optional().describe('Widget name (overrides template)'),\n metricId: z\n .string()\n .optional()\n .describe('Unique slug for the new widget (auto-generated if omitted)'),\n query: z\n .string()\n .optional()\n .describe('SQL query body (overrides template)'),\n chartOptions: z\n .record(z.string(), z.unknown())\n .optional()\n .describe(\n 'Chart config JSON (chart type, colors, legend, axes). Overrides template.'\n ),\n description: z.string().optional(),\n companyIntegrationId: z\n .string()\n .optional()\n .describe(\n 'Datasource UUID override. Auto-resolved from `embedId` or sole active datasource; leave blank unless the user explicitly picked one by ID.'\n ),\n integrationName: z\n .string()\n .optional()\n .describe(\n 'Datasource display name (e.g. \"Snowflake\"). Use this when the user picks a datasource by name — the id is looked up automatically.'\n ),\n isPublished: z\n .boolean()\n .optional()\n .describe('Publish immediately (default true)'),\n body: z\n .record(z.string(), z.unknown())\n .optional()\n .describe(\n 'Raw createMetric body passthrough. If provided, used as-is (after defaults). Overrides all other params.'\n ),\n widgets: z\n .array(z.record(z.string(), z.unknown()))\n .min(1)\n .max(50)\n .optional()\n .describe(\n 'Batch of raw createMetric bodies. Dashboard attachment is added to each body.'\n ),\n },\n WRITE_CREATE,\n async (params) => {\n try {\n const embed = await services.widgetService.resolveEmbedId({\n embedId: params.embedId,\n dashboardName: params.dashboardName,\n workspaceName: params.workspaceName,\n dataAppName: params.dataAppName,\n required: true,\n });\n if (!embed.ok) return toolError(embed.error);\n const embedId = embed.value.embedId as string;\n\n const ctx = await services.widgetService.resolveEmbedContext(\n embedId,\n params.dataAppName\n );\n if (!ctx.externalDashboardId) {\n return toolError(\n `Dashboard \"${params.dashboardName || embedId}\" has no externalDashboardId — cannot attach a widget. Verify via \\`get_embed_details\\`.`\n );\n }\n\n const dataAppName = await services.widgetService.resolveDataAppName(\n params.dataAppName,\n embedId\n );\n if (!dataAppName.ok) return toolError(dataAppName.error);\n\n const tenantScope =\n await services.widgetService.ensureTenantDashboardScope({\n embedId,\n clientId: params.clientId,\n dataAppName: dataAppName.value,\n dashboardName:\n embed.value.resolvedFrom?.dashboardName ||\n params.dashboardName ||\n null,\n });\n if (!tenantScope.ok) return toolError(tenantScope.error);\n\n const guestToken = await services.widgetService.mintGuestToken(\n params.clientId,\n dataAppName.value,\n [embedId]\n );\n\n if (params.widgets) {\n const created: Array<{\n externalMetricId: string;\n metricId: string;\n name: string;\n }> = [];\n for (const widget of params.widgets) {\n const createBody = { ...(widget as CreateMetricBody) };\n if (\n !createBody.externalDashboardIds ||\n createBody.externalDashboardIds.length === 0\n ) {\n createBody.externalDashboardIds = [\n { externalDashboardId: ctx.externalDashboardId },\n ];\n }\n const result = await services.widgetsApi.createMetric(\n guestToken,\n createBody\n );\n if (result.error) {\n return toolError(\n `Widget \"${createBody.metricId || createBody.name || 'unknown'}\" creation failed: ${stringify(result.error)}`\n );\n }\n const inserted = result.insert_externalMetrics_one as\n | Record<string, unknown>\n | undefined;\n created.push({\n externalMetricId:\n (inserted?.id as string) ||\n (inserted?.metricId as string) ||\n 'UNKNOWN_ID',\n metricId: (inserted?.metricId as string) || createBody.metricId,\n name: createBody.name,\n });\n }\n return toolSuccess(\n JSON.stringify({\n count: created.length,\n dashboard: embed.value.resolvedFrom?.dashboardName || embedId,\n clientId: params.clientId,\n widgets: created,\n })\n );\n }\n\n // 3. Build create body.\n let createBody: CreateMetricBody;\n\n if (params.body) {\n createBody = { ...(params.body as CreateMetricBody) };\n if (\n !createBody.externalDashboardIds ||\n createBody.externalDashboardIds.length === 0\n ) {\n createBody.externalDashboardIds = [\n { externalDashboardId: ctx.externalDashboardId },\n ];\n }\n } else if (params.templateMetricId) {\n const overrides: Partial<CreateMetricBody> = {};\n if (params.name !== undefined) overrides.name = params.name;\n if (params.metricId !== undefined)\n overrides.metricId = params.metricId;\n if (params.query !== undefined) overrides.query = params.query;\n if (params.chartOptions !== undefined)\n overrides.chartOptions = params.chartOptions;\n if (params.description !== undefined)\n overrides.description = params.description;\n if (params.companyIntegrationId !== undefined) {\n overrides.companyIntegrationId = params.companyIntegrationId;\n }\n if (params.integrationName !== undefined)\n overrides.integrationName = params.integrationName;\n if (params.isPublished !== undefined)\n overrides.isPublished = params.isPublished;\n\n createBody = await services.widgetService.buildCloneBody(\n guestToken,\n params.templateMetricId,\n overrides,\n ctx.externalDashboardId\n );\n } else {\n // Explicit spec path. Require the minimum set.\n if (!params.name)\n return toolError('`name` is required when not cloning a template.');\n if (!params.query)\n return toolError(\n '`query` is required when not cloning a template.'\n );\n\n const datasource = await services.widgetService.resolveDatasource(\n guestToken,\n {\n embedId,\n clientId: params.clientId,\n integrationId: params.companyIntegrationId,\n integrationName: params.integrationName,\n }\n );\n if (!datasource.ok) return toolError(datasource.error);\n\n createBody = {\n name: params.name,\n metricId: params.metricId || `widget-${Date.now()}`,\n query: params.query,\n chartOptions: params.chartOptions || {},\n description: params.description || '',\n companyIntegrationId: datasource.value.integrationId,\n integrationName: datasource.value.integrationName,\n isPublished: params.isPublished ?? true,\n isCreatedByClient: false,\n externalDashboardIds: [\n { externalDashboardId: ctx.externalDashboardId },\n ],\n };\n }\n\n // 4. Submit.\n const result = await services.widgetsApi.createMetric(\n guestToken,\n createBody\n );\n\n if ((result as Record<string, unknown>).error) {\n return toolError(\n `Widget creation failed: ${stringify((result as Record<string, unknown>).error)}\\n` +\n `\\nRequest body sent:\\n${JSON.stringify(createBody, null, 2).slice(0, 3000)}`\n );\n }\n\n const inserted = (result as Record<string, unknown>)\n .insert_externalMetrics_one as Record<string, unknown> | undefined;\n const newId =\n (inserted?.id as string) ||\n (inserted?.metricId as string) ||\n 'UNKNOWN_ID';\n const newMetricId =\n (inserted?.metricId as string) || createBody.metricId;\n\n return toolSuccess(\n `Widget added successfully.\\n\\n` +\n `- externalMetricId: \\`${newId}\\`\\n` +\n `- metricId: \\`${newMetricId}\\`\\n` +\n `- name: \\`${createBody.name}\\`\\n` +\n `- dashboard: \\`${embed.value.resolvedFrom?.dashboardName || embedId}\\`\\n` +\n `- clientId: \\`${params.clientId}\\`\\n\\n` +\n 'Use `list_widgets` to verify, or `update_widget`/`remove_widget` to adjust.'\n );\n } catch (err) {\n if (err instanceof DatabrainApiError) return err.toToolResponse();\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type { CreateMetricBody } from '../../api/widgets-api.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport {\n DatabrainApiError,\n stringify,\n toolError,\n toolSuccess,\n} from '../../utils/errors.js';\nimport { WRITE_IDEMPOTENT } from '../annotations.js';\nimport {\n APPLY_TO_PRODUCTION_CONFIRMATION,\n productionSafetyNote,\n validateProductionApply,\n} from './production-guards.js';\n\nconst modeSchema = z.enum(['dry_run', 'apply']).default('dry_run');\nconst conflictStrategySchema = z\n .enum(['fail', 'update', 'create_new'])\n .default('fail');\n\nfunction makePlanText(plan: Record<string, unknown>): string {\n return JSON.stringify(plan, null, 2);\n}\n\nfunction externalMetricIdFrom(widget: Record<string, unknown>): string | null {\n return (\n (typeof widget.externalMetricId === 'string' && widget.externalMetricId) ||\n (typeof widget.id === 'string' && widget.id) ||\n (typeof widget._id === 'string' && widget._id) ||\n null\n );\n}\n\nfunction createSuffix(): string {\n return new Date()\n .toISOString()\n .replace(/[-:.TZ]/g, '')\n .slice(0, 14);\n}\n\nexport function registerCreateOrUpdateMetricFromQuery(\n server: McpServer,\n client: DatabrainClient\n): void {\n const services = createServiceBundle(client);\n\n server.tool(\n 'create_or_update_metric_from_query',\n '[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.',\n {\n mode: modeSchema.describe(\n 'dry_run returns the plan only; apply executes after confirmation'\n ),\n confirm: z\n .string()\n .optional()\n .describe(`Required for apply: ${APPLY_TO_PRODUCTION_CONFIRMATION}`),\n conflictStrategy: conflictStrategySchema.describe(\n 'What to do if metricId already exists on the target dashboard'\n ),\n clientId: z\n .string()\n .describe('Client/tenant identifier for the dashboard widget scope'),\n workspaceName: z.string().describe('Target workspace name'),\n dashboardName: z\n .string()\n .optional()\n .describe('Dashboard name to attach to'),\n embedId: z\n .string()\n .optional()\n .describe('Technical embed id alternative to dashboardName'),\n dataAppName: z.string().optional().describe('Optional data app override'),\n name: z.string().describe('Metric/widget display name'),\n metricId: z.string().describe('Stable metric slug to create or update'),\n query: z\n .string()\n .describe('SQL query already validated against the warehouse'),\n description: z.string().optional().describe('Metric description'),\n chartOptions: z\n .record(z.string(), z.unknown())\n .optional()\n .describe('Chart configuration JSON'),\n companyIntegrationId: z\n .string()\n .optional()\n .describe('Datasource UUID override'),\n integrationName: z\n .string()\n .optional()\n .describe('Datasource display name override'),\n isPublished: z\n .boolean()\n .optional()\n .describe(\n 'Publish after apply. Defaults to false for production safety'\n ),\n requestedBy: z\n .string()\n .optional()\n .describe(\n 'Human operator/request context to store on the metric when supported'\n ),\n },\n WRITE_IDEMPOTENT,\n async (params) => {\n try {\n const mode = params.mode || 'dry_run';\n const conflictStrategy = params.conflictStrategy || 'fail';\n if (!params.name.trim()) return toolError('`name` cannot be empty.');\n if (!params.metricId.trim())\n return toolError('`metricId` cannot be empty.');\n if (!params.query.trim()) return toolError('`query` cannot be empty.');\n\n const embed = await services.widgetService.resolveEmbedId({\n embedId: params.embedId,\n dashboardName: params.dashboardName,\n workspaceName: params.workspaceName,\n dataAppName: params.dataAppName,\n required: true,\n });\n if (!embed.ok) return toolError(embed.error);\n const embedId = embed.value.embedId as string;\n\n const ctx = await services.widgetService.resolveEmbedContext(\n embedId,\n params.dataAppName\n );\n if (!ctx.externalDashboardId) {\n return toolError(\n `Dashboard \"${params.dashboardName || embedId}\" has no externalDashboardId. Verify with get_embed_details before creating metrics.`\n );\n }\n\n const dataAppName = await services.widgetService.resolveDataAppName(\n params.dataAppName,\n embedId\n );\n if (!dataAppName.ok) return toolError(dataAppName.error);\n\n const tenantScope =\n await services.widgetService.ensureTenantDashboardScope({\n embedId,\n clientId: params.clientId,\n dataAppName: dataAppName.value,\n dashboardName:\n embed.value.resolvedFrom?.dashboardName ||\n params.dashboardName ||\n null,\n });\n if (!tenantScope.ok) return toolError(tenantScope.error);\n\n const guestToken = await services.widgetService.mintGuestToken(\n params.clientId,\n dataAppName.value,\n [embedId]\n );\n\n const datasource = await services.widgetService.resolveDatasource(\n guestToken,\n {\n embedId,\n clientId: params.clientId,\n integrationId: params.companyIntegrationId,\n integrationName: params.integrationName,\n }\n );\n if (!datasource.ok) return toolError(datasource.error);\n\n const widgets = await services.widgetsApi.listWidgets(\n embedId,\n params.clientId\n );\n const existing = widgets.find(\n (widget) => widget.metricId === params.metricId\n );\n const existingExternalMetricId = existing\n ? externalMetricIdFrom(existing as Record<string, unknown>)\n : null;\n\n if (existing && conflictStrategy === 'fail') {\n return toolError(\n `MetricId \"${params.metricId}\" already exists on this dashboard. ` +\n 'Retry with conflictStrategy=\"update\" to update it or \"create_new\" to create a suffixed copy.'\n );\n }\n if (\n existing &&\n conflictStrategy === 'update' &&\n !existingExternalMetricId\n ) {\n return toolError(\n `MetricId \"${params.metricId}\" exists but no externalMetricId/id was returned, so it cannot be updated safely.`\n );\n }\n\n const finalMetricId =\n existing && conflictStrategy === 'create_new'\n ? `${params.metricId}-${createSuffix()}`\n : params.metricId;\n\n const createBody: CreateMetricBody = {\n name: params.name,\n metricId: finalMetricId,\n query: params.query,\n description: params.description || '',\n chartOptions: params.chartOptions || {},\n companyIntegrationId: datasource.value.integrationId,\n integrationName: datasource.value.integrationName,\n isPublished: params.isPublished ?? false,\n isCreatedByClient: false,\n createdBy: params.requestedBy,\n externalDashboardIds: [\n { externalDashboardId: ctx.externalDashboardId },\n ],\n };\n\n const updateSet: Record<string, unknown> = {\n name: params.name,\n query: params.query,\n description: params.description || '',\n chartOptions: params.chartOptions || {},\n companyIntegrationId: datasource.value.integrationId,\n integrationName: datasource.value.integrationName,\n isPublished: params.isPublished ?? false,\n createdBy: params.requestedBy,\n };\n\n const operation =\n existing && conflictStrategy === 'update'\n ? 'update_metric'\n : 'create_metric';\n\n const plan = {\n mode,\n operation,\n safety: productionSafetyNote(params.workspaceName),\n requiredApplyConfirmation: APPLY_TO_PRODUCTION_CONFIRMATION,\n resolved: {\n workspaceName: params.workspaceName,\n dashboardName:\n embed.value.resolvedFrom?.dashboardName ||\n params.dashboardName ||\n null,\n embedId,\n dataAppName: dataAppName.value,\n externalDashboardId: ctx.externalDashboardId,\n clientId: params.clientId,\n tenantScoped: true,\n datasource: datasource.value,\n },\n conflict: existing\n ? {\n metricId: existing.metricId || params.metricId,\n externalMetricId: existingExternalMetricId,\n strategy: conflictStrategy,\n }\n : null,\n metric:\n operation === 'update_metric'\n ? { externalMetricId: existingExternalMetricId, set: updateSet }\n : createBody,\n };\n\n if (mode === 'dry_run') {\n return toolSuccess(\n makePlanText({\n ...plan,\n status: 'dry_run_only',\n nextStep: `Review this plan. To execute, call again with mode=\"apply\" and confirm=\"${APPLY_TO_PRODUCTION_CONFIRMATION}\".`,\n })\n );\n }\n\n const guardError = validateProductionApply({\n workspaceName: params.workspaceName,\n confirm: params.confirm,\n });\n if (guardError) return toolError(guardError);\n\n if (operation === 'update_metric') {\n const result = await services.widgetsApi.updateMetric(guestToken, {\n externalMetricId: existingExternalMetricId as string,\n set: updateSet,\n });\n if ((result as Record<string, unknown>).error) {\n return toolError(\n `Metric update failed: ${stringify((result as Record<string, unknown>).error)}`\n );\n }\n return toolSuccess(\n makePlanText({\n ...plan,\n status: 'applied',\n result,\n verifyWith: 'list_widgets',\n })\n );\n }\n\n const result = await services.widgetsApi.createMetric(\n guestToken,\n createBody\n );\n if ((result as Record<string, unknown>).error) {\n return toolError(\n `Metric creation failed: ${stringify((result as Record<string, unknown>).error)}`\n );\n }\n\n return toolSuccess(\n makePlanText({\n ...plan,\n status: 'applied',\n result,\n verifyWith: 'list_widgets',\n })\n );\n } catch (err) {\n if (err instanceof DatabrainApiError) return err.toToolResponse();\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport {\n DatabrainApiError,\n toolError,\n toolSuccess,\n} from '../../utils/errors.js';\nimport { WRITE_IDEMPOTENT } from '../annotations.js';\nimport {\n APPLY_TO_PRODUCTION_CONFIRMATION,\n productionSafetyNote,\n validateProductionApply,\n} from './production-guards.js';\n\nconst modeSchema = z.enum(['dry_run', 'apply']).default('dry_run');\n\n/**\n * Create or update a workspace-level metric from validated SQL using the org\n * service token. The metric is scoped to the workspace and is intentionally NOT\n * attached to any dashboard (attaching = the separate \"publish\" action). Hits\n * the internal, service-token-authenticated WorkspaceRouter endpoint, which\n * upserts on the metricId: passing an existing metricId updates that metric in\n * place and re-derives its Dimensions/Measures from the new query. Archived/\n * draft and publish state are preserved across an update.\n */\nexport function registerCreateWorkspaceMetric(\n server: McpServer,\n client: DatabrainClient\n): void {\n server.tool(\n 'create_workspace_metric',\n '[INTERNAL ANALYTICS] Create or update a workspace-level metric from validated SQL (migrating your SQL into Databrain), not embedding. Pass an existing metricId to update in place — query and Dimensions/Measures re-hydrated, publish state preserved; omit to create. Workspace-scoped, unattached. Uses the org service token. Defaults to dry-run; apply needs confirmation.',\n {\n mode: modeSchema.describe(\n 'dry_run validates the SQL only (no write); apply creates or updates the metric after confirmation'\n ),\n confirm: z\n .string()\n .optional()\n .describe(`Required for apply: ${APPLY_TO_PRODUCTION_CONFIRMATION}`),\n workspaceName: z.string().describe('Target workspace name'),\n name: z.string().describe('Metric display name'),\n query: z\n .string()\n .describe(\n '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).'\n ),\n metricId: z\n .string()\n .optional()\n .describe(\n 'Stable metric slug. Pass an existing slug to UPDATE that metric in place. Omit to create — 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.'\n ),\n description: z.string().optional().describe('Metric description'),\n datasourceId: z\n .string()\n .optional()\n .describe(\n 'Datasource UUID override; defaults to the workspace datasource'\n ),\n isPublished: z\n .boolean()\n .optional()\n .describe(\n 'Publish after apply. Defaults to false. Applies to creates; on updates the existing publish state is preserved.'\n ),\n },\n WRITE_IDEMPOTENT,\n async (params) => {\n try {\n const mode = params.mode || 'dry_run';\n if (!params.name.trim()) return toolError('`name` cannot be empty.');\n if (!params.query.trim()) return toolError('`query` cannot be empty.');\n\n const isApply = mode === 'apply';\n if (isApply) {\n const guardError = validateProductionApply({\n workspaceName: params.workspaceName,\n confirm: params.confirm,\n });\n if (guardError) return toolError(guardError);\n }\n\n const body = {\n workspaceName: params.workspaceName,\n name: params.name,\n query: params.query,\n metricId: params.metricId,\n description: params.description,\n datasourceId: params.datasourceId,\n isPublished: params.isPublished ?? false,\n validateOnly: !isApply,\n };\n\n const result = await client.request<Record<string, unknown>>({\n method: 'POST',\n // MCP-only control-plane route (not the public /api/v2 surface).\n path: '/api/mcp/metrics/create',\n auth: 'service',\n body,\n });\n\n // The backend upserts on metricId: if it already exists in this\n // workspace the row is updated in place (query + Dimensions/Measures\n // re-derived; archived/draft + publish state preserved), otherwise a new\n // metric is created. metricId is stable, so re-running with the same one\n // is idempotent.\n return toolSuccess(\n JSON.stringify(\n {\n mode,\n safety: productionSafetyNote(params.workspaceName),\n result,\n nextStep: isApply\n ? 'Saved. If the metricId already existed it was UPDATED in place (query and Dimensions/Measures re-derived; publish state preserved); otherwise a new metric was CREATED, unpublished and unattached. Publish/attach it to a dashboard as a separate step when ready.'\n : 'Dry-run only — no metric written; it validates the SQL and returns the output columns. Re-run with mode \"apply\" and confirm to create or update the metric.',\n },\n null,\n 2\n )\n );\n } catch (err) {\n if (err instanceof DatabrainApiError) return err.toToolResponse();\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { firstRows } from '../../apps/contract.js';\nimport { chartResult, hasChartApps, tagChartTool } from '../../apps/feature.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport {\n DatabrainApiError,\n stringify,\n toolError,\n toolSuccess,\n} from '../../utils/errors.js';\nimport { READ_ONLY } from '../annotations.js';\n\nexport function registerGenerateWidget(\n server: McpServer,\n client: DatabrainClient\n): void {\n const services = createServiceBundle(client);\n\n const tool = server.tool(\n 'generate_widget',\n 'AI-generate a widget draft from a natural-language prompt. Does NOT persist — 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.',\n {\n clientId: z.string().describe('Client/tenant identifier'),\n userInputs: z\n .record(z.string(), z.unknown())\n .describe(\n 'Prompt + context object. Typical shape: { prompt: \"calls per day over last 30 days\", schema: {...}, examples: [...] }. Backend decides which keys it honors.'\n ),\n dashboardName: z\n .string()\n .optional()\n .describe(\n 'Dashboard name (non-technical). Preferred input for CS/CX flows — pass this with optional `workspaceName` instead of `embedId`.'\n ),\n workspaceName: z\n .string()\n .optional()\n .describe(\n 'Workspace name (non-technical). Only needed if `dashboardName` is ambiguous across workspaces.'\n ),\n embedId: z\n .string()\n .optional()\n .describe(\n 'Technical alternative to `dashboardName`. Pass only if you already have the embed identifier.'\n ),\n dataAppName: z\n .string()\n .optional()\n .describe(\n 'Technical override. Auto-resolved from the embed; non-technical callers should leave this blank.'\n ),\n integrationId: z\n .string()\n .optional()\n .describe(\n \"Technical override — the datasource UUID. Non-technical callers must leave this blank; the datasource is inherited from the dashboard's existing widgets.\"\n ),\n integrationName: z\n .string()\n .optional()\n .describe(\n \"Technical override — datasource display name. Non-technical callers must leave this blank; the datasource is inherited from the dashboard's existing widgets.\"\n ),\n },\n READ_ONLY,\n async (params) => {\n try {\n const embed = await services.widgetService.resolveEmbedId({\n embedId: params.embedId,\n dashboardName: params.dashboardName,\n workspaceName: params.workspaceName,\n dataAppName: params.dataAppName,\n required: true,\n });\n if (!embed.ok) return toolError(embed.error);\n const embedId = embed.value.embedId as string;\n\n const dataAppName = await services.widgetService.resolveDataAppName(\n params.dataAppName,\n embedId\n );\n if (!dataAppName.ok) return toolError(dataAppName.error);\n\n const tenantScope =\n await services.widgetService.ensureTenantDashboardScope({\n embedId,\n clientId: params.clientId,\n dataAppName: dataAppName.value,\n dashboardName:\n embed.value.resolvedFrom?.dashboardName ||\n params.dashboardName ||\n null,\n });\n if (!tenantScope.ok) return toolError(tenantScope.error);\n\n const guestToken = await services.widgetService.mintGuestToken(\n params.clientId,\n dataAppName.value,\n [embedId]\n );\n\n const datasource = await services.widgetService.resolveDatasource(\n guestToken,\n {\n embedId,\n clientId: params.clientId,\n integrationId: params.integrationId,\n integrationName: params.integrationName,\n }\n );\n if (!datasource.ok) return toolError(datasource.error);\n\n const result = await services.widgetsApi.generateMetric(guestToken, {\n integrationId: datasource.value.integrationId,\n integrationName: datasource.value.integrationName,\n userInputs: params.userInputs,\n });\n\n const resultRec = result as Record<string, unknown>;\n if (resultRec.error) {\n return toolError(\n `Widget generation failed: ${stringify(resultRec.error)}`\n );\n }\n\n if (hasChartApps(server)) {\n const rows = firstRows(resultRec.result);\n return chartResult(\n 'Widget draft generated. Preview the first page before saving.',\n {\n kind: 'table',\n title: 'Widget draft',\n chartSpec: { type: resultRec.chartType ?? 'table' },\n rows,\n columns: Object.keys(rows[0] ?? {}),\n description:\n 'Unsaved draft. Showing the first page; interactive preview is not available yet.',\n }\n );\n }\n\n return toolSuccess(\n JSON.stringify({\n message:\n 'Draft generated. Review the `query` and `result` fields below, then pass to `add_widget` (using raw `body` passthrough) to persist.',\n resolved: {\n dataAppName: dataAppName.value,\n integrationName: datasource.value.integrationName,\n },\n draft: {\n query: resultRec.query ?? null,\n result: resultRec.result ?? null,\n metaData: resultRec.metaData ?? null,\n timeTaken: resultRec.timeTaken ?? null,\n error: resultRec.error ?? null,\n },\n })\n );\n } catch (err) {\n if (err instanceof DatabrainApiError) return err.toToolResponse();\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n tagChartTool(server, tool);\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type { WidgetSummary } from '../../api/widgets-api.js';\nimport {\n chartIndex,\n chartResult,\n hasChartApps,\n tagChartTool,\n} from '../../apps/feature.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport {\n DatabrainApiError,\n toolError,\n toolSuccess,\n} from '../../utils/errors.js';\nimport { READ_ONLY } from '../annotations.js';\n\n/**\n * The chart tile can only render a widget it can name. `GET /api/v2/data-app/metrics`\n * returns `metricId` and nothing else on the identity side, so the uuid-first order used\n * elsewhere resolves to `undefined` for every row and the tile receives an empty chooser.\n * The chart authorizer accepts either the metric uuid or the `metricId` slug, so fall\n * through to the slug rather than dropping the widget.\n */\nfunction widgetReferenceId(widget: WidgetSummary): string | undefined {\n for (const candidate of [\n widget.externalMetricId,\n widget.id,\n widget._id,\n widget.metricId,\n ]) {\n if (typeof candidate === 'string' && candidate.trim().length > 0)\n return candidate.trim();\n }\n return undefined;\n}\n\nexport function registerListWidgets(\n server: McpServer,\n client: DatabrainClient\n): void {\n const services = createServiceBundle(client);\n const tool = server.tool(\n 'list_widgets',\n \"List saved widgets. Hosted sign-ins read an authorized workspace dashboard without an embed; guest/API flows use clientId and an embed. 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.\",\n {\n clientId: z\n .string()\n .optional()\n .describe('Client/tenant identifier for this dashboard'),\n dataAppName: z\n .string()\n .trim()\n .min(1)\n .optional()\n .describe(\n 'Data app for a tenant/embed read. Omit to resolve it from the embed; hosted workspace reads need none.'\n ),\n workspaceId: z\n .string()\n .min(1)\n .optional()\n .describe(\n 'Workspace UUID from the wid query parameter in a dashboard link.'\n ),\n dashboardId: z\n .string()\n .min(1)\n .optional()\n .describe(\n 'Dashboard UUID or slug returned by list_dashboards. Hosted sign-ins only.'\n ),\n dashboardName: z\n .string()\n .optional()\n .describe(\n 'Dashboard name (non-technical). Preferred input — pass this with optional `workspaceName` instead of `embedId`.'\n ),\n workspaceName: z\n .string()\n .optional()\n .describe(\n 'Workspace name (non-technical). Only needed if `dashboardName` is ambiguous across workspaces.'\n ),\n embedId: z\n .string()\n .optional()\n .describe(\n 'Technical alternative to `dashboardName`. Pass only if you already have the embed identifier.'\n ),\n },\n READ_ONLY,\n async (params) => {\n try {\n if (\n params.dashboardId &&\n (params.clientId !== undefined || params.embedId)\n ) {\n return toolError(\n 'dashboardId is for hosted workspace reads. For a tenant, use clientId with dashboardName or embedId.'\n );\n }\n if (\n client.isHosted() &&\n params.clientId === undefined &&\n !params.embedId\n ) {\n const result = await client.request<{\n dashboardId: string;\n externalDashboardId: string;\n widgets: WidgetSummary[];\n }>({\n method: 'POST',\n path: '/api/v2/workspace/dashboard/widgets',\n auth: 'service',\n body: {\n ...(params.dashboardId\n ? { dashboardId: params.dashboardId }\n : {}),\n ...(params.dashboardName\n ? { dashboardName: params.dashboardName }\n : {}),\n workspaceName: params.workspaceName,\n workspaceId: params.workspaceId,\n },\n });\n const widgets = result.widgets;\n if (hasChartApps(server)) {\n const references = widgets.slice(0, 50).flatMap((widget) => {\n const widgetId = widgetReferenceId(widget);\n return widgetId\n ? [\n {\n name: widget.name || 'Untitled widget',\n chartType:\n typeof widget.chartType === 'string'\n ? widget.chartType\n : null,\n reference: { dashboardId: result.dashboardId, widgetId },\n },\n ]\n : [];\n });\n return chartResult(\n `${widgets.length} saved widgets available. ` +\n chartIndex(\n result.dashboardId,\n references.map((r) => ({\n widgetId: r.reference.widgetId,\n name: r.name,\n chartType: r.chartType,\n }))\n ),\n {\n kind: 'dashboard',\n title: params.dashboardName || 'Dashboard',\n rows: [],\n widgets: references,\n dashboardId: result.dashboardId,\n externalDashboardId: result.externalDashboardId,\n description:\n widgets.length > 50 ? 'Showing the first 50 widgets.' : '',\n }\n );\n }\n return toolSuccess(JSON.stringify(result));\n }\n if (!params.clientId)\n return toolError(\n 'clientId is required for an embed/tenant dashboard. Hosted sign-ins may omit it for a workspace dashboard.'\n );\n const embed = await services.widgetService.resolveEmbedId({\n embedId: params.embedId,\n dashboardName: params.dashboardName,\n workspaceName: params.workspaceName,\n dataAppName: params.dataAppName,\n required: true,\n });\n if (!embed.ok) return toolError(embed.error);\n const embedId = embed.value.embedId as string;\n\n // API keys already bind one app. OAuth must send the resolved app explicitly.\n const app = client.isHosted()\n ? await services.widgetService.resolveDataAppName(\n params.dataAppName,\n embedId\n )\n : { ok: true as const, value: params.dataAppName };\n if (!app.ok) return toolError(app.error);\n const widgets = await services.widgetsApi.listWidgets(\n embedId,\n params.clientId,\n app.value\n );\n\n if (hasChartApps(server)) {\n const visible = (Array.isArray(widgets) ? widgets : []).slice(0, 50);\n const references = visible.flatMap((w) => {\n const widgetId = widgetReferenceId(w);\n return widgetId\n ? [\n {\n name:\n typeof w.name === 'string'\n ? w.name.slice(0, 500)\n : 'Untitled widget',\n reference: {\n widgetId,\n embedId,\n clientId: params.clientId,\n ...(app.value ? { dataAppName: app.value } : {}),\n },\n },\n ]\n : [];\n });\n return chartResult(\n `${references.length} widgets available in the first dashboard page.`,\n {\n kind: 'dashboard',\n title: 'Dashboard',\n rows: [],\n widgets: references,\n description:\n Array.isArray(widgets) && widgets.length > 50\n ? 'Showing the first 50 widgets.'\n : '',\n }\n );\n }\n\n if (!Array.isArray(widgets) || widgets.length === 0) {\n return toolSuccess(\n `No widgets found on dashboard \"${embed.value.resolvedFrom?.dashboardName || embedId}\" for client \"${params.clientId}\".`\n );\n }\n\n return toolSuccess(\n JSON.stringify({\n count: widgets.length,\n dashboardName: embed.value.resolvedFrom?.dashboardName || null,\n embedId,\n clientId: params.clientId,\n widgets: widgets.map((w) => ({\n externalMetricId:\n (typeof w.externalMetricId === 'string' &&\n w.externalMetricId) ||\n (typeof w.id === 'string' && w.id) ||\n (typeof w._id === 'string' && w._id) ||\n null,\n metricId: w.metricId || null,\n name: w.name || null,\n isPublished: w.isPublished ?? null,\n createdByUser: w.createdByUser || null,\n })),\n })\n );\n } catch (err) {\n if (err instanceof DatabrainApiError) return err.toToolResponse();\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n tagChartTool(server, tool);\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport {\n DatabrainApiError,\n stringify,\n toolError,\n toolSuccess,\n} from '../../utils/errors.js';\nimport { DESTRUCTIVE } from '../annotations.js';\n\nexport function registerRemoveWidget(\n server: McpServer,\n client: DatabrainClient\n): void {\n const services = createServiceBundle(client);\n\n server.tool(\n 'remove_widget',\n \"Remove a widget from a customer dashboard. Non-technical flow: pass `clientId` + `dashboardName` (+ optional `workspaceName` if ambiguous) + `externalMetricId`. Per-client soft delete — the widget stays on the template dashboard and on other customers' dashboards.\",\n {\n externalMetricId: z\n .string()\n .describe('Internal uuid of the widget (externalMetrics.id)'),\n clientId: z\n .string()\n .describe(\n 'Client/tenant identifier — the widget will be hidden for this client only'\n ),\n dashboardName: z\n .string()\n .optional()\n .describe(\n 'Dashboard name (non-technical). Preferred input — pass this with optional `workspaceName` instead of `embedId`.'\n ),\n workspaceName: z\n .string()\n .optional()\n .describe(\n 'Workspace name (non-technical). Only needed if `dashboardName` is ambiguous across workspaces.'\n ),\n embedId: z\n .string()\n .optional()\n .describe(\n 'Technical alternative to `dashboardName`. Pass only if you already have the embed identifier.'\n ),\n dataAppName: z\n .string()\n .optional()\n .describe(\n 'Technical override. Auto-resolved from the dashboard; non-technical callers should leave this blank.'\n ),\n },\n DESTRUCTIVE,\n async (params) => {\n try {\n const embed = await services.widgetService.resolveEmbedId({\n embedId: params.embedId,\n dashboardName: params.dashboardName,\n workspaceName: params.workspaceName,\n dataAppName: params.dataAppName,\n required: true,\n });\n if (!embed.ok) return toolError(embed.error);\n const embedId = embed.value.embedId as string;\n\n const dataAppName = await services.widgetService.resolveDataAppName(\n params.dataAppName,\n embedId\n );\n if (!dataAppName.ok) return toolError(dataAppName.error);\n\n const tenantScope =\n await services.widgetService.ensureTenantDashboardScope({\n embedId,\n clientId: params.clientId,\n dataAppName: dataAppName.value,\n dashboardName:\n embed.value.resolvedFrom?.dashboardName ||\n params.dashboardName ||\n null,\n });\n if (!tenantScope.ok) return toolError(tenantScope.error);\n\n const guestToken = await services.widgetService.mintGuestToken(\n params.clientId,\n dataAppName.value,\n [embedId]\n );\n\n const result = await services.widgetsApi.markArchived(guestToken, {\n id: params.externalMetricId,\n clientId: params.clientId,\n });\n\n if ((result as Record<string, unknown>).error) {\n return toolError(\n `Widget removal failed: ${stringify((result as Record<string, unknown>).error)}`\n );\n }\n\n return toolSuccess(\n `Widget removed for client \"${params.clientId}\".\\n\\n` +\n `- externalMetricId: \\`${params.externalMetricId}\\`\\n` +\n `- clientId: \\`${params.clientId}\\`\\n\\n` +\n 'Note: this is a per-client soft delete. The widget remains available for other clients and on the source dashboard.'\n );\n } catch (err) {\n if (err instanceof DatabrainApiError) return err.toToolResponse();\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport {\n DatabrainApiError,\n stringify,\n toolError,\n toolSuccess,\n} from '../../utils/errors.js';\nimport { WRITE_IDEMPOTENT } from '../annotations.js';\n\nexport function registerUpdateWidget(\n server: McpServer,\n client: DatabrainClient\n): void {\n const services = createServiceBundle(client);\n\n server.tool(\n 'update_widget',\n '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.',\n {\n externalMetricId: z\n .string()\n .describe(\n 'Internal uuid of the widget (externalMetrics.id). Not the user-facing metricId slug.'\n ),\n clientId: z.string().describe('Client/tenant identifier'),\n dashboardName: z\n .string()\n .optional()\n .describe(\n 'Dashboard name (non-technical). Preferred input — pass this with optional `workspaceName` instead of `embedId`.'\n ),\n workspaceName: z\n .string()\n .optional()\n .describe(\n 'Workspace name (non-technical). Only needed if `dashboardName` is ambiguous across workspaces.'\n ),\n embedId: z\n .string()\n .optional()\n .describe(\n 'Technical alternative to `dashboardName`. Pass only if you already have the embed identifier.'\n ),\n dataAppName: z\n .string()\n .optional()\n .describe(\n 'Technical override. Auto-resolved from the dashboard; non-technical callers should leave this blank.'\n ),\n set: z\n .record(z.string(), z.unknown())\n .describe(\n 'Partial patch. Keys can include: name, query, chartOptions, description, isPublished, isLive, selectedGroupBy, drillDownSettings, limit, etc.'\n ),\n },\n WRITE_IDEMPOTENT,\n async (params) => {\n try {\n if (!params.set || Object.keys(params.set).length === 0) {\n return toolError('`set` must contain at least one field to update.');\n }\n\n const embed = await services.widgetService.resolveEmbedId({\n embedId: params.embedId,\n dashboardName: params.dashboardName,\n workspaceName: params.workspaceName,\n dataAppName: params.dataAppName,\n required: true,\n });\n if (!embed.ok) return toolError(embed.error);\n const embedId = embed.value.embedId as string;\n\n const dataAppName = await services.widgetService.resolveDataAppName(\n params.dataAppName,\n embedId\n );\n if (!dataAppName.ok) return toolError(dataAppName.error);\n\n const tenantScope =\n await services.widgetService.ensureTenantDashboardScope({\n embedId,\n clientId: params.clientId,\n dataAppName: dataAppName.value,\n dashboardName:\n embed.value.resolvedFrom?.dashboardName ||\n params.dashboardName ||\n null,\n });\n if (!tenantScope.ok) return toolError(tenantScope.error);\n\n const guestToken = await services.widgetService.mintGuestToken(\n params.clientId,\n dataAppName.value,\n [embedId]\n );\n\n const result = await services.widgetsApi.updateMetric(guestToken, {\n externalMetricId: params.externalMetricId,\n set: params.set,\n });\n\n if ((result as Record<string, unknown>).error) {\n return toolError(\n `Widget update failed: ${stringify((result as Record<string, unknown>).error)}`\n );\n }\n\n const updated = (result as Record<string, unknown>)\n .update_externalMetrics_by_pk as Record<string, unknown> | undefined;\n const id = (updated?.id as string) || params.externalMetricId;\n const metricId = (updated?.metricId as string) || null;\n\n return toolSuccess(\n `Widget updated successfully.\\n\\n` +\n `- externalMetricId: \\`${id}\\`\\n` +\n (metricId ? `- metricId: \\`${metricId}\\`\\n` : '') +\n `- fields changed: ${Object.keys(params.set).join(', ')}\\n\\n` +\n 'Use `list_widgets` to verify.'\n );\n } catch (err) {\n if (err instanceof DatabrainApiError) return err.toToolResponse();\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport {\n DatabrainApiError,\n toolError,\n toolSuccess,\n} from '../../utils/errors.js';\nimport { READ_ONLY } from '../annotations.js';\nimport {\n APPLY_TO_PRODUCTION_CONFIRMATION,\n productionSafetyNote,\n} from './production-guards.js';\n\nexport function registerValidateMetricSpec(\n server: McpServer,\n client: DatabrainClient\n): void {\n const services = createServiceBundle(client);\n\n server.tool(\n 'validate_metric_spec',\n 'Validate a production metric spec from SQL without saving it. Resolves dashboard, data app, datasource, conflicts, and required fields.',\n {\n clientId: z\n .string()\n .describe(\n 'Client/tenant identifier used to validate dashboard widget scope'\n ),\n workspaceName: z\n .string()\n .describe('Target production-backed workspace name'),\n dashboardName: z\n .string()\n .optional()\n .describe('Dashboard name to attach to'),\n embedId: z\n .string()\n .optional()\n .describe('Technical embed id alternative to dashboardName'),\n dataAppName: z.string().optional().describe('Optional data app override'),\n name: z.string().describe('Metric/widget display name'),\n metricId: z.string().describe('Stable metric slug to create or update'),\n query: z\n .string()\n .describe('SQL query already validated against the warehouse'),\n description: z.string().optional().describe('Metric description'),\n chartOptions: z\n .record(z.string(), z.unknown())\n .optional()\n .describe('Chart configuration JSON'),\n companyIntegrationId: z\n .string()\n .optional()\n .describe('Datasource UUID override'),\n integrationName: z\n .string()\n .optional()\n .describe('Datasource display name override'),\n },\n READ_ONLY,\n async (params) => {\n try {\n if (!params.name.trim()) return toolError('`name` cannot be empty.');\n if (!params.metricId.trim())\n return toolError('`metricId` cannot be empty.');\n if (!params.query.trim()) return toolError('`query` cannot be empty.');\n\n const embed = await services.widgetService.resolveEmbedId({\n embedId: params.embedId,\n dashboardName: params.dashboardName,\n workspaceName: params.workspaceName,\n dataAppName: params.dataAppName,\n required: true,\n });\n if (!embed.ok) return toolError(embed.error);\n const embedId = embed.value.embedId as string;\n\n const ctx = await services.widgetService.resolveEmbedContext(\n embedId,\n params.dataAppName\n );\n if (!ctx.externalDashboardId) {\n return toolError(\n `Dashboard \"${params.dashboardName || embedId}\" has no externalDashboardId. Verify with get_embed_details before creating metrics.`\n );\n }\n\n const dataAppName = await services.widgetService.resolveDataAppName(\n params.dataAppName,\n embedId\n );\n if (!dataAppName.ok) return toolError(dataAppName.error);\n\n const tenantScope =\n await services.widgetService.ensureTenantDashboardScope({\n embedId,\n clientId: params.clientId,\n dataAppName: dataAppName.value,\n dashboardName:\n embed.value.resolvedFrom?.dashboardName ||\n params.dashboardName ||\n null,\n });\n if (!tenantScope.ok) return toolError(tenantScope.error);\n\n const guestToken = await services.widgetService.mintGuestToken(\n params.clientId,\n dataAppName.value,\n [embedId]\n );\n\n const datasource = await services.widgetService.resolveDatasource(\n guestToken,\n {\n embedId,\n clientId: params.clientId,\n integrationId: params.companyIntegrationId,\n integrationName: params.integrationName,\n }\n );\n if (!datasource.ok) return toolError(datasource.error);\n\n const widgets = await services.widgetsApi.listWidgets(\n embedId,\n params.clientId\n );\n const existing = widgets.find(\n (widget) => widget.metricId === params.metricId\n );\n\n return toolSuccess(\n JSON.stringify(\n {\n status: 'valid_for_production_dry_run',\n safety: productionSafetyNote(params.workspaceName),\n resolved: {\n workspaceName: params.workspaceName,\n dashboardName:\n embed.value.resolvedFrom?.dashboardName ||\n params.dashboardName ||\n null,\n embedId,\n dataAppName: dataAppName.value,\n externalDashboardId: ctx.externalDashboardId,\n tenantScoped: true,\n datasource,\n },\n conflict: existing\n ? {\n strategyNeeded: true,\n metricId: existing.metricId,\n externalMetricId:\n existing.externalMetricId ||\n existing.id ||\n existing._id ||\n null,\n name: existing.name || null,\n }\n : null,\n proposedMetric: {\n name: params.name,\n metricId: params.metricId,\n query: params.query,\n description: params.description || '',\n chartOptions: params.chartOptions || {},\n isPublishedDefault: false,\n },\n nextStep: `Call create_or_update_metric_from_query with mode=\"dry_run\" first, then mode=\"apply\" and confirm=\"${APPLY_TO_PRODUCTION_CONFIRMATION}\" only after reviewing the plan.`,\n },\n null,\n 2\n )\n );\n } catch (err) {\n if (err instanceof DatabrainApiError) return err.toToolResponse();\n return toolError(`Unexpected error: ${(err as Error).message}`);\n }\n }\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { DatabrainClient } from '../client/databrain-client.js';\nimport { toolContext } from '../utils/tool-context.js';\nimport { registerListDashboards } from './analytics/list-dashboards.js';\nimport { registerWhoami } from './auth/whoami.js';\nimport { registerCustomChartAuthor } from './custom-chart/author.js';\nimport { registerListCustomCharts } from './custom-chart/list.js';\nimport { registerPublishCustomChart } from './custom-chart/publish.js';\nimport { registerCustomChartScaffold } from './custom-chart/scaffold.js';\nimport { registerCustomChartUpload } from './custom-chart/upload.js';\nimport { registerCustomChartValidate } from './custom-chart/validate.js';\nimport { registerCreateDashboard } from './dashboard/create-dashboard.js';\nimport { registerDashboardSnapshot } from './dashboard/dashboard-snapshot.js';\nimport { registerGenerateDashboardTiles } from './dashboard/generate-dashboard-tiles.js';\nimport { registerGetDashboard } from './dashboard/get-dashboard.js';\nimport { registerCreateApiToken } from './data-app/create-api-token.js';\nimport { registerCreateDataApp } from './data-app/create-data-app.js';\nimport { registerListApiTokens } from './data-app/list-api-tokens.js';\nimport { registerListDataApps } from './data-app/list-data-apps.js';\nimport { registerListTenants } from './data-app/list-tenants.js';\nimport { registerRotateApiToken } from './data-app/rotate-api-token.js';\nimport { registerCreateEmbed } from './embed/create-embed.js';\nimport { registerCustomizeTheme } from './embed/customize-theme.js';\nimport { registerGetDemoLink } from './embed/get-demo-link.js';\nimport { registerGetEmbedDetails } from './embed/get-embed-details.js';\nimport { registerListEmbeds } from './embed/list-embeds.js';\nimport { registerUpdateEmbed } from './embed/update-embed.js';\nimport { registerGenerateEmbedCode } from './frontend/generate-embed-code.js';\nimport { registerGenerateGuestToken } from './frontend/generate-guest-token.js';\nimport { registerCreateDatamart } from './infrastructure/create-datamart.js';\nimport { registerDiscoverDatasourceSchema } from './infrastructure/discover-datasource-schema.js';\nimport { registerListDatamarts } from './infrastructure/list-datamarts.js';\nimport { registerListDatasources } from './infrastructure/list-datasources.js';\nimport { registerListWorkspaces } from './infrastructure/list-workspaces.js';\nimport { registerSyncDatasource } from './infrastructure/sync-datasource.js';\nimport { registerAskQuestion } from './query/ask-question.js';\nimport { registerGetSemanticLayer } from './query/get-semantic-layer.js';\nimport {\n registerGetSemanticLayerGenerationStatus,\n registerStartSemanticLayerGeneration,\n} from './query/semantic-generation.js';\nimport {\n registerApplySemanticChange,\n registerEvalSemanticModel,\n registerGetSemanticEntity,\n registerProposeSemanticChange,\n registerSearchSemanticModel,\n} from './query/semantic-model.js';\nimport { registerUpdateSemanticLayer } from './query/update-semantic-layer.js';\nimport { registerListScheduledReports } from './reports/list-scheduled-reports.js';\nimport { DEFAULT_TOOL_META, TOOL_METADATA } from './tool-metadata.js';\nimport { toolTitle } from './tool-titles.js';\nimport { registerAddWidget } from './widgets/add-widget.js';\nimport { registerCreateOrUpdateMetricFromQuery } from './widgets/create-or-update-metric-from-query.js';\nimport { registerCreateWorkspaceMetric } from './widgets/create-workspace-metric.js';\nimport { registerGenerateWidget } from './widgets/generate-widget.js';\nimport { registerListWidgets } from './widgets/list-widgets.js';\nimport { registerRemoveWidget } from './widgets/remove-widget.js';\nimport { registerUpdateWidget } from './widgets/update-widget.js';\nimport { registerValidateMetricSpec } from './widgets/validate-metric-spec.js';\n\n/**\n * Wrap server.tool so every tool handler runs inside an AsyncLocalStorage\n * context carrying its intent metadata. DatabrainClient reads that context to\n * tag outbound API calls (X-Databrain-MCP-* headers) — no per-tool changes\n * needed. Done once here so all subsequent register*() calls are instrumented.\n */\nfunction instrumentToolRegistration(server: McpServer): void {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const original = (server.tool as (...args: any[]) => unknown).bind(server);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (server as any).tool = (...args: any[]): unknown => {\n const name = args[0] as string;\n const meta = TOOL_METADATA[name] ?? DEFAULT_TOOL_META;\n const cbIndex = args.length - 1;\n const cb = args[cbIndex];\n if (typeof cb === 'function') {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const handler = cb as (...handlerArgs: any[]) => unknown;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n args[cbIndex] = (...handlerArgs: any[]): unknown =>\n toolContext.run(\n {\n tool: name,\n category: meta.category,\n workflowIntent: meta.workflowIntent,\n inputMode: 'tool_call',\n },\n () => handler(...handlerArgs)\n );\n }\n // Directory listings and hosts show a human title. The shared annotation\n // constants are copied, never mutated, because many tools share one object.\n const title = toolTitle(name);\n const annotationIndex = cbIndex - 1;\n const annotations = args[annotationIndex];\n if (\n annotationIndex > 1 &&\n annotations &&\n typeof annotations === 'object' &&\n ('readOnlyHint' in annotations || 'destructiveHint' in annotations) &&\n !('title' in annotations)\n ) {\n args[annotationIndex] = { title, ...annotations };\n }\n const registered = original(...args) as { title?: string } | undefined;\n if (registered && typeof registered === 'object' && !registered.title)\n registered.title = title;\n return registered;\n };\n}\n\nexport function registerAllTools(\n server: McpServer,\n client: DatabrainClient\n): void {\n instrumentToolRegistration(server);\n\n // Operator identity\n registerWhoami(server, client);\n\n // Infrastructure\n registerListDatasources(server, client);\n registerDiscoverDatasourceSchema(server, client);\n registerListDatamarts(server, client);\n registerListWorkspaces(server, client);\n registerSyncDatasource(server, client);\n registerCreateDatamart(server, client);\n\n // Data app & token management\n registerListDataApps(server, client);\n registerListTenants(server, client);\n registerCreateDataApp(server, client);\n registerListApiTokens(server, client);\n registerCreateApiToken(server, client);\n registerRotateApiToken(server, client);\n\n // Embed management and customization\n registerCreateEmbed(server, client);\n registerListEmbeds(server, client);\n registerGetEmbedDetails(server, client);\n registerUpdateEmbed(server, client);\n registerCustomizeTheme(server, client);\n registerGetDemoLink(server, client);\n\n // Frontend\n registerGenerateGuestToken(server, client);\n registerGenerateEmbedCode(server, client);\n\n // Dashboard discovery\n registerListDashboards(server, client);\n registerCreateDashboard(server, client);\n registerGetDashboard(server, client);\n registerDashboardSnapshot(server, client);\n registerGenerateDashboardTiles(server, client);\n\n // Query & semantic layer\n registerAskQuestion(server, client);\n registerGetSemanticLayer(server, client);\n registerUpdateSemanticLayer(server, client);\n registerStartSemanticLayerGeneration(server, client);\n registerGetSemanticLayerGenerationStatus(server, client);\n registerSearchSemanticModel(server, client);\n registerGetSemanticEntity(server, client);\n registerProposeSemanticChange(server, client);\n registerApplySemanticChange(server, client);\n registerEvalSemanticModel(server, client);\n\n // Widget (metric) CRUD on customer dashboard embeds\n registerListWidgets(server, client);\n registerValidateMetricSpec(server, client);\n registerCreateOrUpdateMetricFromQuery(server, client);\n registerCreateWorkspaceMetric(server, client);\n registerAddWidget(server, client);\n registerUpdateWidget(server, client);\n registerRemoveWidget(server, client);\n registerGenerateWidget(server, client);\n\n // Scheduled reports\n registerListScheduledReports(server, client);\n\n // Custom chart types (DAT-925): scaffold, validate, upload, list, publish\n registerCustomChartScaffold(server, client);\n registerCustomChartAuthor(server, client);\n registerCustomChartValidate(server, client);\n registerCustomChartUpload(server, client);\n registerListCustomCharts(server, client);\n registerPublishCustomChart(server, client);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAO,IAAM,qBAAqB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACA3B,IAAM,mCAAmC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAzC,IAAM,4BAA4B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAlC,IAAM,+BAA+B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACArC,IAAM,8BAA8B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACApC,IAAM,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAxB,IAAM,6BAA6B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;A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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACA5B,IAAM,wBAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACA9B,IAAM,yBAAyB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACA/B,IAAM,wBAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACA9B,IAAM,2BAA2B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAjC,IAAM,0BAA0B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAhC,IAAM,4BAA4B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAlC,IAAM,4BAA4B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAlC,IAAM,wBAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACA9B,IAAM,uBAAuB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACA7B,IAAM,+BAA+B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA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","names":["value","z","datamartId","candidate","id","source","isNonEmptyString","asRecord","candidate","isNonEmptyString","asRecord","id","name","z","z","z","z","z","validateBundle","z","z","z","z","id","z","z","z","z","z","text","z","id","z","z","z","z","z","z","z","z","z","z","z","z","isNonEmptyString","z","z","z","key","z","DEFAULT_ACCESS_SETTINGS","z","body","result","embedId","z","z","z","z","z","z","z","z","id","z","z","result","z","kebabCase","buildAttributes","kebabCase","buildAttributes","kebabCase","buildAttributes","kebabCase","buildAttributes","kebabCase","buildAttributes","kebabCase","buildAttributes","z","z","z","result","z","z","guardError","result","z","z","z","z","z","z","z","z","z","z","z","z","z","datamartId","z","z","stringify","source","key","text","source","id","node","z","id","datamartId","source","z","columnSchema","z","tableSchema","z","z","z","z","createBody","result","inserted","z","z","result","z","modeSchema","z","z","z","z","candidate","z","widgets","z","z","z","z","id","z","z"]}
|