@databrainhq/mcp-server 0.2.1 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/utils/config.ts","../src/server.ts","../src/utils/cache.ts","../src/utils/errors.ts","../src/utils/logger.ts","../src/client/databrain-client.ts","../src/tools/data-app/list-data-apps.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/workspaces-api.ts","../src/services/discovery-service.ts","../src/services/embed-service.ts","../src/services/guest-token-service.ts","../src/services/factory.ts","../src/tools/annotations.ts","../src/tools/data-app/create-data-app.ts","../src/tools/data-app/list-api-tokens.ts","../src/utils/resolve-resource.ts","../src/tools/data-app/create-api-token.ts","../src/tools/data-app/rotate-api-token.ts","../src/tools/infrastructure/list-datasources.ts","../src/tools/infrastructure/discover-datasource-schema.ts","../src/tools/infrastructure/list-datamarts.ts","../src/tools/infrastructure/list-workspaces.ts","../src/tools/infrastructure/link-datamart-to-workspace.ts","../src/tools/embed/create-embed.ts","../src/tools/embed/list-embeds.ts","../src/tools/embed/get-embed-details.ts","../src/tools/embed/update-embed.ts","../src/tools/embed/helpers.ts","../src/tools/embed/customize-theme.ts","../src/tools/embed/configure-embed.ts","../src/tools/embed/diagnose-embed-health.ts","../src/tools/frontend/generate-guest-token.ts","../src/tools/frontend/generate-embed-code.ts","../src/templates/react.ts","../src/templates/nextjs.ts","../src/templates/vue.ts","../src/templates/angular.ts","../src/templates/svelte.ts","../src/templates/solidjs.ts","../src/templates/vanilla.ts","../src/templates/index.ts","../src/tools/analytics/list-dashboards.ts","../src/tools/orchestration/setup-embed-interactive.ts","../src/tools/query/ask-question.ts","../src/tools/query/get-semantic-layer.ts","../src/tools/query/update-semantic-layer.ts","../src/tools/registry.ts","../src/resources/content/getting-started.ts","../src/resources/content/api-reference.ts","../src/resources/content/embedding-guide.ts","../src/resources/content/filter-reference.ts","../src/resources/content/theme-reference.ts","../src/resources/content/web-component-reference.ts","../src/resources/content/self-serve-reference.ts","../src/resources/content/semantic-layer-guide.ts","../src/resources/content/multi-tenancy-guide.ts","../src/resources/content/use-case-guides.ts","../src/resources/content/permission-schema.ts","../src/resources/registry.ts","../src/prompts/embed-existing-dashboard.ts","../src/prompts/embed-blank-dashboard.ts","../src/prompts/enable-metric-creation.ts","../src/prompts/brand-my-embed.ts","../src/prompts/localize-embed.ts","../src/prompts/secure-my-embed.ts","../src/prompts/setup-filters.ts","../src/prompts/manage-embeds.ts","../src/prompts/query-data.ts","../src/prompts/populate-semantic-layer.ts","../src/prompts/registry.ts"],"sourcesContent":["import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { loadConfig } from './utils/config.js';\nimport { createServer } from './server.js';\nimport { logger } from './utils/logger.js';\n\nconst VERSION = '0.2.0';\n\nfunction banner(msg: string): void {\n process.stderr.write(`[databrain] ${msg}\\n`);\n}\n\nasync function main(): Promise<void> {\n try {\n const config = loadConfig();\n const server = createServer(config);\n const transport = new StdioServerTransport();\n\n await server.connect(transport);\n banner(`v${VERSION} ready (24 tools, 11 resources, 10 prompts)`);\n } catch (error) {\n logger.error('Failed to start server', error);\n process.exit(1);\n }\n}\n\nmain();\n","import { z, ZodError } from 'zod';\n\nconst configSchema = z\n .object({\n serviceToken: z.string().min(1).optional(),\n apiToken: z.string().min(1).optional(),\n apiUrl: z.string().url().default('https://api.usedatabrain.com'),\n })\n .refine((c) => c.serviceToken || c.apiToken, {\n message:\n 'At least one of DATABRAIN_SERVICE_TOKEN or DATABRAIN_API_TOKEN must be set',\n });\n\nexport type Config = z.infer<typeof configSchema>;\n\nfunction formatConfigError(err: ZodError): string {\n const issues = err.issues.map((i) => i.message);\n const lines = ['[databrain] Configuration error:'];\n for (const issue of issues) {\n lines.push(` - ${issue}`);\n }\n lines.push('');\n lines.push(' Get a service token at Settings > Service Tokens in your Databrain dashboard.');\n lines.push(' Then add to your MCP config: { \"env\": { \"DATABRAIN_SERVICE_TOKEN\": \"...\" } }');\n return lines.join('\\n');\n}\n\nexport function loadConfig(): Config {\n try {\n return configSchema.parse({\n serviceToken: process.env.DATABRAIN_SERVICE_TOKEN || undefined,\n apiToken: process.env.DATABRAIN_API_TOKEN || undefined,\n apiUrl:\n process.env.DATABRAIN_API_URL || 'https://api.usedatabrain.com',\n });\n } catch (err) {\n if (err instanceof ZodError) {\n process.stderr.write(formatConfigError(err) + '\\n');\n }\n throw err;\n }\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { DatabrainClient } from './client/databrain-client.js';\nimport type { Config } from './utils/config.js';\nimport { registerAllTools } from './tools/registry.js';\nimport { registerAllResources } from './resources/registry.js';\nimport { registerAllPrompts } from './prompts/registry.js';\n\nexport function createServer(config: Config): McpServer {\n const server = new McpServer(\n {\n name: 'databrain',\n version: '0.1.0',\n description:\n 'Databrain MCP Server — embed analytics dashboards and charts into your app. Focused on embed discovery, deterministic embed updates, theming, filters, localization, permissions, and guest token generation.',\n },\n {\n instructions:\n 'Databrain uses two token types — never confuse them:\\n' +\n '• SERVICE TOKEN (DATABRAIN_SERVICE_TOKEN): org-level, pre-configured in MCP server config. Used for: list_datasources, discover_datasource_schema, list_datamarts, list_workspaces, link_datamart_to_workspace, list_data_apps, create_data_app, list_api_tokens, create_api_token, rotate_api_token, list_dashboards (workspace scope), ask_question, get_semantic_layer, update_semantic_layer. You already have this — never ask the user for it.\\n' +\n '• API TOKEN (per data app): scoped to one data app, used for embedding operations (list_embeds, get_embed_details, create_embed, update_embed, generate_guest_token) and data-app scoped dashboard listing. Created/rotated via create_api_token or rotate_api_token during setup.\\n\\n' +\n '4 core use cases — match the user\\'s scenario to the right prompt:\\n' +\n '1. Embed existing dashboard → prompt: embed-existing-dashboard (list_data_apps → create_api_token → list_dashboards → create_embed → generate_guest_token → generate_embed_code)\\n' +\n '2. Blank dashboard per client → prompt: embed-blank-dashboard (list_data_apps → list_datamarts → create_embed with clientId per client → generate_guest_token → generate_embed_code)\\n' +\n '3. Enable metric creation → prompt: enable-metric-creation (list_embeds → update_embed accessSettings → configure_embed → generate_guest_token with permissions)\\n' +\n '4. Explore & query data → prompt: query-data (list_datamarts → get_semantic_layer → if empty, auto-generate descriptions with update_semantic_layer or use populate-semantic-layer prompt → ask_question)\\n\\n' +\n 'Infrastructure CREATION (datasources, datamarts, workspaces) is done in the Databrain UI.\\n' +\n 'However, the **semantic layer** is populated and maintained entirely via MCP tools (get_semantic_layer, update_semantic_layer). When the semantic layer is empty, YOU (the assistant) should auto-generate descriptions from table/column names and push them with update_semantic_layer — do NOT send the user to the UI for this.\\n\\n' +\n 'After embed setup, customize with: brand-my-embed, setup-filters, localize-embed, secure-my-embed.\\n' +\n 'Use generate_guest_token for frontend auth and generate_embed_code for framework snippets.\\n' +\n 'Do NOT ask the user for any tokens — manage them via MCP tools.\\n\\n' +\n 'IMPORTANT — accessSettings defaults:\\n' +\n 'When calling create_embed, only pass accessSettings: { datamartName: \"...\" } plus any flags the user explicitly wants enabled. For multi-tenant dashboard embeds, also pass clientId. The tool auto-fills all required isAllow* fields with secure defaults (all false). Do NOT guess or enumerate accessSettings fields.\\n\\n' +\n 'IMPORTANT — create_data_app does NOT accept workspaceName. Only pass { name: \"...\" }.\\n\\n' +\n 'IMPORTANT — Be interactive. Present results from each tool call and ask the user before proceeding to the next step. Never batch multiple mutating operations without user confirmation.\\n' +\n 'Trigger keywords: embed, dashboard, analytics, Databrain, guest token, theme, filters, permissions, datasource, datamart, workspace, metric creation.',\n },\n );\n\n const client = new DatabrainClient(config);\n\n registerAllTools(server, client);\n registerAllResources(server);\n registerAllPrompts(server);\n\n return server;\n}\n","interface CacheEntry<T> {\n value: T;\n expiresAt: number;\n}\n\nexport class TtlCache {\n private store = new Map<string, CacheEntry<unknown>>();\n\n get<T>(key: string): T | undefined {\n const entry = this.store.get(key);\n if (!entry) return undefined;\n if (Date.now() > entry.expiresAt) {\n this.store.delete(key);\n return undefined;\n }\n return entry.value as T;\n }\n\n set<T>(key: string, value: T, ttlMs: number): void {\n this.store.set(key, { value, expiresAt: Date.now() + ttlMs });\n }\n\n invalidateByPrefix(prefix: string): void {\n for (const key of this.store.keys()) {\n if (key.startsWith(prefix)) {\n this.store.delete(key);\n }\n }\n }\n\n clear(): void {\n this.store.clear();\n }\n}\n","export class DatabrainApiError extends Error {\n constructor(\n public readonly status: number,\n public readonly code: string,\n message: string,\n public readonly details?: unknown,\n ) {\n super(message);\n this.name = 'DatabrainApiError';\n }\n\n toToolResponse(): { content: Array<{ type: 'text'; text: string }>; isError: true } {\n return {\n content: [{ type: 'text', text: `Error: ${this.message}\\n\\n${this.hint()}` }],\n isError: true,\n };\n }\n\n private hint(): string {\n if (this.status === 401 || this.status === 403) {\n if (\n this.code === 'INVALID_SERVICE_TOKEN' ||\n this.code === 'MISSING_SERVICE_TOKEN' ||\n this.message.toLowerCase().includes('service token')\n ) {\n return 'Hint: The service token (DATABRAIN_SERVICE_TOKEN) is invalid, expired, or missing. It must be set in the MCP server config (not at runtime). Check Settings > Service Tokens in the Databrain UI.';\n }\n return 'Hint: The per-data-app API token is invalid or expired. Use `create_api_token` to generate a new one. Do not ask the user — manage tokens via MCP tools.';\n }\n if (this.status === 400) {\n return 'Hint: The request was invalid. Check parameter values match expected types and formats. Use the corresponding list tool to verify IDs and names.';\n }\n if (this.status === 404) {\n return 'Hint: The requested resource was not found. Verify the ID or name is correct using the corresponding list tool.';\n }\n if (this.status === 409) {\n return 'Hint: A resource with this name already exists. Use a different name or list existing resources first.';\n }\n if (this.status === 422) {\n return 'Hint: The request parameters are invalid. Check the required fields and their formats.';\n }\n if (this.status === 429) {\n return 'Hint: API rate limit reached. Wait a moment and try again.';\n }\n if (this.status >= 500) {\n return 'Hint: The Databrain API is experiencing issues. Try again in a few moments.';\n }\n return '';\n }\n}\n\nexport function toolError(message: string): { content: Array<{ type: 'text'; text: string }>; isError: true } {\n return {\n content: [{ type: 'text', text: message }],\n isError: true,\n };\n}\n\nexport function stringify(value: unknown): string {\n if (typeof value === 'string') return value;\n try {\n return JSON.stringify(value, null, 2);\n } catch {\n return String(value);\n }\n}\n\nexport function toolSuccess(text: string): { content: Array<{ type: 'text'; text: string }> } {\n return {\n content: [{ type: 'text', text }],\n };\n}\n","const LOG_LEVELS = { debug: 0, info: 1, warn: 2, error: 3 } as const;\ntype LogLevel = keyof typeof LOG_LEVELS;\n\nconst currentLevel: LogLevel =\n (process.env.DATABRAIN_LOG_LEVEL as LogLevel) || 'warn';\n\nfunction log(level: LogLevel, message: string, data?: unknown): void {\n if (LOG_LEVELS[level] < LOG_LEVELS[currentLevel]) return;\n const line = `[databrain-mcp] [${level.toUpperCase()}] ${message}`;\n if (data !== undefined) {\n process.stderr.write(`${line} ${JSON.stringify(data)}\\n`);\n } else {\n process.stderr.write(`${line}\\n`);\n }\n}\n\nexport const logger = {\n debug: (msg: string, data?: unknown) => log('debug', msg, data),\n info: (msg: string, data?: unknown) => log('info', msg, data),\n warn: (msg: string, data?: unknown) => log('warn', msg, data),\n error: (msg: string, data?: unknown) => log('error', msg, data),\n};\n","import { TtlCache } from '../utils/cache.js';\nimport type { Config } from '../utils/config.js';\nimport { DatabrainApiError } from '../utils/errors.js';\nimport { logger } from '../utils/logger.js';\nimport type { RequestOptions } from './types.js';\n\nconst MCP_SERVER_VERSION = '0.2.0';\nconst MCP_USER_AGENT = `databrain-mcp-server/${MCP_SERVER_VERSION}`;\n\nconst MAX_RETRIES = 3;\nconst REQUEST_TIMEOUT_MS = 30_000;\n\nconst NON_TRANSIENT_PATTERNS = [\n 'out of context',\n 'Definition not found',\n 'not a data question',\n 'Query generation failed',\n 'not found',\n 'not authenticated',\n 'Invalid Service Token',\n 'service token',\n];\n\nexport class DatabrainClient {\n private cache = new TtlCache();\n private runtimeApiToken: string | undefined;\n\n constructor(private config: Config) {}\n\n hasApiToken(): boolean {\n return !!(this.runtimeApiToken || this.config.apiToken);\n }\n\n setRuntimeApiToken(token: string): void {\n this.runtimeApiToken = token;\n logger.info('Runtime API token set for this session');\n }\n\n getServiceToken(): string | undefined {\n return this.config.serviceToken;\n }\n\n getApiUrl(): string {\n return this.config.apiUrl;\n }\n\n private getToken(auth: 'service' | 'api' | 'none'): string | undefined {\n if (auth === 'none') return undefined;\n if (auth === 'service') return this.config.serviceToken;\n return this.runtimeApiToken || this.config.apiToken;\n }\n\n async request<T>(options: RequestOptions): Promise<T> {\n // Invalidate caches first\n if (options.invalidateCache) {\n for (const prefix of options.invalidateCache) {\n this.cache.invalidateByPrefix(prefix);\n }\n }\n\n // Check cache\n if (options.cacheKey && options.cacheTtlMs) {\n const cached = this.cache.get<T>(options.cacheKey);\n if (cached !== undefined) {\n logger.debug(`Cache hit: ${options.cacheKey}`);\n return cached;\n }\n }\n\n const token = this.getToken(options.auth);\n if (options.auth !== 'none' && !token) {\n if (options.auth === 'service') {\n throw new DatabrainApiError(\n 401,\n 'MISSING_SERVICE_TOKEN',\n 'DATABRAIN_SERVICE_TOKEN is required for this operation (org-level token for discovery and data app management). It must be set in the MCP server configuration — do not ask the user for it at runtime.',\n );\n }\n throw new DatabrainApiError(\n 401,\n 'MISSING_API_TOKEN',\n 'A per-data-app API token is required for this embedding operation but none is configured. ' +\n 'Use `setup_embed_interactive` with step `ensure_api_token` to create or set one, ' +\n 'or call `create_api_token` / `set_api_token` directly. Do not ask the user for this token — create it via the MCP tools.',\n );\n }\n\n // Build URL\n let url = `${this.config.apiUrl}${options.path}`;\n if (options.query) {\n const params = new URLSearchParams(options.query);\n url += `?${params.toString()}`;\n }\n\n let lastError: Error | undefined;\n\n for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {\n try {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n 'User-Agent': MCP_USER_AGENT,\n 'X-Databrain-Client': MCP_USER_AGENT,\n };\n if (token) {\n headers['Authorization'] = `Bearer ${token}`;\n }\n\n const response = await fetch(url, {\n method: options.method,\n headers,\n body: options.body ? JSON.stringify(options.body) : undefined,\n signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),\n });\n\n if (!response.ok) {\n const errorBody = await response.text();\n logger.warn(`[API Error] ${options.method} ${options.path} status=${response.status} body=${errorBody.slice(0, 500)}`);\n let parsed: { error?: string; message?: string; code?: string; detail?: string } = {};\n try {\n parsed = JSON.parse(errorBody);\n } catch {\n // not JSON\n }\n\n const errorMsg = parsed.message || parsed.detail || (typeof parsed.error === 'string' ? parsed.error : JSON.stringify(parsed.error)) || `API request failed with status ${response.status}`;\n const error = new DatabrainApiError(\n response.status,\n parsed.code || `HTTP_${response.status}`,\n errorMsg,\n parsed,\n );\n\n // Retry on 429 or 5xx (but not when the error is clearly non-transient)\n const isTransient =\n response.status === 429 ||\n (response.status >= 500 &&\n !NON_TRANSIENT_PATTERNS.some((p) => errorMsg.includes(p)));\n if (isTransient && attempt < MAX_RETRIES) {\n const delay = Math.min(1000 * Math.pow(2, attempt - 1), 8000);\n logger.warn(`Retrying in ${delay}ms (attempt ${attempt}/${MAX_RETRIES})`, {\n status: response.status,\n path: options.path,\n });\n await new Promise((r) => setTimeout(r, delay));\n lastError = error;\n continue;\n }\n\n throw error;\n }\n\n const text = await response.text();\n let data = text ? (JSON.parse(text) as T) : ({} as T);\n\n // Databrain API wraps responses in { data: ... } — unwrap automatically\n if (data && typeof data === 'object' && !Array.isArray(data) && 'data' in data) {\n const inner = (data as Record<string, unknown>).data;\n if (inner !== null && inner !== undefined) {\n data = inner as unknown as T;\n }\n }\n\n // Store in cache\n if (options.cacheKey && options.cacheTtlMs) {\n this.cache.set(options.cacheKey, data, options.cacheTtlMs);\n }\n\n return data;\n } catch (err) {\n if (err instanceof DatabrainApiError) throw err;\n\n if (attempt < MAX_RETRIES && (err as Error)?.name === 'TimeoutError') {\n const delay = Math.min(1000 * Math.pow(2, attempt - 1), 8000);\n logger.warn(`Request timed out, retrying in ${delay}ms`, { path: options.path });\n await new Promise((r) => setTimeout(r, delay));\n lastError = err as Error;\n continue;\n }\n\n throw new DatabrainApiError(\n 0,\n 'NETWORK_ERROR',\n `Failed to connect to Databrain API: ${(err as Error).message}`,\n );\n }\n }\n\n throw lastError || new DatabrainApiError(0, 'UNKNOWN', 'Request failed after retries');\n }\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { DatabrainApiError, toolError, toolSuccess } from '../../utils/errors.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport { READ_ONLY } from '../annotations.js';\n\nexport function registerListDataApps(server: McpServer, client: DatabrainClient): 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(\n 'No data apps found for this account/workspace.'\n );\n }\n\n return toolSuccess(JSON.stringify({\n count: result.length,\n dataApps: result.map((app: any) => {\n const { name, dataAppId, workspaceName } =\n services.discoveryService.normalizeDataApp(app);\n return { name, id: dataAppId || null, workspace: workspaceName || null };\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.request<DashboardRecord[]>({\n method: 'POST',\n path: '/api/v2/workspace/dashboards',\n auth: 'service',\n body: { workspaceName },\n }).then((dashboards) =>\n (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 );\n\n return dashboardsPerWorkspace.flat();\n }\n\n async listDashboardsForWorkspace(workspaceName: string): 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}\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',\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(body: Record<string, unknown>): 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(query?: Record<string, string>): 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(body: Record<string, unknown>): 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(datasourceName: string): 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(datasourceName: string): 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","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 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 return this.client.request<Record<string, unknown>>({\n method: 'POST',\n path: '/api/v2/data-app/embeds',\n body,\n auth: 'api',\n invalidateCache: ['list_embeds'],\n });\n }\n\n async listEmbeds(dataAppName?: string): Promise<EmbedRecord[]> {\n const query =\n dataAppName && dataAppName.trim().length > 0\n ? { dataAppName }\n : undefined;\n return this.client.request<EmbedRecord[]>({\n method: 'GET',\n path: '/api/v2/data-app/embeds',\n auth: 'api',\n query,\n cacheKey: 'list_embeds',\n cacheTtlMs: 5 * 60 * 1000,\n });\n }\n\n async getByEmbedId(embedId: 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 },\n });\n }\n\n async updateEmbed(body: Record<string, unknown>): 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 reasoning: string | null;\n confidence: number | null;\n timeTaken: number;\n sessionId: string | null;\n summary: 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 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 });\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","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(body: Record<string, unknown>): 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 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 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) && dashboard.dashboardName) ||\n 'Unnamed Dashboard',\n dashboardId:\n (isNonEmptyString(dashboard.dashboardId) && dashboard.dashboardId) ||\n (isNonEmptyString(dashboard.externalDashboardId) &&\n dashboard.externalDashboardId) ||\n (isNonEmptyString(dashboard._id) && dashboard._id) ||\n (isNonEmptyString(dashboard.id) && dashboard.id) ||\n (isNonEmptyString(dashboard.uid) && dashboard.uid) ||\n null,\n workspaceName:\n (isNonEmptyString(dashboard.workspaceName) && dashboard.workspaceName) ||\n (isNonEmptyString(dashboard.workspace) && dashboard.workspace) ||\n (isNonEmptyString(dashboard.workspaceId) && dashboard.workspaceId) ||\n null,\n metricCount:\n typeof dashboard.metricCount === 'number' ? dashboard.metricCount : 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 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 Record<string, unknown> | 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(dataAppName?: string): Promise<EmbedRecord[]> {\n return this.embedsApi.listEmbeds(dataAppName);\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(\n {} as EmbedRecord,\n accessSettings,\n );\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(embedId: string): Promise<EmbedRecord> {\n const response = await this.embedsApi.getByEmbedId(embedId);\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(embedId: string): Promise<Record<string, unknown>> {\n const embed = await this.resolveEmbedStrict(embedId);\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 ): Promise<Record<string, unknown>> {\n const body = await this.buildUpdateBase(embedId);\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(body);\n }\n}\n","import { GuestTokenApi, type CreateGuestTokenBody } 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(input: GenerateGuestTokenInput): 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 { DatabrainClient } from '../client/databrain-client.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 { WorkspacesApi } from '../api/workspaces-api.js';\nimport { DiscoveryService } from './discovery-service.js';\nimport { EmbedService } from './embed-service.js';\nimport { GuestTokenService } from './guest-token-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 embedService: EmbedService;\n discoveryService: DiscoveryService;\n guestTokenService: GuestTokenService;\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 workspacesApi = new WorkspacesApi(client);\n\n return {\n embedsApi,\n dashboardsApi,\n dataAppsApi,\n datamartsApi,\n datasourcesApi,\n workspacesApi,\n queryApi,\n embedService: new EmbedService(embedsApi, datamartsApi),\n discoveryService: new DiscoveryService(),\n guestTokenService: new GuestTokenService(guestTokenApi),\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 { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { DatabrainApiError, toolError, toolSuccess, stringify } 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.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(`Data app creation failed: ${stringify(result.error)}`);\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 { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { DatabrainApiError, toolError, toolSuccess } from '../../utils/errors.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport { resolveResource, formatDataApp } 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.string().optional().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(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 } 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 = 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 { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { DatabrainApiError, toolError, toolSuccess, stringify } from '../../utils/errors.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport { resolveResource, formatDataApp } 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.string().optional().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.unknown())\n .optional()\n .describe('Raw API body passthrough for POST /api/v2/data-app/api-tokens'),\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(`API token creation failed: ${stringify(result.error)}`);\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\n return toolSuccess(\n `API token created and set for this MCP session.\\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 { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { DatabrainApiError, toolError, toolSuccess, stringify } from '../../utils/errors.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport { resolveResource, formatDataApp } 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 (invalidate and replace) an API token. Previous token becomes stale.',\n {\n dataAppName: z.string().optional().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.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(`Token rotation failed: ${stringify(rotateRes.error)}`);\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 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}-api-token-rotated`,\n },\n });\n if (createRes.error) {\n return toolError(`Token rotation fallback failed: ${stringify(createRes.error)}`);\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 'Treat previous tokens as stale and update backend secrets.'\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 { DatabrainApiError, toolError, toolSuccess } from '../../utils/errors.js';\nimport { READ_ONLY } from '../annotations.js';\n\nexport function registerListDatasources(server: McpServer, client: DatabrainClient): 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(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 return toolSuccess(JSON.stringify({\n count: active.length,\n datasources: active.map((ds: any) => ({\n name: ds.name,\n type: ds.dbName || ds.datasourceType || 'unknown',\n })),\n inactive: inactive.length > 0\n ? inactive.map((ds: any) => ({ name: ds.name }))\n : undefined,\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 { z } from 'zod';\nimport 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 { createServiceBundle } from '../../services/factory.js';\nimport { resolveResource, formatDatasource } 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 = await services.datasourcesApi.getDatasourceSchema(\n datasourceName,\n );\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(\n `## Datasource Schema: ${result.datasourceName}\\n`,\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 { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { DatabrainApiError, toolError, toolSuccess } from '../../utils/errors.js';\nimport { READ_ONLY } from '../annotations.js';\n\nexport function registerListDatamarts(server: McpServer, client: DatabrainClient): 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(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 } 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 { DatabrainApiError, toolError, toolSuccess } 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(server: McpServer, client: DatabrainClient): 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(JSON.stringify({\n count: result.length,\n workspaces: result.map((ws: any) => ({\n name: ws.name,\n connection: describeConnection(ws),\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 { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { DatabrainApiError, toolError, toolSuccess } from '../../utils/errors.js';\nimport { WRITE_IDEMPOTENT } from '../annotations.js';\n\nexport function registerLinkDatamartToWorkspace(\n server: McpServer,\n client: DatabrainClient,\n): void {\n server.tool(\n 'link_datamart_to_workspace',\n 'Link a datamart to an existing workspace. ALWAYS ask the user which workspace to use — do not auto-select.',\n {\n workspaceName: z\n .string()\n .optional()\n .describe(\n 'Name of the workspace to update. Omit to list available workspaces and let the user choose.',\n ),\n datamartName: z\n .string()\n .describe(\n 'Name of the datamart to link. Use `list_datamarts` to find it.',\n ),\n },\n WRITE_IDEMPOTENT,\n async ({ workspaceName, datamartName }) => {\n try {\n if (!workspaceName) {\n const workspaces = 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(workspaces) || workspaces.length === 0) {\n return toolError(\n 'No workspaces found. Create a workspace in the **Databrain UI** first, then come back here to link the datamart.',\n );\n }\n\n const list = workspaces\n .map((ws: any) => `- **${ws.name}** (ID: ${ws._id || ws.id})`)\n .join('\\n');\n\n return toolSuccess(\n `Found ${workspaces.length} workspace(s):\\n\\n${list}\\n\\n` +\n `**Ask the user** which workspace they want to link to datamart **${datamartName}**, then call \\`link_datamart_to_workspace\\` with both \\`workspaceName\\` and \\`datamartName\\`.`,\n );\n }\n\n const result = await client.request<{\n name?: string;\n error?: unknown;\n }>({\n method: 'PUT',\n path: '/api/v2/workspace',\n body: {\n name: workspaceName,\n connectionType: 'DATAMART',\n datamartName,\n },\n auth: 'service',\n invalidateCache: ['list_workspaces'],\n });\n\n if (result.error) {\n return toolError(\n `Failed to link datamart: ${typeof result.error === 'object' ? JSON.stringify(result.error) : result.error}`,\n );\n }\n\n return toolSuccess(\n `Workspace **${workspaceName}** is now linked to datamart **${datamartName}**.\\n\\n` +\n 'Next steps:\\n' +\n '- Build dashboards in the Databrain UI using this workspace\\n' +\n '- Use `list_dashboards` to find dashboards in this workspace\\n' +\n '- Use `create_embed` to embed dashboards into your app',\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 { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { DatabrainApiError, toolError, toolSuccess, stringify } from '../../utils/errors.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport { resolveResource, formatWorkspace } 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.object({\n datamartName: z.string().describe('Name of the datamart (required)'),\n isAllowMetricCreation: z.boolean().optional().describe('Allow end-users to create metrics'),\n metricCreationMode: z.enum(['DRAG_DROP', 'CHAT']).optional().describe('Metric creation mode'),\n isAllowMetricDeletion: z.boolean().optional().describe('Allow metric deletion'),\n isAllowMetricUpdate: z.boolean().optional().describe('Allow metric editing'),\n isAllowMetricLayoutChange: z.boolean().optional().describe('Allow layout changes'),\n isAllowManageMetrics: z.boolean().optional().describe('Show manage metrics UI'),\n isAllowUnderlyingData: z.boolean().optional().describe('Allow viewing underlying data'),\n isAllowAiPilot: z.boolean().optional().describe('Enable AI pilot features'),\n isAllowEmailReports: z.boolean().optional().describe('Allow email report scheduling'),\n isAllowCreateDashboardView: z.boolean().optional().describe('Allow creating dashboard views'),\n}).describe('Embed access settings. Only datamartName is required — all flags default to false.');\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(server: McpServer, client: DatabrainClient): 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.record(z.unknown()).optional().describe(\n 'Raw API body passthrough. If provided, all other fields are ignored.',\n ),\n dashboardId: z.string().optional().describe('Dashboard identifier for embed creation'),\n workspaceName: z.string().optional().describe('Workspace name. Omit to auto-resolve if only one exists.'),\n embedType: z.enum(['dashboard', 'metric']).optional().describe('Embed type'),\n metricId: z.string().optional().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.string().optional().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.string().optional().describe('Template dashboard ID to clone metrics from'),\n isImportMetrics: z.boolean().optional().describe('Import metrics from template dashboard'),\n metricImportMode: z.enum(['COPY', 'LINK']).optional().describe('COPY duplicates metrics, LINK shares them'),\n isRenameDashboard: z.boolean().optional().describe('Rename the dashboard for this client'),\n },\n WRITE_CREATE,\n async (params) => {\n try {\n const isMultiTenant = !!params.clientId;\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 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 = (body.accessSettings && typeof body.accessSettings === 'object')\n ? body.accessSettings as Record<string, unknown>\n : {};\n body.accessSettings = { ...DEFAULT_ACCESS_SETTINGS, ...callerAccess };\n\n const result = await client.request<Record<string, unknown>>({\n method: 'POST',\n path: '/api/v2/data-app/dashboard-embeds',\n body,\n auth: 'api',\n invalidateCache: ['list_embeds'],\n });\n\n if (result.error) {\n return toolError(`Dashboard embed creation failed: ${stringify(result.error)}`);\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 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('create_embed requires `dashboardId` (or provide full raw `body`).');\n }\n if (!body.workspaceName || typeof body.workspaceName !== 'string') {\n return toolError('create_embed requires `workspaceName` (or provide full raw `body`).');\n }\n const accessSettings = body.accessSettings as Record<string, unknown> | undefined;\n if (!accessSettings || typeof accessSettings !== 'object') {\n return toolError('create_embed requires `accessSettings` and must include `datamartName`.');\n }\n const datamartName = accessSettings.datamartName;\n if (!datamartName || typeof datamartName !== 'string') {\n return toolError('create_embed requires `accessSettings.datamartName`.');\n }\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) ||\n (result.id as string) ||\n '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` and `diagnose_embed_health` to verify update compatibility.',\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 { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { DatabrainApiError, toolError, toolSuccess } from '../../utils/errors.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport { READ_ONLY } from '../annotations.js';\n\nexport function registerListEmbeds(server: McpServer, client: DatabrainClient): 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).',\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(params.dataAppName);\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 return toolSuccess(JSON.stringify({\n count: result.length,\n embeds: result.map((e: any) => {\n const n = services.discoveryService.normalizeEmbed(e);\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 };\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 { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { DatabrainApiError, toolError, toolSuccess } from '../../utils/errors.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport { READ_ONLY } from '../annotations.js';\n\nexport function registerGetEmbedDetails(server: McpServer, client: DatabrainClient): 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 },\n READ_ONLY,\n async (params) => {\n try {\n const embed = await services.embedService.resolveEmbedStrict(params.embedId);\n\n return toolSuccess(JSON.stringify({ embedId: params.embedId, ...embed }));\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 { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { DatabrainApiError, toolError, toolSuccess, stringify } from '../../utils/errors.js';\nimport {\n GUEST_TOKEN_REMINDER,\n maybeBuildCorruptedEmbedGuardrail,\n} from './helpers.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport { WRITE_IDEMPOTENT } from '../annotations.js';\n\nexport function registerUpdateEmbed(server: McpServer, client: DatabrainClient): 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 body: z.record(z.unknown()).optional().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.record(z.unknown()).optional().describe(\n 'Partial update of access settings. See `get_embed_details` for current settings.'\n ),\n theme: z.record(z.unknown()).optional().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 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 );\n\n if (result.error) {\n return toolError(`Embed update failed: ${stringify(result.error)}`);\n }\n\n return toolSuccess(`Embed \"${params.embedId}\" updated successfully.` + GUEST_TOKEN_REMINDER);\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 { DatabrainClient } from '../../client/databrain-client.js';\nimport { DatabrainApiError, toolError } from '../../utils/errors.js';\nimport { createServiceBundle } from '../../services/factory.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(client: DatabrainClient, embedId: string): 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 { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { DatabrainApiError, toolError, toolSuccess, stringify } from '../../utils/errors.js';\nimport {\n GUEST_TOKEN_REMINDER,\n maybeBuildCorruptedEmbedGuardrail,\n} from './helpers.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport { WRITE_IDEMPOTENT } from '../annotations.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: ['#4F46E5', '#10B981', '#F59E0B', '#EF4444', '#8B5CF6', '#06B6D4'],\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: ['#818CF8', '#34D399', '#FBBF24', '#F87171', '#A78BFA', '#22D3EE'],\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: ['#1E40AF', '#059669', '#D97706', '#DC2626', '#7C3AED', '#0891B2'],\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.enum([\n 'Inter', 'Roboto', 'Open Sans', 'Lato', 'Poppins', 'Montserrat',\n 'IBM Plex Sans', 'Source Sans Pro', 'Nunito', 'system-ui',\n]).describe('Font family');\n\nconst tooltipFontSchema = z.object({\n fontFamily: z.string().optional(),\n fontSize: z.number().optional(),\n fontWeight: z.number().optional(),\n fontColor: z.string().optional(),\n}).optional();\n\nconst fontConfigInputSchema = z.object({\n fontSize: z.number().optional(),\n fontFamily: z.string().optional(),\n fontWeight: z.number().optional(),\n color: z.string().optional(),\n}).optional();\n\nfunction mapToFrontendFontConfig(\n input: { fontSize?: number; fontFamily?: string; fontWeight?: number; color?: string } | 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.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.number().optional().describe('Axis title offset from axis'),\n axisLabelMargin: z.number().optional().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.object({\n fontFamily: z.string().optional(),\n fontSize: z.number().optional(),\n fontWeight: z.number().optional(),\n }).optional().describe('Axis title font configuration'),\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 ? { ...presetBase } : {};\n\n const general: Record<string, unknown> = { ...(adminTheme.general as Record<string, unknown> ?? {}) };\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> = { ...(adminTheme.dashboard as Record<string, unknown> ?? {}) };\n if (p.dashboardBackgroundColor) 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) 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> = { ...(adminTheme.cardTitle as Record<string, unknown> ?? {}) };\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> = { ...(adminTheme.cardDescription as Record<string, unknown> ?? {}) };\n if (p.cardDescriptionFontSize) cardDescription.fontSize = p.cardDescriptionFontSize;\n if (p.cardDescriptionFontWeight) cardDescription.fontWeight = p.cardDescriptionFontWeight;\n if (p.cardDescriptionColor) cardDescription.color = p.cardDescriptionColor;\n if (Object.keys(cardDescription).length) adminTheme.cardDescription = cardDescription;\n\n const cardCustomization: Record<string, unknown> = { ...(adminTheme.cardCustomization as Record<string, unknown> ?? {}) };\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) cardCustomization.disableShadowOnHover = p.disableShadowOnHover;\n if (p.disableCardStroke !== undefined) cardCustomization.disableStroke = p.disableCardStroke;\n if (p.cardStrokeColor) cardCustomization.metricStrokeColor = p.cardStrokeColor;\n if (Object.keys(cardCustomization).length) adminTheme.cardCustomization = cardCustomization;\n\n const chart: Record<string, unknown> = { ...(adminTheme.chart as Record<string, unknown> ?? {}) };\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 = [{ name: p.chartPaletteName, colors: p.chartPaletteColors }];\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(p: Record<string, unknown>): Record<string, unknown> {\n const componentTheme: Record<string, unknown> = {};\n\n if (p.buttonPrimaryColor || p.buttonPrimaryTextColor ||\n p.buttonSecondaryColor || p.buttonSecondaryTextColor) {\n componentTheme.button = {\n ...(p.buttonPrimaryColor && { primary: p.buttonPrimaryColor }),\n ...(p.buttonPrimaryTextColor && { primaryText: p.buttonPrimaryTextColor }),\n ...(p.buttonSecondaryColor && { secondary: p.buttonSecondaryColor }),\n ...(p.buttonSecondaryTextColor && { secondaryText: p.buttonSecondaryTextColor }),\n };\n }\n if (p.checkboxCheckedColor || p.checkboxUncheckedColor) {\n componentTheme.checkbox = {\n ...(p.checkboxCheckedColor && { checked: p.checkboxCheckedColor }),\n ...(p.checkboxUncheckedColor && { unChecked: p.checkboxUncheckedColor }),\n };\n }\n if (p.switchEnabledColor || p.switchDisabledColor) {\n componentTheme.switch = {\n ...(p.switchEnabledColor && { enabled: p.switchEnabledColor }),\n ...(p.switchDisabledColor && { disabled: p.switchDisabledColor }),\n };\n }\n if (p.breadcrumbFontFamily || p.breadcrumbFontColor || p.breadcrumbActiveColor) {\n componentTheme.drillBreadCrumbs = {\n ...(p.breadcrumbFontFamily && { fontFamily: p.breadcrumbFontFamily }),\n ...(p.breadcrumbFontColor && { fontColor: p.breadcrumbFontColor }),\n ...(p.breadcrumbActiveColor && { activeColor: p.breadcrumbActiveColor }),\n };\n }\n if (p.filterBadgeColor || p.filterBadgeTextColor) {\n componentTheme.multiSelectFilterDropdown = {\n ...(p.filterBadgeColor && { badgeColor: p.filterBadgeColor }),\n ...(p.filterBadgeTextColor && { badgeTextColor: p.filterBadgeTextColor }),\n };\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) componentTheme.metricLayoutCols = metricLayoutCols;\n\n return componentTheme;\n}\n\nfunction buildChartAppearance(p: Record<string, unknown>): 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) chartAppearance.chartTooltip = chartTooltip;\n\n const chartLabel: Record<string, unknown> = {};\n if (p.labelPosition) chartLabel.position = p.labelPosition;\n if (p.radialLabelPosition) chartLabel.radialChartposition = p.radialLabelPosition;\n if (Object.keys(chartLabel).length) chartAppearance.chartLabel = chartLabel;\n\n if (p.marginTop !== undefined || p.marginLeft !== undefined ||\n p.marginRight !== undefined || p.marginBottom !== undefined) {\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) 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) chartLegend.truncateLegend = p.legendTruncateLength;\n if (p.disableLegendScrolling !== undefined) chartLegend.disableLegendScrolling = p.disableLegendScrolling;\n if (p.enableVariableLegendPosition !== undefined) 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) 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(server: McpServer, client: DatabrainClient): 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 body: z.record(z.unknown()).optional().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.enum(['light', 'dark', 'corporate', 'minimal']).optional()\n .describe('Apply a theme preset as the base. Granular params below override preset values.'),\n accessPreset: z.enum(['view-only', 'power-user', 'export-only', 'ai-enabled']).optional()\n .describe('Apply an access settings preset'),\n\n // --- General ---\n fontFamily: fontFamilyEnum.optional().describe('Global font family'),\n datePickerFormat: z.string().optional().describe('Date picker display format'),\n\n // --- Colors ---\n primaryColor: z.string().optional().describe('Primary accent color (hex)'),\n backgroundColor: z.string().optional().describe('Overall background color (hex)'),\n textColor: z.string().optional().describe('Default text color (hex)'),\n ctaColor: z.string().optional().describe('Call-to-action button color (hex)'),\n ctaTextColor: z.string().optional().describe('CTA button text color (hex)'),\n\n // --- Dashboard ---\n dashboardBackgroundColor: z.string().optional().describe('Dashboard container background (hex)'),\n selectBoxSize: z.enum(['small', 'medium', 'large']).optional().describe('Filter select box size'),\n selectBoxVariant: z.enum(['floating', 'outlined', 'standard']).optional().describe('Filter select box style'),\n selectBoxBorderRadius: z.string().optional().describe('Select box border radius (e.g. \"20px\")'),\n selectBoxTextColor: z.string().optional().describe('Select box text color (hex)'),\n metricCardColor: z.string().optional().describe('Metric card background color (hex)'),\n\n // --- Card Title ---\n cardTitleFontSize: z.string().optional().describe('Card title font size (e.g. \"16px\")'),\n cardTitleFontWeight: z.string().optional().describe('Card title font weight (e.g. \"600\")'),\n cardTitleColor: z.string().optional().describe('Card title text color (hex)'),\n\n // --- Card Description ---\n cardDescriptionFontSize: z.string().optional().describe('Card description font size'),\n cardDescriptionFontWeight: z.string().optional().describe('Card description font weight'),\n cardDescriptionColor: z.string().optional().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.boolean().optional().describe('Disable shadow on card hover'),\n disableCardStroke: z.boolean().optional().describe('Remove card border stroke'),\n cardStrokeColor: z.string().optional().describe('Card border stroke color (hex)'),\n\n // --- Chart Colors (admin theme level) ---\n chartFontFamily: z.string().optional().describe('Font family for chart text'),\n chartFontColor: z.string().optional().describe('Font color for chart text (hex)'),\n chartColors: z.array(z.string()).optional().describe('Array of chart series colors (hex)'),\n chartPaletteName: z.string().optional().describe('Name for a custom palette'),\n chartPaletteColors: z.array(z.string()).optional().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.string().optional().describe('Primary button background (hex)'),\n buttonPrimaryTextColor: z.string().optional().describe('Primary button text (hex)'),\n buttonSecondaryColor: z.string().optional().describe('Secondary button background (hex)'),\n buttonSecondaryTextColor: z.string().optional().describe('Secondary button text (hex)'),\n checkboxCheckedColor: z.string().optional().describe('Checked checkbox color (hex)'),\n checkboxUncheckedColor: z.string().optional().describe('Unchecked checkbox color (hex)'),\n switchEnabledColor: z.string().optional().describe('Enabled switch color (hex)'),\n switchDisabledColor: z.string().optional().describe('Disabled switch color (hex)'),\n breadcrumbFontFamily: z.string().optional().describe('Drill breadcrumb font family'),\n breadcrumbFontColor: z.string().optional().describe('Drill breadcrumb font color (hex)'),\n breadcrumbActiveColor: z.string().optional().describe('Active breadcrumb color (hex)'),\n filterBadgeColor: z.string().optional().describe('Multi-select filter badge color (hex)'),\n filterBadgeTextColor: z.string().optional().describe('Filter badge text color (hex)'),\n datePickerColor: z.string().optional().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.number().optional().describe('Grid columns at XL breakpoint'),\n layoutColsLg: z.number().optional().describe('Grid columns at LG breakpoint'),\n layoutColsMd: z.number().optional().describe('Grid columns at MD breakpoint'),\n layoutColsSm: z.number().optional().describe('Grid columns at SM breakpoint'),\n layoutColsXs: z.number().optional().describe('Grid columns at XS breakpoint'),\n layoutColsXxs: z.number().optional().describe('Grid columns at XXS breakpoint'),\n\n // --- Chart Appearance (detailed) ---\n tooltipHeaderStyle: fontConfigInputSchema.describe('Tooltip header: fontSize, fontFamily, fontWeight, color'),\n tooltipLabelStyle: fontConfigInputSchema.describe('Tooltip label: fontSize, fontFamily, fontWeight, color'),\n tooltipValueStyle: fontConfigInputSchema.describe('Tooltip value: fontSize, fontFamily, fontWeight, color'),\n labelPosition: z.enum(['hidden', 'top', 'left', 'right', 'bottom', 'inside']).optional()\n .describe('Data label position on charts'),\n radialLabelPosition: z.enum(['outside', 'inside']).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.number().optional().describe('Chart right margin in pixels'),\n marginBottom: z.number().optional().describe('Chart bottom margin in pixels'),\n legendShow: z.boolean().optional().describe('Show or hide chart legend'),\n legendPosition: z.enum([\n 'top-left', 'top-center', 'top-right',\n 'left-center', 'right-center',\n 'bottom-left', 'bottom-center', 'bottom-right',\n ]).optional().describe('Legend position'),\n legendLayout: z.enum(['horizontal', 'vertical']).optional().describe('Legend layout direction'),\n legendShape: z.enum(['circle', 'rect', 'roundRect', 'triangle', 'diamond', 'arrow', 'none']).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.number().optional().describe('Max characters before truncating legend'),\n disableLegendScrolling: z.boolean().optional().describe('Disable scrolling in legend'),\n enableVariableLegendPosition: z.boolean().optional().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 { embedId, body, themePreset, accessPreset, ...themeParams } = 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 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(client, embedId, 'customize theme', err);\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(themeParams as Record<string, unknown>, presetBase);\n if (Object.keys(adminTheme).length) patch.adminThemeOptions = adminTheme;\n\n // Component theme (buttons, checkboxes, breakpoints, layout)\n const componentTheme = buildComponentTheme(themeParams as Record<string, unknown>);\n if (Object.keys(componentTheme).length) patch.theme = componentTheme;\n\n // Chart appearance (tooltip styles, legend, axes, labels, margins)\n const chartAppearance = buildChartAppearance(themeParams as Record<string, unknown>);\n const options: Record<string, unknown> = {};\n if (Object.keys(chartAppearance).length) options.chartAppearance = chartAppearance;\n if (themeParams.chartColors) 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('No theme properties provided. Specify at least one property, or use a themePreset.');\n }\n\n try {\n const result = await services.embedService.updateEmbed(embedId, patch);\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) applied.push(`admin theme (${Object.keys(adminTheme).join(', ')})`);\n if (patch.theme) applied.push(`component theme (${Object.keys(componentTheme).join(', ')})`);\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(client, embedId, 'customize theme', err);\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 { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { DatabrainApiError, toolError, toolSuccess, stringify } from '../../utils/errors.js';\nimport {\n GUEST_TOKEN_REMINDER,\n maybeBuildCorruptedEmbedGuardrail,\n} from './helpers.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport { WRITE_IDEMPOTENT } from '../annotations.js';\n\n// ---------------------------------------------------------------------------\n// Filter sub-schemas (from configure-filters)\n// ---------------------------------------------------------------------------\nconst stringFilterSchema = z.object({\n filterName: z.string().describe('Name of the filter as it appears in the dashboard'),\n options: z.array(z.object({\n value: z.string(),\n label: z.string(),\n })).describe('Dropdown options'),\n defaultOption: z.union([z.string(), z.array(z.string())]).optional()\n .describe('Default selected value (string or array for multi-select)'),\n});\n\nconst numberFilterSchema = z.object({\n filterName: z.string().describe('Name of the filter'),\n min: z.number().describe('Minimum value'),\n max: z.number().describe('Maximum value'),\n});\n\nconst datePresetSchema = z.object({\n type: z.string().optional().describe('Preset type (e.g. \"Last\", \"This\")'),\n interval: z.string().optional().describe('Interval (e.g. \"Days\", \"Months\", \"Years\")'),\n timeGrain: z.string().optional().describe('Time grain'),\n label: z.string().describe('Display label (e.g. \"Last 30 Days\")'),\n startDate: z.string().optional().describe('Start date (YYYY-MM-DD)'),\n endDate: z.string().optional().describe('End date (YYYY-MM-DD)'),\n});\n\nconst dateFilterSchema = z.object({\n filterName: z.string().describe('Name of the filter'),\n startDate: z.string().optional().describe('Default start date (YYYY-MM-DD)'),\n endDate: z.string().optional().describe('Default end date (YYYY-MM-DD)'),\n datePresetOptions: z.array(datePresetSchema).optional()\n .describe('Custom date presets to show in the date picker'),\n});\n\nconst sqlFilterSchema = z.object({\n filterName: z.string().describe('Name of the filter'),\n sql: z.string().describe('SQL query to fetch filter options'),\n columnName: z.string().describe('Column from the SQL result to use as option values'),\n});\n\nconst SUPPORTED_LANGUAGES = [\n 'en', 'fr', 'es', 'de', 'it', 'pt', 'zh', 'ja', 'ko', 'hi', 'ar', 'ru',\n] as const;\n\n// ---------------------------------------------------------------------------\n// Consolidated tool: configure_embed\n// Replaces: configure_embed_options + configure_filters + configure_internationalization\n// ---------------------------------------------------------------------------\nexport function registerConfigureEmbed(server: McpServer, client: DatabrainClient): void {\n const services = createServiceBundle(client);\n server.tool(\n 'configure_embed',\n 'Configure embed options (UI toggles, downloads, layout), filters (string/date/number/SQL), and i18n (language, translations).',\n {\n embedId: z.string().describe('ID of the embed to configure'),\n body: z.record(z.unknown()).optional().describe(\n 'Raw API body for PUT /api/v2/data-app/embeds. If provided, sent directly and convenience fields are ignored.',\n ),\n\n // ===== OPTIONS (from configure_embed_options) =====\n\n // Metric Operations\n disableMetricCreation: z.boolean().optional().describe('Disable creating new metrics'),\n disableMetricUpdation: z.boolean().optional().describe('Disable updating existing metrics'),\n disableMetricDeletion: z.boolean().optional().describe('Disable deleting metrics'),\n disableManageMetrics: z.boolean().optional().describe('Hide the manage metrics interface'),\n\n // Layout\n disableLayoutCustomization: z.boolean().optional().describe('Prevent layout changes'),\n disableSaveLayout: z.boolean().optional().describe('Prevent saving layout changes'),\n\n // Downloads & Export\n enableDownloadCsv: z.boolean().optional().describe('Enable CSV download for individual metrics'),\n enableEmailCsv: z.boolean().optional().describe('Enable emailing metric data as CSV'),\n disableDownloadPng: z.boolean().optional().describe('Disable PNG download in fullscreen'),\n enableDownloadAllMetrics: z.boolean().optional().describe('Enable bulk download of all metrics as CSV'),\n enableDownloadAllPdf: z.boolean().optional().describe('Enable downloading entire dashboard as PDF'),\n disableDownloadDataNoFilters: z.boolean().optional().describe('Prevent data download when no filters'),\n disableDownloadUnderlyingDataNoFilters: z.boolean().optional().describe('Prevent underlying data download without filters'),\n\n // UI Visibility\n hideDashboardName: z.boolean().optional().describe('Hide the dashboard title'),\n hideMetricCardShadow: z.boolean().optional().describe('Remove card shadow effects'),\n disableMetricCardBorder: z.boolean().optional().describe('Remove metric card borders'),\n showDashboardActions: z.boolean().optional().describe('Show/hide dashboard action buttons'),\n disableFullscreen: z.boolean().optional().describe('Disable fullscreen mode'),\n isHideTablePreview: z.boolean().optional().describe('Hide table preview in fullscreen'),\n isHideChartSettings: z.boolean().optional().describe('Hide chart settings in fullscreen'),\n shouldFitFullScreen: z.boolean().optional().describe('Make fullscreen modal fit the component space'),\n\n // Loaders\n disableMainLoader: z.boolean().optional().describe('Hide the main loading indicator'),\n disableMetricLoader: z.boolean().optional().describe('Hide metric-level loading indicators'),\n\n // Data Access\n disableUnderlyingData: z.boolean().optional().describe('Disable access to underlying data'),\n isShowNoDataFoundScreen: z.boolean().optional().describe('Show a \"no data\" screen when data unavailable'),\n\n // Scheduling\n disableScheduleEmailReports: z.boolean().optional().describe('Disable email report scheduling'),\n\n // Interactions\n isStickyDashboardFilters: z.boolean().optional().describe('Make filters sticky when scrolling'),\n enableMultiMetricFilters: z.boolean().optional().describe('Enable cross-metric filter interactions'),\n optionsIcon: z.enum(['kebab-menu-vertical', 'download']).optional().describe('Menu icon style'),\n enableTitleClickFullscreen: z.boolean().optional().describe('Click metric title to enter fullscreen'),\n\n // Export\n exportMsgPosition: z.enum([\n 'bottom', 'bottom-left', 'bottom-right', 'center', 'top', 'top-left', 'top-right',\n ]).optional().describe('Position of \"exporting\" notification message'),\n isModifyUrl: z.boolean().optional().describe('Whether navigating metrics modifies the browser URL'),\n\n // No-data visuals\n noDataImg: z.string().optional().describe('URL to custom image when no data found'),\n noDataFoundSvg: z.string().optional().describe('Inline SVG when no data found'),\n\n // Metric description\n longDescriptionWidth: z.string().optional().describe('Width of long-description tooltip (e.g. \"300px\")'),\n longDescriptionFontColor: z.string().optional().describe('Font color for long-description tooltip (hex)'),\n\n // Settings icon\n settingsIconName: z.string().optional().describe('Custom name/label for the settings icon'),\n settingsIconSvg: z.string().optional().describe('Inline SVG for a custom settings icon'),\n\n // Advanced: per-chart settings\n customChartSettings: z.record(z.unknown()).optional().describe('Per-chart override settings (JSON)'),\n\n // Custom Messages\n tokenExpiryMessage: z.string().optional().describe('Custom message when token expires'),\n tokenAbsentMessage: z.string().optional().describe('Custom message when token is missing'),\n\n // ===== FILTERS (from configure_filters) =====\n stringFilters: z.array(stringFilterSchema).optional()\n .describe('String filter configurations with dropdown options and defaults'),\n numberFilters: z.array(numberFilterSchema).optional()\n .describe('Number filter configurations with min/max defaults'),\n dateFilters: z.array(dateFilterSchema).optional()\n .describe('Date filter configurations with default ranges and presets'),\n sqlFilters: z.array(sqlFilterSchema).optional()\n .describe('SQL-based filter options for large option sets'),\n hideDashboardFilters: z.array(z.string()).optional()\n .describe('Filter names to hide from the dashboard UI'),\n hideDatePickerOptions: z.array(z.string()).optional()\n .describe('Date picker options to hide (e.g. [\"this month\", \"yesterday\"])'),\n metricFilterPosition: z.enum(['inside', 'outside']).optional()\n .describe('Where to display metric-level filters'),\n\n // ===== INTERNATIONALIZATION (from configure_internationalization) =====\n language: z.enum(SUPPORTED_LANGUAGES).optional()\n .describe('Primary language code (e.g. \"fr\", \"es\", \"ja\")'),\n calendarType: z.enum(['default', 'ind']).optional()\n .describe('Calendar system: \"default\" or \"ind\" (Indian)'),\n translations: z.array(z.object({\n key: z.string().describe('Original text to translate (must match exactly)'),\n translations: z.record(z.string()).describe('Language code → translation mapping'),\n })).optional()\n .describe('Translation dictionary entries'),\n },\n WRITE_IDEMPOTENT,\n async (params) => {\n const { embedId, body, ...opts } = 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 const result = await services.embedsApi.updateEmbed(rawBody);\n if (result.error) {\n return toolError(`Embed configuration failed: ${stringify(result.error)}`);\n }\n return toolSuccess(\n `Embed configured for \"${embedId}\" (raw passthrough mode).` +\n GUEST_TOKEN_REMINDER,\n );\n } catch (err) {\n const guardrail = await maybeBuildCorruptedEmbedGuardrail(client, embedId, 'configure embed', err);\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 options: Record<string, unknown> = {};\n const attrs: Record<string, unknown> = {};\n const configured: string[] = [];\n\n // ---- Options ----\n if (opts.disableMetricCreation !== undefined) options.disableMetricCreation = opts.disableMetricCreation;\n if (opts.disableMetricUpdation !== undefined) options.disableMetricUpdation = opts.disableMetricUpdation;\n if (opts.disableMetricDeletion !== undefined) options.disableMetricDeletion = opts.disableMetricDeletion;\n if (opts.disableManageMetrics !== undefined) options.disableManageMetrics = opts.disableManageMetrics;\n if (opts.disableLayoutCustomization !== undefined) options.disableLayoutCustomization = opts.disableLayoutCustomization;\n if (opts.disableSaveLayout !== undefined) options.disableSaveLayout = opts.disableSaveLayout;\n if (opts.disableDownloadDataNoFilters !== undefined) options.disableDownloadDataNoFilters = opts.disableDownloadDataNoFilters;\n if (opts.disableDownloadUnderlyingDataNoFilters !== undefined) options.disableDownloadUnderlyingDataNoFilters = opts.disableDownloadUnderlyingDataNoFilters;\n if (opts.hideDashboardName !== undefined) options.hideDashboardName = opts.hideDashboardName;\n if (opts.hideMetricCardShadow !== undefined) options.hideMetricCardShadow = opts.hideMetricCardShadow;\n if (opts.disableMetricCardBorder !== undefined) options.disableMetricCardBorder = opts.disableMetricCardBorder;\n if (opts.showDashboardActions !== undefined) options.showDashboardActions = opts.showDashboardActions;\n if (opts.shouldFitFullScreen !== undefined) options.shouldFitFullScreen = opts.shouldFitFullScreen;\n if (opts.isShowNoDataFoundScreen !== undefined) options.isShowNoDataFoundScreen = opts.isShowNoDataFoundScreen;\n if (opts.disableMainLoader !== undefined) options.disableMainLoader = opts.disableMainLoader;\n if (opts.disableMetricLoader !== undefined) options.disableMetricLoader = opts.disableMetricLoader;\n if (opts.disableUnderlyingData !== undefined) options.disableUnderlyingData = opts.disableUnderlyingData;\n if (opts.disableScheduleEmailReports !== undefined) options.disableScheduleEmailReports = opts.disableScheduleEmailReports;\n if (opts.exportMsgPosition) options.exportMsgPosition = opts.exportMsgPosition;\n if (opts.isModifyUrl !== undefined) options.isModifyUrl = opts.isModifyUrl;\n\n // Component attributes\n if (opts.enableDownloadCsv !== undefined) attrs.enableDownloadCsv = opts.enableDownloadCsv;\n if (opts.enableEmailCsv !== undefined) attrs.enableEmailCsv = opts.enableEmailCsv;\n if (opts.disableDownloadPng !== undefined) attrs.disableDownloadPng = opts.disableDownloadPng;\n if (opts.enableDownloadAllMetrics !== undefined) attrs.enableDownloadAllMetrics = opts.enableDownloadAllMetrics;\n if (opts.enableDownloadAllPdf !== undefined) attrs.enableDownloadAllPdf = opts.enableDownloadAllPdf;\n if (opts.disableFullscreen !== undefined) attrs.disableFullscreen = opts.disableFullscreen;\n if (opts.isHideTablePreview !== undefined) attrs.isHideTablePreview = opts.isHideTablePreview;\n if (opts.isHideChartSettings !== undefined) attrs.isHideChartSettings = opts.isHideChartSettings;\n if (opts.isStickyDashboardFilters !== undefined) attrs.isStickyDashboardFilters = opts.isStickyDashboardFilters;\n if (opts.enableMultiMetricFilters !== undefined) attrs.enableMultiMetricFilters = opts.enableMultiMetricFilters;\n if (opts.optionsIcon) attrs.optionsIcon = opts.optionsIcon;\n if (opts.enableTitleClickFullscreen !== undefined) attrs.enableTitleClickFullscreen = opts.enableTitleClickFullscreen;\n if (opts.noDataImg) attrs.noDataImg = opts.noDataImg;\n if (opts.noDataFoundSvg) attrs.noDataFoundSvg = opts.noDataFoundSvg;\n if (opts.customChartSettings) attrs.customChartSettings = opts.customChartSettings;\n\n if (opts.longDescriptionWidth || opts.longDescriptionFontColor) {\n attrs.longDescriptionConfig = {\n ...(opts.longDescriptionWidth && { width: opts.longDescriptionWidth }),\n ...(opts.longDescriptionFontColor && { fontColor: opts.longDescriptionFontColor }),\n };\n }\n if (opts.settingsIconName || opts.settingsIconSvg) {\n attrs.settingsIcon = {\n ...(opts.settingsIconName && { name: opts.settingsIconName }),\n ...(opts.settingsIconSvg && { iconSvg: opts.settingsIconSvg }),\n };\n }\n\n // Custom messages\n const customMessages: Record<string, unknown> = {};\n if (opts.tokenExpiryMessage) customMessages.tokenExpiry = opts.tokenExpiryMessage;\n if (opts.tokenAbsentMessage) customMessages.tokenAbsent = opts.tokenAbsentMessage;\n if (Object.keys(customMessages).length) options.customMessages = customMessages;\n\n // ---- Filters ----\n const globalFilterOptions: Record<string, unknown> = {};\n\n if (opts.stringFilters) {\n for (const f of opts.stringFilters) {\n globalFilterOptions[f.filterName] = {\n options: f.options,\n ...(f.defaultOption !== undefined && { defaultOption: f.defaultOption }),\n };\n }\n configured.push(`${opts.stringFilters.length} string filter(s)`);\n }\n if (opts.numberFilters) {\n for (const f of opts.numberFilters) {\n globalFilterOptions[f.filterName] = {\n defaultOption: { min: f.min, max: f.max },\n };\n }\n configured.push(`${opts.numberFilters.length} number filter(s)`);\n }\n if (opts.dateFilters) {\n for (const f of opts.dateFilters) {\n const config: Record<string, unknown> = {};\n if (f.startDate || f.endDate) {\n config.defaultOption = {\n ...(f.startDate && { startDate: f.startDate }),\n ...(f.endDate && { endDate: f.endDate }),\n };\n }\n if (f.datePresetOptions) config.datePresetOptions = f.datePresetOptions;\n globalFilterOptions[f.filterName] = config;\n }\n configured.push(`${opts.dateFilters.length} date filter(s)`);\n }\n if (opts.sqlFilters) {\n for (const f of opts.sqlFilters) {\n globalFilterOptions[f.filterName] = {\n sql: f.sql,\n columnName: f.columnName,\n };\n }\n configured.push(`${opts.sqlFilters.length} SQL filter(s)`);\n }\n if (Object.keys(globalFilterOptions).length) options.globalFilterOptions = globalFilterOptions;\n\n if (opts.hideDashboardFilters) {\n attrs.hideDashboardFilters = opts.hideDashboardFilters;\n configured.push(`hiding ${opts.hideDashboardFilters.length} filter(s)`);\n }\n if (opts.hideDatePickerOptions) {\n options.hideDatePickerOptions = opts.hideDatePickerOptions;\n configured.push(`hiding ${opts.hideDatePickerOptions.length} date picker option(s)`);\n }\n if (opts.metricFilterPosition) {\n attrs.metricFilterPosition = opts.metricFilterPosition;\n configured.push(`metric filter position: ${opts.metricFilterPosition}`);\n }\n\n // ---- Internationalization ----\n if (opts.language) {\n attrs.language = opts.language;\n configured.push(`language: ${opts.language}`);\n }\n if (opts.calendarType) {\n attrs.calendarType = opts.calendarType;\n configured.push(`calendar: ${opts.calendarType}`);\n }\n if (opts.translations?.length) {\n const dict: Record<string, Record<string, string>> = {};\n for (const entry of opts.translations) {\n dict[entry.key] = entry.translations;\n }\n attrs.translationDictionary = dict;\n configured.push(`${opts.translations.length} translation(s)`);\n }\n\n // Count option-level configured items\n const optionKeys = Object.keys(options).filter((k) => k !== 'globalFilterOptions' && k !== 'customMessages' && k !== 'hideDatePickerOptions');\n const attrKeys = Object.keys(attrs).filter((k) =>\n k !== 'hideDashboardFilters' && k !== 'metricFilterPosition' &&\n k !== 'language' && k !== 'calendarType' && k !== 'translationDictionary',\n );\n if (optionKeys.length || attrKeys.length) {\n configured.push(`${optionKeys.length + attrKeys.length} display option(s)`);\n }\n\n if (Object.keys(options).length === 0 && Object.keys(attrs).length === 0) {\n return toolError('No configuration provided. Specify at least one option, filter, or i18n setting.');\n }\n\n try {\n const patch: Record<string, unknown> = {};\n if (Object.keys(options).length) patch.options = options;\n if (Object.keys(attrs).length) patch.componentAttributes = attrs;\n const result = await services.embedService.updateEmbed(embedId, patch);\n\n if (result.error) {\n return toolError(`Embed configuration failed: ${stringify(result.error)}`);\n }\n\n return toolSuccess(\n `Embed configured for \"${embedId}\".\\n\\n` +\n `**Configured:** ${configured.join(', ')}\\n\\n` +\n 'Use `get_embed_details` to view the full configuration.' +\n GUEST_TOKEN_REMINDER,\n );\n } catch (err) {\n const guardrail = await maybeBuildCorruptedEmbedGuardrail(client, embedId, 'configure embed', err);\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 { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { DatabrainApiError, toolError, toolSuccess } from '../../utils/errors.js';\nimport { READ_ONLY } from '../annotations.js';\n\nfunction asRecord(value: unknown): Record<string, unknown> | null {\n return value && typeof value === 'object' ? (value as Record<string, unknown>) : null;\n}\n\nfunction firstString(...values: Array<unknown>): string | null {\n for (const v of values) {\n if (typeof v === 'string' && v.trim().length > 0) return v;\n }\n return null;\n}\n\ntype CheckResult = {\n check: string;\n status: 'pass' | 'fail' | 'warn';\n details: string;\n};\n\nfunction runRuntimeReadinessChecks(params: {\n guestTokenBody?: Record<string, unknown>;\n clientId?: string;\n dataAppName?: string;\n permissions?: Record<string, unknown>;\n embedOptions?: { disableMetricCreation?: boolean };\n dashboardRuntime?: { isAllowedToCreateMetrics?: boolean; metricCreationMode?: string };\n}): CheckResult[] {\n const payload = params.guestTokenBody ?? {\n clientId: params.clientId,\n dataAppName: params.dataAppName,\n permissions: params.permissions,\n };\n\n const checks: CheckResult[] = [];\n const topLevelPermissions = payload.permissions;\n const paramsObj = payload.params as Record<string, unknown> | undefined;\n const nestedPermissions = paramsObj?.permissions;\n\n checks.push({\n check: 'Top-level dataAppName',\n status: typeof payload.dataAppName === 'string' && (payload.dataAppName as string).length > 0 ? 'pass' : 'fail',\n details: typeof payload.dataAppName === 'string' && (payload.dataAppName as string).length > 0\n ? 'dataAppName is present at top level.'\n : 'Missing top-level dataAppName in guest token body.',\n });\n checks.push({\n check: 'Top-level permissions object',\n status: typeof topLevelPermissions === 'object' && topLevelPermissions !== null ? 'pass' : 'fail',\n details: typeof topLevelPermissions === 'object' && topLevelPermissions !== null\n ? 'permissions is present at top level.'\n : 'Missing top-level permissions object.',\n });\n checks.push({\n check: 'No nested permissions in params',\n status: nestedPermissions ? 'fail' : 'pass',\n details: nestedPermissions\n ? 'Found params.permissions. Move permissions to top level.'\n : 'No nested permissions found.',\n });\n\n const disableMetricCreationFromToken =\n typeof topLevelPermissions === 'object' && topLevelPermissions !== null\n ? (topLevelPermissions as Record<string, unknown>).isDisableMetricCreation\n : undefined;\n checks.push({\n check: 'Guest token metric creation gate',\n status: disableMetricCreationFromToken === true ? 'fail' : 'pass',\n details: disableMetricCreationFromToken === true\n ? 'permissions.isDisableMetricCreation=true blocks + Create Metric.'\n : 'permissions.isDisableMetricCreation is not forcing metric creation off.',\n });\n\n if (params.embedOptions) {\n checks.push({\n check: 'Embed option metric creation gate',\n status: params.embedOptions.disableMetricCreation === true ? 'fail' : 'pass',\n details: params.embedOptions.disableMetricCreation === true\n ? 'embed option disableMetricCreation=true blocks + Create Metric.'\n : 'Embed options are not forcing metric creation off.',\n });\n }\n\n if (params.dashboardRuntime) {\n checks.push({\n check: 'Dashboard runtime: isAllowedToCreateMetrics',\n status: params.dashboardRuntime.isAllowedToCreateMetrics === true ? 'pass' : 'fail',\n details: params.dashboardRuntime.isAllowedToCreateMetrics === true\n ? 'Dashboard runtime allows metric creation.'\n : 'Dashboard runtime says metric creation is not allowed.',\n });\n checks.push({\n check: 'Dashboard runtime: metricCreationMode',\n status: params.dashboardRuntime.metricCreationMode === 'DRAG_DROP' ? 'pass' : 'warn',\n details: `metricCreationMode is \"${params.dashboardRuntime.metricCreationMode ?? 'unknown'}\".`,\n });\n }\n\n return checks;\n}\n\nexport function registerDiagnoseEmbedHealth(\n server: McpServer,\n client: DatabrainClient,\n): void {\n server.tool(\n 'diagnose_embed_health',\n 'Diagnose embed shape and required fields. Optionally validates runtime readiness if guestTokenBody or permissions are provided.',\n {\n embedId: z.string().describe('Embed ID to diagnose'),\n dataAppName: z.string().optional().describe('Optional data app name to scope dashboard checks'),\n\n // Runtime readiness params (absorbed from check_runtime_readiness)\n guestTokenBody: z.record(z.unknown()).optional().describe(\n 'Exact request body sent to POST /api/v2/guest-token/create (for runtime validation).',\n ),\n permissions: z.record(z.unknown()).optional().describe(\n 'Guest token permissions (used when guestTokenBody is not provided).',\n ),\n embedOptions: z.object({\n disableMetricCreation: z.boolean().optional(),\n }).optional().describe('Embed web component options (if known).'),\n dashboardRuntime: z.object({\n isAllowedToCreateMetrics: z.boolean().optional(),\n metricCreationMode: z.string().optional(),\n }).optional().describe('Runtime flags from dashboard response payload.'),\n },\n READ_ONLY,\n async (params) => {\n try {\n const raw = await client.request<unknown>({\n method: 'GET',\n path: '/api/v2/data-app/embeds',\n auth: 'api',\n query: { embedId: params.embedId },\n });\n\n const embedList = Array.isArray(raw) ? raw : [raw];\n const embed =\n embedList.find((e: any) => (e?.embedId || e?._id || e?.id) === params.embedId) ||\n embedList[0];\n const embedObj = asRecord(embed);\n\n if (!embedObj) {\n return toolError(\n `Embed \"${params.embedId}\" is not returned as an object by GET /embeds. ` +\n 'This indicates malformed API data for this record.'\n );\n }\n\n const embedMetadata = asRecord(embedObj.embedMetadata);\n const accessSettings =\n asRecord(embedObj.accessSettings) ||\n (embedMetadata ? asRecord(embedMetadata.accessSettings) : null);\n\n const dashboardIdCandidates = [\n firstString(embedObj.dashboardId),\n firstString(embedObj.externalDashboardId),\n embedMetadata ? firstString(embedMetadata.dashboardId) : null,\n ].filter(Boolean) as string[];\n\n const workspaceCandidates = [\n firstString(embedObj.workspaceName),\n firstString(embedObj.workspace),\n firstString(embedObj.workspaceId),\n embedMetadata ? firstString(embedMetadata.workspaceName) : null,\n embedMetadata ? firstString(embedMetadata.workspaceId) : null,\n ].filter(Boolean) as string[];\n\n const datamartName = firstString(\n accessSettings?.datamartName,\n embedObj.datamartName,\n embedMetadata?.datamartName,\n );\n\n let datamartsCount = 0;\n let datamartNames: string[] = [];\n try {\n const datamarts = await client.request<unknown[]>({\n method: 'GET',\n path: '/api/v2/data-app/datamarts',\n auth: 'service',\n cacheKey: 'list_datamarts',\n cacheTtlMs: 5 * 60 * 1000,\n });\n if (Array.isArray(datamarts)) {\n datamartsCount = datamarts.length;\n datamartNames = datamarts\n .map((d: any) => firstString(d?.name, d?.datamartName))\n .filter(Boolean)\n .slice(0, 10) as string[];\n }\n } catch {\n // Best-effort diagnostic only\n }\n\n let dashboardsCount = 0;\n let dashboardIdSample: string[] = [];\n try {\n const dashboardQuery =\n params.dataAppName && params.dataAppName.trim().length > 0\n ? { dataAppName: params.dataAppName }\n : undefined;\n const dashboards = await client.request<unknown[]>({\n method: 'GET',\n path: '/api/v2/data-app/dashboards',\n auth: 'api',\n query: dashboardQuery,\n cacheKey: 'list_dashboards',\n cacheTtlMs: 5 * 60 * 1000,\n });\n if (Array.isArray(dashboards)) {\n dashboardsCount = dashboards.length;\n dashboardIdSample = dashboards\n .map((d: any) =>\n firstString(\n d?.dashboardId,\n d?.externalDashboardId,\n d?._id,\n d?.id,\n d?.uid,\n ),\n )\n .filter(Boolean)\n .slice(0, 10) as string[];\n }\n } catch {\n // Best-effort diagnostic only\n }\n\n const issues: string[] = [];\n if (!firstString(embedObj.embedId, embedObj.id, embedObj._id)) {\n issues.push('No stable embed identifier found in record');\n }\n if (!accessSettings) {\n issues.push('Missing accessSettings');\n }\n if (!datamartName) {\n issues.push('Missing datamartName (in accessSettings or embed metadata)');\n }\n if (dashboardIdCandidates.length === 0) {\n issues.push('No dashboard identifier found on embed');\n }\n if (workspaceCandidates.length === 0) {\n issues.push('No workspace identifier/name found on embed');\n }\n\n const health = issues.length === 0 ? 'healthy-shape' : 'inconsistent-shape';\n\n let report =\n `Embed Health Report: \\`${params.embedId}\\`\\n\\n` +\n `- **Status:** ${health}\\n` +\n `- **Issues:** ${issues.length ? issues.join('; ') : 'none detected in shape checks'}\\n` +\n `- **Dashboard ID candidates:** ${dashboardIdCandidates.length ? dashboardIdCandidates.map((id) => `\\`${id}\\``).join(', ') : 'none'}\\n` +\n `- **Workspace candidates:** ${workspaceCandidates.length ? workspaceCandidates.map((id) => `\\`${id}\\``).join(', ') : 'none'}\\n` +\n `- **Resolved datamartName:** ${datamartName ? `\\`${datamartName}\\`` : 'none'}\\n` +\n `- **Datamarts visible:** ${datamartsCount}${datamartNames.length ? ` (sample: ${datamartNames.join(', ')})` : ''}\\n` +\n `- **Dashboards visible:** ${dashboardsCount}${dashboardIdSample.length ? ` (ID sample: ${dashboardIdSample.map((id) => `\\`${id}\\``).join(', ')})` : ''}\\n`;\n\n // Runtime readiness checks (optional — when guest token info is provided)\n if (params.guestTokenBody || params.permissions || params.embedOptions || params.dashboardRuntime) {\n const runtimeChecks = runRuntimeReadinessChecks({\n guestTokenBody: params.guestTokenBody as Record<string, unknown> | undefined,\n clientId: undefined,\n dataAppName: params.dataAppName,\n permissions: params.permissions as Record<string, unknown> | undefined,\n embedOptions: params.embedOptions,\n dashboardRuntime: params.dashboardRuntime,\n });\n const hasFail = runtimeChecks.some((c) => c.status === 'fail');\n report += `\\n### Runtime Readiness: ${hasFail ? 'NOT_READY' : 'READY'}\\n\\n`;\n for (const c of runtimeChecks) {\n const icon = c.status === 'pass' ? 'PASS' : c.status === 'fail' ? 'FAIL' : 'WARN';\n report += `- **[${icon}]** ${c.check}: ${c.details}\\n`;\n }\n }\n\n report += `\\nRaw embed payload:\\n` +\n '```json\\n' +\n JSON.stringify(embedObj, null, 2) +\n '\\n```';\n\n return toolSuccess(report);\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 { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { DatabrainApiError, toolError, toolSuccess } from '../../utils/errors.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport { resolveResource, formatDataApp } from '../../utils/resolve-resource.js';\nimport { WRITE_CREATE } from '../annotations.js';\n\nexport function registerGenerateGuestToken(server: McpServer, client: DatabrainClient): 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.string().describe('Unique end-user identifier for multi-tenant filtering. Use \"None\" if no tenancy.'),\n dataAppName: z.string().optional().describe('Name of the data app. Omit to list available data apps.'),\n body: z.record(z.unknown()).optional().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.object({\n allowedEmbeds: z.array(z.string()).optional().describe('Restrict token to specific embed IDs'),\n rlsSettings: z.array(z.object({\n metricId: z.string().describe('Metric ID'),\n values: z.record(z.unknown()).describe('RLS values by column name'),\n })).optional().describe('Legacy alias used in docs/examples; forwarded as params.rlsSettings'),\n appFilters: z.array(z.object({\n metricId: z.string().describe('Metric ID'),\n values: z.record(z.unknown()).describe('Filter values by column name'),\n })).optional().describe('Metric-level app filters'),\n dashboardAppFilters: z.array(z.object({\n dashboardId: z.string().describe('Dashboard ID'),\n values: z.record(z.unknown()).describe('Filter values by dashboard filter name'),\n isShowOnUrl: z.boolean().optional().describe('Whether filters are shown in URL params'),\n })).optional().describe('Dashboard-level app filters'),\n hideDashboardFilters: z.array(z.string()).optional().describe('Dashboard filter names to hide'),\n userIdentifier: z.string().optional().describe('End-user identifier for private metrics support'),\n timezone: z.string().optional().describe('IANA timezone, e.g. \"America/New_York\"'),\n }).optional().describe('Advanced token params'),\n\n // Legacy convenience fields (auto-mapped into params for backward compatibility)\n timezone: z.string().optional().describe('Legacy: moved under params.timezone'),\n allowedEmbeds: z.array(z.string()).optional().describe('Legacy: moved under params.allowedEmbeds'),\n rlsSettings: z.array(z.object({\n metricId: z.string().describe('Metric ID'),\n values: z.record(z.unknown()).describe('RLS values by column name'),\n })).optional().describe('Legacy: moved under params.rlsSettings'),\n appFilters: z.array(z.object({\n metricId: z.string().describe('Metric ID'),\n values: z.record(z.unknown()).describe('Filter values by column name'),\n })).optional().describe('Legacy: moved under params.appFilters'),\n dashboardAppFilters: z.array(z.object({\n dashboardId: z.string().describe('Dashboard ID to apply filters to'),\n values: z.record(z.unknown()).describe('Filter values for this dashboard'),\n isShowOnUrl: z.boolean().optional().describe('Whether filters are shown in URL params'),\n })).optional().describe('Legacy: moved under params.dashboardAppFilters'),\n permissions: z.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 }).optional().describe('Runtime permission overrides (merge with and override embed-level settings)'),\n theme: z.record(z.unknown()).optional().describe('Runtime theme overrides (overrides embed-level theme)'),\n hideDashboardFilters: z.array(z.string()).optional().describe('Legacy: moved under params.hideDashboardFilters'),\n userIdentifier: z.string().optional().describe('Legacy: moved under params.userIdentifier'),\n expiryTime: z.number().optional().describe('Token TTL in milliseconds'),\n datasourceName: z.string().optional().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 = 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 { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { toolSuccess } from '../../utils/errors.js';\nimport { getTemplate } from '../../templates/index.js';\nimport type { TemplateContext } from '../../templates/types.js';\nimport { READ_ONLY } from '../annotations.js';\n\nconst FRAMEWORKS = ['react', 'nextjs', 'vue', 'angular', 'svelte', 'solidjs', 'vanilla'] as const;\n\nexport function registerGenerateEmbedCode(server: McpServer, _client: DatabrainClient): 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.enum(['dashboard', 'metric']).optional().default('dashboard'),\n options: z.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.unknown()).optional(),\n optionsIcon: z.enum(['kebab-menu-vertical', 'download']).optional(),\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 { TemplateContext, GeneratedCode } 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://app.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 { TemplateContext, GeneratedCode } 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://app.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 { TemplateContext, GeneratedCode } 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://app.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 type { TemplateContext, GeneratedCode } 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://app.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 { TemplateContext, GeneratedCode } 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://app.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 { TemplateContext, GeneratedCode } 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://app.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 { TemplateContext, GeneratedCode } 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://app.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 { TemplateContext, GeneratedCode } from './types.js';\nimport { reactTemplate } from './react.js';\nimport { nextjsTemplate } from './nextjs.js';\nimport { vueTemplate } from './vue.js';\nimport { angularTemplate } from './angular.js';\nimport { svelteTemplate } from './svelte.js';\nimport { solidjsTemplate } from './solidjs.js';\nimport { vanillaTemplate } from './vanilla.js';\n\ntype Framework = 'react' | 'nextjs' | 'vue' | 'angular' | 'svelte' | 'solidjs' | '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(framework: Framework, ctx: TemplateContext): GeneratedCode {\n return templates[framework](ctx);\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { DatabrainApiError, toolError, toolSuccess } from '../../utils/errors.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport { READ_ONLY } from '../annotations.js';\n\nexport function registerListDashboards(server: McpServer, client: DatabrainClient): 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('Data app name for data_app scope. Ignored for global scope.'),\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(JSON.stringify({\n count: result.length,\n scope: useDataAppScope ? 'data_app' : 'global',\n dashboards: result.map((d: any) => {\n const { name, dashboardId, workspaceName, metricCount } =\n services.discoveryService.normalizeDashboard(d as Record<string, unknown>);\n return {\n id: dashboardId || null,\n name,\n workspace: workspaceName || null,\n metricCount: metricCount ?? 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 { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { DatabrainApiError, toolError, toolSuccess } from '../../utils/errors.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport { WRITE_CREATE } from '../annotations.js';\n\nconst STEPS = [\n 'discover_data_apps',\n 'choose_data_app',\n 'create_data_app',\n 'ensure_api_token',\n 'discover_workspaces',\n 'choose_workspace',\n 'list_dashboards',\n 'choose_dashboard',\n 'create_embed',\n 'runtime_readiness',\n 'complete',\n] as const;\ntype Step = (typeof STEPS)[number];\n\nconst stateSchema = z.object({\n dataAppName: z.string().optional(),\n dataAppId: z.string().optional(),\n workspaceName: z.string().optional(),\n embedType: z.enum(['dashboard', 'metric']).optional(),\n dashboardId: z.string().optional(),\n metricId: z.string().optional(),\n datamartName: z.string().optional(),\n embedId: z.string().optional(),\n embedName: z.string().optional(),\n clientId: z.string().optional(),\n runtimeValidated: z.boolean().optional(),\n});\n\ntype SetupEnvelopeStatus = 'CHOICE_REQUIRED' | 'CONFIRM_REQUIRED' | 'READY' | 'DONE';\n\nfunction emit(\n status: SetupEnvelopeStatus,\n step: Step,\n state: Record<string, unknown>,\n message: string,\n options?: Array<Record<string, unknown>>,\n nextStep?: Step,\n): ReturnType<typeof toolSuccess> {\n const payload: Record<string, unknown> = {\n status,\n step,\n message,\n state,\n };\n if (options) payload.options = options;\n if (nextStep) payload.nextStep = nextStep;\n return toolSuccess(JSON.stringify(payload, null, 2));\n}\n\nfunction parseUserChoiceObject(\n userChoice?: string,\n): Record<string, unknown> | null {\n if (!userChoice) return null;\n try {\n const parsed = JSON.parse(userChoice);\n if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {\n return parsed as Record<string, unknown>;\n }\n return null;\n } catch {\n return null;\n }\n}\n\nfunction parseNameFromUserChoice(userChoice?: string): string | null {\n if (!userChoice) return null;\n const choiceObj = parseUserChoiceObject(userChoice);\n if (choiceObj) {\n const rawName = choiceObj.name;\n if (typeof rawName === 'string' && rawName.trim().length > 0) return rawName.trim();\n return null;\n }\n const trimmed = userChoice.trim();\n return trimmed.length > 0 ? trimmed : null;\n}\n\nexport function registerSetupEmbedInteractive(\n server: McpServer,\n client: DatabrainClient,\n): void {\n const services = createServiceBundle(client);\n const listDashboardsForContext = async (\n currentState: Record<string, unknown>,\n ): Promise<{ dashboards: Array<Record<string, unknown>>; scope: 'data_app' | 'workspace' | 'global' }> => {\n const dataAppName = currentState.dataAppName as string | undefined;\n const workspaceName = currentState.workspaceName as string | undefined;\n\n if (dataAppName && dataAppName.trim().length > 0 && client.hasApiToken()) {\n const dashboards = await services.dashboardsApi.listDashboards(dataAppName);\n if (Array.isArray(dashboards) && dashboards.length > 0) {\n return { dashboards: dashboards as Array<Record<string, unknown>>, scope: 'data_app' };\n }\n }\n\n if (workspaceName && workspaceName.trim().length > 0) {\n const dashboards = await services.dashboardsApi.listDashboardsForWorkspace(workspaceName);\n return { dashboards: dashboards as Array<Record<string, unknown>>, scope: 'workspace' };\n }\n\n const dashboards = await services.dashboardsApi.listDashboardsAcrossWorkspaces();\n return { dashboards: dashboards as Array<Record<string, unknown>>, scope: 'global' };\n };\n\n server.tool(\n 'setup_embed_interactive',\n 'Step-by-step embed setup wizard. Pass step and state from previous call.',\n {\n step: z.enum(STEPS).describe('Current orchestration step'),\n state: stateSchema.optional().describe('State from previous step — pass forward unchanged'),\n userChoice: z\n .string()\n .optional()\n .describe('User response for CHOICE_REQUIRED or CONFIRM_REQUIRED'),\n },\n WRITE_CREATE,\n async (params) => {\n const state = params.state ?? {};\n const step = params.step as Step;\n\n try {\n // ── Step 1: Discover data apps (service token) ───────────\n if (step === 'discover_data_apps') {\n const apps = await services.dataAppsApi.listDataApps();\n\n if (!Array.isArray(apps) || apps.length === 0) {\n return emit(\n 'CHOICE_REQUIRED',\n step,\n state,\n 'No data apps found. Ask user for a data app name to create one.',\n [\n { id: 'create', label: 'Create a new data app' },\n { id: 'stop', label: 'Stop setup' },\n ],\n 'create_data_app',\n );\n }\n\n if (apps.length === 1) {\n const app = services.discoveryService.normalizeDataApp(apps[0]);\n return emit(\n 'CONFIRM_REQUIRED',\n step,\n {\n ...state,\n dataAppName: app.name,\n dataAppId: app.dataAppId || undefined,\n },\n `Found one data app: \"${app.name}\". Confirm to continue.`,\n [{ id: app.name, label: `${app.name} (${app.dataAppId || 'no-id'})` }],\n 'ensure_api_token',\n );\n }\n\n const options = apps.map((a) => {\n const n = services.discoveryService.normalizeDataApp(a);\n return {\n id: n.dataAppId || n.name,\n label: `${n.name} (${n.dataAppId || 'no-id'})`,\n dataAppName: n.name,\n dataAppId: n.dataAppId,\n };\n });\n return emit(\n 'CHOICE_REQUIRED',\n step,\n state,\n `Found ${apps.length} data app(s). Ask the user which one to embed from.`,\n options,\n 'choose_data_app',\n );\n }\n\n // ── Step 2a: Choose data app ─────────────────────────────\n if (step === 'choose_data_app') {\n if (!params.userChoice) {\n return toolError('userChoice is required for choose_data_app.');\n }\n const apps = await services.dataAppsApi.listDataApps();\n const q = params.userChoice.toLowerCase();\n const match = apps.find((a) => {\n const n = services.discoveryService.normalizeDataApp(a);\n return (\n n.name.toLowerCase() === q ||\n (n.dataAppId || '').toLowerCase() === q ||\n n.name.toLowerCase().includes(q)\n );\n });\n if (!match) {\n return toolError(\n `No data app matched \"${params.userChoice}\". Re-run discover_data_apps.`,\n );\n }\n const n = services.discoveryService.normalizeDataApp(match);\n return emit(\n 'READY',\n step,\n {\n ...state,\n dataAppName: n.name,\n dataAppId: n.dataAppId || undefined,\n },\n `Selected data app: \"${n.name}\".`,\n undefined,\n 'ensure_api_token',\n );\n }\n\n // ── Step 2b: Create data app (fresh setup) ───────────────\n if (step === 'create_data_app') {\n const name = parseNameFromUserChoice(params.userChoice);\n if (!name) {\n return toolError(\n 'Provide data app name in userChoice. Accepts plain string or JSON: {\"name\":\"my-data-app\"}.',\n );\n }\n const created = await client.request<Record<string, unknown>>({\n method: 'POST',\n path: '/api/v2/data-app/',\n auth: 'service',\n body: { name },\n invalidateCache: ['list_data_apps'],\n });\n return emit(\n 'READY',\n step,\n {\n ...state,\n dataAppName: name,\n dataAppId: (created.id as string | undefined) || undefined,\n },\n `Created data app \"${name}\".`,\n undefined,\n 'ensure_api_token',\n );\n }\n\n // ── Step 3: Ensure API token for selected data app ───────\n if (step === 'ensure_api_token') {\n const appName = state.dataAppName as string | undefined;\n if (!appName) {\n return toolError('state.dataAppName is required. Run discover_data_apps first.');\n }\n\n const tokens = await client.request<Array<Record<string, unknown>>>({\n method: 'GET',\n path: '/api/v2/data-app/api-tokens',\n auth: 'service',\n query: { dataAppName: appName },\n });\n\n if (Array.isArray(tokens) && tokens.length > 0) {\n const tokenValue =\n (tokens[0].token as string | undefined) ||\n (tokens[0].apiToken as string | undefined) ||\n (tokens[0].key as string | undefined);\n if (tokenValue) {\n client.setRuntimeApiToken(tokenValue);\n return emit(\n 'READY',\n step,\n { ...state, dataAppName: appName },\n `API token found and activated for \"${appName}\".`,\n undefined,\n 'discover_workspaces',\n );\n }\n return emit(\n 'CHOICE_REQUIRED',\n step,\n { ...state, dataAppName: appName },\n `\"${appName}\" has API token(s) but the value was not returned. Call \\`create_api_token\\` to generate a new one, or \\`set_api_token\\` if you have the value. Then re-run discover_workspaces.`,\n [\n { id: 'create', label: 'Create new API token (call create_api_token)' },\n { id: 'set', label: 'Set existing token (call set_api_token)' },\n ],\n 'discover_workspaces',\n );\n }\n\n return emit(\n 'CHOICE_REQUIRED',\n step,\n { ...state, dataAppName: appName },\n `No API token for \"${appName}\". Call \\`create_api_token\\` to generate one. Then proceed to discover_workspaces.`,\n [\n { id: 'create', label: 'Create API token now (call create_api_token)' },\n ],\n 'discover_workspaces',\n );\n }\n\n // ── Step 4a: Discover workspaces ─────────────────────────\n if (step === 'discover_workspaces') {\n const workspaces = await services.workspacesApi.listWorkspaces();\n\n if (!Array.isArray(workspaces) || workspaces.length === 0) {\n return emit(\n 'READY',\n step,\n state,\n 'No workspaces found. Create a workspace in Databrain UI first, then re-run this step.',\n );\n }\n\n if (workspaces.length === 1) {\n const ws = workspaces[0];\n const wsName = (typeof ws.name === 'string' ? ws.name.trim() : '') || 'Unnamed';\n return emit(\n 'READY',\n step,\n { ...state, workspaceName: wsName },\n `Found one workspace: \"${wsName}\". Auto-selected.`,\n undefined,\n 'list_dashboards',\n );\n }\n\n const options = workspaces\n .filter((ws) => typeof ws.name === 'string' && ws.name.trim().length > 0)\n .map((ws) => ({\n id: ws.name!,\n label: `${ws.name} (${ws._id || ws.id || 'no-id'})`,\n workspaceName: ws.name,\n }));\n return emit(\n 'CHOICE_REQUIRED',\n step,\n state,\n `Found ${workspaces.length} workspace(s). Ask the user which workspace to use.`,\n options,\n 'choose_workspace',\n );\n }\n\n // ── Step 4b: Choose workspace ─────────────────────────────\n if (step === 'choose_workspace') {\n if (!params.userChoice) {\n return toolError('userChoice is required for choose_workspace.');\n }\n const workspaces = await services.workspacesApi.listWorkspaces();\n const q = params.userChoice.toLowerCase();\n const match = workspaces.find((ws) => {\n const name = (typeof ws.name === 'string' ? ws.name.trim() : '').toLowerCase();\n const wsId = ((ws._id || ws.id || '') as string).toLowerCase();\n return name === q || wsId === q || name.includes(q);\n });\n if (!match) {\n return toolError(\n `No workspace matched \"${params.userChoice}\". Re-run discover_workspaces.`,\n );\n }\n const wsName = (typeof match.name === 'string' ? match.name.trim() : '') || 'Unnamed';\n return emit(\n 'READY',\n step,\n { ...state, workspaceName: wsName },\n `Selected workspace: \"${wsName}\".`,\n undefined,\n 'list_dashboards',\n );\n }\n\n // ── Step 5: List dashboards (data-app, workspace, or global context) ─\n if (step === 'list_dashboards') {\n const { dashboards, scope } = await listDashboardsForContext(state);\n\n if (!Array.isArray(dashboards) || dashboards.length === 0) {\n const scopeMsg =\n scope === 'data_app'\n ? `No dashboards found for data app \"${(state.dataAppName as string) || 'unknown'}\".`\n : scope === 'workspace'\n ? `No dashboards found in workspace \"${(state.workspaceName as string) || 'unknown'}\". Create a dashboard in Databrain UI first, then re-run this step.`\n : 'No dashboards found in available workspaces. Create a dashboard in Databrain UI first, then re-run this step.';\n return emit('READY', step, state, scopeMsg);\n }\n\n const options = dashboards.map((d) => {\n const n = services.discoveryService.normalizeDashboard(d);\n return {\n id: n.dashboardId || n.name,\n label: `${n.name} (${n.dashboardId || 'no-id'})${n.workspaceName ? ` — workspace: ${n.workspaceName}` : ''}`,\n dashboardId: n.dashboardId,\n workspaceName: n.workspaceName,\n };\n });\n const foundMsg =\n scope === 'data_app'\n ? `Found ${dashboards.length} dashboard(s) for data app \"${(state.dataAppName as string) || 'unknown'}\". Ask the user which dashboard to embed.`\n : scope === 'workspace'\n ? `Found ${dashboards.length} dashboard(s) in workspace \"${(state.workspaceName as string) || 'unknown'}\". Ask the user which dashboard to embed.`\n : `Found ${dashboards.length} dashboard(s) across workspaces. Ask the user which dashboard to embed.`;\n return emit(\n 'CHOICE_REQUIRED',\n step,\n state,\n foundMsg,\n options,\n 'choose_dashboard',\n );\n }\n\n // ── Step 6: Choose dashboard ─────────────────────────────\n if (step === 'choose_dashboard') {\n if (!params.userChoice) {\n return toolError('userChoice is required for choose_dashboard. Pass dashboardId or name.');\n }\n\n const { dashboards } = await listDashboardsForContext(state);\n const q = params.userChoice.toLowerCase();\n const match = dashboards.find((d) => {\n const n = services.discoveryService.normalizeDashboard(d);\n return (\n (n.dashboardId || '').toLowerCase() === q ||\n (n.name || '').toLowerCase() === q ||\n (n.name || '').toLowerCase().includes(q)\n );\n });\n if (!match) {\n return toolError(\n `No dashboard matched \"${params.userChoice}\". Re-run list_dashboards.`,\n );\n }\n const n = services.discoveryService.normalizeDashboard(match);\n\n // Auto-resolve datamartName if possible.\n let resolvedDatamartName = state.datamartName as string | undefined;\n const resolveAppId = (state.dataAppId || n.workspaceName) as string | undefined;\n if (!resolvedDatamartName && resolveAppId) {\n try {\n const datamarts = await services.datamartsApi.listDatamartsByDataAppId(resolveAppId);\n const names = Array.from(\n new Set(\n datamarts\n .map((dm) => dm.name || dm.datamartName)\n .filter((v): v is string => typeof v === 'string' && v.trim().length > 0),\n ),\n );\n if (names.length === 1) resolvedDatamartName = names[0];\n } catch {\n // Non-fatal; will be prompted in create_embed.\n }\n }\n\n return emit(\n 'READY',\n step,\n {\n ...state,\n dashboardId: n.dashboardId,\n embedType: 'dashboard',\n ...(n.workspaceName ? { workspaceName: n.workspaceName } : {}),\n ...(resolvedDatamartName ? { datamartName: resolvedDatamartName } : {}),\n },\n `Selected dashboard: \"${n.name}\" (${n.dashboardId}).${n.workspaceName ? ` workspaceName=${n.workspaceName}.` : ''}${resolvedDatamartName ? ` datamartName=${resolvedDatamartName}.` : ''} Proceeding to create embed.`,\n undefined,\n 'create_embed',\n );\n }\n\n // ── Step 7: Create embed (POST /api/v2/data-app/embeds) ──\n if (step === 'create_embed') {\n const choiceObj = parseUserChoiceObject(params.userChoice);\n const merged: Record<string, unknown> = {\n ...state,\n ...(choiceObj || {}),\n };\n\n const dashboardId = merged.dashboardId as string | undefined;\n const metricId = merged.metricId as string | undefined;\n let resolvedWorkspaceName = merged.workspaceName as string | undefined;\n const embedType =\n (merged.embedType as string | undefined)?.toLowerCase() === 'metric'\n ? 'metric' as const\n : 'dashboard' as const;\n const datamartName = merged.datamartName as string | undefined;\n const embedName =\n (merged.embedName as string | undefined) ||\n (embedType === 'dashboard' && dashboardId\n ? `embed-${dashboardId}`\n : embedType === 'metric' && metricId\n ? `embed-metric-${metricId}`\n : undefined);\n\n // Per API docs: workspaceName, dashboardId, embedType required.\n // accessSettings.datamartName required for dashboard embeds.\n // Try to resolve datamartName deterministically before prompting.\n let resolvedDatamartName = datamartName;\n let resolveAppId = merged.dataAppId as string | undefined;\n let availableDatamartNames: string[] = [];\n\n if (!resolveAppId) {\n const appName = merged.dataAppName as string | undefined;\n if (appName) {\n try {\n const apps = await services.dataAppsApi.listDataApps();\n const app = apps.find((a) => {\n const n = services.discoveryService.normalizeDataApp(a);\n return (\n n.name.toLowerCase() === appName.toLowerCase() ||\n (n.dataAppId || '').toLowerCase() === appName.toLowerCase()\n );\n });\n if (app) {\n resolveAppId =\n services.discoveryService.normalizeDataApp(app).dataAppId || undefined;\n }\n } catch {\n // Non-fatal; continue with best effort.\n }\n }\n }\n\n // Explicit dependency validation: selected dashboard must exist in selected data app context.\n if (embedType === 'dashboard' && dashboardId && (merged.dataAppName as string | undefined) && client.hasApiToken()) {\n try {\n const scopedDashboards = await services.dashboardsApi.listDashboards(\n merged.dataAppName as string | undefined,\n );\n const dashboardMatch = scopedDashboards.find((d) => {\n const n = services.discoveryService.normalizeDashboard(d);\n return (\n (n.dashboardId || '').toLowerCase() === dashboardId.toLowerCase()\n );\n });\n if (!dashboardMatch) {\n return emit(\n 'CHOICE_REQUIRED',\n step,\n merged,\n `dashboardId \"${dashboardId}\" is not available under data app \"${(merged.dataAppName as string) || 'unknown'}\". Re-run list_dashboards and choose from the current data app scope.`,\n [],\n 'list_dashboards',\n );\n }\n const dashboardNormalized = services.discoveryService.normalizeDashboard(dashboardMatch);\n if (dashboardNormalized.workspaceName) {\n if (resolvedWorkspaceName && resolvedWorkspaceName !== dashboardNormalized.workspaceName) {\n return emit(\n 'CHOICE_REQUIRED',\n step,\n merged,\n `workspaceName \"${resolvedWorkspaceName}\" does not match dashboard workspace \"${dashboardNormalized.workspaceName}\". Use the dashboard workspace.`,\n [\n {\n id: 'use_dashboard_workspace',\n label: dashboardNormalized.workspaceName,\n workspaceName: dashboardNormalized.workspaceName,\n },\n ],\n 'create_embed',\n );\n }\n resolvedWorkspaceName = dashboardNormalized.workspaceName;\n }\n } catch {\n // Non-fatal; missing-field validation below still applies.\n }\n }\n\n if (embedType === 'dashboard' && !resolvedDatamartName) {\n if (resolveAppId) {\n try {\n const datamarts = await services.datamartsApi.listDatamartsByDataAppId(\n resolveAppId,\n );\n const names = Array.from(\n new Set(\n datamarts\n .map((dm) => dm.name || dm.datamartName)\n .filter(\n (v): v is string => typeof v === 'string' && v.trim().length > 0,\n ),\n ),\n );\n availableDatamartNames = names;\n\n if (names.length === 1) {\n resolvedDatamartName = names[0];\n } else if (names.length > 1) {\n return emit(\n 'CHOICE_REQUIRED',\n step,\n merged,\n 'Multiple datamarts are available for this data app. Ask the user to select one for accessSettings.datamartName.',\n names.map((name) => ({\n id: name,\n label: name,\n datamartName: name,\n })),\n 'create_embed',\n );\n }\n } catch {\n // Non-fatal; fallback prompt below.\n }\n }\n }\n\n // Explicit dependency validation: datamartName must be one of available datamarts for this data app.\n if (\n embedType === 'dashboard' &&\n resolvedDatamartName &&\n resolveAppId &&\n availableDatamartNames.length === 0\n ) {\n try {\n const datamarts = await services.datamartsApi.listDatamartsByDataAppId(resolveAppId);\n availableDatamartNames = Array.from(\n new Set(\n datamarts\n .map((dm) => dm.name || dm.datamartName)\n .filter((v): v is string => typeof v === 'string' && v.trim().length > 0),\n ),\n );\n } catch {\n // Non-fatal.\n }\n }\n if (\n embedType === 'dashboard' &&\n resolvedDatamartName &&\n availableDatamartNames.length > 0 &&\n !availableDatamartNames.includes(resolvedDatamartName)\n ) {\n return emit(\n 'CHOICE_REQUIRED',\n step,\n merged,\n `datamartName \"${resolvedDatamartName}\" is invalid for this data app. Choose one of the available datamarts.`,\n availableDatamartNames.map((name) => ({\n id: name,\n label: name,\n datamartName: name,\n })),\n 'create_embed',\n );\n }\n\n const missing: string[] = [];\n if (!resolvedWorkspaceName) missing.push('workspaceName');\n if (!dashboardId) missing.push('dashboardId');\n if (embedType === 'metric' && !metricId) missing.push('metricId');\n if (embedType === 'dashboard' && !resolvedDatamartName) missing.push('datamartName');\n\n if (missing.length > 0) {\n return emit(\n 'CHOICE_REQUIRED',\n step,\n {\n ...merged,\n ...(resolvedDatamartName ? { datamartName: resolvedDatamartName } : {}),\n },\n `Missing required fields for embed creation: ${missing.join(', ')}. Provide via userChoice JSON.`,\n [\n {\n id: 'provide_fields',\n label: 'Provide JSON: {\"dashboardId\":\"...\",\"workspaceName\":\"...\",\"datamartName\":\"...\"}',\n },\n ],\n 'create_embed',\n );\n }\n\n const created = await services.embedService.createEmbedStrict({\n dashboardId,\n metricId,\n workspaceName: resolvedWorkspaceName,\n embedType,\n name: embedName,\n accessSettings: {\n datamartName: resolvedDatamartName,\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 });\n\n const embedId =\n (created.embedId as string | undefined) ||\n (created.id as string | undefined) ||\n (created._id as string | undefined) ||\n undefined;\n\n return emit(\n 'READY',\n step,\n { ...merged, embedType, embedId },\n `Embed created successfully${embedId ? ` (embedId: ${embedId})` : ''}. Next: run runtime readiness validation before finishing setup.`,\n undefined,\n 'runtime_readiness',\n );\n }\n\n // ── Step 8: Runtime readiness check ──────────────────────\n if (step === 'runtime_readiness') {\n const appName = state.dataAppName as string | undefined;\n if (!appName) {\n return toolError('state.dataAppName is required. Run discover_data_apps first.');\n }\n\n const choiceObj = parseUserChoiceObject(params.userChoice);\n const clientId =\n (choiceObj?.clientId as string | undefined) ||\n (state.clientId as string | undefined) ||\n 'None';\n const permissions: Record<string, unknown> = {\n isEnableManageMetrics: true,\n isEnableMetricUpdation: true,\n isEnableCustomizeLayout: true,\n isEnableCreateDashboardView: true,\n isDisableMetricCreation: false,\n ...((choiceObj?.permissions as Record<string, unknown> | undefined) || {}),\n };\n\n await services.guestTokenService.generateToken({\n clientId,\n dataAppName: appName,\n permissions,\n });\n\n return emit(\n 'DONE',\n step,\n {\n ...state,\n clientId,\n runtimeValidated: true,\n },\n 'Runtime contract validated by generating a guest token with top-level clientId/dataAppName/permissions. Next: run generate_embed_code and then continue with brand-my-embed or secure-my-embed as needed.',\n );\n }\n\n // ── Step 9: Complete ─────────────────────────────────────\n if (step === 'complete') {\n return emit(\n 'DONE',\n step,\n state,\n 'Setup complete. Recommended before handoff: run runtime_readiness. Then use brand-my-embed, secure-my-embed, setup-filters, or localize-embed prompts for further customization.',\n );\n }\n\n return toolError(`Unknown step: ${step}`);\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 { z } from 'zod';\nimport 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 { createServiceBundle } from '../../services/factory.js';\nimport { formatDatamart } from '../../utils/resolve-resource.js';\nimport { logger } from '../../utils/logger.js';\nimport { WRITE_CREATE } from '../annotations.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 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 if (!datamartName) {\n const datamarts = await services.datamartsApi.listDatamarts();\n if (!Array.isArray(datamarts) || datamarts.length === 0) {\n return toolError(\n 'No datamarts found. 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 (datamarts.length === 1) {\n datamartName = datamarts[0].name || datamarts[0].datamartName;\n } else {\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\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 = await services.queryApi.getSemanticLayer(\n datamartName,\n );\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 const table = formatDataTable(data, result.columns);\n\n const parts: string[] = [];\n parts.push(`## Query Results\\n`);\n parts.push(\n `**Question:** ${params.question}`,\n );\n parts.push(\n `**Suggested chart type:** ${result.suggestedChartType}`,\n );\n if (result.confidence !== null) {\n parts.push(\n `**Confidence:** ${Math.round(result.confidence * 100)}%`,\n );\n }\n parts.push(\n `**Rows returned:** ${data.length} | **Time:** ${result.timeTaken}ms`,\n );\n if (result.reasoning) {\n parts.push(`\\n### Reasoning\\n${result.reasoning}`);\n }\n if (result.summary) {\n parts.push(`\\n### Summary\\n${result.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 `\\n**Dimensions:** ${dims}\\n**Measures:** ${meas}`,\n );\n }\n if (result.sessionId) {\n parts.push(\n `\\n_Session ID for follow-up: \\`${result.sessionId}\\`_`,\n );\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}\n","import { z } from 'zod';\nimport 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 { createServiceBundle } from '../../services/factory.js';\nimport { resolveResource, formatDatamart } 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 = hasTables && result.tables.some(\n (t: any) =>\n t.description ||\n (t.columns ?? []).some(\n (c: any) => c.description || c.columnType,\n ),\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(\n `**Completion Score:** ${result.completionScore}%`,\n );\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 { z } from 'zod';\nimport 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 { createServiceBundle } from '../../services/factory.js';\nimport { resolveResource, formatDatamart } 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('Semantic column type. Use \"Identifier\" for IDs/foreign keys, \"Number\" for numeric values, \"String\" for text. Omit for date columns.'),\n});\n\nconst tableSchema = z.object({\n name: z.string().describe('Table name (must exist in the datamart)'),\n description: z\n .string()\n .optional()\n .describe(\n 'Business-friendly description of what this table represents',\n ),\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\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\n await services.queryApi.updateSemanticLayer({\n datamartName,\n tables: params.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 type { DatabrainClient } from '../client/databrain-client.js';\n\nimport { registerListDataApps } from './data-app/list-data-apps.js';\nimport { registerCreateDataApp } from './data-app/create-data-app.js';\nimport { registerListApiTokens } from './data-app/list-api-tokens.js';\nimport { registerCreateApiToken } from './data-app/create-api-token.js';\nimport { registerRotateApiToken } from './data-app/rotate-api-token.js';\n\n// Infrastructure tools (read-only + linking — creation tools delisted for V1)\nimport { registerListDatasources } from './infrastructure/list-datasources.js';\nimport { registerDiscoverDatasourceSchema } from './infrastructure/discover-datasource-schema.js';\nimport { registerListDatamarts } from './infrastructure/list-datamarts.js';\nimport { registerListWorkspaces } from './infrastructure/list-workspaces.js';\nimport { registerLinkDatamartToWorkspace } from './infrastructure/link-datamart-to-workspace.js';\n\n// Embed tools (consolidated)\nimport { registerCreateEmbed } from './embed/create-embed.js';\nimport { registerListEmbeds } from './embed/list-embeds.js';\nimport { registerGetEmbedDetails } from './embed/get-embed-details.js';\nimport { registerUpdateEmbed } from './embed/update-embed.js';\nimport { registerCustomizeTheme } from './embed/customize-theme.js';\nimport { registerConfigureEmbed } from './embed/configure-embed.js';\nimport { registerDiagnoseEmbedHealth } from './embed/diagnose-embed-health.js';\n\n// Frontend tools\nimport { registerGenerateGuestToken } from './frontend/generate-guest-token.js';\nimport { registerGenerateEmbedCode } from './frontend/generate-embed-code.js';\n\n// Analytics tools\nimport { registerListDashboards } from './analytics/list-dashboards.js';\nimport { registerSetupEmbedInteractive } from './orchestration/setup-embed-interactive.js';\n\n// Query tools\nimport { registerAskQuestion } from './query/ask-question.js';\nimport { registerGetSemanticLayer } from './query/get-semantic-layer.js';\nimport { registerUpdateSemanticLayer } from './query/update-semantic-layer.js';\n\nexport function registerAllTools(server: McpServer, client: DatabrainClient): void {\n // Infrastructure — exploration + linking (creation tools delisted for V1)\n registerListDatasources(server, client);\n registerDiscoverDatasourceSchema(server, client);\n registerListDatamarts(server, client);\n registerListWorkspaces(server, client);\n registerLinkDatamartToWorkspace(server, client);\n\n // Data app & token management\n registerListDataApps(server, client);\n registerCreateDataApp(server, client);\n registerListApiTokens(server, client);\n registerCreateApiToken(server, client);\n registerRotateApiToken(server, client);\n\n // Embed management and customization (consolidated)\n registerCreateEmbed(server, client);\n registerListEmbeds(server, client);\n registerGetEmbedDetails(server, client);\n registerUpdateEmbed(server, client);\n registerCustomizeTheme(server, client);\n registerConfigureEmbed(server, client);\n registerDiagnoseEmbedHealth(server, client);\n\n // Frontend\n registerGenerateGuestToken(server, client);\n registerGenerateEmbedCode(server, client);\n\n // Dashboard discovery\n registerListDashboards(server, client);\n registerSetupEmbedInteractive(server, client);\n\n // Query & semantic layer\n registerAskQuestion(server, client);\n registerGetSemanticLayer(server, client);\n registerUpdateSemanticLayer(server, client);\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 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 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 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","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# 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 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 \"Acme Corp\" (org_id = \"acme\") 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: 'acme', // Maps to org_id values in the database\n }),\n});\n\\`\\`\\`\n\nWhen a user from \"Globex\" (org_id = \"globex\") 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: 'globex',\n }),\n});\n\\`\\`\\`\n\n### Step 6: Render\n\nBoth users see the same dashboard layout and metrics, but:\n- Acme sees only their projects, tasks, and team members\n- Globex sees only their projects, tasks, and team members\n- Both see all task statuses (shared reference table)\n\n### Result\n\n\\`\\`\\`\nAcme User sees:\n - 12 projects (all with org_id = 'acme')\n - 87 tasks\n - 15 team members\n\nGlobex User sees:\n - 8 projects (all with org_id = 'globex')\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 useCaseGuidesContent = `# Databrain Use Case Guides\n\nDatabrain supports 4 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: Enable Metric Creation\n**When to use:** You want end-users to build their own metrics/charts on embedded dashboards.\n**Prompt:** \\`enable-metric-creation\\`\n**Two modes:**\n- **DRAG_DROP:** Visual metric builder — users drag columns, pick chart types. No AI needed.\n- **CHAT:** AI-powered natural language — users type questions. Requires LLM connector in Databrain admin.\n**Tool sequence:** \\`list_embeds\\` → \\`update_embed\\` (set accessSettings) → \\`configure_embed\\` → \\`generate_guest_token\\` (with permissions)\n\n## Use Case 4: 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 these prompts to customize:\n\n| Prompt | Purpose |\n|--------|---------|\n| \\`brand-my-embed\\` | Colors, fonts, chart styles, theme presets |\n| \\`setup-filters\\` | String, date, number, SQL, and server-side filters |\n| \\`localize-embed\\` | Multi-language support and locale settings |\n| \\`secure-my-embed\\` | Permissions, access controls, role-based tokens |\n| \\`manage-embeds\\` | List, compare, and manage existing embeds |\n| \\`query-data\\` | Natural language querying and semantic layer management |\n| \\`populate-semantic-layer\\` | Auto-generate table/column descriptions for AI features |\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| Do you want end-users to create metrics? | Yes → Use Case 3 |\n| Want to explore or query your data? | Yes → Use Case 4 |\n| Just need to brand/filter/secure? | Use customization prompts |\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","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { gettingStartedContent } from './content/getting-started.js';\nimport { apiReferenceContent } from './content/api-reference.js';\nimport { embeddingGuideContent } from './content/embedding-guide.js';\nimport { filterReferenceContent } from './content/filter-reference.js';\nimport { themeReferenceContent } from './content/theme-reference.js';\nimport { webComponentReferenceContent } from './content/web-component-reference.js';\nimport { selfServeReferenceContent } from './content/self-serve-reference.js';\nimport { semanticLayerGuideContent } from './content/semantic-layer-guide.js';\nimport { multiTenancyGuideContent } from './content/multi-tenancy-guide.js';\nimport { useCaseGuidesContent } from './content/use-case-guides.js';\nimport { permissionSchemaContent } from './content/permission-schema.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: '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: '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: '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: '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: '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: '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: '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: '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: '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: 'Summary of 4 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: '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(res.name, res.uri, { description: res.description }, async () => ({\n contents: [\n {\n uri: res.uri,\n mimeType: 'text/markdown',\n text: res.content,\n },\n ],\n }));\n }\n}\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\\` and \\`diagnose_embed_health\\` 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\\`, \\`setup-filters\\`, \\`localize-embed\\`, \\`secure-my-embed\\`.`;\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\\`, \\`setup-filters\\`, \\`enable-metric-creation\\`, \\`secure-my-embed\\`.`;\n","export const enableMetricCreationPrompt = `You are helping the user enable end-user metric creation on their embedded dashboards. Databrain supports two modes: DRAG_DROP (visual builder) and CHAT (AI-powered natural language).\n\n**CRITICAL: This is an interactive guide. You MUST stop and ask the user at each decision point before proceeding. Never assume answers.**\n\n**Two Metric Creation Modes:**\n- **DRAG_DROP**: Visual metric builder where users drag columns, choose chart types, and configure metrics. No AI needed.\n- **CHAT**: AI-powered natural language metric creation. Users type questions like \"Show me revenue by month\" and Databrain generates the metric. Requires an LLM connector configured in the Databrain admin panel.\n\n**Step 1 — Identify the Embed**\nCall \\`list_embeds\\` to show available embeds.\nSTOP and ASK the user: \"Which embed do you want to enable metric creation on?\"\nOnly after they answer, call \\`get_embed_details\\` to see current access settings.\n\n**Step 2 — Choose the Mode**\nSTOP and ASK the user:\n- \"Which metric creation mode do you want?\"\n - **DRAG_DROP**: Visual builder, no AI dependency\n - **CHAT**: AI-powered, requires LLM connector setup in Databrain admin\nDo NOT proceed until the user picks a mode.\n\nIf they choose CHAT, tell them: \"CHAT mode requires an LLM connector configured in the Databrain admin panel (Settings > AI Configuration). Have you set this up?\"\n\n**Step 3 — Update Embed Access Settings**\nCall \\`update_embed\\` with the embed ID and updated \\`accessSettings\\`:\n\nFor DRAG_DROP mode:\n\\`\\`\\`json\n{\n \"accessSettings\": {\n \"isAllowMetricCreation\": true,\n \"metricCreationMode\": \"DRAG_DROP\"\n }\n}\n\\`\\`\\`\n\nFor CHAT mode:\n\\`\\`\\`json\n{\n \"accessSettings\": {\n \"isAllowMetricCreation\": true,\n \"metricCreationMode\": \"CHAT\"\n }\n}\n\\`\\`\\`\n\n**Step 4 — Configure Embed Options**\nCall \\`configure_embed\\` to ensure the UI supports metric creation:\n- \\`disableMetricCreation\\`: false\n- \\`hideCreateMetricButton\\`: false\n- \\`hideChartSettings\\`: false (so users can customize their created metrics)\n\n**Step 5 — Set Guest Token Permissions**\nRemind the user: guest token \\`permissions\\` override embed \\`accessSettings\\` at runtime. When generating guest tokens via \\`generate_guest_token\\`, include:\n\\`\\`\\`json\n{\n \"permissions\": {\n \"isDisableMetricCreation\": false\n }\n}\n\\`\\`\\`\n\n**Step 6 — Verify and Test**\nCall \\`get_embed_details\\` to verify the settings were applied correctly.\nTell the user to refresh their embed and look for the \"+ Create Metric\" button.\n\nIf using CHAT mode, remind the user:\n- An LLM connector must be configured in Databrain admin (Settings > AI Configuration)\n- The datamart should have a populated semantic layer for best AI results (use \\`get_semantic_layer\\` to check, and \\`update_semantic_layer\\` or the \\`populate-semantic-layer\\` prompt to populate it)\n\n**Important rules:**\n- STOP and ASK at each decision point. Never skip ahead.\n- Guest token \\`permissions\\` take precedence over embed \\`accessSettings\\` — both must allow metric creation.\n- CHAT mode requires external LLM connector setup (not available via MCP).\n- After enabling, suggest: \\`secure-my-embed\\` to fine-tune which users get metric creation access.`;\n","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 \\`configure_embed\\` 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 localizeEmbedPrompt = `You are helping the user set up multi-language support for their embedded Databrain dashboard. Follow these steps.\n\n**Step 1 — Identify the Embed and Target Languages**\nCall \\`list_embeds\\` and ask the user which embed to localize. Then ask:\n- Which languages do they need? (Supported: English, French, Spanish, German, Italian, Portuguese, Chinese, Japanese, Korean, Hindi, Arabic, Russian)\n- What is the default/primary language?\n\n**Step 2 — Set the Primary Language**\nUse \\`configure_embed\\` with the \\`language\\` parameter set to their primary language code (e.g. \"fr\" for French).\n\n**Step 3 — Gather Translations**\nCall \\`get_embed_details\\` to understand what text is in the dashboard. Then help the user build translations:\n\nAsk the user to list the key text elements in their dashboard:\n- Dashboard title\n- Metric titles and descriptions\n- Filter labels\n- Any footnotes or annotations\n\nFor each text element, ask for translations in their target languages. Build translation entries like:\n\\`\\`\\`\n{ key: \"Revenue\", translations: { fr: \"Revenus\", es: \"Ingresos\", de: \"Einnahmen\" } }\n\\`\\`\\`\n\n**Important rules for translation keys:**\n- Keys must match the dashboard text EXACTLY (case-sensitive)\n- Define longer keys before shorter ones to avoid partial matches\n- If a translation is missing for a language, the original key text is shown as fallback\n\n**Step 4 — Apply Translations**\nUse \\`configure_embed\\` with the \\`translations\\` array containing all entries.\n\n**Step 5 — Configure Calendar (if needed)**\nAsk if they need a different calendar system:\n- \\`\"default\"\\` — standard Gregorian calendar\n- \\`\"ind\"\\` — Indian calendar format\n\nSet via \\`calendarType\\` in \\`configure_embed\\` (\\`language\\` and \\`calendarType\\` params).\n\n**Step 6 — Set Custom Messages**\nAsk if they want to translate system messages:\n- Token expiry message (shown when session expires)\n- Token absent message (shown when no auth token)\n\nUse \\`configure_embed\\` with \\`tokenExpiryMessage\\` and \\`tokenAbsentMessage\\` in their primary language.\n\n**Step 7 — Test**\nTell the user to refresh the embed and verify translations appear correctly. If any text isn't translating, double-check that the key matches exactly.\n\nRemind the user: translations can also be applied per-user at the web component level using the \\`translation-dictionary\\` attribute, which is useful for dynamically switching languages based on user preferences.\n\n**Tip:** The \\`language\\`, \\`calendarType\\`, \\`hideDashboardFilters\\`, and filter settings are all available in the same \\`configure_embed\\` tool.\n\n**Important:** After changing language or translation settings, 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","export const secureMyEmbedPrompt = `You are helping the user secure and configure permissions for their embedded Databrain dashboard. Follow these steps.\n\n**Step 1 — Understand User Roles**\nAsk the user about their end-user roles. Common patterns:\n- **Viewer** — can see data, maybe filter, but can't modify anything\n- **Analyst** — can export data, drill down, use filters\n- **Builder/Power User** — can create/edit metrics, change layouts\n- **Admin** — full access including AI features\n\nAsk: \"What roles do your end-users have? What should each role be allowed to do?\"\n\n**Step 2 — Lock Down the Embed Defaults**\nUse \\`configure_embed\\` to set restrictive defaults (principle of least privilege):\n\n\\`\\`\\`\nconfigure_embed(embedId,\n disableMetricCreation: true,\n disableMetricUpdation: true,\n disableMetricDeletion: true,\n disableManageMetrics: true,\n disableLayoutCustomization: true,\n disableSaveLayout: true,\n disableUnderlyingData: true,\n disableScheduleEmailReports: true,\n enableDownloadCsv: false,\n enableDownloadAllPdf: false)\n\\`\\`\\`\n\nExplain: \"We start with everything locked down, then use guest token permissions to grant access per role.\"\n\n**Step 3 — Create Role-Based Guest Token Examples**\nShow the user how to generate tokens for each role:\n\n**Viewer (default — no overrides needed):**\n\\`\\`\\`\ngenerate_guest_token(clientId, dataAppName)\n\\`\\`\\`\n\n**Analyst (can export and drill down):**\n\\`\\`\\`\ngenerate_guest_token(clientId, dataAppName, {\n permissions: {\n isEnableDownloadMetrics: true,\n isEnableUnderlyingData: true\n }\n})\n\\`\\`\\`\n\n**Builder (can create and edit):**\n\\`\\`\\`\ngenerate_guest_token(clientId, dataAppName, {\n permissions: {\n isEnableManageMetrics: true,\n isEnableMetricUpdation: true,\n isEnableCustomizeLayout: true\n }\n})\n\\`\\`\\`\n\n**Admin (full access with AI):**\n\\`\\`\\`\ngenerate_guest_token(clientId, dataAppName, {\n permissions: {\n isEnableManageMetrics: true,\n isEnableMetricUpdation: true,\n isEnableCustomizeLayout: true,\n isEnableDownloadMetrics: true,\n isEnableUnderlyingData: true\n }\n})\n\\`\\`\\`\n\n**Step 4 — Multi-Tenancy Check**\nAsk: \"Do different customers/organizations see different data?\"\n\nIf yes:\n- Explain that \\`clientId\\` in the guest token controls row-level security\n- The \\`clientId\\` must match values in the datamart's client column\n- Suggest using \\`params.appFilters\\` / \\`params.dashboardAppFilters\\` in \\`generate_guest_token\\` for server-side row-level filtering\n\n**Step 5 — Security Checklist**\nWalk through this checklist with the user:\n\n1. ✅ API token is stored server-side only (never in frontend code)\n2. ✅ Guest tokens are generated server-side per request\n3. ✅ Guest tokens have appropriate expiry time\n4. ✅ Embed defaults are restrictive (locked down in Step 2)\n5. ✅ Role-based permissions are granted via guest token overrides\n6. ✅ Multi-tenancy is configured if serving multiple customers\n7. ✅ Download restrictions are set (\\`disableDownloadDataNoFilters\\` if needed)\n\n**Step 6 — Generate Secure Frontend Code**\nCall \\`generate_embed_code\\` for their framework. Emphasize that the generated code includes a backend route for token generation — this is the secure pattern.\n\nWhen reviewing runtime behavior (for example missing \\`+ Create Metric\\`), verify contract shape explicitly:\n- Guest token request body must send \\`permissions\\` at top level (not nested inside \\`params\\`)\n- Include \\`dataAppName\\` at top level\n- For metric creation flows, ensure \\`permissions.isDisableMetricCreation=false\\` and \\`permissions.isEnableManageMetrics=true\\`\n- Confirm embed options do not set \\`disableMetricCreation=true\\`\n- In browser network response for \\`/api/v2/dashboard\\`, confirm \\`isAllowedToCreateMetrics=true\\` and \\`metricCreationMode=DRAG_DROP\\`\n\n**Important:** After changing embed permissions or access settings, 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://self-serve-reference\\` for all permission flags and \\`databrain://multi-tenancy-guide\\` for row-level security details.`;\n","export const setupFiltersPrompt = `You are helping the user configure dashboard filters for their embedded Databrain dashboard. Follow these steps.\n\n**Step 1 — Understand the Data**\nCall \\`list_embeds\\` and ask which embed to configure. Then call \\`get_embed_details\\` to see the current filter configuration.\n\n**Step 2 — Identify Filter Needs**\nAsk the user:\n- \"What filters do your end-users need?\" (e.g. date range, region, product category, status)\n- \"Should any filters have default values?\"\n- \"Are there filters you want to hide from end-users?\" (e.g. internal IDs)\n- \"Do any filters have very large option lists?\" (100+ options — these benefit from SQL-based filters)\n\n**Step 3 — Configure String Filters**\nFor text/category filters, use \\`configure_embed\\` with \\`stringFilters\\`:\n\n\\`\\`\\`\nstringFilters: [{\n filterName: \"Region\",\n options: [\n { value: \"US\", label: \"United States\" },\n { value: \"EU\", label: \"Europe\" },\n { value: \"APAC\", label: \"Asia Pacific\" }\n ],\n defaultOption: \"US\"\n}]\n\\`\\`\\`\n\nFor multi-select defaults, use an array: \\`defaultOption: [\"US\", \"EU\"]\\`\n\n**Step 4 — Configure Date Filters**\nFor date range filters, use \\`dateFilters\\`:\n\n\\`\\`\\`\ndateFilters: [{\n filterName: \"Date Range\",\n startDate: \"2024-01-01\",\n endDate: \"2024-12-31\",\n datePresetOptions: [\n { label: \"Last 30 Days\", type: \"Last\", interval: \"Days\" },\n { label: \"This Quarter\", type: \"This\", interval: \"Quarter\" },\n { label: \"This Year\", type: \"This\", interval: \"Year\" }\n ]\n}]\n\\`\\`\\`\n\n**Step 5 — Configure Number Filters**\nFor numeric range filters, use \\`numberFilters\\`:\n\n\\`\\`\\`\nnumberFilters: [{\n filterName: \"Revenue\",\n min: 0,\n max: 1000000\n}]\n\\`\\`\\`\n\n**Step 6 — SQL-Based Filters (for large datasets)**\nIf a filter has 100+ options (e.g. company names, product SKUs), use \\`sqlFilters\\`:\n\n\\`\\`\\`\nsqlFilters: [{\n filterName: \"Company\",\n sql: \"SELECT DISTINCT \\\\\"company_name\\\\\" FROM \\\\\"companies\\\\\" ORDER BY \\\\\"company_name\\\\\"\",\n columnName: \"company_name\"\n}]\n\\`\\`\\`\n\nExplain: \"SQL filters dynamically fetch options from the database, so they're always up-to-date and don't bloat the embed configuration.\"\n\n**Step 7 — Hide Unnecessary Filters**\nIf the user has filters that should be hidden (e.g. internal IDs, tenant columns already handled by clientId):\n\n\\`\\`\\`\nhideDashboardFilters: [\"internal_id\", \"tenant_id\"]\n\\`\\`\\`\n\n**Step 8 — Configure Date Picker Options**\nAsk if they want to hide certain date picker presets:\n\n\\`\\`\\`\nhideDatePickerOptions: [\"yesterday\", \"last week\"]\n\\`\\`\\`\n\n**Step 9 — Metric Filter Position**\nAsk: \"Do you want metric-level filters inside the card or outside?\"\n- \\`\"inside\"\\` — compact, within each metric card (default)\n- \\`\"outside\"\\` — above the card, more prominent\n\nAlso ask if they want cross-metric filtering (\\`enableMultiMetricFilters\\`).\n\n**Step 10 — Server-Side Filters (via Guest Token)**\nIf the user needs filters that end-users cannot remove (e.g. for security):\n- Explain that \\`appFilters\\` in \\`generate_guest_token\\` are server-side enforced\n- These are invisible to the end-user and cannot be overridden\n- Perfect for tenant filtering, role-based data access, or compliance requirements\n\nShow an example:\n\\`\\`\\`\ngenerate_guest_token(clientId, dataAppName, {\n params: {\n appFilters: [{\n metricId: \"metric_123\",\n values: {\n region: [\"US\", \"CA\"]\n }\n }]\n }\n})\n\\`\\`\\`\n\n**Important:** After changing filter settings, 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://filter-reference\\` for all filter types, operators, and combination rules.`;\n","export const manageEmbedsPrompt = `You are helping the user manage Databrain embed configurations — list, compare, and review settings. Follow these steps based on what the user needs.\n\n**Step 1 — Understand the Task**\nAsk the user what they want to do:\n1. **List and compare embeds** — see all embeds and their configurations\n2. **Review embed settings** — audit theme, permissions, and options\n\n**For Listing and Comparing Embeds:**\n1. Call \\`list_embeds\\` to show all embed configurations\n2. For detailed comparison, call \\`get_embed_details\\` on each embed the user wants to compare\n3. Present a comparison table showing:\n - Embed name and ID\n - Linked dashboard\n - Theme (preset or custom)\n - Key permissions (metric creation, downloads, AI pilot)\n - Multi-tenancy settings\n\n**For Reviewing Embed Settings:**\n1. Call \\`get_embed_details\\` for the embed\n2. Present a clear summary organized by category:\n\n **Theme:**\n - Current preset or custom theme values\n - Suggest \\`customize_embed_theme\\` if they want changes\n\n **Permissions / Access Settings:**\n - What's enabled vs disabled\n - Suggest \\`configure_embed\\` for changes\n\n **Filters:**\n - Current filter configuration\n - Suggest \\`configure_embed\\` with filter params for changes\n\n **Internationalization:**\n - Current language and translations\n - Suggest \\`configure_embed\\` with \\`language\\` and \\`translations\\` params for changes\n\n3. Ask: \"Would you like to modify any of these settings?\"\n\n**Tips:**\n- Embed IDs are permanent — even if you rename an embed, the ID stays the same\n- After any embed setting changes, existing guest tokens still carry the old configuration — **regenerate guest tokens** for changes to take effect`;\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**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 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**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:** Set semantic types when obvious: \"Date\", \"Number\", \"Identifier\", \"Category\", \"Currency\", \"Email\", \"Name\", etc.\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","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { embedExistingDashboardPrompt } from './embed-existing-dashboard.js';\nimport { embedBlankDashboardPrompt } from './embed-blank-dashboard.js';\nimport { enableMetricCreationPrompt } from './enable-metric-creation.js';\nimport { brandMyEmbedPrompt } from './brand-my-embed.js';\nimport { localizeEmbedPrompt } from './localize-embed.js';\nimport { secureMyEmbedPrompt } from './secure-my-embed.js';\nimport { setupFiltersPrompt } from './setup-filters.js';\nimport { manageEmbedsPrompt } from './manage-embeds.js';\nimport { queryDataPrompt } from './query-data.js';\nimport { populateSemanticLayerPrompt } from './populate-semantic-layer.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: '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: 'Multi-tenant blank dashboard setup: each client gets their own dashboard copy via create_embed with clientId',\n content: embedBlankDashboardPrompt,\n },\n {\n name: 'enable-metric-creation',\n description: 'Enable end-user metric creation on embeds: DRAG_DROP (visual) or CHAT (AI-powered) modes',\n content: enableMetricCreationPrompt,\n },\n {\n name: 'brand-my-embed',\n description: 'Customize colors, fonts, chart styles, and component theme to match your brand',\n content: brandMyEmbedPrompt,\n },\n {\n name: 'localize-embed',\n description: 'Set up multi-language support with translations and locale settings',\n content: localizeEmbedPrompt,\n },\n {\n name: 'secure-my-embed',\n description: 'Configure permissions, access controls, and role-based guest tokens',\n content: secureMyEmbedPrompt,\n },\n {\n name: 'setup-filters',\n description: 'Configure dashboard filters: string, date, number, SQL-based, and server-side filters',\n content: setupFiltersPrompt,\n },\n {\n name: 'manage-embeds',\n description: 'List, compare, rename, delete embeds and rotate API tokens',\n content: manageEmbedsPrompt,\n },\n {\n name: 'query-data',\n description: '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: 'Auto-generate and push table/column descriptions to enable natural language querying on a datamart',\n content: populateSemanticLayerPrompt,\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"],"mappings":"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AAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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,sBAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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,+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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACArC,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;;;ACAlC,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,uBAAuB;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;;;ACAnC,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,sBAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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,sBAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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,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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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,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;;;ACA3B,IAAM,kBAAkB;AAAA;AAAA;AAAA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","names":["z","isNonEmptyString","z","z","z","z","z","z","z","z","z","key","z","z","z","z","z","z","z","DEFAULT_ACCESS_SETTINGS","z","body","result","embedId","z","z","z","z","z","z","result","z","z","z","z","z","asRecord","z","z","z","result","z","kebabCase","buildAttributes","kebabCase","buildAttributes","kebabCase","buildAttributes","kebabCase","buildAttributes","kebabCase","buildAttributes","kebabCase","buildAttributes","z","z","z","z","z","dashboards","n","z","z","z","z","z","z"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/utils/config.ts","../src/server.ts","../src/utils/cache.ts","../src/utils/errors.ts","../src/utils/logger.ts","../src/client/databrain-client.ts","../src/tools/data-app/list-data-apps.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/workspaces-api.ts","../src/services/discovery-service.ts","../src/services/embed-service.ts","../src/services/guest-token-service.ts","../src/services/factory.ts","../src/tools/annotations.ts","../src/tools/data-app/create-data-app.ts","../src/tools/data-app/list-api-tokens.ts","../src/utils/resolve-resource.ts","../src/tools/data-app/create-api-token.ts","../src/tools/data-app/rotate-api-token.ts","../src/tools/infrastructure/list-datasources.ts","../src/tools/infrastructure/discover-datasource-schema.ts","../src/tools/infrastructure/list-datamarts.ts","../src/tools/infrastructure/list-workspaces.ts","../src/tools/infrastructure/link-datamart-to-workspace.ts","../src/tools/embed/create-embed.ts","../src/tools/embed/list-embeds.ts","../src/tools/embed/get-embed-details.ts","../src/tools/embed/update-embed.ts","../src/tools/embed/helpers.ts","../src/tools/embed/customize-theme.ts","../src/tools/frontend/generate-guest-token.ts","../src/tools/frontend/generate-embed-code.ts","../src/templates/react.ts","../src/templates/nextjs.ts","../src/templates/vue.ts","../src/templates/angular.ts","../src/templates/svelte.ts","../src/templates/solidjs.ts","../src/templates/vanilla.ts","../src/templates/index.ts","../src/tools/analytics/list-dashboards.ts","../src/tools/query/ask-question.ts","../src/tools/query/get-semantic-layer.ts","../src/tools/query/update-semantic-layer.ts","../src/tools/registry.ts","../src/resources/content/getting-started.ts","../src/resources/content/api-reference.ts","../src/resources/content/embedding-guide.ts","../src/resources/content/filter-reference.ts","../src/resources/content/theme-reference.ts","../src/resources/content/web-component-reference.ts","../src/resources/content/self-serve-reference.ts","../src/resources/content/semantic-layer-guide.ts","../src/resources/content/multi-tenancy-guide.ts","../src/resources/content/use-case-guides.ts","../src/resources/content/permission-schema.ts","../src/resources/registry.ts","../src/prompts/embed-existing-dashboard.ts","../src/prompts/embed-blank-dashboard.ts","../src/prompts/enable-metric-creation.ts","../src/prompts/brand-my-embed.ts","../src/prompts/localize-embed.ts","../src/prompts/secure-my-embed.ts","../src/prompts/setup-filters.ts","../src/prompts/manage-embeds.ts","../src/prompts/query-data.ts","../src/prompts/populate-semantic-layer.ts","../src/prompts/registry.ts"],"sourcesContent":["import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { loadConfig } from './utils/config.js';\nimport { createServer } from './server.js';\nimport { logger } from './utils/logger.js';\n\nconst VERSION = '0.2.0';\n\nfunction banner(msg: string): void {\n process.stderr.write(`[databrain] ${msg}\\n`);\n}\n\nasync function main(): Promise<void> {\n try {\n const config = loadConfig();\n const server = createServer(config);\n const transport = new StdioServerTransport();\n\n await server.connect(transport);\n banner(`v${VERSION} ready (24 tools, 11 resources, 10 prompts)`);\n } catch (error) {\n logger.error('Failed to start server', error);\n process.exit(1);\n }\n}\n\nmain();\n","import { z, ZodError } from 'zod';\n\nconst configSchema = z\n .object({\n serviceToken: z.string().min(1).optional(),\n apiToken: z.string().min(1).optional(),\n apiUrl: z.string().url().default('https://api.usedatabrain.com'),\n })\n .refine((c) => c.serviceToken || c.apiToken, {\n message:\n 'At least one of DATABRAIN_SERVICE_TOKEN or DATABRAIN_API_TOKEN must be set',\n });\n\nexport type Config = z.infer<typeof configSchema>;\n\nfunction formatConfigError(err: ZodError): string {\n const issues = err.issues.map((i) => i.message);\n const lines = ['[databrain] Configuration error:'];\n for (const issue of issues) {\n lines.push(` - ${issue}`);\n }\n lines.push('');\n lines.push(' Get a service token at Settings > Service Tokens in your Databrain dashboard.');\n lines.push(' Then add to your MCP config: { \"env\": { \"DATABRAIN_SERVICE_TOKEN\": \"...\" } }');\n return lines.join('\\n');\n}\n\nexport function loadConfig(): Config {\n try {\n return configSchema.parse({\n serviceToken: process.env.DATABRAIN_SERVICE_TOKEN || undefined,\n apiToken: process.env.DATABRAIN_API_TOKEN || undefined,\n apiUrl:\n process.env.DATABRAIN_API_URL || 'https://api.usedatabrain.com',\n });\n } catch (err) {\n if (err instanceof ZodError) {\n process.stderr.write(formatConfigError(err) + '\\n');\n }\n throw err;\n }\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { DatabrainClient } from './client/databrain-client.js';\nimport type { Config } from './utils/config.js';\nimport { registerAllTools } from './tools/registry.js';\nimport { registerAllResources } from './resources/registry.js';\nimport { registerAllPrompts } from './prompts/registry.js';\n\nexport function createServer(config: Config): McpServer {\n const server = new McpServer(\n {\n name: 'databrain',\n version: '0.1.0',\n description:\n 'Databrain MCP Server — embed analytics dashboards and charts into your app. Focused on embed discovery, deterministic embed updates, theming, filters, localization, permissions, and guest token generation.',\n },\n {\n instructions:\n 'Databrain uses two token types — never confuse them:\\n' +\n '• SERVICE TOKEN (DATABRAIN_SERVICE_TOKEN): org-level, pre-configured in MCP server config. Used for: list_datasources, discover_datasource_schema, list_datamarts, list_workspaces, link_datamart_to_workspace, list_data_apps, create_data_app, list_api_tokens, create_api_token, rotate_api_token, list_dashboards (workspace scope), ask_question, get_semantic_layer, update_semantic_layer. You already have this — never ask the user for it.\\n' +\n '• API TOKEN (per data app): scoped to one data app, used for embedding operations (list_embeds, get_embed_details, create_embed, update_embed, generate_guest_token) and data-app scoped dashboard listing. Created/rotated via create_api_token or rotate_api_token during setup.\\n\\n' +\n '4 core use cases — match the user\\'s scenario to the right prompt:\\n' +\n '1. Embed existing dashboard → prompt: embed-existing-dashboard (list_data_apps → create_api_token → list_dashboards → create_embed → generate_guest_token → generate_embed_code)\\n' +\n '2. Blank dashboard per client → prompt: embed-blank-dashboard (list_data_apps → list_datamarts → create_embed with clientId per client → generate_guest_token → generate_embed_code)\\n' +\n '3. Enable metric creation → prompt: enable-metric-creation (list_embeds → update_embed accessSettings → generate_guest_token with permissions)\\n' +\n '4. Explore & query data → prompt: query-data (list_datamarts → get_semantic_layer → if empty, auto-generate descriptions with update_semantic_layer or use populate-semantic-layer prompt → ask_question)\\n\\n' +\n 'Infrastructure CREATION (datasources, datamarts, workspaces) is done in the Databrain UI.\\n' +\n 'However, the **semantic layer** is populated and maintained entirely via MCP tools (get_semantic_layer, update_semantic_layer). When the semantic layer is empty, YOU (the assistant) should auto-generate descriptions from table/column names and push them with update_semantic_layer — do NOT send the user to the UI for this.\\n\\n' +\n 'After embed setup, customize with: brand-my-embed, setup-filters, localize-embed, secure-my-embed.\\n' +\n 'Use generate_guest_token for frontend auth and generate_embed_code for framework snippets.\\n' +\n 'For advanced embed configuration (UI toggles, filters, i18n), use update_embed with a body passthrough.\\n' +\n 'To diagnose embed issues, use get_embed_details and reason about the response.\\n' +\n 'Do NOT ask the user for any tokens — manage them via MCP tools.\\n\\n' +\n 'IMPORTANT — accessSettings defaults:\\n' +\n 'When calling create_embed, only pass accessSettings: { datamartName: \"...\" } plus any flags the user explicitly wants enabled. For multi-tenant dashboard embeds, also pass clientId. The tool auto-fills all required isAllow* fields with secure defaults (all false). Do NOT guess or enumerate accessSettings fields.\\n\\n' +\n 'IMPORTANT — create_data_app does NOT accept workspaceName. Only pass { name: \"...\" }.\\n\\n' +\n 'IMPORTANT — Be interactive. Present results from each tool call and ask the user before proceeding to the next step. Never batch multiple mutating operations without user confirmation.\\n' +\n 'Trigger keywords: embed, dashboard, analytics, Databrain, guest token, theme, filters, permissions, datasource, datamart, workspace, metric creation.',\n },\n );\n\n const client = new DatabrainClient(config);\n\n registerAllTools(server, client);\n registerAllResources(server);\n registerAllPrompts(server);\n\n return server;\n}\n","interface CacheEntry<T> {\n value: T;\n expiresAt: number;\n}\n\nexport class TtlCache {\n private store = new Map<string, CacheEntry<unknown>>();\n\n get<T>(key: string): T | undefined {\n const entry = this.store.get(key);\n if (!entry) return undefined;\n if (Date.now() > entry.expiresAt) {\n this.store.delete(key);\n return undefined;\n }\n return entry.value as T;\n }\n\n set<T>(key: string, value: T, ttlMs: number): void {\n this.store.set(key, { value, expiresAt: Date.now() + ttlMs });\n }\n\n invalidateByPrefix(prefix: string): void {\n for (const key of this.store.keys()) {\n if (key.startsWith(prefix)) {\n this.store.delete(key);\n }\n }\n }\n\n clear(): void {\n this.store.clear();\n }\n}\n","export class DatabrainApiError extends Error {\n constructor(\n public readonly status: number,\n public readonly code: string,\n message: string,\n public readonly details?: unknown,\n ) {\n super(message);\n this.name = 'DatabrainApiError';\n }\n\n toToolResponse(): { content: Array<{ type: 'text'; text: string }>; isError: true } {\n return {\n content: [{ type: 'text', text: `Error: ${this.message}\\n\\n${this.hint()}` }],\n isError: true,\n };\n }\n\n private hint(): string {\n if (this.status === 401 || this.status === 403) {\n if (\n this.code === 'INVALID_SERVICE_TOKEN' ||\n this.code === 'MISSING_SERVICE_TOKEN' ||\n this.message.toLowerCase().includes('service token')\n ) {\n return 'Hint: The service token (DATABRAIN_SERVICE_TOKEN) is invalid, expired, or missing. It must be set in the MCP server config (not at runtime). Check Settings > Service Tokens in the Databrain UI.';\n }\n return 'Hint: The per-data-app API token is invalid or expired. Use `create_api_token` to generate a new one. Do not ask the user — manage tokens via MCP tools.';\n }\n if (this.status === 400) {\n return 'Hint: The request was invalid. Check parameter values match expected types and formats. Use the corresponding list tool to verify IDs and names.';\n }\n if (this.status === 404) {\n return 'Hint: The requested resource was not found. Verify the ID or name is correct using the corresponding list tool.';\n }\n if (this.status === 409) {\n return 'Hint: A resource with this name already exists. Use a different name or list existing resources first.';\n }\n if (this.status === 422) {\n return 'Hint: The request parameters are invalid. Check the required fields and their formats.';\n }\n if (this.status === 429) {\n return 'Hint: API rate limit reached. Wait a moment and try again.';\n }\n if (this.status >= 500) {\n return 'Hint: The Databrain API is experiencing issues. Try again in a few moments.';\n }\n return '';\n }\n}\n\nexport function toolError(message: string): { content: Array<{ type: 'text'; text: string }>; isError: true } {\n return {\n content: [{ type: 'text', text: message }],\n isError: true,\n };\n}\n\nexport function stringify(value: unknown): string {\n if (typeof value === 'string') return value;\n try {\n return JSON.stringify(value, null, 2);\n } catch {\n return String(value);\n }\n}\n\nexport function toolSuccess(text: string): { content: Array<{ type: 'text'; text: string }> } {\n return {\n content: [{ type: 'text', text }],\n };\n}\n","const LOG_LEVELS = { debug: 0, info: 1, warn: 2, error: 3 } as const;\ntype LogLevel = keyof typeof LOG_LEVELS;\n\nconst currentLevel: LogLevel =\n (process.env.DATABRAIN_LOG_LEVEL as LogLevel) || 'warn';\n\nfunction log(level: LogLevel, message: string, data?: unknown): void {\n if (LOG_LEVELS[level] < LOG_LEVELS[currentLevel]) return;\n const line = `[databrain-mcp] [${level.toUpperCase()}] ${message}`;\n if (data !== undefined) {\n process.stderr.write(`${line} ${JSON.stringify(data)}\\n`);\n } else {\n process.stderr.write(`${line}\\n`);\n }\n}\n\nexport const logger = {\n debug: (msg: string, data?: unknown) => log('debug', msg, data),\n info: (msg: string, data?: unknown) => log('info', msg, data),\n warn: (msg: string, data?: unknown) => log('warn', msg, data),\n error: (msg: string, data?: unknown) => log('error', msg, data),\n};\n","import { TtlCache } from '../utils/cache.js';\nimport type { Config } from '../utils/config.js';\nimport { DatabrainApiError } from '../utils/errors.js';\nimport { logger } from '../utils/logger.js';\nimport type { RequestOptions } from './types.js';\n\nconst MCP_SERVER_VERSION = '0.2.0';\nconst MCP_USER_AGENT = `databrain-mcp-server/${MCP_SERVER_VERSION}`;\n\nconst MAX_RETRIES = 3;\nconst REQUEST_TIMEOUT_MS = 30_000;\n\nconst NON_TRANSIENT_PATTERNS = [\n 'out of context',\n 'Definition not found',\n 'not a data question',\n 'Query generation failed',\n 'not found',\n 'not authenticated',\n 'Invalid Service Token',\n 'service token',\n];\n\nexport class DatabrainClient {\n private cache = new TtlCache();\n private runtimeApiToken: string | undefined;\n\n constructor(private config: Config) { }\n\n hasApiToken(): boolean {\n return !!(this.runtimeApiToken || this.config.apiToken);\n }\n\n setRuntimeApiToken(token: string): void {\n this.runtimeApiToken = token;\n logger.info('Runtime API token set for this session');\n }\n\n getServiceToken(): string | undefined {\n return this.config.serviceToken;\n }\n\n getApiUrl(): string {\n return this.config.apiUrl;\n }\n\n private getToken(auth: 'service' | 'api' | 'none'): string | undefined {\n if (auth === 'none') return undefined;\n if (auth === 'service') return this.config.serviceToken;\n return this.runtimeApiToken || this.config.apiToken;\n }\n\n async request<T>(options: RequestOptions): Promise<T> {\n // Invalidate caches first\n if (options.invalidateCache) {\n for (const prefix of options.invalidateCache) {\n this.cache.invalidateByPrefix(prefix);\n }\n }\n\n // Check cache\n if (options.cacheKey && options.cacheTtlMs) {\n const cached = this.cache.get<T>(options.cacheKey);\n if (cached !== undefined) {\n logger.debug(`Cache hit: ${options.cacheKey}`);\n return cached;\n }\n }\n\n const token = this.getToken(options.auth);\n if (options.auth !== 'none' && !token) {\n if (options.auth === 'service') {\n throw new DatabrainApiError(\n 401,\n 'MISSING_SERVICE_TOKEN',\n 'DATABRAIN_SERVICE_TOKEN is required for this operation (org-level token for discovery and data app management). It must be set in the MCP server configuration — do not ask the user for it at runtime.',\n );\n }\n throw new DatabrainApiError(\n 401,\n 'MISSING_API_TOKEN',\n 'A per-data-app API token is required for this embedding operation but none is configured. ' +\n 'Call `create_api_token` to generate one, or `set_api_token` if you already have the value. Do not ask the user for this token — create it via the MCP tools.',\n );\n }\n\n // Build URL\n let url = `${this.config.apiUrl}${options.path}`;\n if (options.query) {\n const params = new URLSearchParams(options.query);\n url += `?${params.toString()}`;\n }\n\n let lastError: Error | undefined;\n\n for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {\n try {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n 'User-Agent': MCP_USER_AGENT,\n 'X-Databrain-Client': MCP_USER_AGENT,\n };\n if (token) {\n headers['Authorization'] = `Bearer ${token}`;\n }\n\n const response = await fetch(url, {\n method: options.method,\n headers,\n body: options.body ? JSON.stringify(options.body) : undefined,\n signal: AbortSignal.timeout(options.timeoutMs || REQUEST_TIMEOUT_MS),\n });\n\n if (!response.ok) {\n const errorBody = await response.text();\n logger.warn(`[API Error] ${options.method} ${options.path} status=${response.status} body=${errorBody.slice(0, 500)}`);\n let parsed: { error?: string; message?: string; code?: string; detail?: string } = {};\n try {\n parsed = JSON.parse(errorBody);\n } catch {\n // not JSON\n }\n\n const errorMsg = parsed.message || parsed.detail || (typeof parsed.error === 'string' ? parsed.error : JSON.stringify(parsed.error)) || `API request failed with status ${response.status}`;\n const error = new DatabrainApiError(\n response.status,\n parsed.code || `HTTP_${response.status}`,\n errorMsg,\n parsed,\n );\n\n // Retry on 429 or 5xx (but not when the error is clearly non-transient)\n const isTransient =\n response.status === 429 ||\n (response.status >= 500 &&\n !NON_TRANSIENT_PATTERNS.some((p) => errorMsg.includes(p)));\n if (isTransient && attempt < MAX_RETRIES) {\n const delay = Math.min(1000 * Math.pow(2, attempt - 1), 8000);\n logger.warn(`Retrying in ${delay}ms (attempt ${attempt}/${MAX_RETRIES})`, {\n status: response.status,\n path: options.path,\n });\n await new Promise((r) => setTimeout(r, delay));\n lastError = error;\n continue;\n }\n\n throw error;\n }\n\n const text = await response.text();\n let data = text ? (JSON.parse(text) as T) : ({} as T);\n\n // Databrain API wraps responses in { data: ... } — unwrap automatically\n if (data && typeof data === 'object' && !Array.isArray(data) && 'data' in data) {\n const inner = (data as Record<string, unknown>).data;\n if (inner !== null && inner !== undefined) {\n data = inner as unknown as T;\n }\n }\n\n // Store in cache\n if (options.cacheKey && options.cacheTtlMs) {\n this.cache.set(options.cacheKey, data, options.cacheTtlMs);\n }\n\n return data;\n } catch (err) {\n if (err instanceof DatabrainApiError) throw err;\n\n if (attempt < MAX_RETRIES && (err as Error)?.name === 'TimeoutError' && !options.noRetryOnTimeout) {\n const delay = Math.min(1000 * Math.pow(2, attempt - 1), 8000);\n logger.warn(`Request timed out, retrying in ${delay}ms`, { path: options.path });\n await new Promise((r) => setTimeout(r, delay));\n lastError = err as Error;\n continue;\n }\n\n throw new DatabrainApiError(\n 0,\n 'NETWORK_ERROR',\n `Failed to connect to Databrain API: ${(err as Error).message}`,\n );\n }\n }\n\n throw lastError || new DatabrainApiError(0, 'UNKNOWN', 'Request failed after retries');\n }\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { DatabrainApiError, toolError, toolSuccess } from '../../utils/errors.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport { READ_ONLY } from '../annotations.js';\n\nexport function registerListDataApps(server: McpServer, client: DatabrainClient): 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(\n 'No data apps found for this account/workspace.'\n );\n }\n\n return toolSuccess(JSON.stringify({\n count: result.length,\n dataApps: result.map((app: any) => {\n const { name, dataAppId, workspaceName } =\n services.discoveryService.normalizeDataApp(app);\n return { name, id: dataAppId || null, workspace: workspaceName || null };\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.request<DashboardRecord[]>({\n method: 'POST',\n path: '/api/v2/workspace/dashboards',\n auth: 'service',\n body: { workspaceName },\n }).then((dashboards) =>\n (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 );\n\n return dashboardsPerWorkspace.flat();\n }\n\n async listDashboardsForWorkspace(workspaceName: string): 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}\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',\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(body: Record<string, unknown>): 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(query?: Record<string, string>): 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(body: Record<string, unknown>): 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(datasourceName: string): 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(datasourceName: string): 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","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 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 return this.client.request<Record<string, unknown>>({\n method: 'POST',\n path: '/api/v2/data-app/embeds',\n body,\n auth: 'api',\n invalidateCache: ['list_embeds'],\n });\n }\n\n async listEmbeds(dataAppName?: string): Promise<EmbedRecord[]> {\n const query =\n dataAppName && dataAppName.trim().length > 0\n ? { dataAppName }\n : undefined;\n return this.client.request<EmbedRecord[]>({\n method: 'GET',\n path: '/api/v2/data-app/embeds',\n auth: 'api',\n query,\n cacheKey: 'list_embeds',\n cacheTtlMs: 5 * 60 * 1000,\n });\n }\n\n async getByEmbedId(embedId: 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 },\n });\n }\n\n async updateEmbed(body: Record<string, unknown>): 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 reasoning: string | null;\n confidence: number | null;\n timeTaken: number;\n sessionId: string | null;\n summary: 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 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","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(body: Record<string, unknown>): 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 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 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) && dashboard.dashboardName) ||\n 'Unnamed Dashboard',\n dashboardId:\n (isNonEmptyString(dashboard.dashboardId) && dashboard.dashboardId) ||\n (isNonEmptyString(dashboard.externalDashboardId) &&\n dashboard.externalDashboardId) ||\n (isNonEmptyString(dashboard._id) && dashboard._id) ||\n (isNonEmptyString(dashboard.id) && dashboard.id) ||\n (isNonEmptyString(dashboard.uid) && dashboard.uid) ||\n null,\n workspaceName:\n (isNonEmptyString(dashboard.workspaceName) && dashboard.workspaceName) ||\n (isNonEmptyString(dashboard.workspace) && dashboard.workspace) ||\n (isNonEmptyString(dashboard.workspaceId) && dashboard.workspaceId) ||\n null,\n metricCount:\n typeof dashboard.metricCount === 'number' ? dashboard.metricCount : 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 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 Record<string, unknown> | 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(dataAppName?: string): Promise<EmbedRecord[]> {\n return this.embedsApi.listEmbeds(dataAppName);\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(\n {} as EmbedRecord,\n accessSettings,\n );\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(embedId: string): Promise<EmbedRecord> {\n const response = await this.embedsApi.getByEmbedId(embedId);\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(embedId: string): Promise<Record<string, unknown>> {\n const embed = await this.resolveEmbedStrict(embedId);\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 ): Promise<Record<string, unknown>> {\n const body = await this.buildUpdateBase(embedId);\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(body);\n }\n}\n","import { GuestTokenApi, type CreateGuestTokenBody } 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(input: GenerateGuestTokenInput): 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 { DatabrainClient } from '../client/databrain-client.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 { WorkspacesApi } from '../api/workspaces-api.js';\nimport { DiscoveryService } from './discovery-service.js';\nimport { EmbedService } from './embed-service.js';\nimport { GuestTokenService } from './guest-token-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 embedService: EmbedService;\n discoveryService: DiscoveryService;\n guestTokenService: GuestTokenService;\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 workspacesApi = new WorkspacesApi(client);\n\n return {\n embedsApi,\n dashboardsApi,\n dataAppsApi,\n datamartsApi,\n datasourcesApi,\n workspacesApi,\n queryApi,\n embedService: new EmbedService(embedsApi, datamartsApi),\n discoveryService: new DiscoveryService(),\n guestTokenService: new GuestTokenService(guestTokenApi),\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 { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { DatabrainApiError, toolError, toolSuccess, stringify } 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.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(`Data app creation failed: ${stringify(result.error)}`);\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 { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { DatabrainApiError, toolError, toolSuccess } from '../../utils/errors.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport { resolveResource, formatDataApp } 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.string().optional().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(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 } 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 = 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 { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { DatabrainApiError, toolError, toolSuccess, stringify } from '../../utils/errors.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport { resolveResource, formatDataApp } 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.string().optional().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.unknown())\n .optional()\n .describe('Raw API body passthrough for POST /api/v2/data-app/api-tokens'),\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(`API token creation failed: ${stringify(result.error)}`);\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\n return toolSuccess(\n `API token created and set for this MCP session.\\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 { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { DatabrainApiError, toolError, toolSuccess, stringify } from '../../utils/errors.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport { resolveResource, formatDataApp } 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 (invalidate and replace) an API token. Previous token becomes stale.',\n {\n dataAppName: z.string().optional().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.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(`Token rotation failed: ${stringify(rotateRes.error)}`);\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 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}-api-token-rotated`,\n },\n });\n if (createRes.error) {\n return toolError(`Token rotation fallback failed: ${stringify(createRes.error)}`);\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 'Treat previous tokens as stale and update backend secrets.'\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 { DatabrainApiError, toolError, toolSuccess } from '../../utils/errors.js';\nimport { READ_ONLY } from '../annotations.js';\n\nexport function registerListDatasources(server: McpServer, client: DatabrainClient): 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(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 return toolSuccess(JSON.stringify({\n count: active.length,\n datasources: active.map((ds: any) => ({\n name: ds.name,\n type: ds.dbName || ds.datasourceType || 'unknown',\n })),\n inactive: inactive.length > 0\n ? inactive.map((ds: any) => ({ name: ds.name }))\n : undefined,\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 { z } from 'zod';\nimport 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 { createServiceBundle } from '../../services/factory.js';\nimport { resolveResource, formatDatasource } 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 = await services.datasourcesApi.getDatasourceSchema(\n datasourceName,\n );\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(\n `## Datasource Schema: ${result.datasourceName}\\n`,\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 { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { DatabrainApiError, toolError, toolSuccess } from '../../utils/errors.js';\nimport { READ_ONLY } from '../annotations.js';\n\nexport function registerListDatamarts(server: McpServer, client: DatabrainClient): 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(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 } 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 { DatabrainApiError, toolError, toolSuccess } 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(server: McpServer, client: DatabrainClient): 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(JSON.stringify({\n count: result.length,\n workspaces: result.map((ws: any) => ({\n name: ws.name,\n connection: describeConnection(ws),\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 { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { DatabrainApiError, toolError, toolSuccess } from '../../utils/errors.js';\nimport { WRITE_IDEMPOTENT } from '../annotations.js';\n\nexport function registerLinkDatamartToWorkspace(\n server: McpServer,\n client: DatabrainClient,\n): void {\n server.tool(\n 'link_datamart_to_workspace',\n 'Link a datamart to an existing workspace. ALWAYS ask the user which workspace to use — do not auto-select.',\n {\n workspaceName: z\n .string()\n .optional()\n .describe(\n 'Name of the workspace to update. Omit to list available workspaces and let the user choose.',\n ),\n datamartName: z\n .string()\n .describe(\n 'Name of the datamart to link. Use `list_datamarts` to find it.',\n ),\n },\n WRITE_IDEMPOTENT,\n async ({ workspaceName, datamartName }) => {\n try {\n if (!workspaceName) {\n const workspaces = 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(workspaces) || workspaces.length === 0) {\n return toolError(\n 'No workspaces found. Create a workspace in the **Databrain UI** first, then come back here to link the datamart.',\n );\n }\n\n const list = workspaces\n .map((ws: any) => `- **${ws.name}** (ID: ${ws._id || ws.id})`)\n .join('\\n');\n\n return toolSuccess(\n `Found ${workspaces.length} workspace(s):\\n\\n${list}\\n\\n` +\n `**Ask the user** which workspace they want to link to datamart **${datamartName}**, then call \\`link_datamart_to_workspace\\` with both \\`workspaceName\\` and \\`datamartName\\`.`,\n );\n }\n\n const result = await client.request<{\n name?: string;\n error?: unknown;\n }>({\n method: 'PUT',\n path: '/api/v2/workspace',\n body: {\n name: workspaceName,\n connectionType: 'DATAMART',\n datamartName,\n },\n auth: 'service',\n invalidateCache: ['list_workspaces'],\n });\n\n if (result.error) {\n return toolError(\n `Failed to link datamart: ${typeof result.error === 'object' ? JSON.stringify(result.error) : result.error}`,\n );\n }\n\n return toolSuccess(\n `Workspace **${workspaceName}** is now linked to datamart **${datamartName}**.\\n\\n` +\n 'Next steps:\\n' +\n '- Build dashboards in the Databrain UI using this workspace\\n' +\n '- Use `list_dashboards` to find dashboards in this workspace\\n' +\n '- Use `create_embed` to embed dashboards into your app',\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 { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { DatabrainApiError, toolError, toolSuccess, stringify } from '../../utils/errors.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport { resolveResource, formatWorkspace } 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.object({\n datamartName: z.string().describe('Name of the datamart (required)'),\n isAllowMetricCreation: z.boolean().optional().describe('Allow end-users to create metrics'),\n metricCreationMode: z.enum(['DRAG_DROP', 'CHAT']).optional().describe('Metric creation mode'),\n isAllowMetricDeletion: z.boolean().optional().describe('Allow metric deletion'),\n isAllowMetricUpdate: z.boolean().optional().describe('Allow metric editing'),\n isAllowMetricLayoutChange: z.boolean().optional().describe('Allow layout changes'),\n isAllowManageMetrics: z.boolean().optional().describe('Show manage metrics UI'),\n isAllowUnderlyingData: z.boolean().optional().describe('Allow viewing underlying data'),\n isAllowAiPilot: z.boolean().optional().describe('Enable AI pilot features'),\n isAllowEmailReports: z.boolean().optional().describe('Allow email report scheduling'),\n isAllowCreateDashboardView: z.boolean().optional().describe('Allow creating dashboard views'),\n}).describe('Embed access settings. Only datamartName is required — all flags default to false.');\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(server: McpServer, client: DatabrainClient): 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.record(z.unknown()).optional().describe(\n 'Raw API body passthrough. If provided, all other fields are ignored.',\n ),\n dashboardId: z.string().optional().describe('Dashboard identifier for embed creation'),\n workspaceName: z.string().optional().describe('Workspace name. Omit to auto-resolve if only one exists.'),\n embedType: z.enum(['dashboard', 'metric']).optional().describe('Embed type'),\n metricId: z.string().optional().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.string().optional().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.string().optional().describe('Template dashboard ID to clone metrics from'),\n isImportMetrics: z.boolean().optional().describe('Import metrics from template dashboard'),\n metricImportMode: z.enum(['COPY', 'LINK']).optional().describe('COPY duplicates metrics, LINK shares them'),\n isRenameDashboard: z.boolean().optional().describe('Rename the dashboard for this client'),\n },\n WRITE_CREATE,\n async (params) => {\n try {\n const isMultiTenant = !!params.clientId;\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 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 = (body.accessSettings && typeof body.accessSettings === 'object')\n ? body.accessSettings as Record<string, unknown>\n : {};\n body.accessSettings = { ...DEFAULT_ACCESS_SETTINGS, ...callerAccess };\n\n const result = await client.request<Record<string, unknown>>({\n method: 'POST',\n path: '/api/v2/data-app/dashboard-embeds',\n body,\n auth: 'api',\n invalidateCache: ['list_embeds'],\n });\n\n if (result.error) {\n return toolError(`Dashboard embed creation failed: ${stringify(result.error)}`);\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 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('create_embed requires `dashboardId` (or provide full raw `body`).');\n }\n if (!body.workspaceName || typeof body.workspaceName !== 'string') {\n return toolError('create_embed requires `workspaceName` (or provide full raw `body`).');\n }\n const accessSettings = body.accessSettings as Record<string, unknown> | undefined;\n if (!accessSettings || typeof accessSettings !== 'object') {\n return toolError('create_embed requires `accessSettings` and must include `datamartName`.');\n }\n const datamartName = accessSettings.datamartName;\n if (!datamartName || typeof datamartName !== 'string') {\n return toolError('create_embed requires `accessSettings.datamartName`.');\n }\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) ||\n (result.id as string) ||\n '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 { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { DatabrainApiError, toolError, toolSuccess } from '../../utils/errors.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport { READ_ONLY } from '../annotations.js';\n\nexport function registerListEmbeds(server: McpServer, client: DatabrainClient): 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).',\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(params.dataAppName);\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 return toolSuccess(JSON.stringify({\n count: result.length,\n embeds: result.map((e: any) => {\n const n = services.discoveryService.normalizeEmbed(e);\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 };\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 { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { DatabrainApiError, toolError, toolSuccess } from '../../utils/errors.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport { READ_ONLY } from '../annotations.js';\n\nexport function registerGetEmbedDetails(server: McpServer, client: DatabrainClient): 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 },\n READ_ONLY,\n async (params) => {\n try {\n const embed = await services.embedService.resolveEmbedStrict(params.embedId);\n\n return toolSuccess(JSON.stringify({ embedId: params.embedId, ...embed }));\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 { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { DatabrainApiError, toolError, toolSuccess, stringify } from '../../utils/errors.js';\nimport {\n GUEST_TOKEN_REMINDER,\n maybeBuildCorruptedEmbedGuardrail,\n} from './helpers.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport { WRITE_IDEMPOTENT } from '../annotations.js';\n\nexport function registerUpdateEmbed(server: McpServer, client: DatabrainClient): 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 body: z.record(z.unknown()).optional().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.record(z.unknown()).optional().describe(\n 'Partial update of access settings. See `get_embed_details` for current settings.'\n ),\n theme: z.record(z.unknown()).optional().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 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 );\n\n if (result.error) {\n return toolError(`Embed update failed: ${stringify(result.error)}`);\n }\n\n return toolSuccess(`Embed \"${params.embedId}\" updated successfully.` + GUEST_TOKEN_REMINDER);\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 { DatabrainClient } from '../../client/databrain-client.js';\nimport { DatabrainApiError, toolError } from '../../utils/errors.js';\nimport { createServiceBundle } from '../../services/factory.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(client: DatabrainClient, embedId: string): 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 { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { DatabrainApiError, toolError, toolSuccess, stringify } from '../../utils/errors.js';\nimport {\n GUEST_TOKEN_REMINDER,\n maybeBuildCorruptedEmbedGuardrail,\n} from './helpers.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport { WRITE_IDEMPOTENT } from '../annotations.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: ['#4F46E5', '#10B981', '#F59E0B', '#EF4444', '#8B5CF6', '#06B6D4'],\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: ['#818CF8', '#34D399', '#FBBF24', '#F87171', '#A78BFA', '#22D3EE'],\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: ['#1E40AF', '#059669', '#D97706', '#DC2626', '#7C3AED', '#0891B2'],\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.enum([\n 'Inter', 'Roboto', 'Open Sans', 'Lato', 'Poppins', 'Montserrat',\n 'IBM Plex Sans', 'Source Sans Pro', 'Nunito', 'system-ui',\n]).describe('Font family');\n\nconst tooltipFontSchema = z.object({\n fontFamily: z.string().optional(),\n fontSize: z.number().optional(),\n fontWeight: z.number().optional(),\n fontColor: z.string().optional(),\n}).optional();\n\nconst fontConfigInputSchema = z.object({\n fontSize: z.number().optional(),\n fontFamily: z.string().optional(),\n fontWeight: z.number().optional(),\n color: z.string().optional(),\n}).optional();\n\nfunction mapToFrontendFontConfig(\n input: { fontSize?: number; fontFamily?: string; fontWeight?: number; color?: string } | 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.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.number().optional().describe('Axis title offset from axis'),\n axisLabelMargin: z.number().optional().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.object({\n fontFamily: z.string().optional(),\n fontSize: z.number().optional(),\n fontWeight: z.number().optional(),\n }).optional().describe('Axis title font configuration'),\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 ? { ...presetBase } : {};\n\n const general: Record<string, unknown> = { ...(adminTheme.general as Record<string, unknown> ?? {}) };\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> = { ...(adminTheme.dashboard as Record<string, unknown> ?? {}) };\n if (p.dashboardBackgroundColor) 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) 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> = { ...(adminTheme.cardTitle as Record<string, unknown> ?? {}) };\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> = { ...(adminTheme.cardDescription as Record<string, unknown> ?? {}) };\n if (p.cardDescriptionFontSize) cardDescription.fontSize = p.cardDescriptionFontSize;\n if (p.cardDescriptionFontWeight) cardDescription.fontWeight = p.cardDescriptionFontWeight;\n if (p.cardDescriptionColor) cardDescription.color = p.cardDescriptionColor;\n if (Object.keys(cardDescription).length) adminTheme.cardDescription = cardDescription;\n\n const cardCustomization: Record<string, unknown> = { ...(adminTheme.cardCustomization as Record<string, unknown> ?? {}) };\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) cardCustomization.disableShadowOnHover = p.disableShadowOnHover;\n if (p.disableCardStroke !== undefined) cardCustomization.disableStroke = p.disableCardStroke;\n if (p.cardStrokeColor) cardCustomization.metricStrokeColor = p.cardStrokeColor;\n if (Object.keys(cardCustomization).length) adminTheme.cardCustomization = cardCustomization;\n\n const chart: Record<string, unknown> = { ...(adminTheme.chart as Record<string, unknown> ?? {}) };\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 = [{ name: p.chartPaletteName, colors: p.chartPaletteColors }];\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(p: Record<string, unknown>): Record<string, unknown> {\n const componentTheme: Record<string, unknown> = {};\n\n if (p.buttonPrimaryColor || p.buttonPrimaryTextColor ||\n p.buttonSecondaryColor || p.buttonSecondaryTextColor) {\n componentTheme.button = {\n ...(p.buttonPrimaryColor && { primary: p.buttonPrimaryColor }),\n ...(p.buttonPrimaryTextColor && { primaryText: p.buttonPrimaryTextColor }),\n ...(p.buttonSecondaryColor && { secondary: p.buttonSecondaryColor }),\n ...(p.buttonSecondaryTextColor && { secondaryText: p.buttonSecondaryTextColor }),\n };\n }\n if (p.checkboxCheckedColor || p.checkboxUncheckedColor) {\n componentTheme.checkbox = {\n ...(p.checkboxCheckedColor && { checked: p.checkboxCheckedColor }),\n ...(p.checkboxUncheckedColor && { unChecked: p.checkboxUncheckedColor }),\n };\n }\n if (p.switchEnabledColor || p.switchDisabledColor) {\n componentTheme.switch = {\n ...(p.switchEnabledColor && { enabled: p.switchEnabledColor }),\n ...(p.switchDisabledColor && { disabled: p.switchDisabledColor }),\n };\n }\n if (p.breadcrumbFontFamily || p.breadcrumbFontColor || p.breadcrumbActiveColor) {\n componentTheme.drillBreadCrumbs = {\n ...(p.breadcrumbFontFamily && { fontFamily: p.breadcrumbFontFamily }),\n ...(p.breadcrumbFontColor && { fontColor: p.breadcrumbFontColor }),\n ...(p.breadcrumbActiveColor && { activeColor: p.breadcrumbActiveColor }),\n };\n }\n if (p.filterBadgeColor || p.filterBadgeTextColor) {\n componentTheme.multiSelectFilterDropdown = {\n ...(p.filterBadgeColor && { badgeColor: p.filterBadgeColor }),\n ...(p.filterBadgeTextColor && { badgeTextColor: p.filterBadgeTextColor }),\n };\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) componentTheme.metricLayoutCols = metricLayoutCols;\n\n return componentTheme;\n}\n\nfunction buildChartAppearance(p: Record<string, unknown>): 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) chartAppearance.chartTooltip = chartTooltip;\n\n const chartLabel: Record<string, unknown> = {};\n if (p.labelPosition) chartLabel.position = p.labelPosition;\n if (p.radialLabelPosition) chartLabel.radialChartposition = p.radialLabelPosition;\n if (Object.keys(chartLabel).length) chartAppearance.chartLabel = chartLabel;\n\n if (p.marginTop !== undefined || p.marginLeft !== undefined ||\n p.marginRight !== undefined || p.marginBottom !== undefined) {\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) 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) chartLegend.truncateLegend = p.legendTruncateLength;\n if (p.disableLegendScrolling !== undefined) chartLegend.disableLegendScrolling = p.disableLegendScrolling;\n if (p.enableVariableLegendPosition !== undefined) 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) 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(server: McpServer, client: DatabrainClient): 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 body: z.record(z.unknown()).optional().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.enum(['light', 'dark', 'corporate', 'minimal']).optional()\n .describe('Apply a theme preset as the base. Granular params below override preset values.'),\n accessPreset: z.enum(['view-only', 'power-user', 'export-only', 'ai-enabled']).optional()\n .describe('Apply an access settings preset'),\n\n // --- General ---\n fontFamily: fontFamilyEnum.optional().describe('Global font family'),\n datePickerFormat: z.string().optional().describe('Date picker display format'),\n\n // --- Colors ---\n primaryColor: z.string().optional().describe('Primary accent color (hex)'),\n backgroundColor: z.string().optional().describe('Overall background color (hex)'),\n textColor: z.string().optional().describe('Default text color (hex)'),\n ctaColor: z.string().optional().describe('Call-to-action button color (hex)'),\n ctaTextColor: z.string().optional().describe('CTA button text color (hex)'),\n\n // --- Dashboard ---\n dashboardBackgroundColor: z.string().optional().describe('Dashboard container background (hex)'),\n selectBoxSize: z.enum(['small', 'medium', 'large']).optional().describe('Filter select box size'),\n selectBoxVariant: z.enum(['floating', 'outlined', 'standard']).optional().describe('Filter select box style'),\n selectBoxBorderRadius: z.string().optional().describe('Select box border radius (e.g. \"20px\")'),\n selectBoxTextColor: z.string().optional().describe('Select box text color (hex)'),\n metricCardColor: z.string().optional().describe('Metric card background color (hex)'),\n\n // --- Card Title ---\n cardTitleFontSize: z.string().optional().describe('Card title font size (e.g. \"16px\")'),\n cardTitleFontWeight: z.string().optional().describe('Card title font weight (e.g. \"600\")'),\n cardTitleColor: z.string().optional().describe('Card title text color (hex)'),\n\n // --- Card Description ---\n cardDescriptionFontSize: z.string().optional().describe('Card description font size'),\n cardDescriptionFontWeight: z.string().optional().describe('Card description font weight'),\n cardDescriptionColor: z.string().optional().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.boolean().optional().describe('Disable shadow on card hover'),\n disableCardStroke: z.boolean().optional().describe('Remove card border stroke'),\n cardStrokeColor: z.string().optional().describe('Card border stroke color (hex)'),\n\n // --- Chart Colors (admin theme level) ---\n chartFontFamily: z.string().optional().describe('Font family for chart text'),\n chartFontColor: z.string().optional().describe('Font color for chart text (hex)'),\n chartColors: z.array(z.string()).optional().describe('Array of chart series colors (hex)'),\n chartPaletteName: z.string().optional().describe('Name for a custom palette'),\n chartPaletteColors: z.array(z.string()).optional().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.string().optional().describe('Primary button background (hex)'),\n buttonPrimaryTextColor: z.string().optional().describe('Primary button text (hex)'),\n buttonSecondaryColor: z.string().optional().describe('Secondary button background (hex)'),\n buttonSecondaryTextColor: z.string().optional().describe('Secondary button text (hex)'),\n checkboxCheckedColor: z.string().optional().describe('Checked checkbox color (hex)'),\n checkboxUncheckedColor: z.string().optional().describe('Unchecked checkbox color (hex)'),\n switchEnabledColor: z.string().optional().describe('Enabled switch color (hex)'),\n switchDisabledColor: z.string().optional().describe('Disabled switch color (hex)'),\n breadcrumbFontFamily: z.string().optional().describe('Drill breadcrumb font family'),\n breadcrumbFontColor: z.string().optional().describe('Drill breadcrumb font color (hex)'),\n breadcrumbActiveColor: z.string().optional().describe('Active breadcrumb color (hex)'),\n filterBadgeColor: z.string().optional().describe('Multi-select filter badge color (hex)'),\n filterBadgeTextColor: z.string().optional().describe('Filter badge text color (hex)'),\n datePickerColor: z.string().optional().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.number().optional().describe('Grid columns at XL breakpoint'),\n layoutColsLg: z.number().optional().describe('Grid columns at LG breakpoint'),\n layoutColsMd: z.number().optional().describe('Grid columns at MD breakpoint'),\n layoutColsSm: z.number().optional().describe('Grid columns at SM breakpoint'),\n layoutColsXs: z.number().optional().describe('Grid columns at XS breakpoint'),\n layoutColsXxs: z.number().optional().describe('Grid columns at XXS breakpoint'),\n\n // --- Chart Appearance (detailed) ---\n tooltipHeaderStyle: fontConfigInputSchema.describe('Tooltip header: fontSize, fontFamily, fontWeight, color'),\n tooltipLabelStyle: fontConfigInputSchema.describe('Tooltip label: fontSize, fontFamily, fontWeight, color'),\n tooltipValueStyle: fontConfigInputSchema.describe('Tooltip value: fontSize, fontFamily, fontWeight, color'),\n labelPosition: z.enum(['hidden', 'top', 'left', 'right', 'bottom', 'inside']).optional()\n .describe('Data label position on charts'),\n radialLabelPosition: z.enum(['outside', 'inside']).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.number().optional().describe('Chart right margin in pixels'),\n marginBottom: z.number().optional().describe('Chart bottom margin in pixels'),\n legendShow: z.boolean().optional().describe('Show or hide chart legend'),\n legendPosition: z.enum([\n 'top-left', 'top-center', 'top-right',\n 'left-center', 'right-center',\n 'bottom-left', 'bottom-center', 'bottom-right',\n ]).optional().describe('Legend position'),\n legendLayout: z.enum(['horizontal', 'vertical']).optional().describe('Legend layout direction'),\n legendShape: z.enum(['circle', 'rect', 'roundRect', 'triangle', 'diamond', 'arrow', 'none']).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.number().optional().describe('Max characters before truncating legend'),\n disableLegendScrolling: z.boolean().optional().describe('Disable scrolling in legend'),\n enableVariableLegendPosition: z.boolean().optional().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 { embedId, body, themePreset, accessPreset, ...themeParams } = 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 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(client, embedId, 'customize theme', err);\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(themeParams as Record<string, unknown>, presetBase);\n if (Object.keys(adminTheme).length) patch.adminThemeOptions = adminTheme;\n\n // Component theme (buttons, checkboxes, breakpoints, layout)\n const componentTheme = buildComponentTheme(themeParams as Record<string, unknown>);\n if (Object.keys(componentTheme).length) patch.theme = componentTheme;\n\n // Chart appearance (tooltip styles, legend, axes, labels, margins)\n const chartAppearance = buildChartAppearance(themeParams as Record<string, unknown>);\n const options: Record<string, unknown> = {};\n if (Object.keys(chartAppearance).length) options.chartAppearance = chartAppearance;\n if (themeParams.chartColors) 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('No theme properties provided. Specify at least one property, or use a themePreset.');\n }\n\n try {\n const result = await services.embedService.updateEmbed(embedId, patch);\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) applied.push(`admin theme (${Object.keys(adminTheme).join(', ')})`);\n if (patch.theme) applied.push(`component theme (${Object.keys(componentTheme).join(', ')})`);\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(client, embedId, 'customize theme', err);\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 { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { DatabrainApiError, toolError, toolSuccess } from '../../utils/errors.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport { resolveResource, formatDataApp } from '../../utils/resolve-resource.js';\nimport { WRITE_CREATE } from '../annotations.js';\n\nexport function registerGenerateGuestToken(server: McpServer, client: DatabrainClient): 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.string().describe('Unique end-user identifier for multi-tenant filtering. Use \"None\" if no tenancy.'),\n dataAppName: z.string().optional().describe('Name of the data app. Omit to list available data apps.'),\n body: z.record(z.unknown()).optional().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.object({\n allowedEmbeds: z.array(z.string()).optional().describe('Restrict token to specific embed IDs'),\n rlsSettings: z.array(z.object({\n metricId: z.string().describe('Metric ID'),\n values: z.record(z.unknown()).describe('RLS values by column name'),\n })).optional().describe('Legacy alias used in docs/examples; forwarded as params.rlsSettings'),\n appFilters: z.array(z.object({\n metricId: z.string().describe('Metric ID'),\n values: z.record(z.unknown()).describe('Filter values by column name'),\n })).optional().describe('Metric-level app filters'),\n dashboardAppFilters: z.array(z.object({\n dashboardId: z.string().describe('Dashboard ID'),\n values: z.record(z.unknown()).describe('Filter values by dashboard filter name'),\n isShowOnUrl: z.boolean().optional().describe('Whether filters are shown in URL params'),\n })).optional().describe('Dashboard-level app filters'),\n hideDashboardFilters: z.array(z.string()).optional().describe('Dashboard filter names to hide'),\n userIdentifier: z.string().optional().describe('End-user identifier for private metrics support'),\n timezone: z.string().optional().describe('IANA timezone, e.g. \"America/New_York\"'),\n }).optional().describe('Advanced token params'),\n\n // Legacy convenience fields (auto-mapped into params for backward compatibility)\n timezone: z.string().optional().describe('Legacy: moved under params.timezone'),\n allowedEmbeds: z.array(z.string()).optional().describe('Legacy: moved under params.allowedEmbeds'),\n rlsSettings: z.array(z.object({\n metricId: z.string().describe('Metric ID'),\n values: z.record(z.unknown()).describe('RLS values by column name'),\n })).optional().describe('Legacy: moved under params.rlsSettings'),\n appFilters: z.array(z.object({\n metricId: z.string().describe('Metric ID'),\n values: z.record(z.unknown()).describe('Filter values by column name'),\n })).optional().describe('Legacy: moved under params.appFilters'),\n dashboardAppFilters: z.array(z.object({\n dashboardId: z.string().describe('Dashboard ID to apply filters to'),\n values: z.record(z.unknown()).describe('Filter values for this dashboard'),\n isShowOnUrl: z.boolean().optional().describe('Whether filters are shown in URL params'),\n })).optional().describe('Legacy: moved under params.dashboardAppFilters'),\n permissions: z.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 }).optional().describe('Runtime permission overrides (merge with and override embed-level settings)'),\n theme: z.record(z.unknown()).optional().describe('Runtime theme overrides (overrides embed-level theme)'),\n hideDashboardFilters: z.array(z.string()).optional().describe('Legacy: moved under params.hideDashboardFilters'),\n userIdentifier: z.string().optional().describe('Legacy: moved under params.userIdentifier'),\n expiryTime: z.number().optional().describe('Token TTL in milliseconds'),\n datasourceName: z.string().optional().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 = 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 { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { toolSuccess } from '../../utils/errors.js';\nimport { getTemplate } from '../../templates/index.js';\nimport type { TemplateContext } from '../../templates/types.js';\nimport { READ_ONLY } from '../annotations.js';\n\nconst FRAMEWORKS = ['react', 'nextjs', 'vue', 'angular', 'svelte', 'solidjs', 'vanilla'] as const;\n\nexport function registerGenerateEmbedCode(server: McpServer, _client: DatabrainClient): 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.enum(['dashboard', 'metric']).optional().default('dashboard'),\n options: z.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.unknown()).optional(),\n optionsIcon: z.enum(['kebab-menu-vertical', 'download']).optional(),\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 { TemplateContext, GeneratedCode } 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://app.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 { TemplateContext, GeneratedCode } 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://app.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 { TemplateContext, GeneratedCode } 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://app.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 type { TemplateContext, GeneratedCode } 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://app.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 { TemplateContext, GeneratedCode } 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://app.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 { TemplateContext, GeneratedCode } 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://app.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 { TemplateContext, GeneratedCode } 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://app.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 { TemplateContext, GeneratedCode } from './types.js';\nimport { reactTemplate } from './react.js';\nimport { nextjsTemplate } from './nextjs.js';\nimport { vueTemplate } from './vue.js';\nimport { angularTemplate } from './angular.js';\nimport { svelteTemplate } from './svelte.js';\nimport { solidjsTemplate } from './solidjs.js';\nimport { vanillaTemplate } from './vanilla.js';\n\ntype Framework = 'react' | 'nextjs' | 'vue' | 'angular' | 'svelte' | 'solidjs' | '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(framework: Framework, ctx: TemplateContext): GeneratedCode {\n return templates[framework](ctx);\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { DatabrainClient } from '../../client/databrain-client.js';\nimport { DatabrainApiError, toolError, toolSuccess } from '../../utils/errors.js';\nimport { createServiceBundle } from '../../services/factory.js';\nimport { READ_ONLY } from '../annotations.js';\n\nexport function registerListDashboards(server: McpServer, client: DatabrainClient): 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('Data app name for data_app scope. Ignored for global scope.'),\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(JSON.stringify({\n count: result.length,\n scope: useDataAppScope ? 'data_app' : 'global',\n dashboards: result.map((d: any) => {\n const { name, dashboardId, workspaceName, metricCount } =\n services.discoveryService.normalizeDashboard(d as Record<string, unknown>);\n return {\n id: dashboardId || null,\n name,\n workspace: workspaceName || null,\n metricCount: metricCount ?? 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 { z } from 'zod';\nimport 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 { createServiceBundle } from '../../services/factory.js';\nimport { formatDatamart } from '../../utils/resolve-resource.js';\nimport { logger } from '../../utils/logger.js';\nimport { WRITE_CREATE } from '../annotations.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 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 if (!datamartName) {\n const datamarts = await services.datamartsApi.listDatamarts();\n if (!Array.isArray(datamarts) || datamarts.length === 0) {\n return toolError(\n 'No datamarts found. 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 (datamarts.length === 1) {\n datamartName = datamarts[0].name || datamarts[0].datamartName;\n } else {\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\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 = await services.queryApi.getSemanticLayer(\n datamartName,\n );\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 const table = formatDataTable(data, result.columns);\n\n const parts: string[] = [];\n parts.push(`## Query Results\\n`);\n parts.push(\n `**Question:** ${params.question}`,\n );\n parts.push(\n `**Suggested chart type:** ${result.suggestedChartType}`,\n );\n if (result.confidence !== null) {\n parts.push(\n `**Confidence:** ${Math.round(result.confidence * 100)}%`,\n );\n }\n parts.push(\n `**Rows returned:** ${data.length} | **Time:** ${result.timeTaken}ms`,\n );\n if (result.reasoning) {\n parts.push(`\\n### Reasoning\\n${result.reasoning}`);\n }\n if (result.summary) {\n parts.push(`\\n### Summary\\n${result.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 `\\n**Dimensions:** ${dims}\\n**Measures:** ${meas}`,\n );\n }\n if (result.sessionId) {\n parts.push(\n `\\n_Session ID for follow-up: \\`${result.sessionId}\\`_`,\n );\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}\n","import { z } from 'zod';\nimport 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 { createServiceBundle } from '../../services/factory.js';\nimport { resolveResource, formatDatamart } 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 = hasTables && result.tables.some(\n (t: any) =>\n t.description ||\n (t.columns ?? []).some(\n (c: any) => c.description || c.columnType,\n ),\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(\n `**Completion Score:** ${result.completionScore}%`,\n );\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 { z } from 'zod';\nimport 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 { createServiceBundle } from '../../services/factory.js';\nimport { resolveResource, formatDatamart } 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('Semantic column type. Use \"Identifier\" for IDs/foreign keys, \"Number\" for numeric values, \"String\" for text. Omit for date columns.'),\n});\n\nconst tableSchema = z.object({\n name: z.string().describe('Table name (must exist in the datamart)'),\n description: z\n .string()\n .optional()\n .describe(\n 'Business-friendly description of what this table represents',\n ),\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\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\n await services.queryApi.updateSemanticLayer({\n datamartName,\n tables: params.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 type { DatabrainClient } from '../client/databrain-client.js';\n\nimport { registerListDataApps } from './data-app/list-data-apps.js';\nimport { registerCreateDataApp } from './data-app/create-data-app.js';\nimport { registerListApiTokens } from './data-app/list-api-tokens.js';\nimport { registerCreateApiToken } from './data-app/create-api-token.js';\nimport { registerRotateApiToken } from './data-app/rotate-api-token.js';\n\nimport { registerListDatasources } from './infrastructure/list-datasources.js';\nimport { registerDiscoverDatasourceSchema } from './infrastructure/discover-datasource-schema.js';\nimport { registerListDatamarts } from './infrastructure/list-datamarts.js';\nimport { registerListWorkspaces } from './infrastructure/list-workspaces.js';\nimport { registerLinkDatamartToWorkspace } from './infrastructure/link-datamart-to-workspace.js';\n\nimport { registerCreateEmbed } from './embed/create-embed.js';\nimport { registerListEmbeds } from './embed/list-embeds.js';\nimport { registerGetEmbedDetails } from './embed/get-embed-details.js';\nimport { registerUpdateEmbed } from './embed/update-embed.js';\nimport { registerCustomizeTheme } from './embed/customize-theme.js';\n\nimport { registerGenerateGuestToken } from './frontend/generate-guest-token.js';\nimport { registerGenerateEmbedCode } from './frontend/generate-embed-code.js';\n\nimport { registerListDashboards } from './analytics/list-dashboards.js';\n\nimport { registerAskQuestion } from './query/ask-question.js';\nimport { registerGetSemanticLayer } from './query/get-semantic-layer.js';\nimport { registerUpdateSemanticLayer } from './query/update-semantic-layer.js';\n\nexport function registerAllTools(server: McpServer, client: DatabrainClient): void {\n // Infrastructure\n registerListDatasources(server, client);\n registerDiscoverDatasourceSchema(server, client);\n registerListDatamarts(server, client);\n registerListWorkspaces(server, client);\n registerLinkDatamartToWorkspace(server, client);\n\n // Data app & token management\n registerListDataApps(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\n // Frontend\n registerGenerateGuestToken(server, client);\n registerGenerateEmbedCode(server, client);\n\n // Dashboard discovery\n registerListDashboards(server, client);\n\n // Query & semantic layer\n registerAskQuestion(server, client);\n registerGetSemanticLayer(server, client);\n registerUpdateSemanticLayer(server, client);\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 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 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 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","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# 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 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 \"Acme Corp\" (org_id = \"acme\") 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: 'acme', // Maps to org_id values in the database\n }),\n});\n\\`\\`\\`\n\nWhen a user from \"Globex\" (org_id = \"globex\") 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: 'globex',\n }),\n});\n\\`\\`\\`\n\n### Step 6: Render\n\nBoth users see the same dashboard layout and metrics, but:\n- Acme sees only their projects, tasks, and team members\n- Globex sees only their projects, tasks, and team members\n- Both see all task statuses (shared reference table)\n\n### Result\n\n\\`\\`\\`\nAcme User sees:\n - 12 projects (all with org_id = 'acme')\n - 87 tasks\n - 15 team members\n\nGlobex User sees:\n - 8 projects (all with org_id = 'globex')\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 useCaseGuidesContent = `# Databrain Use Case Guides\n\nDatabrain supports 4 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: Enable Metric Creation\n**When to use:** You want end-users to build their own metrics/charts on embedded dashboards.\n**Prompt:** \\`enable-metric-creation\\`\n**Two modes:**\n- **DRAG_DROP:** Visual metric builder — users drag columns, pick chart types. No AI needed.\n- **CHAT:** AI-powered natural language — users type questions. Requires LLM connector in Databrain admin.\n**Tool sequence:** \\`list_embeds\\` → \\`update_embed\\` (set accessSettings and options) → \\`generate_guest_token\\` (with permissions)\n\n## Use Case 4: 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 these prompts to customize:\n\n| Prompt | Purpose |\n|--------|---------|\n| \\`brand-my-embed\\` | Colors, fonts, chart styles, theme presets |\n| \\`setup-filters\\` | String, date, number, SQL, and server-side filters |\n| \\`localize-embed\\` | Multi-language support and locale settings |\n| \\`secure-my-embed\\` | Permissions, access controls, role-based tokens |\n| \\`manage-embeds\\` | List, compare, and manage existing embeds |\n| \\`query-data\\` | Natural language querying and semantic layer management |\n| \\`populate-semantic-layer\\` | Auto-generate table/column descriptions for AI features |\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| Do you want end-users to create metrics? | Yes → Use Case 3 |\n| Want to explore or query your data? | Yes → Use Case 4 |\n| Just need to brand/filter/secure? | Use customization prompts |\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","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { gettingStartedContent } from './content/getting-started.js';\nimport { apiReferenceContent } from './content/api-reference.js';\nimport { embeddingGuideContent } from './content/embedding-guide.js';\nimport { filterReferenceContent } from './content/filter-reference.js';\nimport { themeReferenceContent } from './content/theme-reference.js';\nimport { webComponentReferenceContent } from './content/web-component-reference.js';\nimport { selfServeReferenceContent } from './content/self-serve-reference.js';\nimport { semanticLayerGuideContent } from './content/semantic-layer-guide.js';\nimport { multiTenancyGuideContent } from './content/multi-tenancy-guide.js';\nimport { useCaseGuidesContent } from './content/use-case-guides.js';\nimport { permissionSchemaContent } from './content/permission-schema.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: '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: '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: '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: '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: '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: '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: '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: '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: '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: 'Summary of 4 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: '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(res.name, res.uri, { description: res.description }, async () => ({\n contents: [\n {\n uri: res.uri,\n mimeType: 'text/markdown',\n text: res.content,\n },\n ],\n }));\n }\n}\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\\`, \\`setup-filters\\`, \\`localize-embed\\`, \\`secure-my-embed\\`.`;\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\\`, \\`setup-filters\\`, \\`enable-metric-creation\\`, \\`secure-my-embed\\`.`;\n","export const enableMetricCreationPrompt = `You are helping the user enable end-user metric creation on their embedded dashboards. Databrain supports two modes: DRAG_DROP (visual builder) and CHAT (AI-powered natural language).\n\n**CRITICAL: This is an interactive guide. You MUST stop and ask the user at each decision point before proceeding. Never assume answers.**\n\n**Two Metric Creation Modes:**\n- **DRAG_DROP**: Visual metric builder where users drag columns, choose chart types, and configure metrics. No AI needed.\n- **CHAT**: AI-powered natural language metric creation. Users type questions like \"Show me revenue by month\" and Databrain generates the metric. Requires an LLM connector configured in the Databrain admin panel.\n\n**Step 1 — Identify the Embed**\nCall \\`list_embeds\\` to show available embeds.\nSTOP and ASK the user: \"Which embed do you want to enable metric creation on?\"\nOnly after they answer, call \\`get_embed_details\\` to see current access settings.\n\n**Step 2 — Choose the Mode**\nSTOP and ASK the user:\n- \"Which metric creation mode do you want?\"\n - **DRAG_DROP**: Visual builder, no AI dependency\n - **CHAT**: AI-powered, requires LLM connector setup in Databrain admin\nDo NOT proceed until the user picks a mode.\n\nIf they choose CHAT, tell them: \"CHAT mode requires an LLM connector configured in the Databrain admin panel (Settings > AI Configuration). Have you set this up?\"\n\n**Step 3 — Update Embed Access Settings**\nCall \\`update_embed\\` with the embed ID and updated \\`accessSettings\\`:\n\nFor DRAG_DROP mode:\n\\`\\`\\`json\n{\n \"accessSettings\": {\n \"isAllowMetricCreation\": true,\n \"metricCreationMode\": \"DRAG_DROP\"\n }\n}\n\\`\\`\\`\n\nFor CHAT mode:\n\\`\\`\\`json\n{\n \"accessSettings\": {\n \"isAllowMetricCreation\": true,\n \"metricCreationMode\": \"CHAT\"\n }\n}\n\\`\\`\\`\n\n**Step 4 — Configure Embed Options**\nCall \\`update_embed\\` (body passthrough with options) to ensure the UI supports metric creation:\n- \\`disableMetricCreation\\`: false\n- \\`hideCreateMetricButton\\`: false\n- \\`hideChartSettings\\`: false (so users can customize their created metrics)\n\n**Step 5 — Set Guest Token Permissions**\nRemind the user: guest token \\`permissions\\` override embed \\`accessSettings\\` at runtime. When generating guest tokens via \\`generate_guest_token\\`, include:\n\\`\\`\\`json\n{\n \"permissions\": {\n \"isDisableMetricCreation\": false\n }\n}\n\\`\\`\\`\n\n**Step 6 — Verify and Test**\nCall \\`get_embed_details\\` to verify the settings were applied correctly.\nTell the user to refresh their embed and look for the \"+ Create Metric\" button.\n\nIf using CHAT mode, remind the user:\n- An LLM connector must be configured in Databrain admin (Settings > AI Configuration)\n- The datamart should have a populated semantic layer for best AI results (use \\`get_semantic_layer\\` to check, and \\`update_semantic_layer\\` or the \\`populate-semantic-layer\\` prompt to populate it)\n\n**Important rules:**\n- STOP and ASK at each decision point. Never skip ahead.\n- Guest token \\`permissions\\` take precedence over embed \\`accessSettings\\` — both must allow metric creation.\n- CHAT mode requires external LLM connector setup (not available via MCP).\n- After enabling, suggest: \\`secure-my-embed\\` to fine-tune which users get metric creation access.`;\n","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 localizeEmbedPrompt = `You are helping the user set up multi-language support for their embedded Databrain dashboard. Follow these steps.\n\n**Step 1 — Identify the Embed and Target Languages**\nCall \\`list_embeds\\` and ask the user which embed to localize. Then ask:\n- Which languages do they need? (Supported: English, French, Spanish, German, Italian, Portuguese, Chinese, Japanese, Korean, Hindi, Arabic, Russian)\n- What is the default/primary language?\n\n**Step 2 — Set the Primary Language**\nUse \\`update_embed\\` (body passthrough with componentAttributes) with the \\`language\\` parameter set to their primary language code (e.g. \"fr\" for French).\n\n**Step 3 — Gather Translations**\nCall \\`get_embed_details\\` to understand what text is in the dashboard. Then help the user build translations:\n\nAsk the user to list the key text elements in their dashboard:\n- Dashboard title\n- Metric titles and descriptions\n- Filter labels\n- Any footnotes or annotations\n\nFor each text element, ask for translations in their target languages. Build translation entries like:\n\\`\\`\\`\n{ key: \"Revenue\", translations: { fr: \"Revenus\", es: \"Ingresos\", de: \"Einnahmen\" } }\n\\`\\`\\`\n\n**Important rules for translation keys:**\n- Keys must match the dashboard text EXACTLY (case-sensitive)\n- Define longer keys before shorter ones to avoid partial matches\n- If a translation is missing for a language, the original key text is shown as fallback\n\n**Step 4 — Apply Translations**\nUse \\`update_embed\\` (body passthrough with componentAttributes.translationDictionary) with the translations.\n\n**Step 5 — Configure Calendar (if needed)**\nAsk if they need a different calendar system:\n- \\`\"default\"\\` — standard Gregorian calendar\n- \\`\"ind\"\\` — Indian calendar format\n\nSet via \\`calendarType\\` in \\`update_embed\\` (body passthrough with componentAttributes).\n\n**Step 6 — Set Custom Messages**\nAsk if they want to translate system messages:\n- Token expiry message (shown when session expires)\n- Token absent message (shown when no auth token)\n\nUse \\`update_embed\\` (body passthrough with options.customMessages) with \\`tokenExpiry\\` and \\`tokenAbsent\\` in their primary language.\n\n**Step 7 — Test**\nTell the user to refresh the embed and verify translations appear correctly. If any text isn't translating, double-check that the key matches exactly.\n\nRemind the user: translations can also be applied per-user at the web component level using the \\`translation-dictionary\\` attribute, which is useful for dynamically switching languages based on user preferences.\n\n**Tip:** The \\`language\\`, \\`calendarType\\`, \\`hideDashboardFilters\\`, and filter settings are all configurable via \\`update_embed\\` body passthrough.\n\n**Important:** After changing language or translation settings, 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","export const secureMyEmbedPrompt = `You are helping the user secure and configure permissions for their embedded Databrain dashboard. Follow these steps.\n\n**Step 1 — Understand User Roles**\nAsk the user about their end-user roles. Common patterns:\n- **Viewer** — can see data, maybe filter, but can't modify anything\n- **Analyst** — can export data, drill down, use filters\n- **Builder/Power User** — can create/edit metrics, change layouts\n- **Admin** — full access including AI features\n\nAsk: \"What roles do your end-users have? What should each role be allowed to do?\"\n\n**Step 2 — Lock Down the Embed Defaults**\nUse \\`update_embed\\` (body passthrough with options) to set restrictive defaults (principle of least privilege):\n\n\\`\\`\\`\nupdate_embed(embedId, body: { options: {\n disableMetricCreation: true,\n disableMetricUpdation: true,\n disableMetricDeletion: true,\n disableManageMetrics: true,\n disableLayoutCustomization: true,\n disableSaveLayout: true,\n disableUnderlyingData: true,\n disableScheduleEmailReports: true,\n enableDownloadCsv: false,\n enableDownloadAllPdf: false)\n\\`\\`\\`\n\nExplain: \"We start with everything locked down, then use guest token permissions to grant access per role.\"\n\n**Step 3 — Create Role-Based Guest Token Examples**\nShow the user how to generate tokens for each role:\n\n**Viewer (default — no overrides needed):**\n\\`\\`\\`\ngenerate_guest_token(clientId, dataAppName)\n\\`\\`\\`\n\n**Analyst (can export and drill down):**\n\\`\\`\\`\ngenerate_guest_token(clientId, dataAppName, {\n permissions: {\n isEnableDownloadMetrics: true,\n isEnableUnderlyingData: true\n }\n})\n\\`\\`\\`\n\n**Builder (can create and edit):**\n\\`\\`\\`\ngenerate_guest_token(clientId, dataAppName, {\n permissions: {\n isEnableManageMetrics: true,\n isEnableMetricUpdation: true,\n isEnableCustomizeLayout: true\n }\n})\n\\`\\`\\`\n\n**Admin (full access with AI):**\n\\`\\`\\`\ngenerate_guest_token(clientId, dataAppName, {\n permissions: {\n isEnableManageMetrics: true,\n isEnableMetricUpdation: true,\n isEnableCustomizeLayout: true,\n isEnableDownloadMetrics: true,\n isEnableUnderlyingData: true\n }\n})\n\\`\\`\\`\n\n**Step 4 — Multi-Tenancy Check**\nAsk: \"Do different customers/organizations see different data?\"\n\nIf yes:\n- Explain that \\`clientId\\` in the guest token controls row-level security\n- The \\`clientId\\` must match values in the datamart's client column\n- Suggest using \\`params.appFilters\\` / \\`params.dashboardAppFilters\\` in \\`generate_guest_token\\` for server-side row-level filtering\n\n**Step 5 — Security Checklist**\nWalk through this checklist with the user:\n\n1. ✅ API token is stored server-side only (never in frontend code)\n2. ✅ Guest tokens are generated server-side per request\n3. ✅ Guest tokens have appropriate expiry time\n4. ✅ Embed defaults are restrictive (locked down in Step 2)\n5. ✅ Role-based permissions are granted via guest token overrides\n6. ✅ Multi-tenancy is configured if serving multiple customers\n7. ✅ Download restrictions are set (\\`disableDownloadDataNoFilters\\` if needed)\n\n**Step 6 — Generate Secure Frontend Code**\nCall \\`generate_embed_code\\` for their framework. Emphasize that the generated code includes a backend route for token generation — this is the secure pattern.\n\nWhen reviewing runtime behavior (for example missing \\`+ Create Metric\\`), verify contract shape explicitly:\n- Guest token request body must send \\`permissions\\` at top level (not nested inside \\`params\\`)\n- Include \\`dataAppName\\` at top level\n- For metric creation flows, ensure \\`permissions.isDisableMetricCreation=false\\` and \\`permissions.isEnableManageMetrics=true\\`\n- Confirm embed options do not set \\`disableMetricCreation=true\\`\n- In browser network response for \\`/api/v2/dashboard\\`, confirm \\`isAllowedToCreateMetrics=true\\` and \\`metricCreationMode=DRAG_DROP\\`\n\n**Important:** After changing embed permissions or access settings, 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://self-serve-reference\\` for all permission flags and \\`databrain://multi-tenancy-guide\\` for row-level security details.`;\n","export const setupFiltersPrompt = `You are helping the user configure dashboard filters for their embedded Databrain dashboard. Follow these steps.\n\n**Step 1 — Understand the Data**\nCall \\`list_embeds\\` and ask which embed to configure. Then call \\`get_embed_details\\` to see the current filter configuration.\n\n**Step 2 — Identify Filter Needs**\nAsk the user:\n- \"What filters do your end-users need?\" (e.g. date range, region, product category, status)\n- \"Should any filters have default values?\"\n- \"Are there filters you want to hide from end-users?\" (e.g. internal IDs)\n- \"Do any filters have very large option lists?\" (100+ options — these benefit from SQL-based filters)\n\n**Step 3 — Configure String Filters**\nFor text/category filters, use \\`update_embed\\` (body passthrough with options.globalFilterOptions) for \\`stringFilters\\`:\n\n\\`\\`\\`\nstringFilters: [{\n filterName: \"Region\",\n options: [\n { value: \"US\", label: \"United States\" },\n { value: \"EU\", label: \"Europe\" },\n { value: \"APAC\", label: \"Asia Pacific\" }\n ],\n defaultOption: \"US\"\n}]\n\\`\\`\\`\n\nFor multi-select defaults, use an array: \\`defaultOption: [\"US\", \"EU\"]\\`\n\n**Step 4 — Configure Date Filters**\nFor date range filters, use \\`dateFilters\\`:\n\n\\`\\`\\`\ndateFilters: [{\n filterName: \"Date Range\",\n startDate: \"2024-01-01\",\n endDate: \"2024-12-31\",\n datePresetOptions: [\n { label: \"Last 30 Days\", type: \"Last\", interval: \"Days\" },\n { label: \"This Quarter\", type: \"This\", interval: \"Quarter\" },\n { label: \"This Year\", type: \"This\", interval: \"Year\" }\n ]\n}]\n\\`\\`\\`\n\n**Step 5 — Configure Number Filters**\nFor numeric range filters, use \\`numberFilters\\`:\n\n\\`\\`\\`\nnumberFilters: [{\n filterName: \"Revenue\",\n min: 0,\n max: 1000000\n}]\n\\`\\`\\`\n\n**Step 6 — SQL-Based Filters (for large datasets)**\nIf a filter has 100+ options (e.g. company names, product SKUs), use \\`sqlFilters\\`:\n\n\\`\\`\\`\nsqlFilters: [{\n filterName: \"Company\",\n sql: \"SELECT DISTINCT \\\\\"company_name\\\\\" FROM \\\\\"companies\\\\\" ORDER BY \\\\\"company_name\\\\\"\",\n columnName: \"company_name\"\n}]\n\\`\\`\\`\n\nExplain: \"SQL filters dynamically fetch options from the database, so they're always up-to-date and don't bloat the embed configuration.\"\n\n**Step 7 — Hide Unnecessary Filters**\nIf the user has filters that should be hidden (e.g. internal IDs, tenant columns already handled by clientId):\n\n\\`\\`\\`\nhideDashboardFilters: [\"internal_id\", \"tenant_id\"]\n\\`\\`\\`\n\n**Step 8 — Configure Date Picker Options**\nAsk if they want to hide certain date picker presets:\n\n\\`\\`\\`\nhideDatePickerOptions: [\"yesterday\", \"last week\"]\n\\`\\`\\`\n\n**Step 9 — Metric Filter Position**\nAsk: \"Do you want metric-level filters inside the card or outside?\"\n- \\`\"inside\"\\` — compact, within each metric card (default)\n- \\`\"outside\"\\` — above the card, more prominent\n\nAlso ask if they want cross-metric filtering (\\`enableMultiMetricFilters\\`).\n\n**Step 10 — Server-Side Filters (via Guest Token)**\nIf the user needs filters that end-users cannot remove (e.g. for security):\n- Explain that \\`appFilters\\` in \\`generate_guest_token\\` are server-side enforced\n- These are invisible to the end-user and cannot be overridden\n- Perfect for tenant filtering, role-based data access, or compliance requirements\n\nShow an example:\n\\`\\`\\`\ngenerate_guest_token(clientId, dataAppName, {\n params: {\n appFilters: [{\n metricId: \"metric_123\",\n values: {\n region: [\"US\", \"CA\"]\n }\n }]\n }\n})\n\\`\\`\\`\n\n**Important:** After changing filter settings, 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://filter-reference\\` for all filter types, operators, and combination rules.`;\n","export const manageEmbedsPrompt = `You are helping the user manage Databrain embed configurations — list, compare, and review settings. Follow these steps based on what the user needs.\n\n**Step 1 — Understand the Task**\nAsk the user what they want to do:\n1. **List and compare embeds** — see all embeds and their configurations\n2. **Review embed settings** — audit theme, permissions, and options\n\n**For Listing and Comparing Embeds:**\n1. Call \\`list_embeds\\` to show all embed configurations\n2. For detailed comparison, call \\`get_embed_details\\` on each embed the user wants to compare\n3. Present a comparison table showing:\n - Embed name and ID\n - Linked dashboard\n - Theme (preset or custom)\n - Key permissions (metric creation, downloads, AI pilot)\n - Multi-tenancy settings\n\n**For Reviewing Embed Settings:**\n1. Call \\`get_embed_details\\` for the embed\n2. Present a clear summary organized by category:\n\n **Theme:**\n - Current preset or custom theme values\n - Suggest \\`customize_embed_theme\\` if they want changes\n\n **Permissions / Access Settings:**\n - What's enabled vs disabled\n - Suggest \\`update_embed\\` for changes\n\n **Filters:**\n - Current filter configuration\n - Suggest \\`update_embed\\` (body passthrough with options.globalFilterOptions) for changes\n\n **Internationalization:**\n - Current language and translations\n - Suggest \\`update_embed\\` (body passthrough with componentAttributes) for changes\n\n3. Ask: \"Would you like to modify any of these settings?\"\n\n**Tips:**\n- Embed IDs are permanent — even if you rename an embed, the ID stays the same\n- After any embed setting changes, existing guest tokens still carry the old configuration — **regenerate guest tokens** for changes to take effect`;\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**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 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**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:** Set semantic types when obvious: \"Date\", \"Number\", \"Identifier\", \"Category\", \"Currency\", \"Email\", \"Name\", etc.\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","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { embedExistingDashboardPrompt } from './embed-existing-dashboard.js';\nimport { embedBlankDashboardPrompt } from './embed-blank-dashboard.js';\nimport { enableMetricCreationPrompt } from './enable-metric-creation.js';\nimport { brandMyEmbedPrompt } from './brand-my-embed.js';\nimport { localizeEmbedPrompt } from './localize-embed.js';\nimport { secureMyEmbedPrompt } from './secure-my-embed.js';\nimport { setupFiltersPrompt } from './setup-filters.js';\nimport { manageEmbedsPrompt } from './manage-embeds.js';\nimport { queryDataPrompt } from './query-data.js';\nimport { populateSemanticLayerPrompt } from './populate-semantic-layer.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: '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: 'Multi-tenant blank dashboard setup: each client gets their own dashboard copy via create_embed with clientId',\n content: embedBlankDashboardPrompt,\n },\n {\n name: 'enable-metric-creation',\n description: 'Enable end-user metric creation on embeds: DRAG_DROP (visual) or CHAT (AI-powered) modes',\n content: enableMetricCreationPrompt,\n },\n {\n name: 'brand-my-embed',\n description: 'Customize colors, fonts, chart styles, and component theme to match your brand',\n content: brandMyEmbedPrompt,\n },\n {\n name: 'localize-embed',\n description: 'Set up multi-language support with translations and locale settings',\n content: localizeEmbedPrompt,\n },\n {\n name: 'secure-my-embed',\n description: 'Configure permissions, access controls, and role-based guest tokens',\n content: secureMyEmbedPrompt,\n },\n {\n name: 'setup-filters',\n description: 'Configure dashboard filters: string, date, number, SQL-based, and server-side filters',\n content: setupFiltersPrompt,\n },\n {\n name: 'manage-embeds',\n description: 'List, compare, rename, delete embeds and rotate API tokens',\n content: manageEmbedsPrompt,\n },\n {\n name: 'query-data',\n description: '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: 'Auto-generate and push table/column descriptions to enable natural language querying on a datamart',\n content: populateSemanticLayerPrompt,\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"],"mappings":"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AA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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,sBAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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,+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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACArC,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;;;ACAlC,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,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;AA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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;;;ACAnC,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,sBAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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,sBAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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,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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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,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;;;ACA3B,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;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","names":["z","isNonEmptyString","z","z","z","z","z","z","z","z","z","key","z","z","z","z","z","z","z","DEFAULT_ACCESS_SETTINGS","z","body","result","embedId","z","z","z","z","z","z","result","z","z","z","z","result","z","kebabCase","buildAttributes","kebabCase","buildAttributes","kebabCase","buildAttributes","kebabCase","buildAttributes","kebabCase","buildAttributes","kebabCase","buildAttributes","z","z","z","z","z","z","z","z","z"]}