drizzle-cube 0.4.44 → 0.4.45

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.
@@ -0,0 +1,70 @@
1
+ const e=require(`./utils-tNZ6Cvzw.cjs`),t=require(`./mcp-prompts-DsAkafVn.cjs`);let n=require(`fs`),r=require(`path`),i=require(`url`);var a=`ui://drizzle-cube/visualization.html`,o=`text/html;profile=mcp-app`,s=null;function c(){if(!(typeof process<`u`&&process.env.NODE_ENV!==`production`)&&s!==null)return s;let e=(0,r.dirname)((0,i.fileURLToPath)({}.url)),t=[(0,r.join)(e,`../mcp-app/mcp-app.html`),(0,r.join)(e,`../../dist/mcp-app/mcp-app.html`)];for(let e of t)try{let t=(0,n.readFileSync)(e,`utf-8`);if(t.length>1e3)return s=t,s}catch{}return null}var l=[`2025-11-25`,`2025-06-18`,`2025-03-26`],u=`2025-11-25`;function d(e){let t=S(e[`mcp-protocol-version`])||`2025-11-25`;return{ok:l.includes(t),negotiated:l.includes(t)?t:null,supported:l}}function f(e){if(!e)return!1;let t=e.split(`,`).map(e=>e.trim().toLowerCase()),n=t.includes(`text/event-stream`),r=t.includes(`application/json`);return n&&!r}var p=`mcp-session-id`;function m(e){if(!e)return!1;let t=e.split(`,`).map(e=>e.trim().toLowerCase().split(`;`)[0]),n=t.some(e=>e===`application/json`),r=t.some(e=>e===`text/event-stream`);return n&&r}function h(e,t={}){let{allowMissingOrigin:n=!0,allowedOrigins:r}=t;if(!e)return n?{valid:!0}:{valid:!1,reason:`Origin header is required`};if(!r||r.length===0)return{valid:!0};let i;try{i=new URL(e)}catch{return{valid:!1,reason:`Invalid Origin header format`}}return r.map(e=>{try{return new URL(e).origin}catch{return e}}).includes(i.origin)?{valid:!0}:{valid:!1,reason:`Origin not in allowed list`}}function g(e,t,n){let r=[];return t&&r.push(`id: ${t}`),n&&n>0&&r.push(`retry: ${n}`),r.push(`event: message`),r.push(`data: ${JSON.stringify(e)}`),r.push(``),r.join(`
2
+ `)}function _(e,t,n,r){return{jsonrpc:`2.0`,id:e??null,error:{code:t,message:n,...r===void 0?{}:{data:r}}}}function v(e,t){return{jsonrpc:`2.0`,id:e??null,result:t}}function y(e){if(!e||typeof e!=`object`)return null;let t=e;return t.jsonrpc!==`2.0`||typeof t.method!=`string`?null:{jsonrpc:`2.0`,method:t.method,id:t.id,params:t.params}}async function b(t,n,r){let{semanticLayer:i,extractSecurityContext:a,rawRequest:o,rawResponse:s,appEnabled:c}=r,d=r.prompts??k,f=r.resources??A,p=c?[...f,...O()]:f;switch(t){case`initialize`:{let e=n?.protocolVersion,t;return t=e&&l.includes(e)?e:u,{protocolVersion:t,capabilities:{tools:{listChanged:!1},resources:{listChanged:!1},prompts:{listChanged:!1},sampling:{}},sessionId:w(),serverInfo:{name:`drizzle-cube`,version:typeof process<`u`?process.env?.npm_package_version||`dev`:`worker`}}}case`list_tools`:case`tools/list`:return{tools:T({appEnabled:c}),nextCursor:``};case`call_tool`:case`tools/call`:return E(n,r);case`resources/list`:return{resources:p.map(({uri:e,name:t,description:n,mimeType:r})=>({uri:e,name:t,description:n,mimeType:r})),nextCursor:``};case`resources/templates/list`:return{resourceTemplates:[],nextCursor:``};case`resources/read`:{let e=n?.uri,t=p.find(t=>t.uri===e)||p[0];if(!t)throw x(-32602,`resource not found`);return{contents:[{uri:t.uri,mimeType:t.mimeType,text:t.text}]}}case`prompts/list`:return{prompts:d.map(({name:e,description:t})=>({name:e,description:t})),nextCursor:``};case`ping`:return{};case`notifications/initialized`:return{};case`prompts/get`:{let e=n?.name,t=d.find(t=>t.name===e)||d[0];if(!t)throw x(-32602,`prompt not found`);return{name:t.name,description:t.description,messages:t.messages}}case`discover`:return e.d(i,n||{});case`validate`:{let t=n||{};if(!t.query)throw x(-32602,`query is required`);return e.h(i,t)}case`load`:{let t=n||{};if(!t.query)throw x(-32602,`query is required`);return e.p(i,await a(o,s),t)}default:throw x(-32601,`Unknown MCP method: ${t}`)}}function x(e,t,n){let r=Error(t);return r.code=e,n!==void 0&&(r.data=n),r}function S(e){return e?Array.isArray(e)?e[0]||null:e:null}function C(e){return e.id===void 0||e.id===null}function w(){return`evt-${e.c()}`}function T(e){let t=[{name:`discover`,description:`Find relevant cubes based on topic or intent. Call this FIRST to understand available data.
3
+
4
+ Returns cubes with:
5
+ - All measures and dimensions with their types
6
+ - Relationship information (joins) showing how cubes connect
7
+ - Metadata hints (eventStream for funnels, etc.)
8
+
9
+ IMPORTANT: The 'joins' property shows relationships between cubes. You can include dimensions from ANY related cube in your query - the system auto-joins them.
10
+
11
+ Example: If Productivity has a join to Employees, you can query:
12
+ { "measures": ["Productivity.totalPullRequests"], "dimensions": ["Employees.name"] }`,inputSchema:{type:`object`,properties:{topic:{type:`string`,description:`Keyword to search (e.g., "sales", "employees")`},intent:{type:`string`,description:`Natural language goal (e.g., "analyze productivity trends")`},limit:{type:`number`,description:`Max results (default: 10)`},minScore:{type:`number`,description:`Min relevance 0-1 (default: 0.1)`}}}},{name:`validate`,description:`Validate a query and get auto-corrections for issues.
13
+
14
+ Checks:
15
+ - Field existence (measures, dimensions exist in schema)
16
+ - Filter syntax and operators
17
+ - Cross-cube join validity
18
+
19
+ Returns corrected query if issues found.`,inputSchema:{type:`object`,required:[`query`],properties:{query:{type:`object`,description:`CubeQuery to validate`}}}},{name:`load`,description:`Execute a semantic query and return aggregated results.
20
+
21
+ QUERY CONSTRUCTION RULES:
22
+
23
+ 1. CROSS-CUBE JOINS (use dimensions from related cubes!)
24
+ Check 'joins' in discover results. Include dimensions from ANY related cube.
25
+ Example - get employee names with their productivity:
26
+ {
27
+ "measures": ["Productivity.totalPullRequests"],
28
+ "dimensions": ["Employees.name"],
29
+ "filters": [{ "member": "Productivity.date", "operator": "inDateRange", "values": ["last 3 months"] }]
30
+ }
31
+
32
+ 2. DATE FILTERING vs TIME GROUPING
33
+ For AGGREGATED TOTALS: use 'filters' with 'inDateRange' (NOT timeDimensions)
34
+ {
35
+ "measures": ["Productivity.totalPullRequests"],
36
+ "dimensions": ["Employees.name"],
37
+ "filters": [{ "member": "Productivity.date", "operator": "inDateRange", "values": ["last 3 months"] }],
38
+ "order": { "Productivity.totalPullRequests": "desc" },
39
+ "limit": 5
40
+ }
41
+
42
+ For TIME SERIES: use 'timeDimensions' WITH 'granularity'
43
+ {
44
+ "measures": ["Productivity.totalPullRequests"],
45
+ "timeDimensions": [{ "dimension": "Productivity.date", "dateRange": "last 3 months", "granularity": "month" }]
46
+ }
47
+
48
+ WARNING: timeDimensions WITHOUT granularity groups by day, returning many rows!
49
+
50
+ 3. TOP N PATTERN: filters + order + limit
51
+
52
+ CHART HINTS: When an MCP App UI is available, include a "chart" object to control the rendered chart.
53
+ Available types: bar, line, area, pie, scatter, kpiNumber, table, treemap
54
+
55
+ Guidelines for choosing chart type:
56
+ - Single aggregate number → kpiNumber
57
+ - Trend over time → line (or area for cumulative)
58
+ - Category comparison → bar (few categories) or table (many)
59
+ - Part-of-whole / share → pie (≤10 categories)
60
+ - Correlation between 2 measures → scatter (set xAxis/yAxis to measures)
61
+ - Hierarchical breakdown → treemap
62
+ - Raw data / detail → table`,inputSchema:{type:`object`,required:[`query`],properties:{query:{type:`object`,description:`CubeQuery object with:
63
+ - measures: string[] - Aggregations (from any cube)
64
+ - dimensions: string[] - Grouping fields (can be from RELATED cubes via joins)
65
+ - filters: [{ member, operator, values }] - Use 'inDateRange' for date filtering
66
+ - timeDimensions: [{ dimension, granularity, dateRange }] - ONLY for time series
67
+ - order: { "Cube.field": "asc"|"desc" }
68
+ - limit: number`},chart:{type:`object`,description:`Optional chart configuration for the MCP App UI. If omitted, chart type is auto-detected.`,properties:{type:{type:`string`,enum:[`bar`,`line`,`area`,`pie`,`scatter`,`kpiNumber`,`table`,`treemap`],description:`Chart type to render`},xAxis:{type:`string`,description:`Field for X axis (e.g. "Cube.dimension"). For scatter with 2 measures, set to the first measure.`},yAxis:{type:`array`,items:{type:`string`},description:`Fields for Y axis (measures). For scatter, use a single measure here paired with xAxis as the other measure.`},title:{type:`string`,description:`Chart title`}}}}}}];if(e?.appEnabled){let e=t.find(e=>e.name===`load`);e&&(e._meta={ui:{resourceUri:a}})}return t}async function E(t,n){let{semanticLayer:r,extractSecurityContext:i,rawRequest:a,rawResponse:o}=n,s=t||{};if(!s.name)throw x(-32602,`name is required for tools/call`);let c=s.arguments;switch(s.name){case`discover`:return D(await e.d(r,c||{}));case`validate`:{let t=c||{};if(!t.query)throw x(-32602,`query is required`);return D(await e.h(r,t))}case`load`:{let t=c||{};if(!t.query)throw x(-32602,`query is required`);return D(await e.p(r,await i(a,o),t))}default:throw x(-32601,`Unknown tool: ${s.name}`)}}function D(e){return{content:[{type:`text`,text:typeof e==`string`?e:JSON.stringify(e)}],isError:!1}}function O(){let e=c();return e?[{uri:a,name:`Drizzle Cube Visualization`,description:`Interactive chart visualization for query results`,mimeType:o,text:e}]:[]}var k=t.a(),A=[{uri:`drizzle-cube://quickstart`,name:`Drizzle Cube MCP Quickstart`,description:`Minimal guide for using discover/suggest/validate/load`,mimeType:`text/markdown`,text:[`# Drizzle Cube MCP Quickstart`,``,`Tools:`,`- discover: { topic?, intent?, limit?, minScore? } → cubes list`,`- suggest: { naturalLanguage, cube? } → draft query`,`- validate: { query } → corrected query + issues`,`- load: { query } → data + annotation`,``,`Recommended flow:`,`1) tools/list`,`2) tools/call name=discover intent="<goal>"`,`3) tools/call name=suggest naturalLanguage="<goal>"`,`4) tools/call name=validate query=<from suggest>`,`5) tools/call name=load query=<validated>`,``,`Query shapes supported:`,`- regular Cube.js-style query { measures, dimensions, filters, timeDimensions, order, limit, offset }`,`- funnel { bindingKey, timeDimension, steps[], includeTimeMetrics? }`,`- flow { bindingKey, eventDimension, steps?, window? }`,`- retention { bindingKey, timeDimension, periods, granularity, retentionType, breakdownDimensions }`,``,`Filter rules: flat arrays of { member, operator, values }; do not nest arrays.`].join(`
69
+ `)},{uri:`drizzle-cube://query-shapes`,name:`Query Shapes Reference`,description:`Detailed schema examples for regular, funnel, flow, and retention queries`,mimeType:`text/markdown`,text:[`# Query Shapes`,``,`## Regular query`,"```json",`{`,` "measures": ["Sales.count"],`,` "dimensions": ["Sales.channel"],`,` "filters": [ { "member": "Sales.status", "operator": "equals", "values": ["paid"] } ],`,` "timeDimensions": [ { "dimension": "Sales.createdAt", "dateRange": "last 30 days", "granularity": "day" } ],`,` "order": { "Sales.createdAt": "asc" },`,` "limit": 500`,`}`,"```",``,`## Funnel`,"```json",`{`,` "funnel": {`,` "bindingKey": "Events.userId",`,` "timeDimension": "Events.timestamp",`,` "steps": [`,` { "name": "Signup", "filter": [{ "member": "Events.eventType", "operator": "equals", "values": ["signup"] }] },`,` { "name": "Purchase", "filter": [{ "member": "Events.eventType", "operator": "equals", "values": ["purchase"] }] }`,` ],`,` "includeTimeMetrics": true`,` }`,`}`,"```",``,`## Flow`,"```json",`{`,` "flow": {`,` "bindingKey": "Events.sessionId",`,` "eventDimension": "Events.eventType",`,` "steps": ["view", "add_to_cart", "checkout"],`,` "window": { "unit": "minute", "value": 30 }`,` }`,`}`,"```",``,`## Retention`,"```json",`{`,` "retention": {`,` "bindingKey": "Users.id",`,` "timeDimension": "Events.timestamp",`,` "periods": 8,`,` "granularity": "week",`,` "retentionType": "rolling",`,` "breakdownDimensions": ["Events.country"]`,` }`,`}`,"```",``,`### Filter rules`,`- Always a flat array of filter objects: [{ member, operator, values }]`,`- For funnels, put time filter (inDateRange) only on step 0`,`- Operators: equals, notEquals, inDateRange, gt, gte, lt, lte, contains, notContains, set, notSet`,``,`### Time handling`,`- Relative ranges ("last 3 months") -> add ONLY an inDateRange filter on the time dimension (do NOT add timeDimensions unless grouping is requested).`,`- Grouping ("by month/week/day") -> add timeDimensions entry with granularity.`,`- Both can be combined: inDateRange filter + timeDimensions granularity.`].join(`
70
+ `)}];function j(){return A}function M(){return k}Object.defineProperty(exports,`_`,{enumerable:!0,get:function(){return h}}),Object.defineProperty(exports,`a`,{enumerable:!0,get:function(){return v}}),Object.defineProperty(exports,`c`,{enumerable:!0,get:function(){return M}}),Object.defineProperty(exports,`d`,{enumerable:!0,get:function(){return C}}),Object.defineProperty(exports,`f`,{enumerable:!0,get:function(){return d}}),Object.defineProperty(exports,`g`,{enumerable:!0,get:function(){return m}}),Object.defineProperty(exports,`h`,{enumerable:!0,get:function(){return g}}),Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return _}}),Object.defineProperty(exports,`l`,{enumerable:!0,get:function(){return j}}),Object.defineProperty(exports,`m`,{enumerable:!0,get:function(){return w}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return a}}),Object.defineProperty(exports,`o`,{enumerable:!0,get:function(){return T}}),Object.defineProperty(exports,`p`,{enumerable:!0,get:function(){return y}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return p}}),Object.defineProperty(exports,`s`,{enumerable:!0,get:function(){return b}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return o}}),Object.defineProperty(exports,`u`,{enumerable:!0,get:function(){return c}}),Object.defineProperty(exports,`v`,{enumerable:!0,get:function(){return f}});
@@ -1,31 +1,44 @@
1
1
  import { c as e, d as t, h as n, p as r } from "./utils-C7Nrw9Wb.js";
2
2
  import { a as i } from "./mcp-prompts-BAutSQYA.js";
3
+ import { readFileSync as a } from "fs";
4
+ import { dirname as o, join as s } from "path";
5
+ import { fileURLToPath as c } from "url";
3
6
  //#region src/adapters/mcp-transport.ts
4
- var a = [
7
+ var l = "ui://drizzle-cube/visualization.html", u = "text/html;profile=mcp-app", d = null;
8
+ function f() {
9
+ if (!(typeof process < "u" && process.env.NODE_ENV !== "production") && d !== null) return d;
10
+ let e = o(c(import.meta.url)), t = [s(e, "../mcp-app/mcp-app.html"), s(e, "../../dist/mcp-app/mcp-app.html")];
11
+ for (let e of t) try {
12
+ let t = a(e, "utf-8");
13
+ if (t.length > 1e3) return d = t, d;
14
+ } catch {}
15
+ return null;
16
+ }
17
+ var p = [
5
18
  "2025-11-25",
6
19
  "2025-06-18",
7
20
  "2025-03-26"
8
- ], o = "2025-11-25";
9
- function s(e) {
10
- let t = v(e["mcp-protocol-version"]) || "2025-11-25";
21
+ ], m = "2025-11-25";
22
+ function h(e) {
23
+ let t = E(e["mcp-protocol-version"]) || "2025-11-25";
11
24
  return {
12
- ok: a.includes(t),
13
- negotiated: a.includes(t) ? t : null,
14
- supported: a
25
+ ok: p.includes(t),
26
+ negotiated: p.includes(t) ? t : null,
27
+ supported: p
15
28
  };
16
29
  }
17
- function c(e) {
30
+ function g(e) {
18
31
  if (!e) return !1;
19
32
  let t = e.split(",").map((e) => e.trim().toLowerCase()), n = t.includes("text/event-stream"), r = t.includes("application/json");
20
33
  return n && !r;
21
34
  }
22
- var l = "mcp-session-id";
23
- function u(e) {
35
+ var _ = "mcp-session-id";
36
+ function v(e) {
24
37
  if (!e) return !1;
25
38
  let t = e.split(",").map((e) => e.trim().toLowerCase().split(";")[0]), n = t.some((e) => e === "application/json"), r = t.some((e) => e === "text/event-stream");
26
39
  return n && r;
27
40
  }
28
- function d(e, t = {}) {
41
+ function y(e, t = {}) {
29
42
  let { allowMissingOrigin: n = !0, allowedOrigins: r } = t;
30
43
  if (!e) return n ? { valid: !0 } : {
31
44
  valid: !1,
@@ -52,11 +65,11 @@ function d(e, t = {}) {
52
65
  reason: "Origin not in allowed list"
53
66
  };
54
67
  }
55
- function f(e, t, n) {
68
+ function b(e, t, n) {
56
69
  let r = [];
57
70
  return t && r.push(`id: ${t}`), n && n > 0 && r.push(`retry: ${n}`), r.push("event: message"), r.push(`data: ${JSON.stringify(e)}`), r.push(""), r.join("\n");
58
71
  }
59
- function p(e, t, n, r) {
72
+ function x(e, t, n, r) {
60
73
  return {
61
74
  jsonrpc: "2.0",
62
75
  id: e ?? null,
@@ -67,14 +80,14 @@ function p(e, t, n, r) {
67
80
  }
68
81
  };
69
82
  }
70
- function m(e, t) {
83
+ function S(e, t) {
71
84
  return {
72
85
  jsonrpc: "2.0",
73
86
  id: e ?? null,
74
87
  result: t
75
88
  };
76
89
  }
77
- function h(e) {
90
+ function C(e) {
78
91
  if (!e || typeof e != "object") return null;
79
92
  let t = e;
80
93
  return t.jsonrpc !== "2.0" || typeof t.method != "string" ? null : {
@@ -84,12 +97,12 @@ function h(e) {
84
97
  params: t.params
85
98
  };
86
99
  }
87
- async function g(e, i, s) {
88
- let { semanticLayer: c, extractSecurityContext: l, rawRequest: u, rawResponse: d } = s, f = s.prompts ?? w, p = s.resources ?? T;
100
+ async function w(e, i, a) {
101
+ let { semanticLayer: o, extractSecurityContext: s, rawRequest: c, rawResponse: l, appEnabled: u } = a, d = a.prompts ?? N, f = a.resources ?? P, h = u ? [...f, ...M()] : f;
89
102
  switch (e) {
90
103
  case "initialize": {
91
104
  let e = i?.protocolVersion, t;
92
- return t = e && a.includes(e) ? e : o, {
105
+ return t = e && p.includes(e) ? e : m, {
93
106
  protocolVersion: t,
94
107
  capabilities: {
95
108
  tools: { listChanged: !1 },
@@ -97,7 +110,7 @@ async function g(e, i, s) {
97
110
  prompts: { listChanged: !1 },
98
111
  sampling: {}
99
112
  },
100
- sessionId: b(),
113
+ sessionId: O(),
101
114
  serverInfo: {
102
115
  name: "drizzle-cube",
103
116
  version: typeof process < "u" ? process.env?.npm_package_version || "dev" : "worker"
@@ -106,13 +119,13 @@ async function g(e, i, s) {
106
119
  }
107
120
  case "list_tools":
108
121
  case "tools/list": return {
109
- tools: x(),
122
+ tools: k({ appEnabled: u }),
110
123
  nextCursor: ""
111
124
  };
112
125
  case "call_tool":
113
- case "tools/call": return S(i, s);
126
+ case "tools/call": return A(i, a);
114
127
  case "resources/list": return {
115
- resources: p.map(({ uri: e, name: t, description: n, mimeType: r }) => ({
128
+ resources: h.map(({ uri: e, name: t, description: n, mimeType: r }) => ({
116
129
  uri: e,
117
130
  name: t,
118
131
  description: n,
@@ -125,8 +138,8 @@ async function g(e, i, s) {
125
138
  nextCursor: ""
126
139
  };
127
140
  case "resources/read": {
128
- let e = i?.uri, t = p.find((t) => t.uri === e) || p[0];
129
- if (!t) throw _(-32602, "resource not found");
141
+ let e = i?.uri, t = h.find((t) => t.uri === e) || h[0];
142
+ if (!t) throw T(-32602, "resource not found");
130
143
  return { contents: [{
131
144
  uri: t.uri,
132
145
  mimeType: t.mimeType,
@@ -134,7 +147,7 @@ async function g(e, i, s) {
134
147
  }] };
135
148
  }
136
149
  case "prompts/list": return {
137
- prompts: f.map(({ name: e, description: t }) => ({
150
+ prompts: d.map(({ name: e, description: t }) => ({
138
151
  name: e,
139
152
  description: t
140
153
  })),
@@ -143,43 +156,43 @@ async function g(e, i, s) {
143
156
  case "ping": return {};
144
157
  case "notifications/initialized": return {};
145
158
  case "prompts/get": {
146
- let e = i?.name, t = f.find((t) => t.name === e) || f[0];
147
- if (!t) throw _(-32602, "prompt not found");
159
+ let e = i?.name, t = d.find((t) => t.name === e) || d[0];
160
+ if (!t) throw T(-32602, "prompt not found");
148
161
  return {
149
162
  name: t.name,
150
163
  description: t.description,
151
164
  messages: t.messages
152
165
  };
153
166
  }
154
- case "discover": return t(c, i || {});
167
+ case "discover": return t(o, i || {});
155
168
  case "validate": {
156
169
  let e = i || {};
157
- if (!e.query) throw _(-32602, "query is required");
158
- return n(c, e);
170
+ if (!e.query) throw T(-32602, "query is required");
171
+ return n(o, e);
159
172
  }
160
173
  case "load": {
161
174
  let e = i || {};
162
- if (!e.query) throw _(-32602, "query is required");
163
- return r(c, await l(u, d), e);
175
+ if (!e.query) throw T(-32602, "query is required");
176
+ return r(o, await s(c, l), e);
164
177
  }
165
- default: throw _(-32601, `Unknown MCP method: ${e}`);
178
+ default: throw T(-32601, `Unknown MCP method: ${e}`);
166
179
  }
167
180
  }
168
- function _(e, t, n) {
181
+ function T(e, t, n) {
169
182
  let r = Error(t);
170
183
  return r.code = e, n !== void 0 && (r.data = n), r;
171
184
  }
172
- function v(e) {
185
+ function E(e) {
173
186
  return e ? Array.isArray(e) ? e[0] || null : e : null;
174
187
  }
175
- function y(e) {
188
+ function D(e) {
176
189
  return e.id === void 0 || e.id === null;
177
190
  }
178
- function b() {
191
+ function O() {
179
192
  return `evt-${e()}`;
180
193
  }
181
- function x() {
182
- return [
194
+ function k(e) {
195
+ let t = [
183
196
  {
184
197
  name: "discover",
185
198
  description: "Find relevant cubes based on topic or intent. Call this FIRST to understand available data.\n\nReturns cubes with:\n- All measures and dimensions with their types\n- Relationship information (joins) showing how cubes connect\n- Metadata hints (eventStream for funnels, etc.)\n\nIMPORTANT: The 'joins' property shows relationships between cubes. You can include dimensions from ANY related cube in your query - the system auto-joins them.\n\nExample: If Productivity has a join to Employees, you can query:\n{ \"measures\": [\"Productivity.totalPullRequests\"], \"dimensions\": [\"Employees.name\"] }",
@@ -219,38 +232,78 @@ function x() {
219
232
  },
220
233
  {
221
234
  name: "load",
222
- description: "Execute a semantic query and return aggregated results.\n\nQUERY CONSTRUCTION RULES:\n\n1. CROSS-CUBE JOINS (use dimensions from related cubes!)\n Check 'joins' in discover results. Include dimensions from ANY related cube.\n Example - get employee names with their productivity:\n {\n \"measures\": [\"Productivity.totalPullRequests\"],\n \"dimensions\": [\"Employees.name\"],\n \"filters\": [{ \"member\": \"Productivity.date\", \"operator\": \"inDateRange\", \"values\": [\"last 3 months\"] }]\n }\n\n2. DATE FILTERING vs TIME GROUPING\n For AGGREGATED TOTALS: use 'filters' with 'inDateRange' (NOT timeDimensions)\n {\n \"measures\": [\"Productivity.totalPullRequests\"],\n \"dimensions\": [\"Employees.name\"],\n \"filters\": [{ \"member\": \"Productivity.date\", \"operator\": \"inDateRange\", \"values\": [\"last 3 months\"] }],\n \"order\": { \"Productivity.totalPullRequests\": \"desc\" },\n \"limit\": 5\n }\n\n For TIME SERIES: use 'timeDimensions' WITH 'granularity'\n {\n \"measures\": [\"Productivity.totalPullRequests\"],\n \"timeDimensions\": [{ \"dimension\": \"Productivity.date\", \"dateRange\": \"last 3 months\", \"granularity\": \"month\" }]\n }\n\n WARNING: timeDimensions WITHOUT granularity groups by day, returning many rows!\n\n3. TOP N PATTERN: filters + order + limit",
235
+ description: "Execute a semantic query and return aggregated results.\n\nQUERY CONSTRUCTION RULES:\n\n1. CROSS-CUBE JOINS (use dimensions from related cubes!)\n Check 'joins' in discover results. Include dimensions from ANY related cube.\n Example - get employee names with their productivity:\n {\n \"measures\": [\"Productivity.totalPullRequests\"],\n \"dimensions\": [\"Employees.name\"],\n \"filters\": [{ \"member\": \"Productivity.date\", \"operator\": \"inDateRange\", \"values\": [\"last 3 months\"] }]\n }\n\n2. DATE FILTERING vs TIME GROUPING\n For AGGREGATED TOTALS: use 'filters' with 'inDateRange' (NOT timeDimensions)\n {\n \"measures\": [\"Productivity.totalPullRequests\"],\n \"dimensions\": [\"Employees.name\"],\n \"filters\": [{ \"member\": \"Productivity.date\", \"operator\": \"inDateRange\", \"values\": [\"last 3 months\"] }],\n \"order\": { \"Productivity.totalPullRequests\": \"desc\" },\n \"limit\": 5\n }\n\n For TIME SERIES: use 'timeDimensions' WITH 'granularity'\n {\n \"measures\": [\"Productivity.totalPullRequests\"],\n \"timeDimensions\": [{ \"dimension\": \"Productivity.date\", \"dateRange\": \"last 3 months\", \"granularity\": \"month\" }]\n }\n\n WARNING: timeDimensions WITHOUT granularity groups by day, returning many rows!\n\n3. TOP N PATTERN: filters + order + limit\n\nCHART HINTS: When an MCP App UI is available, include a \"chart\" object to control the rendered chart.\nAvailable types: bar, line, area, pie, scatter, kpiNumber, table, treemap\n\nGuidelines for choosing chart type:\n- Single aggregate number → kpiNumber\n- Trend over time → line (or area for cumulative)\n- Category comparison → bar (few categories) or table (many)\n- Part-of-whole / share → pie (≤10 categories)\n- Correlation between 2 measures → scatter (set xAxis/yAxis to measures)\n- Hierarchical breakdown → treemap\n- Raw data / detail → table",
223
236
  inputSchema: {
224
237
  type: "object",
225
238
  required: ["query"],
226
- properties: { query: {
227
- type: "object",
228
- description: "CubeQuery object with:\n- measures: string[] - Aggregations (from any cube)\n- dimensions: string[] - Grouping fields (can be from RELATED cubes via joins)\n- filters: [{ member, operator, values }] - Use 'inDateRange' for date filtering\n- timeDimensions: [{ dimension, granularity, dateRange }] - ONLY for time series\n- order: { \"Cube.field\": \"asc\"|\"desc\" }\n- limit: number"
229
- } }
239
+ properties: {
240
+ query: {
241
+ type: "object",
242
+ description: "CubeQuery object with:\n- measures: string[] - Aggregations (from any cube)\n- dimensions: string[] - Grouping fields (can be from RELATED cubes via joins)\n- filters: [{ member, operator, values }] - Use 'inDateRange' for date filtering\n- timeDimensions: [{ dimension, granularity, dateRange }] - ONLY for time series\n- order: { \"Cube.field\": \"asc\"|\"desc\" }\n- limit: number"
243
+ },
244
+ chart: {
245
+ type: "object",
246
+ description: "Optional chart configuration for the MCP App UI. If omitted, chart type is auto-detected.",
247
+ properties: {
248
+ type: {
249
+ type: "string",
250
+ enum: [
251
+ "bar",
252
+ "line",
253
+ "area",
254
+ "pie",
255
+ "scatter",
256
+ "kpiNumber",
257
+ "table",
258
+ "treemap"
259
+ ],
260
+ description: "Chart type to render"
261
+ },
262
+ xAxis: {
263
+ type: "string",
264
+ description: "Field for X axis (e.g. \"Cube.dimension\"). For scatter with 2 measures, set to the first measure."
265
+ },
266
+ yAxis: {
267
+ type: "array",
268
+ items: { type: "string" },
269
+ description: "Fields for Y axis (measures). For scatter, use a single measure here paired with xAxis as the other measure."
270
+ },
271
+ title: {
272
+ type: "string",
273
+ description: "Chart title"
274
+ }
275
+ }
276
+ }
277
+ }
230
278
  }
231
279
  }
232
280
  ];
281
+ if (e?.appEnabled) {
282
+ let e = t.find((e) => e.name === "load");
283
+ e && (e._meta = { ui: { resourceUri: l } });
284
+ }
285
+ return t;
233
286
  }
234
- async function S(e, i) {
287
+ async function A(e, i) {
235
288
  let { semanticLayer: a, extractSecurityContext: o, rawRequest: s, rawResponse: c } = i, l = e || {};
236
- if (!l.name) throw _(-32602, "name is required for tools/call");
289
+ if (!l.name) throw T(-32602, "name is required for tools/call");
237
290
  let u = l.arguments;
238
291
  switch (l.name) {
239
- case "discover": return C(await t(a, u || {}));
292
+ case "discover": return j(await t(a, u || {}));
240
293
  case "validate": {
241
294
  let e = u || {};
242
- if (!e.query) throw _(-32602, "query is required");
243
- return C(await n(a, e));
295
+ if (!e.query) throw T(-32602, "query is required");
296
+ return j(await n(a, e));
244
297
  }
245
298
  case "load": {
246
299
  let e = u || {};
247
- if (!e.query) throw _(-32602, "query is required");
248
- return C(await r(a, await o(s, c), e));
300
+ if (!e.query) throw T(-32602, "query is required");
301
+ return j(await r(a, await o(s, c), e));
249
302
  }
250
- default: throw _(-32601, `Unknown tool: ${l.name}`);
303
+ default: throw T(-32601, `Unknown tool: ${l.name}`);
251
304
  }
252
305
  }
253
- function C(e) {
306
+ function j(e) {
254
307
  return {
255
308
  content: [{
256
309
  type: "text",
@@ -259,7 +312,17 @@ function C(e) {
259
312
  isError: !1
260
313
  };
261
314
  }
262
- var w = i(), T = [{
315
+ function M() {
316
+ let e = f();
317
+ return e ? [{
318
+ uri: l,
319
+ name: "Drizzle Cube Visualization",
320
+ description: "Interactive chart visualization for query results",
321
+ mimeType: u,
322
+ text: e
323
+ }] : [];
324
+ }
325
+ var N = i(), P = [{
263
326
  uri: "drizzle-cube://quickstart",
264
327
  name: "Drizzle Cube MCP Quickstart",
265
328
  description: "Minimal guide for using discover/suggest/validate/load",
@@ -360,11 +423,11 @@ var w = i(), T = [{
360
423
  "- Both can be combined: inDateRange filter + timeDimensions granularity."
361
424
  ].join("\n")
362
425
  }];
363
- function E() {
364
- return T;
426
+ function F() {
427
+ return P;
365
428
  }
366
- function D() {
367
- return w;
429
+ function I() {
430
+ return N;
368
431
  }
369
432
  //#endregion
370
- export { g as a, y as c, b as d, f, c as h, x as i, s as l, d as m, p as n, D as o, u as p, m as r, E as s, l as t, h as u };
433
+ export { y as _, S as a, I as c, D as d, h as f, v as g, b as h, x as i, F as l, O as m, l as n, k as o, C as p, _ as r, w as s, u as t, f as u, g as v };
@@ -1,6 +1,17 @@
1
1
  import { SemanticLayerCompiler, SecurityContext } from '../server';
2
2
  import { MCPPrompt } from '../server/ai/mcp-prompts';
3
3
  export { type MCPPrompt };
4
+ export declare const MCP_APP_RESOURCE_URI = "ui://drizzle-cube/visualization.html";
5
+ export declare const MCP_APP_MIME_TYPE = "text/html;profile=mcp-app";
6
+ /**
7
+ * Read the bundled MCP App HTML from dist/mcp-app/mcp-app.html.
8
+ * Lazy-loaded and cached for performance.
9
+ *
10
+ * Searches two paths:
11
+ * - From dist/adapters/ (production): ../mcp-app/mcp-app.html → dist/mcp-app/mcp-app.html
12
+ * - From src/adapters/ (dev via tsx): ../../dist/mcp-app/mcp-app.html → dist/mcp-app/mcp-app.html
13
+ */
14
+ export declare function getMcpAppHtml(): string | null;
4
15
  export type JsonRpcId = string | number | null | undefined;
5
16
  export interface JsonRpcRequest {
6
17
  jsonrpc: '2.0';
@@ -26,6 +37,8 @@ export interface McpDispatchContext {
26
37
  negotiatedProtocol?: string | null;
27
38
  resources?: MCPResource[];
28
39
  prompts?: MCPPrompt[];
40
+ /** Enable MCP App visualization for load tool */
41
+ appEnabled?: boolean;
29
42
  }
30
43
  export interface MCPResource {
31
44
  uri: string;
@@ -95,7 +108,9 @@ export declare function jsonRpcError(code: number, message: string, data?: unkno
95
108
  export declare function normalizeHeader(value: string | string[] | undefined): string | null;
96
109
  export declare function isNotification(request: JsonRpcRequest): boolean;
97
110
  export declare function primeEventId(): string;
98
- export declare function buildToolList(): ({
111
+ export declare function buildToolList(options?: {
112
+ appEnabled?: boolean;
113
+ }): ({
99
114
  name: string;
100
115
  description: string;
101
116
  inputSchema: {
@@ -118,6 +133,7 @@ export declare function buildToolList(): ({
118
133
  description: string;
119
134
  };
120
135
  query?: undefined;
136
+ chart?: undefined;
121
137
  };
122
138
  required?: undefined;
123
139
  };
@@ -136,6 +152,50 @@ export declare function buildToolList(): ({
136
152
  intent?: undefined;
137
153
  limit?: undefined;
138
154
  minScore?: undefined;
155
+ chart?: undefined;
156
+ };
157
+ };
158
+ } | {
159
+ name: string;
160
+ description: string;
161
+ inputSchema: {
162
+ type: string;
163
+ required: string[];
164
+ properties: {
165
+ query: {
166
+ type: string;
167
+ description: string;
168
+ };
169
+ chart: {
170
+ type: string;
171
+ description: string;
172
+ properties: {
173
+ type: {
174
+ type: string;
175
+ enum: string[];
176
+ description: string;
177
+ };
178
+ xAxis: {
179
+ type: string;
180
+ description: string;
181
+ };
182
+ yAxis: {
183
+ type: string;
184
+ items: {
185
+ type: string;
186
+ };
187
+ description: string;
188
+ };
189
+ title: {
190
+ type: string;
191
+ description: string;
192
+ };
193
+ };
194
+ };
195
+ topic?: undefined;
196
+ intent?: undefined;
197
+ limit?: undefined;
198
+ minScore?: undefined;
139
199
  };
140
200
  };
141
201
  })[];
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`../utils-tNZ6Cvzw.cjs`),t=require(`../compiler-CA6iopu7.cjs`),n=require(`../mcp-transport-MOoCDu2M.cjs`);let r=require(`next/server`);function i(e){let{cubes:n,drizzle:r,schema:i,engineType:a,cache:o,rlsSetup:s}=e;if(!n||n.length===0)throw Error(`At least one cube must be provided in the cubes array`);let c=new t.t({drizzle:r,schema:i,engineType:a,cache:o,rlsSetup:s});return n.forEach(e=>{c.registerCube(e)}),c}function a(e,t){let n=e.headers.get(`origin`),r={};return t.origin&&(typeof t.origin==`string`?r[`Access-Control-Allow-Origin`]=t.origin:Array.isArray(t.origin)?n&&t.origin.includes(n)&&(r[`Access-Control-Allow-Origin`]=n):typeof t.origin==`function`&&n&&t.origin(n)&&(r[`Access-Control-Allow-Origin`]=n)),t.methods&&(r[`Access-Control-Allow-Methods`]=t.methods.join(`, `)),t.allowedHeaders&&(r[`Access-Control-Allow-Headers`]=t.allowedHeaders.join(`, `)),t.credentials&&(r[`Access-Control-Allow-Credentials`]=`true`),r}function o(e){return async function(t){let n=a(t,e);return new Response(null,{status:200,headers:n})}}function s(t){let{extractSecurityContext:n,cors:o}=t,s=i(t);return async function(t,i){try{let c;if(t.method===`POST`){let e=await t.json();c=e.query||e}else if(t.method===`GET`){let n=t.nextUrl.searchParams.get(`query`);if(!n)return r.NextResponse.json(e.i(`Query parameter is required`,400),{status:400});try{c=JSON.parse(n)}catch{return r.NextResponse.json(e.i(`Invalid JSON in query parameter`,400),{status:400})}}else return r.NextResponse.json(e.i(`Method not allowed`,405),{status:405});let l=await n(t,i),u=s.validateQuery(c);if(!u.isValid)return r.NextResponse.json(e.i(`Query validation failed: ${u.errors.join(`, `)}`,400),{status:400});let d=t.headers.get(`x-cache-control`)===`no-cache`,f=await s.executeMultiCubeQuery(c,l,{skipCache:d}),p=e.r(c,f,s);return r.NextResponse.json(p,{headers:o?a(t,o):{}})}catch(t){return process.env.NODE_ENV!==`test`&&console.error(`Next.js load handler error:`,t),r.NextResponse.json(e.i(t instanceof Error?t.message:`Query execution failed`,500),{status:500})}}}function c(t){let{cors:n}=t,o=i(t);return async function(t,i){try{let i=e.a(o.getMetadata());return r.NextResponse.json(i,{headers:n?a(t,n):{}})}catch(t){return process.env.NODE_ENV!==`test`&&console.error(`Next.js meta handler error:`,t),r.NextResponse.json(e.i(t instanceof Error?t.message:`Failed to fetch metadata`,500),{status:500})}}}function l(t){let{extractSecurityContext:n,cors:o}=t,s=i(t);return async function(t,i){try{let c;if(t.method===`POST`){let e=await t.json();c=e.query||e}else if(t.method===`GET`){let n=t.nextUrl.searchParams.get(`query`);if(!n)return r.NextResponse.json(e.i(`Query parameter is required`,400),{status:400});try{c=JSON.parse(n)}catch{return r.NextResponse.json(e.i(`Invalid JSON in query parameter`,400),{status:400})}}else return r.NextResponse.json(e.i(`Method not allowed`,405),{status:405});let l=await n(t,i),u=s.validateQuery(c);if(!u.isValid)return r.NextResponse.json(e.i(`Query validation failed: ${u.errors.join(`, `)}`,400),{status:400});let d=c.measures?.[0]||c.dimensions?.[0];if(!d)return r.NextResponse.json(e.i(`No measures or dimensions specified`,400),{status:400});let f=d.split(`.`)[0],p=await s.generateSQL(f,c,l),m=e.o(c,p);return r.NextResponse.json(m,{headers:o?a(t,o):{}})}catch(t){return process.env.NODE_ENV!==`test`&&console.error(`Next.js SQL handler error:`,t),r.NextResponse.json(e.i(t instanceof Error?t.message:`SQL generation failed`,500),{status:500})}}}function u(t){let{extractSecurityContext:n,cors:o}=t,s=i(t);return async function(t,i){try{let c;if(t.method===`POST`){let e=await t.json();c=e.query||e}else if(t.method===`GET`){let e=t.nextUrl.searchParams.get(`query`);if(!e)return r.NextResponse.json({error:`Query parameter is required`,valid:!1},{status:400});try{c=JSON.parse(e)}catch{return r.NextResponse.json({error:`Invalid JSON in query parameter`,valid:!1},{status:400})}}else return r.NextResponse.json({error:`Method not allowed`,valid:!1},{status:405});let l=await n(t,i),u=await e.f(c,l,s);return r.NextResponse.json(u,{headers:o?a(t,o):{}})}catch(e){return process.env.NODE_ENV!==`test`&&console.error(`Next.js dry-run handler error:`,e),r.NextResponse.json({error:e instanceof Error?e.message:`Dry-run validation failed`,valid:!1},{status:400})}}}function d(t){let{extractSecurityContext:n,cors:o}=t,s=i(t);return async function(t,i){try{if(t.method!==`POST`)return r.NextResponse.json(e.i(`Method not allowed - use POST`,405),{status:405});let{queries:c}=await t.json();if(!c||!Array.isArray(c))return r.NextResponse.json(e.i(`Request body must contain a "queries" array`,400),{status:400});if(c.length===0)return r.NextResponse.json(e.i(`Queries array cannot be empty`,400),{status:400});let l=await e.u(c,await n(t,i),s,{skipCache:t.headers.get(`x-cache-control`)===`no-cache`});return r.NextResponse.json(l,{headers:o?a(t,o):{}})}catch(t){return process.env.NODE_ENV!==`test`&&console.error(`Next.js batch handler error:`,t),r.NextResponse.json(e.i(t instanceof Error?t.message:`Batch execution failed`,500),{status:500})}}}function f(e){let{extractSecurityContext:t,cors:n}=e,o=i(e);return async function(e,i){try{if(e.method!==`POST`)return r.NextResponse.json({error:`Method not allowed`},{status:405});let s=await e.json(),c=s.query||s,l=s.options||{},u=await t(e,i),d=o.validateQuery(c);if(!d.isValid)return r.NextResponse.json({error:`Query validation failed: ${d.errors.join(`, `)}`},{status:400});let f=await o.explainQuery(c,u,l);return r.NextResponse.json(f,{headers:n?a(e,n):{}})}catch(e){return process.env.NODE_ENV!==`test`&&console.error(`Next.js explain handler error:`,e),r.NextResponse.json({error:e instanceof Error?e.message:`Explain query failed`},{status:500})}}}function p(t){let{cors:n}=t,o=i(t);return async function(t,i){try{if(t.method!==`POST`)return r.NextResponse.json(e.i(`Method not allowed - use POST`,405),{status:405});let i=await e.d(o,await t.json());return r.NextResponse.json(i,{headers:n?a(t,n):{}})}catch(t){return process.env.NODE_ENV!==`test`&&console.error(`Next.js discover handler error:`,t),r.NextResponse.json(e.i(t instanceof Error?t.message:`Discovery failed`,500),{status:500})}}}function m(t){let{cors:n}=t,o=i(t);return async function(t,i){try{if(t.method!==`POST`)return r.NextResponse.json(e.i(`Method not allowed - use POST`,405),{status:405});let i=await t.json();if(!i.naturalLanguage)return r.NextResponse.json(e.i(`naturalLanguage field is required`,400),{status:400});let s=await e.m(o,i);return r.NextResponse.json(s,{headers:n?a(t,n):{}})}catch(t){return process.env.NODE_ENV!==`test`&&console.error(`Next.js suggest handler error:`,t),r.NextResponse.json(e.i(t instanceof Error?t.message:`Query suggestion failed`,500),{status:500})}}}function h(t){let{cors:n}=t,o=i(t);return async function(t,i){try{if(t.method!==`POST`)return r.NextResponse.json(e.i(`Method not allowed - use POST`,405),{status:405});let i=await t.json();if(!i.query)return r.NextResponse.json(e.i(`query field is required`,400),{status:400});let s=await e.h(o,i);return r.NextResponse.json(s,{headers:n?a(t,n):{}})}catch(t){return process.env.NODE_ENV!==`test`&&console.error(`Next.js validate handler error:`,t),r.NextResponse.json(e.i(t instanceof Error?t.message:`Query validation failed`,500),{status:500})}}}function g(t){let{extractSecurityContext:n,cors:o}=t,s=i(t);return async function(t,i){try{if(t.method!==`POST`)return r.NextResponse.json(e.i(`Method not allowed - use POST`,405),{status:405});let c=await t.json();if(!c.query)return r.NextResponse.json(e.i(`query field is required`,400),{status:400});let l=await e.p(s,await n(t,i),c);return r.NextResponse.json(l,{headers:o?a(t,o):{}})}catch(t){return process.env.NODE_ENV!==`test`&&console.error(`Next.js MCP load handler error:`,t),r.NextResponse.json(e.i(t instanceof Error?t.message:`Query execution failed`,500),{status:500})}}}function _(t){let{extractSecurityContext:o,cors:s,mcp:c={enabled:!0}}=t,l=i(t);return async function(t){if(t.method===`DELETE`)return r.NextResponse.json({error:`Session termination not supported`},{status:405});if(t.method===`GET`){let e=new TextEncoder,i=n.d(),o=new ReadableStream({start(t){t.enqueue(e.encode(n.f({jsonrpc:`2.0`,method:`mcp/ready`,params:{protocol:`streamable-http`}},i,15e3)))}}),c=new Headers({"Content-Type":`text/event-stream`,"Cache-Control":`no-cache`,Connection:`keep-alive`});if(s){let e=a(t,s);Object.entries(e).forEach(([e,t])=>c.set(e,t))}return new r.NextResponse(o,{status:200,headers:c})}if(t.method!==`POST`)return r.NextResponse.json(e.i(`Method not allowed - use POST`,405),{status:405});let i=n.m(t.headers.get(`origin`),c.allowedOrigins?{allowedOrigins:c.allowedOrigins}:{});if(!i.valid)return r.NextResponse.json(n.n(null,-32600,i.reason),{status:403});let u=t.headers.get(`accept`);if(!n.p(u))return r.NextResponse.json(n.n(null,-32600,`Accept header must include both application/json and text/event-stream`),{status:400});let d=n.l(Object.fromEntries(t.headers.entries()));if(!d.ok)return r.NextResponse.json({error:`Unsupported MCP protocol version`,supported:d.supported},{status:426});let f;try{f=await t.json()}catch{f=null}let p=n.u(f);if(!p)return r.NextResponse.json(n.n(null,-32600,`Invalid JSON-RPC 2.0 request`),{status:400});let m=n.h(u),h=p.method===`initialize`,g=(e,n=200,i={})=>r.NextResponse.json(e,{status:n,headers:{...s?a(t,s):{},...i}});try{let e=await n.a(p.method,p.params,{semanticLayer:l,extractSecurityContext:e=>o(e),rawRequest:t,rawResponse:null});if(n.c(p))return new r.NextResponse(null,{status:202});let i=h&&e&&typeof e==`object`&&`sessionId`in e?e.sessionId:void 0,c={};i&&(c[n.t]=i);let u=n.r(p.id??null,e);if(m){let e=new TextEncoder,i=n.d(),o=new ReadableStream({start(t){t.enqueue(e.encode(`id: ${i}\n\n`)),t.enqueue(e.encode(n.f(u,i))),t.close()}}),l=new Headers({"Content-Type":`text/event-stream`,"Cache-Control":`no-cache`,Connection:`keep-alive`,...c});if(s){let e=a(t,s);Object.entries(e).forEach(([e,t])=>l.set(e,t))}return new r.NextResponse(o,{status:200,headers:l})}return g(u,200,c)}catch(e){if(n.c(p))return process.env.NODE_ENV!==`test`&&console.error(`Next.js MCP notification processing error:`,e),new r.NextResponse(null,{status:202});process.env.NODE_ENV!==`test`&&console.error(`Next.js MCP RPC handler error:`,e);let i=e?.code??-32603,o=e?.data,c=e.message||`MCP request failed`,l=n.n(p.id??null,i,c,o);if(m){let e=new TextEncoder,i=n.d(),o=new ReadableStream({start(t){t.enqueue(e.encode(`id: ${i}\n\n`)),t.enqueue(e.encode(n.f(l,i))),t.close()}}),c=new Headers({"Content-Type":`text/event-stream`,"Cache-Control":`no-cache`,Connection:`keep-alive`});if(s){let e=a(t,s);Object.entries(e).forEach(([e,t])=>c.set(e,t))}return new r.NextResponse(o,{status:200,headers:c})}return g(l,200)}}}function v(e){let{extractSecurityContext:t,cors:n,agent:o}=e;if(!o)throw Error(`agent config is required for createAgentChatHandler`);let s=i(e);return async function(e,i){try{if(e.method!==`POST`)return r.NextResponse.json({error:`Method not allowed - use POST`},{status:405});let{handleAgentChat:c}=await Promise.resolve().then(()=>require(`../handler-BO2nq6IS.cjs`)),{message:l,sessionId:u,history:d}=await e.json();if(!l||typeof l!=`string`)return r.NextResponse.json({error:`message is required and must be a string`},{status:400});let f=(o.apiKey||``).trim();if(o.allowClientApiKey){let t=e.headers.get(`x-agent-api-key`);t&&(f=t.trim())}if(!f)return r.NextResponse.json({error:`No API key configured. Set agent.apiKey in server config or send X-Agent-Api-Key header.`},{status:401});let p=o.allowClientApiKey&&e.headers.get(`x-agent-provider`)||void 0,m=o.allowClientApiKey&&e.headers.get(`x-agent-model`)||void 0,h=o.allowClientApiKey&&e.headers.get(`x-agent-provider-endpoint`)||void 0,g=await t(e,i),_=o.buildSystemContext?.(g),v=new TextEncoder,y=new ReadableStream({async start(e){try{let t=c({message:l,sessionId:u,history:d,semanticLayer:s,securityContext:g,agentConfig:o,apiKey:f,systemContext:_,providerOverride:p,modelOverride:m,baseURLOverride:h});for await(let n of t){let t=`data: ${JSON.stringify(n)}\n\n`;e.enqueue(v.encode(t))}}catch(t){let n={type:`error`,data:{message:t instanceof Error?t.message:`Stream failed`}};e.enqueue(v.encode(`data: ${JSON.stringify(n)}\n\n`))}finally{e.close()}}}),b=new Headers({"Content-Type":`text/event-stream`,"Cache-Control":`no-cache`,Connection:`keep-alive`});if(n){let t=a(e,n);Object.entries(t).forEach(([e,t])=>b.set(e,t))}return new Response(y,{status:200,headers:b})}catch(e){return process.env.NODE_ENV!==`test`&&console.error(`Next.js agent chat handler error:`,e),r.NextResponse.json({error:e instanceof Error?e.message:`Agent chat failed`},{status:500})}}}function y(e){let{mcp:t={enabled:!0}}=e,n={load:s(e),meta:c(e),sql:l(e),dryRun:u(e),batch:d(e),explain:f(e)};return t.enabled!==!1&&(n.mcpRpc=_(e)),e.agent&&(n.agentChat=v(e)),n}exports.createAgentChatHandler=v,exports.createBatchHandler=d,exports.createCubeHandlers=y,exports.createDiscoverHandler=p,exports.createDryRunHandler=u,exports.createExplainHandler=f,exports.createLoadHandler=s,exports.createMcpLoadHandler=g,exports.createMcpRpcHandler=_,exports.createMetaHandler=c,exports.createOptionsHandler=o,exports.createSqlHandler=l,exports.createSuggestHandler=m,exports.createValidateHandler=h;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`../utils-tNZ6Cvzw.cjs`),t=require(`../compiler-CA6iopu7.cjs`),n=require(`../mcp-transport-DbLtza1I.cjs`);let r=require(`next/server`);function i(e){let{cubes:n,drizzle:r,schema:i,engineType:a,cache:o,rlsSetup:s}=e;if(!n||n.length===0)throw Error(`At least one cube must be provided in the cubes array`);let c=new t.t({drizzle:r,schema:i,engineType:a,cache:o,rlsSetup:s});return n.forEach(e=>{c.registerCube(e)}),c}function a(e,t){let n=e.headers.get(`origin`),r={};return t.origin&&(typeof t.origin==`string`?r[`Access-Control-Allow-Origin`]=t.origin:Array.isArray(t.origin)?n&&t.origin.includes(n)&&(r[`Access-Control-Allow-Origin`]=n):typeof t.origin==`function`&&n&&t.origin(n)&&(r[`Access-Control-Allow-Origin`]=n)),t.methods&&(r[`Access-Control-Allow-Methods`]=t.methods.join(`, `)),t.allowedHeaders&&(r[`Access-Control-Allow-Headers`]=t.allowedHeaders.join(`, `)),t.credentials&&(r[`Access-Control-Allow-Credentials`]=`true`),r}function o(e){return async function(t){let n=a(t,e);return new Response(null,{status:200,headers:n})}}function s(t){let{extractSecurityContext:n,cors:o}=t,s=i(t);return async function(t,i){try{let c;if(t.method===`POST`){let e=await t.json();c=e.query||e}else if(t.method===`GET`){let n=t.nextUrl.searchParams.get(`query`);if(!n)return r.NextResponse.json(e.i(`Query parameter is required`,400),{status:400});try{c=JSON.parse(n)}catch{return r.NextResponse.json(e.i(`Invalid JSON in query parameter`,400),{status:400})}}else return r.NextResponse.json(e.i(`Method not allowed`,405),{status:405});let l=await n(t,i),u=s.validateQuery(c);if(!u.isValid)return r.NextResponse.json(e.i(`Query validation failed: ${u.errors.join(`, `)}`,400),{status:400});let d=t.headers.get(`x-cache-control`)===`no-cache`,f=await s.executeMultiCubeQuery(c,l,{skipCache:d}),p=e.r(c,f,s);return r.NextResponse.json(p,{headers:o?a(t,o):{}})}catch(t){return process.env.NODE_ENV!==`test`&&console.error(`Next.js load handler error:`,t),r.NextResponse.json(e.i(t instanceof Error?t.message:`Query execution failed`,500),{status:500})}}}function c(t){let{cors:n}=t,o=i(t);return async function(t,i){try{let i=e.a(o.getMetadata());return r.NextResponse.json(i,{headers:n?a(t,n):{}})}catch(t){return process.env.NODE_ENV!==`test`&&console.error(`Next.js meta handler error:`,t),r.NextResponse.json(e.i(t instanceof Error?t.message:`Failed to fetch metadata`,500),{status:500})}}}function l(t){let{extractSecurityContext:n,cors:o}=t,s=i(t);return async function(t,i){try{let c;if(t.method===`POST`){let e=await t.json();c=e.query||e}else if(t.method===`GET`){let n=t.nextUrl.searchParams.get(`query`);if(!n)return r.NextResponse.json(e.i(`Query parameter is required`,400),{status:400});try{c=JSON.parse(n)}catch{return r.NextResponse.json(e.i(`Invalid JSON in query parameter`,400),{status:400})}}else return r.NextResponse.json(e.i(`Method not allowed`,405),{status:405});let l=await n(t,i),u=s.validateQuery(c);if(!u.isValid)return r.NextResponse.json(e.i(`Query validation failed: ${u.errors.join(`, `)}`,400),{status:400});let d=c.measures?.[0]||c.dimensions?.[0];if(!d)return r.NextResponse.json(e.i(`No measures or dimensions specified`,400),{status:400});let f=d.split(`.`)[0],p=await s.generateSQL(f,c,l),m=e.o(c,p);return r.NextResponse.json(m,{headers:o?a(t,o):{}})}catch(t){return process.env.NODE_ENV!==`test`&&console.error(`Next.js SQL handler error:`,t),r.NextResponse.json(e.i(t instanceof Error?t.message:`SQL generation failed`,500),{status:500})}}}function u(t){let{extractSecurityContext:n,cors:o}=t,s=i(t);return async function(t,i){try{let c;if(t.method===`POST`){let e=await t.json();c=e.query||e}else if(t.method===`GET`){let e=t.nextUrl.searchParams.get(`query`);if(!e)return r.NextResponse.json({error:`Query parameter is required`,valid:!1},{status:400});try{c=JSON.parse(e)}catch{return r.NextResponse.json({error:`Invalid JSON in query parameter`,valid:!1},{status:400})}}else return r.NextResponse.json({error:`Method not allowed`,valid:!1},{status:405});let l=await n(t,i),u=await e.f(c,l,s);return r.NextResponse.json(u,{headers:o?a(t,o):{}})}catch(e){return process.env.NODE_ENV!==`test`&&console.error(`Next.js dry-run handler error:`,e),r.NextResponse.json({error:e instanceof Error?e.message:`Dry-run validation failed`,valid:!1},{status:400})}}}function d(t){let{extractSecurityContext:n,cors:o}=t,s=i(t);return async function(t,i){try{if(t.method!==`POST`)return r.NextResponse.json(e.i(`Method not allowed - use POST`,405),{status:405});let{queries:c}=await t.json();if(!c||!Array.isArray(c))return r.NextResponse.json(e.i(`Request body must contain a "queries" array`,400),{status:400});if(c.length===0)return r.NextResponse.json(e.i(`Queries array cannot be empty`,400),{status:400});let l=await e.u(c,await n(t,i),s,{skipCache:t.headers.get(`x-cache-control`)===`no-cache`});return r.NextResponse.json(l,{headers:o?a(t,o):{}})}catch(t){return process.env.NODE_ENV!==`test`&&console.error(`Next.js batch handler error:`,t),r.NextResponse.json(e.i(t instanceof Error?t.message:`Batch execution failed`,500),{status:500})}}}function f(e){let{extractSecurityContext:t,cors:n}=e,o=i(e);return async function(e,i){try{if(e.method!==`POST`)return r.NextResponse.json({error:`Method not allowed`},{status:405});let s=await e.json(),c=s.query||s,l=s.options||{},u=await t(e,i),d=o.validateQuery(c);if(!d.isValid)return r.NextResponse.json({error:`Query validation failed: ${d.errors.join(`, `)}`},{status:400});let f=await o.explainQuery(c,u,l);return r.NextResponse.json(f,{headers:n?a(e,n):{}})}catch(e){return process.env.NODE_ENV!==`test`&&console.error(`Next.js explain handler error:`,e),r.NextResponse.json({error:e instanceof Error?e.message:`Explain query failed`},{status:500})}}}function p(t){let{cors:n}=t,o=i(t);return async function(t,i){try{if(t.method!==`POST`)return r.NextResponse.json(e.i(`Method not allowed - use POST`,405),{status:405});let i=await e.d(o,await t.json());return r.NextResponse.json(i,{headers:n?a(t,n):{}})}catch(t){return process.env.NODE_ENV!==`test`&&console.error(`Next.js discover handler error:`,t),r.NextResponse.json(e.i(t instanceof Error?t.message:`Discovery failed`,500),{status:500})}}}function m(t){let{cors:n}=t,o=i(t);return async function(t,i){try{if(t.method!==`POST`)return r.NextResponse.json(e.i(`Method not allowed - use POST`,405),{status:405});let i=await t.json();if(!i.naturalLanguage)return r.NextResponse.json(e.i(`naturalLanguage field is required`,400),{status:400});let s=await e.m(o,i);return r.NextResponse.json(s,{headers:n?a(t,n):{}})}catch(t){return process.env.NODE_ENV!==`test`&&console.error(`Next.js suggest handler error:`,t),r.NextResponse.json(e.i(t instanceof Error?t.message:`Query suggestion failed`,500),{status:500})}}}function h(t){let{cors:n}=t,o=i(t);return async function(t,i){try{if(t.method!==`POST`)return r.NextResponse.json(e.i(`Method not allowed - use POST`,405),{status:405});let i=await t.json();if(!i.query)return r.NextResponse.json(e.i(`query field is required`,400),{status:400});let s=await e.h(o,i);return r.NextResponse.json(s,{headers:n?a(t,n):{}})}catch(t){return process.env.NODE_ENV!==`test`&&console.error(`Next.js validate handler error:`,t),r.NextResponse.json(e.i(t instanceof Error?t.message:`Query validation failed`,500),{status:500})}}}function g(t){let{extractSecurityContext:n,cors:o}=t,s=i(t);return async function(t,i){try{if(t.method!==`POST`)return r.NextResponse.json(e.i(`Method not allowed - use POST`,405),{status:405});let c=await t.json();if(!c.query)return r.NextResponse.json(e.i(`query field is required`,400),{status:400});let l=await e.p(s,await n(t,i),c);return r.NextResponse.json(l,{headers:o?a(t,o):{}})}catch(t){return process.env.NODE_ENV!==`test`&&console.error(`Next.js MCP load handler error:`,t),r.NextResponse.json(e.i(t instanceof Error?t.message:`Query execution failed`,500),{status:500})}}}function _(t){let{extractSecurityContext:o,cors:s,mcp:c={enabled:!0}}=t,l=i(t);return async function(t){if(t.method===`DELETE`)return r.NextResponse.json({error:`Session termination not supported`},{status:405});if(t.method===`GET`){let e=new TextEncoder,i=n.m(),o=new ReadableStream({start(t){t.enqueue(e.encode(n.h({jsonrpc:`2.0`,method:`mcp/ready`,params:{protocol:`streamable-http`}},i,15e3)))}}),c=new Headers({"Content-Type":`text/event-stream`,"Cache-Control":`no-cache`,Connection:`keep-alive`});if(s){let e=a(t,s);Object.entries(e).forEach(([e,t])=>c.set(e,t))}return new r.NextResponse(o,{status:200,headers:c})}if(t.method!==`POST`)return r.NextResponse.json(e.i(`Method not allowed - use POST`,405),{status:405});let i=n._(t.headers.get(`origin`),c.allowedOrigins?{allowedOrigins:c.allowedOrigins}:{});if(!i.valid)return r.NextResponse.json(n.i(null,-32600,i.reason),{status:403});let u=t.headers.get(`accept`);if(!n.g(u))return r.NextResponse.json(n.i(null,-32600,`Accept header must include both application/json and text/event-stream`),{status:400});let d=n.f(Object.fromEntries(t.headers.entries()));if(!d.ok)return r.NextResponse.json({error:`Unsupported MCP protocol version`,supported:d.supported},{status:426});let f;try{f=await t.json()}catch{f=null}let p=n.p(f);if(!p)return r.NextResponse.json(n.i(null,-32600,`Invalid JSON-RPC 2.0 request`),{status:400});let m=n.v(u),h=p.method===`initialize`,g=(e,n=200,i={})=>r.NextResponse.json(e,{status:n,headers:{...s?a(t,s):{},...i}});try{let e=await n.s(p.method,p.params,{semanticLayer:l,extractSecurityContext:e=>o(e),rawRequest:t,rawResponse:null,appEnabled:!!c.app});if(n.d(p))return new r.NextResponse(null,{status:202});let i=h&&e&&typeof e==`object`&&`sessionId`in e?e.sessionId:void 0,u={};i&&(u[n.r]=i);let d=n.a(p.id??null,e);if(m){let e=new TextEncoder,i=n.m(),o=new ReadableStream({start(t){t.enqueue(e.encode(`id: ${i}\n\n`)),t.enqueue(e.encode(n.h(d,i))),t.close()}}),c=new Headers({"Content-Type":`text/event-stream`,"Cache-Control":`no-cache`,Connection:`keep-alive`,...u});if(s){let e=a(t,s);Object.entries(e).forEach(([e,t])=>c.set(e,t))}return new r.NextResponse(o,{status:200,headers:c})}return g(d,200,u)}catch(e){if(n.d(p))return process.env.NODE_ENV!==`test`&&console.error(`Next.js MCP notification processing error:`,e),new r.NextResponse(null,{status:202});process.env.NODE_ENV!==`test`&&console.error(`Next.js MCP RPC handler error:`,e);let i=e?.code??-32603,o=e?.data,c=e.message||`MCP request failed`,l=n.i(p.id??null,i,c,o);if(m){let e=new TextEncoder,i=n.m(),o=new ReadableStream({start(t){t.enqueue(e.encode(`id: ${i}\n\n`)),t.enqueue(e.encode(n.h(l,i))),t.close()}}),c=new Headers({"Content-Type":`text/event-stream`,"Cache-Control":`no-cache`,Connection:`keep-alive`});if(s){let e=a(t,s);Object.entries(e).forEach(([e,t])=>c.set(e,t))}return new r.NextResponse(o,{status:200,headers:c})}return g(l,200)}}}function v(e){let{extractSecurityContext:t,cors:n,agent:o}=e;if(!o)throw Error(`agent config is required for createAgentChatHandler`);let s=i(e);return async function(e,i){try{if(e.method!==`POST`)return r.NextResponse.json({error:`Method not allowed - use POST`},{status:405});let{handleAgentChat:c}=await Promise.resolve().then(()=>require(`../handler-BO2nq6IS.cjs`)),{message:l,sessionId:u,history:d}=await e.json();if(!l||typeof l!=`string`)return r.NextResponse.json({error:`message is required and must be a string`},{status:400});let f=(o.apiKey||``).trim();if(o.allowClientApiKey){let t=e.headers.get(`x-agent-api-key`);t&&(f=t.trim())}if(!f)return r.NextResponse.json({error:`No API key configured. Set agent.apiKey in server config or send X-Agent-Api-Key header.`},{status:401});let p=o.allowClientApiKey&&e.headers.get(`x-agent-provider`)||void 0,m=o.allowClientApiKey&&e.headers.get(`x-agent-model`)||void 0,h=o.allowClientApiKey&&e.headers.get(`x-agent-provider-endpoint`)||void 0,g=await t(e,i),_=o.buildSystemContext?.(g),v=new TextEncoder,y=new ReadableStream({async start(e){try{let t=c({message:l,sessionId:u,history:d,semanticLayer:s,securityContext:g,agentConfig:o,apiKey:f,systemContext:_,providerOverride:p,modelOverride:m,baseURLOverride:h});for await(let n of t){let t=`data: ${JSON.stringify(n)}\n\n`;e.enqueue(v.encode(t))}}catch(t){let n={type:`error`,data:{message:t instanceof Error?t.message:`Stream failed`}};e.enqueue(v.encode(`data: ${JSON.stringify(n)}\n\n`))}finally{e.close()}}}),b=new Headers({"Content-Type":`text/event-stream`,"Cache-Control":`no-cache`,Connection:`keep-alive`});if(n){let t=a(e,n);Object.entries(t).forEach(([e,t])=>b.set(e,t))}return new Response(y,{status:200,headers:b})}catch(e){return process.env.NODE_ENV!==`test`&&console.error(`Next.js agent chat handler error:`,e),r.NextResponse.json({error:e instanceof Error?e.message:`Agent chat failed`},{status:500})}}}function y(e){let{mcp:t={enabled:!0}}=e,n={load:s(e),meta:c(e),sql:l(e),dryRun:u(e),batch:d(e),explain:f(e)};return t.enabled!==!1&&(n.mcpRpc=_(e)),e.agent&&(n.agentChat=v(e)),n}exports.createAgentChatHandler=v,exports.createBatchHandler=d,exports.createCubeHandlers=y,exports.createDiscoverHandler=p,exports.createDryRunHandler=u,exports.createExplainHandler=f,exports.createLoadHandler=s,exports.createMcpLoadHandler=g,exports.createMcpRpcHandler=_,exports.createMetaHandler=c,exports.createOptionsHandler=o,exports.createSqlHandler=l,exports.createSuggestHandler=m,exports.createValidateHandler=h;