@hypequery/mcp 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -24,7 +24,7 @@ pnpm add @hypequery/mcp
24
24
  Create `mcp-config.ts`:
25
25
 
26
26
  ```typescript
27
- import { MetricExecutor } from '@hypequery/datasets';
27
+ import { createDatasetClient } from '@hypequery/datasets';
28
28
  import { createQueryBuilder } from '@hypequery/clickhouse';
29
29
  import { OrdersDataset, CustomersDataset } from './datasets/index.js';
30
30
 
@@ -45,14 +45,15 @@ export const datasets = {
45
45
  },
46
46
  };
47
47
 
48
- // Export your executor
49
- const builderFactory = createQueryBuilder({
50
- host: process.env.CLICKHOUSE_HOST,
48
+ // Export the semantic runner consumed by the MCP server
49
+ const db = createQueryBuilder({
50
+ url: process.env.CLICKHOUSE_URL,
51
51
  username: process.env.CLICKHOUSE_USER,
52
52
  password: process.env.CLICKHOUSE_PASSWORD,
53
+ database: process.env.CLICKHOUSE_DATABASE,
53
54
  });
54
55
 
55
- export const executor = new MetricExecutor({ builderFactory });
56
+ export const analytics = createDatasetClient({ queryBuilder: db });
56
57
  ```
57
58
 
58
59
  ### 2. Run the MCP Server
@@ -107,6 +108,7 @@ Lists all available datasets with their descriptions.
107
108
  "name": "orders",
108
109
  "description": "Customer orders and revenue data",
109
110
  "dimensionCount": 5,
111
+ "measureCount": 4,
110
112
  "metricCount": 4
111
113
  }
112
114
  ],
@@ -136,8 +138,12 @@ Gets the complete schema for a dataset.
136
138
  "region": { "type": "string", "label": "Region" },
137
139
  "status": { "type": "string", "label": "Order Status" }
138
140
  },
141
+ "measures": {
142
+ "revenue": { "aggregation": "sum", "field": "amount", "label": "Revenue" },
143
+ "orderCount": { "aggregation": "count", "field": "id", "label": "Order Count" }
144
+ },
139
145
  "metrics": {
140
- "revenue": { "type": "sum", "label": "Total Revenue", "format": "currency" }
146
+ "totalRevenue": { "type": "metric", "aggregation": "revenue", "label": "Total Revenue" }
141
147
  }
142
148
  }
143
149
  ```
@@ -183,7 +189,7 @@ Executes a pre-defined metric query.
183
189
 
184
190
  ### `query_dataset`
185
191
 
186
- Executes an ad-hoc dataset query with custom dimensions and metrics.
192
+ Executes an ad-hoc dataset query with custom dimensions and measures.
187
193
 
188
194
  **Example:**
189
195
  ```typescript
@@ -192,7 +198,7 @@ Executes an ad-hoc dataset query with custom dimensions and metrics.
192
198
  "arguments": {
193
199
  "dataset": "orders",
194
200
  "dimensions": ["region", "status"],
195
- "metrics": ["revenue", "orderCount"],
201
+ "measures": ["revenue", "orderCount"],
196
202
  "limit": 100
197
203
  }
198
204
  }
@@ -204,15 +210,19 @@ You can also use the MCP server programmatically in your application:
204
210
 
205
211
  ```typescript
206
212
  import { createMCPServer } from '@hypequery/mcp';
207
- import { MetricExecutor } from '@hypequery/datasets';
213
+ import { createDatasetClient } from '@hypequery/datasets';
208
214
  import { datasets } from './datasets/index.js';
209
- import { queryBuilder } from './db/index.js';
210
215
 
211
- const executor = new MetricExecutor({ builderFactory: queryBuilder });
216
+ const analytics = createDatasetClient({
217
+ url: process.env.CLICKHOUSE_URL,
218
+ username: process.env.CLICKHOUSE_USER,
219
+ password: process.env.CLICKHOUSE_PASSWORD,
220
+ database: process.env.CLICKHOUSE_DATABASE,
221
+ });
212
222
 
213
223
  const server = await createMCPServer({
214
224
  datasets,
215
- executor,
225
+ analytics,
216
226
  name: 'my-analytics-mcp',
217
227
  version: '1.0.0',
218
228
  });
@@ -250,8 +260,8 @@ The MCP server also exposes a `dataset_guide` prompt that provides natural langu
250
260
  Your config file can use environment variables for database credentials:
251
261
 
252
262
  ```typescript
253
- const queryBuilder = createQueryBuilder({
254
- host: process.env.CLICKHOUSE_HOST || 'localhost',
263
+ const analytics = createDatasetClient({
264
+ url: process.env.CLICKHOUSE_URL || 'http://localhost:8123',
255
265
  username: process.env.CLICKHOUSE_USER || 'default',
256
266
  password: process.env.CLICKHOUSE_PASSWORD,
257
267
  database: process.env.CLICKHOUSE_DATABASE || 'default',
@@ -263,7 +273,7 @@ const queryBuilder = createQueryBuilder({
263
273
  ### MCP server not connecting
264
274
 
265
275
  1. Check that the config file path is absolute, not relative
266
- 2. Ensure the config file exports both `datasets` and `executor`
276
+ 2. Ensure the config file exports both `datasets` and `analytics`
267
277
  3. Check Claude Desktop logs for errors
268
278
 
269
279
  ### Queries failing
package/dist/bin.d.ts CHANGED
@@ -3,10 +3,10 @@
3
3
  * MCP Server CLI
4
4
  *
5
5
  * This is a standalone executable that starts the MCP server.
6
- * Users can configure it by creating a config file that exports datasets and executor.
6
+ * Users can configure it by creating a config file that exports datasets and analytics.
7
7
  *
8
8
  * Usage:
9
- * npx hypequery-mcp --config ./mcp-config.js
9
+ * npx hypequery-mcp --config ./mcp-config.mjs
10
10
  */
11
11
  export {};
12
12
  //# sourceMappingURL=bin.d.ts.map
package/dist/bin.js CHANGED
@@ -3,10 +3,10 @@
3
3
  * MCP Server CLI
4
4
  *
5
5
  * This is a standalone executable that starts the MCP server.
6
- * Users can configure it by creating a config file that exports datasets and executor.
6
+ * Users can configure it by creating a config file that exports datasets and analytics.
7
7
  *
8
8
  * Usage:
9
- * npx hypequery-mcp --config ./mcp-config.js
9
+ * npx hypequery-mcp --config ./mcp-config.mjs
10
10
  */
11
11
  import { createMCPServer } from './server.js';
12
12
  import { pathToFileURL } from 'url';
@@ -29,29 +29,29 @@ async function main() {
29
29
  if (configIndex === -1 || !args[configIndex + 1]) {
30
30
  console.error('Error: --config flag is required');
31
31
  console.error('');
32
- console.error('Usage: hypequery-mcp --config ./mcp-config.js');
32
+ console.error('Usage: hypequery-mcp --config ./mcp-config.mjs');
33
33
  console.error('');
34
- console.error('The config file should export { datasets, executor }:');
34
+ console.error('The config file should export { datasets, analytics }:');
35
35
  console.error('');
36
36
  console.error(' export const datasets = { ... };');
37
- console.error(' export const executor = new MetricExecutor(...);');
37
+ console.error(' export const analytics = createDatasetClient({ ... });');
38
38
  process.exit(1);
39
39
  }
40
40
  const configPath = resolve(process.cwd(), args[configIndex + 1]);
41
41
  try {
42
42
  // Dynamic import of the config file
43
43
  const configModule = await import(pathToFileURL(configPath).href);
44
- const { datasets, executor } = configModule;
44
+ const { datasets, analytics } = configModule;
45
45
  if (!datasets) {
46
46
  throw new Error('Config file must export "datasets"');
47
47
  }
48
- if (!executor) {
49
- throw new Error('Config file must export "executor"');
48
+ if (!analytics) {
49
+ throw new Error('Config file must export "analytics"');
50
50
  }
51
51
  // Create and start the MCP server
52
52
  await createMCPServer({
53
53
  datasets,
54
- executor,
54
+ analytics,
55
55
  name: 'hypequery-mcp-server',
56
56
  version: '0.1.0',
57
57
  });
package/dist/index.d.ts CHANGED
@@ -10,6 +10,6 @@ export { getDatasetSchemaTool } from './tools/introspect.js';
10
10
  export { queryMetricTool } from './tools/query-metric.js';
11
11
  export { queryDatasetTool } from './tools/query-dataset.js';
12
12
  export { datasetGuidePrompt } from './prompts/dataset-guide.js';
13
- export type { DatasetRegistry, QueryMetricArgs, QueryDatasetArgs, GetDatasetSchemaArgs, MCPToolResponse, DatasetSchema, DimensionSchema, MetricSchema, RelationshipSchema, DatasetListItem, DatasetsListResponse, QueryResultResponse, QueryResultMeta, } from './types.js';
13
+ export type { DatasetRegistry, QueryMetricArgs, QueryDatasetArgs, QueryToolOptions, GetDatasetSchemaArgs, MCPToolResponse, DatasetSchema, DimensionSchema, MetricSchema, RelationshipSchema, DatasetListItem, DatasetsListResponse, QueryResultResponse, QueryResultMeta, } from './types.js';
14
14
  export { MAX_QUERY_LIMIT, DEFAULT_QUERY_LIMIT } from './types.js';
15
15
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AACxF,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAGhE,YAAY,EACV,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,oBAAoB,EACpB,eAAe,EACf,aAAa,EACb,eAAe,EACf,YAAY,EACZ,kBAAkB,EAClB,eAAe,EACf,oBAAoB,EACpB,mBAAmB,EACnB,eAAe,GAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AACxF,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAGhE,YAAY,EACV,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,gBAAgB,EAChB,oBAAoB,EACpB,eAAe,EACf,aAAa,EACb,eAAe,EACf,YAAY,EACZ,kBAAkB,EAClB,eAAe,EACf,oBAAoB,EACpB,mBAAmB,EACnB,eAAe,GAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"dataset-guide.d.ts","sourceRoot":"","sources":["../../src/prompts/dataset-guide.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,eAAe,EAAE,WAAW,CAAC,EAAE,MAAM;;;;;;;;EAmIjF"}
1
+ {"version":3,"file":"dataset-guide.d.ts","sourceRoot":"","sources":["../../src/prompts/dataset-guide.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,eAAe,EAAE,WAAW,CAAC,EAAE,MAAM;;;;;;;;EAuIjF"}
@@ -12,12 +12,16 @@ export function datasetGuidePrompt(datasets, datasetName) {
12
12
  const datasetAny = dataset;
13
13
  // Generate dataset-specific guide
14
14
  const dimensions = datasetAny.dimensions ? Object.keys(datasetAny.dimensions) : [];
15
+ const measures = datasetAny.measures ? Object.keys(datasetAny.measures) : [];
15
16
  const metrics = datasetAny.metrics ? Object.keys(datasetAny.metrics) : [];
16
17
  const guide = `# Querying the ${datasetName} dataset
17
18
 
18
19
  ## Available Dimensions
19
20
  ${dimensions.map((d) => `- ${d}`).join('\n')}
20
21
 
22
+ ## Available Measures
23
+ ${measures.map((m) => `- ${m}`).join('\n')}
24
+
21
25
  ## Available Metrics
22
26
  ${metrics.map((m) => `- ${m}`).join('\n')}
23
27
 
@@ -46,7 +50,7 @@ Show "${metrics[0] || 'revenue'}" by month for the last year
46
50
  ## Tips
47
51
  - Use natural language to describe what you want to see
48
52
  - The system will translate your query into the appropriate dataset query
49
- - You can filter, group, and aggregate data using the available dimensions and metrics
53
+ - You can filter, group, and aggregate data using the available dimensions, measures, and metrics
50
54
  `;
51
55
  return {
52
56
  messages: [
@@ -70,9 +74,9 @@ ${datasetList.map((name) => `- ${name}`).join('\n')}
70
74
  ## How to Query
71
75
 
72
76
  1. **List datasets**: Use the \`list_datasets\` tool to see all available datasets
73
- 2. **Get schema**: Use the \`get_dataset_schema\` tool to see dimensions and metrics for a dataset
77
+ 2. **Get schema**: Use the \`get_dataset_schema\` tool to see dimensions, measures, and metrics for a dataset
74
78
  3. **Query metric**: Use the \`query_metric\` tool to execute a pre-defined metric
75
- 4. **Query dataset**: Use the \`query_dataset\` tool for ad-hoc queries with custom dimensions and metrics
79
+ 4. **Query dataset**: Use the \`query_dataset\` tool for ad-hoc queries with custom dimensions and measures
76
80
 
77
81
  ## Example Workflow
78
82
 
package/dist/server.d.ts CHANGED
@@ -4,7 +4,7 @@
4
4
  * Exposes datasets and metrics via Model Context Protocol (MCP)
5
5
  * for use with Claude Desktop, Cursor, and other MCP-compatible tools.
6
6
  */
7
- import type { MetricExecutor } from '@hypequery/datasets';
7
+ import type { DatasetClient } from '@hypequery/datasets';
8
8
  import type { DatasetRegistry } from './types.js';
9
9
  export interface MCPServerConfig {
10
10
  /**
@@ -12,9 +12,9 @@ export interface MCPServerConfig {
12
12
  */
13
13
  datasets: DatasetRegistry;
14
14
  /**
15
- * Metric executor for running queries
15
+ * Semantic analytics for running metric and dataset queries
16
16
  */
17
- executor: MetricExecutor;
17
+ analytics: DatasetClient;
18
18
  /**
19
19
  * Server name (shown in MCP client)
20
20
  */
@@ -23,6 +23,10 @@ export interface MCPServerConfig {
23
23
  * Server version
24
24
  */
25
25
  version?: string;
26
+ /**
27
+ * Trusted tenant id used to scope tenant-keyed datasets.
28
+ */
29
+ tenantId?: string;
26
30
  }
27
31
  export declare class HypequeryMCPServer {
28
32
  private server;
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAUH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAM1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,WAAW,eAAe;IAC9B;;OAEG;IACH,QAAQ,EAAE,eAAe,CAAC;IAE1B;;OAEG;IACH,QAAQ,EAAE,cAAc,CAAC;IAEzB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAkB;gBAEpB,MAAM,EAAE,eAAe;IAmBnC,OAAO,CAAC,aAAa;IA6NrB;;OAEG;IACG,KAAK;IAQX;;OAEG;IACG,IAAI;CAGX;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAI1F"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAUH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAMzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,WAAW,eAAe;IAC9B;;OAEG;IACH,QAAQ,EAAE,eAAe,CAAC;IAE1B;;OAEG;IACH,SAAS,EAAE,aAAa,CAAC;IAEzB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAiCD,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAkB;gBAEpB,MAAM,EAAE,eAAe;IAoBnC,OAAO,CAAC,aAAa;IAuOrB;;OAEG;IACG,KAAK;IAQX;;OAEG;IACG,IAAI;CAGX;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAI1F"}
package/dist/server.js CHANGED
@@ -12,10 +12,34 @@ import { getDatasetSchemaTool } from './tools/introspect.js';
12
12
  import { queryMetricTool } from './tools/query-metric.js';
13
13
  import { queryDatasetTool } from './tools/query-dataset.js';
14
14
  import { datasetGuidePrompt } from './prompts/dataset-guide.js';
15
+ function isRecord(value) {
16
+ return !!value && typeof value === 'object';
17
+ }
18
+ function getTenantKey(dataset) {
19
+ if (!isRecord(dataset)) {
20
+ return undefined;
21
+ }
22
+ const config = dataset.config;
23
+ const configTenantKey = isRecord(config) ? config.tenantKey : undefined;
24
+ const tenantKey = dataset.tenantKey ?? configTenantKey;
25
+ return typeof tenantKey === 'string' && tenantKey.length > 0 ? tenantKey : undefined;
26
+ }
27
+ function validateTenantConfig(config) {
28
+ if (config.tenantId) {
29
+ return;
30
+ }
31
+ const tenantScopedDatasets = Object.entries(config.datasets ?? {})
32
+ .filter(([, ds]) => getTenantKey(ds))
33
+ .map(([name]) => name);
34
+ if (tenantScopedDatasets.length > 0) {
35
+ throw new Error(`MCP server tenantId is required for tenant-scoped datasets: ${tenantScopedDatasets.join(', ')}`);
36
+ }
37
+ }
15
38
  export class HypequeryMCPServer {
16
39
  server;
17
40
  config;
18
41
  constructor(config) {
42
+ validateTenantConfig(config);
19
43
  this.config = config;
20
44
  this.server = new Server({
21
45
  name: config.name ?? 'hypequery-mcp-server',
@@ -42,7 +66,7 @@ export class HypequeryMCPServer {
42
66
  },
43
67
  {
44
68
  name: 'get_dataset_schema',
45
- description: 'Get the schema (dimensions, metrics, relationships) for a specific dataset',
69
+ description: 'Get the schema (dimensions, measures, named metrics, filters, relationships) for a specific dataset',
46
70
  inputSchema: {
47
71
  type: 'object',
48
72
  properties: {
@@ -110,13 +134,17 @@ export class HypequeryMCPServer {
110
134
  type: 'number',
111
135
  description: 'Maximum number of rows to return (optional)',
112
136
  },
137
+ offset: {
138
+ type: 'number',
139
+ description: 'Number of rows to skip before returning results (optional)',
140
+ },
113
141
  },
114
142
  required: ['dataset', 'metric'],
115
143
  },
116
144
  },
117
145
  {
118
146
  name: 'query_dataset',
119
- description: 'Execute an ad-hoc dataset query with custom dimensions and metrics',
147
+ description: 'Execute an ad-hoc dataset query with custom dimensions and measures',
120
148
  inputSchema: {
121
149
  type: 'object',
122
150
  properties: {
@@ -129,10 +157,10 @@ export class HypequeryMCPServer {
129
157
  items: { type: 'string' },
130
158
  description: 'Dimensions to select',
131
159
  },
132
- metrics: {
160
+ measures: {
133
161
  type: 'array',
134
162
  items: { type: 'string' },
135
- description: 'Metrics to calculate',
163
+ description: 'Measures to calculate',
136
164
  },
137
165
  filters: {
138
166
  type: 'array',
@@ -171,6 +199,10 @@ export class HypequeryMCPServer {
171
199
  type: 'number',
172
200
  description: 'Maximum number of rows to return (optional)',
173
201
  },
202
+ offset: {
203
+ type: 'number',
204
+ description: 'Number of rows to skip before returning results (optional)',
205
+ },
174
206
  },
175
207
  required: ['dataset'],
176
208
  },
@@ -187,9 +219,9 @@ export class HypequeryMCPServer {
187
219
  case 'get_dataset_schema':
188
220
  return await getDatasetSchemaTool(this.config.datasets, args);
189
221
  case 'query_metric':
190
- return await queryMetricTool(this.config.datasets, this.config.executor, args);
222
+ return await queryMetricTool(this.config.datasets, this.config.analytics, args, { tenantId: this.config.tenantId });
191
223
  case 'query_dataset':
192
- return await queryDatasetTool(this.config.datasets, this.config.executor, args);
224
+ return await queryDatasetTool(this.config.datasets, this.config.analytics, args, { tenantId: this.config.tenantId });
193
225
  default:
194
226
  throw new Error(`Unknown tool: ${name}`);
195
227
  }
@@ -0,0 +1,137 @@
1
+ import { z } from 'zod';
2
+ import { type MetricFilter } from '@hypequery/datasets';
3
+ export declare const queryMetricArgsSchema: z.ZodObject<{
4
+ dimensions: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
5
+ filters: z.ZodOptional<z.ZodArray<z.ZodObject<{
6
+ field: z.ZodString;
7
+ operator: z.ZodEnum<["eq", "neq", "gt", "gte", "lt", "lte", "in", "notIn", "between", "like"]>;
8
+ value: z.ZodEffects<z.ZodAny, any, any>;
9
+ }, "strict", z.ZodTypeAny, {
10
+ operator: "eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "in" | "notIn" | "between" | "like";
11
+ field: string;
12
+ value?: any;
13
+ }, {
14
+ operator: "eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "in" | "notIn" | "between" | "like";
15
+ field: string;
16
+ value?: any;
17
+ }>, "many">>;
18
+ grain: z.ZodOptional<z.ZodEnum<["day", "week", "month", "quarter", "year"]>>;
19
+ orderBy: z.ZodOptional<z.ZodArray<z.ZodObject<{
20
+ field: z.ZodString;
21
+ direction: z.ZodEnum<["asc", "desc"]>;
22
+ }, "strict", z.ZodTypeAny, {
23
+ field: string;
24
+ direction: "asc" | "desc";
25
+ }, {
26
+ field: string;
27
+ direction: "asc" | "desc";
28
+ }>, "many">>;
29
+ limit: z.ZodOptional<z.ZodNumber>;
30
+ offset: z.ZodOptional<z.ZodNumber>;
31
+ } & {
32
+ dataset: z.ZodOptional<z.ZodString>;
33
+ metric: z.ZodOptional<z.ZodString>;
34
+ }, "strict", z.ZodTypeAny, {
35
+ dataset?: string | undefined;
36
+ metric?: string | undefined;
37
+ dimensions?: string[] | undefined;
38
+ filters?: {
39
+ operator: "eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "in" | "notIn" | "between" | "like";
40
+ field: string;
41
+ value?: any;
42
+ }[] | undefined;
43
+ grain?: "day" | "week" | "month" | "quarter" | "year" | undefined;
44
+ orderBy?: {
45
+ field: string;
46
+ direction: "asc" | "desc";
47
+ }[] | undefined;
48
+ limit?: number | undefined;
49
+ offset?: number | undefined;
50
+ }, {
51
+ dataset?: string | undefined;
52
+ metric?: string | undefined;
53
+ dimensions?: string[] | undefined;
54
+ filters?: {
55
+ operator: "eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "in" | "notIn" | "between" | "like";
56
+ field: string;
57
+ value?: any;
58
+ }[] | undefined;
59
+ grain?: "day" | "week" | "month" | "quarter" | "year" | undefined;
60
+ orderBy?: {
61
+ field: string;
62
+ direction: "asc" | "desc";
63
+ }[] | undefined;
64
+ limit?: number | undefined;
65
+ offset?: number | undefined;
66
+ }>;
67
+ export declare const queryDatasetArgsSchema: z.ZodObject<{
68
+ dimensions: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
69
+ filters: z.ZodOptional<z.ZodArray<z.ZodObject<{
70
+ field: z.ZodString;
71
+ operator: z.ZodEnum<["eq", "neq", "gt", "gte", "lt", "lte", "in", "notIn", "between", "like"]>;
72
+ value: z.ZodEffects<z.ZodAny, any, any>;
73
+ }, "strict", z.ZodTypeAny, {
74
+ operator: "eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "in" | "notIn" | "between" | "like";
75
+ field: string;
76
+ value?: any;
77
+ }, {
78
+ operator: "eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "in" | "notIn" | "between" | "like";
79
+ field: string;
80
+ value?: any;
81
+ }>, "many">>;
82
+ grain: z.ZodOptional<z.ZodEnum<["day", "week", "month", "quarter", "year"]>>;
83
+ orderBy: z.ZodOptional<z.ZodArray<z.ZodObject<{
84
+ field: z.ZodString;
85
+ direction: z.ZodEnum<["asc", "desc"]>;
86
+ }, "strict", z.ZodTypeAny, {
87
+ field: string;
88
+ direction: "asc" | "desc";
89
+ }, {
90
+ field: string;
91
+ direction: "asc" | "desc";
92
+ }>, "many">>;
93
+ limit: z.ZodOptional<z.ZodNumber>;
94
+ offset: z.ZodOptional<z.ZodNumber>;
95
+ } & {
96
+ dataset: z.ZodOptional<z.ZodString>;
97
+ measures: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
98
+ }, "strict", z.ZodTypeAny, {
99
+ dataset?: string | undefined;
100
+ dimensions?: string[] | undefined;
101
+ filters?: {
102
+ operator: "eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "in" | "notIn" | "between" | "like";
103
+ field: string;
104
+ value?: any;
105
+ }[] | undefined;
106
+ grain?: "day" | "week" | "month" | "quarter" | "year" | undefined;
107
+ orderBy?: {
108
+ field: string;
109
+ direction: "asc" | "desc";
110
+ }[] | undefined;
111
+ limit?: number | undefined;
112
+ offset?: number | undefined;
113
+ measures?: string[] | undefined;
114
+ }, {
115
+ dataset?: string | undefined;
116
+ dimensions?: string[] | undefined;
117
+ filters?: {
118
+ operator: "eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "in" | "notIn" | "between" | "like";
119
+ field: string;
120
+ value?: any;
121
+ }[] | undefined;
122
+ grain?: "day" | "week" | "month" | "quarter" | "year" | undefined;
123
+ orderBy?: {
124
+ field: string;
125
+ direction: "asc" | "desc";
126
+ }[] | undefined;
127
+ limit?: number | undefined;
128
+ offset?: number | undefined;
129
+ measures?: string[] | undefined;
130
+ }>;
131
+ export declare function parseToolArgs<T>(schema: z.ZodType<T>, toolName: string, args: unknown): T;
132
+ export declare function toMetricFilters(filters?: Array<{
133
+ field: string;
134
+ operator: MetricFilter['operator'];
135
+ value?: unknown;
136
+ }>): MetricFilter[];
137
+ //# sourceMappingURL=args.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../../src/tools/args.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAA6B,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAuBnF,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAGhC,CAAC;AAEH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAGjC,CAAC;AAWH,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,CAAC,CAMzF;AAED,wBAAgB,eAAe,CAC7B,OAAO,GAAE,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,YAAY,CAAC,UAAU,CAAC,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,CAAM,GAC1F,YAAY,EAAE,CAMhB"}
@@ -0,0 +1,50 @@
1
+ import { z } from 'zod';
2
+ import { SEMANTIC_FILTER_OPERATORS } from '@hypequery/datasets';
3
+ import { MAX_QUERY_LIMIT } from '../types.js';
4
+ const filterSchema = z.object({
5
+ field: z.string().min(1),
6
+ operator: z.enum(SEMANTIC_FILTER_OPERATORS),
7
+ value: z.any().refine(value => value !== undefined, 'Required'),
8
+ }).strict();
9
+ const orderBySchema = z.object({
10
+ field: z.string().min(1),
11
+ direction: z.enum(['asc', 'desc']),
12
+ }).strict();
13
+ const baseQuerySchema = z.object({
14
+ dimensions: z.array(z.string().min(1)).optional(),
15
+ filters: z.array(filterSchema).optional(),
16
+ grain: z.enum(['day', 'week', 'month', 'quarter', 'year']).optional(),
17
+ orderBy: z.array(orderBySchema).optional(),
18
+ limit: z.number().int().nonnegative().max(MAX_QUERY_LIMIT).optional(),
19
+ offset: z.number().int().nonnegative().optional(),
20
+ }).strict();
21
+ export const queryMetricArgsSchema = baseQuerySchema.extend({
22
+ dataset: z.string().min(1).optional(),
23
+ metric: z.string().min(1).optional(),
24
+ });
25
+ export const queryDatasetArgsSchema = baseQuerySchema.extend({
26
+ dataset: z.string().min(1).optional(),
27
+ measures: z.array(z.string().min(1)).optional(),
28
+ });
29
+ function formatZodError(error) {
30
+ return error.issues
31
+ .map(issue => {
32
+ const path = issue.path.length > 0 ? issue.path.join('.') : 'arguments';
33
+ return `${path}: ${issue.message}`;
34
+ })
35
+ .join('; ');
36
+ }
37
+ export function parseToolArgs(schema, toolName, args) {
38
+ const result = schema.safeParse(args);
39
+ if (!result.success) {
40
+ throw new Error(`Invalid ${toolName} arguments: ${formatZodError(result.error)}`);
41
+ }
42
+ return result.data;
43
+ }
44
+ export function toMetricFilters(filters = []) {
45
+ return filters.map(filter => ({
46
+ field: filter.field,
47
+ operator: filter.operator,
48
+ value: filter.value,
49
+ }));
50
+ }
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * Get Dataset Schema Tool
3
3
  *
4
- * Returns the complete schema for a dataset including dimensions, metrics,
5
- * and relationships.
4
+ * Returns the complete schema for a dataset including dimensions, measures,
5
+ * named metrics, filters, and relationships.
6
6
  */
7
7
  import type { DatasetRegistry, MCPToolResponse } from '../types.js';
8
8
  export declare function getDatasetSchemaTool(datasets: DatasetRegistry, args: unknown): Promise<MCPToolResponse>;
@@ -1 +1 @@
1
- {"version":3,"file":"introspect.d.ts","sourceRoot":"","sources":["../../src/tools/introspect.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAwB,eAAe,EAAoE,MAAM,aAAa,CAAC;AAE5J,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,eAAe,EACzB,IAAI,EAAE,OAAO,GACZ,OAAO,CAAC,eAAe,CAAC,CA6E1B"}
1
+ {"version":3,"file":"introspect.d.ts","sourceRoot":"","sources":["../../src/tools/introspect.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EACV,eAAe,EAEf,eAAe,EAOhB,MAAM,aAAa,CAAC;AAMrB,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,eAAe,EACzB,IAAI,EAAE,OAAO,GACZ,OAAO,CAAC,eAAe,CAAC,CA+K1B"}
@@ -1,9 +1,13 @@
1
1
  /**
2
2
  * Get Dataset Schema Tool
3
3
  *
4
- * Returns the complete schema for a dataset including dimensions, metrics,
5
- * and relationships.
4
+ * Returns the complete schema for a dataset including dimensions, measures,
5
+ * named metrics, filters, and relationships.
6
6
  */
7
+ import { getDatasetCatalog } from '@hypequery/datasets';
8
+ function isDatasetInstance(value) {
9
+ return !!value && typeof value === 'object' && value.__type === 'dataset';
10
+ }
7
11
  export async function getDatasetSchemaTool(datasets, args) {
8
12
  // Parse and validate args
9
13
  const validatedArgs = args;
@@ -15,7 +19,6 @@ export async function getDatasetSchemaTool(datasets, args) {
15
19
  if (!dataset) {
16
20
  throw new Error(`Dataset not found: ${datasetName}`);
17
21
  }
18
- // Build schema response with proper types
19
22
  const datasetAny = dataset;
20
23
  const schema = {
21
24
  name: datasetName,
@@ -24,24 +27,129 @@ export async function getDatasetSchemaTool(datasets, args) {
24
27
  timeKey: datasetAny.timeKey || datasetAny.config?.timeKey || null,
25
28
  tenantKey: datasetAny.tenantKey || datasetAny.config?.tenantKey || null,
26
29
  dimensions: {},
30
+ measures: {},
27
31
  metrics: {},
32
+ filters: {},
28
33
  relationships: {},
34
+ limits: datasetAny.limits,
29
35
  };
30
- // Extract dimensions with proper typing
31
- if (datasetAny.dimensions) {
32
- for (const [name, dimension] of Object.entries(datasetAny.dimensions)) {
36
+ if (isDatasetInstance(dataset)) {
37
+ const catalog = getDatasetCatalog(dataset);
38
+ schema.source = catalog.source;
39
+ schema.timeKey = catalog.timeKey ?? null;
40
+ schema.tenantKey = catalog.tenantKey ?? null;
41
+ schema.limits = catalog.limits;
42
+ for (const [name, dimension] of Object.entries(catalog.dimensions)) {
33
43
  const dimSchema = {
34
- type: dimension.fieldType || dimension.type || 'unknown',
35
- column: dimension.column || name,
44
+ type: dimension.type,
45
+ column: dimension.column ?? name,
46
+ sql: dimension.sql ?? null,
36
47
  label: dimension.label || name,
37
48
  description: dimension.description || '',
38
- examples: dimension.examples || [],
49
+ examples: [],
50
+ filterable: dimension.filterable,
51
+ groupable: dimension.groupable,
39
52
  };
40
53
  schema.dimensions[name] = dimSchema;
41
54
  }
55
+ for (const [name, measure] of Object.entries(catalog.measures)) {
56
+ const measureSchema = {
57
+ aggregation: measure.aggregation,
58
+ field: measure.field,
59
+ sql: measure.sql ?? null,
60
+ label: measure.label || name,
61
+ description: measure.description || '',
62
+ };
63
+ schema.measures[name] = measureSchema;
64
+ }
65
+ for (const [name, filter] of Object.entries(catalog.filters)) {
66
+ const filterSchema = {
67
+ field: filter.field,
68
+ label: filter.label || name,
69
+ description: filter.description || '',
70
+ operators: filter.operators ? [...filter.operators] : null,
71
+ };
72
+ schema.filters[name] = filterSchema;
73
+ }
74
+ for (const [name, metric] of Object.entries(catalog.metrics)) {
75
+ const metSchema = {
76
+ type: metric.kind,
77
+ aggregation: metric.measures?.join(', ') || '',
78
+ label: metric.label || name,
79
+ description: metric.description || '',
80
+ format: null,
81
+ };
82
+ schema.metrics[name] = metSchema;
83
+ }
84
+ for (const [name, relationship] of Object.entries(catalog.relationships)) {
85
+ const relSchema = {
86
+ type: relationship.kind,
87
+ target: relationship.target,
88
+ from: relationship.from,
89
+ to: relationship.to,
90
+ execution: relationship.execution,
91
+ description: '',
92
+ };
93
+ schema.relationships[name] = relSchema;
94
+ }
95
+ }
96
+ else {
97
+ // Legacy object-shaped fixtures/configs.
98
+ if (datasetAny.dimensions) {
99
+ for (const [name, dimension] of Object.entries(datasetAny.dimensions)) {
100
+ const dimSchema = {
101
+ type: dimension.fieldType || dimension.type || 'unknown',
102
+ column: dimension.column || name,
103
+ sql: dimension.sql || null,
104
+ label: dimension.label || name,
105
+ description: dimension.description || '',
106
+ examples: dimension.examples || [],
107
+ filterable: dimension.filterable !== false,
108
+ groupable: dimension.groupable !== false,
109
+ };
110
+ schema.dimensions[name] = dimSchema;
111
+ }
112
+ }
113
+ if (datasetAny.measures) {
114
+ for (const [name, measure] of Object.entries(datasetAny.measures)) {
115
+ const measureSchema = {
116
+ aggregation: measure.aggregation || measure.type || 'unknown',
117
+ field: measure.field || name,
118
+ sql: measure.sql || null,
119
+ label: measure.label || name,
120
+ description: measure.description || '',
121
+ };
122
+ schema.measures[name] = measureSchema;
123
+ }
124
+ }
125
+ if (datasetAny.filters) {
126
+ for (const [name, filter] of Object.entries(datasetAny.filters)) {
127
+ const filterSchema = {
128
+ field: filter.field || name,
129
+ label: filter.label || name,
130
+ description: filter.description || '',
131
+ operators: filter.operators || null,
132
+ };
133
+ schema.filters[name] = filterSchema;
134
+ }
135
+ }
136
+ if (datasetAny.relationships) {
137
+ for (const [name, relationship] of Object.entries(datasetAny.relationships)) {
138
+ const rel = relationship;
139
+ const relSchema = {
140
+ type: rel.type || rel.kind || 'unknown',
141
+ target: typeof rel.target === 'function' ? rel.target()?.name || '' : rel.target || rel.dataset?.name || '',
142
+ from: rel.from,
143
+ to: rel.to,
144
+ execution: rel.execution,
145
+ description: rel.description || '',
146
+ };
147
+ schema.relationships[name] = relSchema;
148
+ }
149
+ }
42
150
  }
43
- // Extract metrics with proper typing
44
- if (datasetAny.metrics) {
151
+ // Backward compatibility for legacy object-shaped dataset fixtures.
152
+ if (!isDatasetInstance(dataset) && datasetAny.metrics) {
45
153
  for (const [name, metric] of Object.entries(datasetAny.metrics)) {
46
154
  const metSchema = {
47
155
  type: metric.spec?.__type || metric.type || 'unknown',
@@ -53,18 +161,6 @@ export async function getDatasetSchemaTool(datasets, args) {
53
161
  schema.metrics[name] = metSchema;
54
162
  }
55
163
  }
56
- // Extract relationships with proper typing
57
- if (datasetAny.relationships) {
58
- for (const [name, relationship] of Object.entries(datasetAny.relationships)) {
59
- const rel = relationship;
60
- const relSchema = {
61
- type: rel.type || rel.kind || 'unknown',
62
- target: typeof rel.target === 'function' ? rel.target()?.name || '' : rel.target || rel.dataset?.name || '',
63
- description: rel.description || '',
64
- };
65
- schema.relationships[name] = relSchema;
66
- }
67
- }
68
164
  return {
69
165
  content: [
70
166
  {
@@ -1 +1 @@
1
- {"version":3,"file":"list-datasets.d.ts","sourceRoot":"","sources":["../../src/tools/list-datasets.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAyC,MAAM,aAAa,CAAC;AAE3G,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,CA6B1F"}
1
+ {"version":3,"file":"list-datasets.d.ts","sourceRoot":"","sources":["../../src/tools/list-datasets.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAyC,MAAM,aAAa,CAAC;AAM3G,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,CA2C1F"}
@@ -3,17 +3,33 @@
3
3
  *
4
4
  * Returns a list of all available datasets with their descriptions.
5
5
  */
6
+ import { getDatasetCatalog } from '@hypequery/datasets';
7
+ function isDatasetInstance(value) {
8
+ return !!value && typeof value === 'object' && value.__type === 'dataset';
9
+ }
6
10
  export async function listDatasetsTool(datasets) {
7
11
  const datasetList = Object.entries(datasets).map(([name, dataset]) => {
8
12
  const datasetAny = dataset;
9
13
  // Try to extract description from dataset instance
10
14
  const description = datasetAny.description || datasetAny.config?.description || 'No description available';
15
+ if (isDatasetInstance(dataset)) {
16
+ const catalog = getDatasetCatalog(dataset);
17
+ return {
18
+ name,
19
+ description,
20
+ dimensionCount: Object.keys(catalog.dimensions).length,
21
+ measureCount: Object.keys(catalog.measures).length,
22
+ metricCount: Object.keys(catalog.metrics).length,
23
+ };
24
+ }
11
25
  const dimensionCount = datasetAny.dimensions ? Object.keys(datasetAny.dimensions).length : 0;
26
+ const measureCount = datasetAny.measures ? Object.keys(datasetAny.measures).length : 0;
12
27
  const metricCount = datasetAny.metrics ? Object.keys(datasetAny.metrics).length : 0;
13
28
  return {
14
29
  name,
15
30
  description,
16
31
  dimensionCount,
32
+ measureCount,
17
33
  metricCount,
18
34
  };
19
35
  });
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * Query Dataset Tool
3
3
  *
4
- * Executes an ad-hoc dataset query with custom dimensions and metrics.
4
+ * Executes an ad-hoc dataset query with custom dimensions and measures.
5
5
  */
6
- import type { MetricExecutor } from '@hypequery/datasets';
7
- import type { DatasetRegistry, MCPToolResponse } from '../types.js';
8
- export declare function queryDatasetTool(datasets: DatasetRegistry, executor: MetricExecutor, args: unknown): Promise<MCPToolResponse>;
6
+ import type { DatasetClient } from '@hypequery/datasets';
7
+ import type { DatasetRegistry, MCPToolResponse, QueryToolOptions } from '../types.js';
8
+ export declare function queryDatasetTool(datasets: DatasetRegistry, analytics: DatasetClient, args: unknown, options?: QueryToolOptions): Promise<MCPToolResponse>;
9
9
  //# sourceMappingURL=query-dataset.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"query-dataset.d.ts","sourceRoot":"","sources":["../../src/tools/query-dataset.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,eAAe,EAAoB,eAAe,EAAwC,MAAM,aAAa,CAAC;AAE5H,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,eAAe,EACzB,QAAQ,EAAE,cAAc,EACxB,IAAI,EAAE,OAAO,GACZ,OAAO,CAAC,eAAe,CAAC,CAgE1B"}
1
+ {"version":3,"file":"query-dataset.d.ts","sourceRoot":"","sources":["../../src/tools/query-dataset.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAgB,MAAM,qBAAqB,CAAC;AACvE,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAuB,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAG3G,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,eAAe,EACzB,SAAS,EAAE,aAAa,EACxB,IAAI,EAAE,OAAO,EACb,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,eAAe,CAAC,CA8D1B"}
@@ -1,13 +1,12 @@
1
1
  /**
2
2
  * Query Dataset Tool
3
3
  *
4
- * Executes an ad-hoc dataset query with custom dimensions and metrics.
4
+ * Executes an ad-hoc dataset query with custom dimensions and measures.
5
5
  */
6
- import { runDatasetQuery } from '@hypequery/datasets/internal';
7
- export async function queryDatasetTool(datasets, executor, args) {
8
- // Parse and validate args
9
- const validatedArgs = args;
10
- const { dataset: datasetName, dimensions, metrics, filters, grain, orderBy, limit } = validatedArgs;
6
+ import { parseToolArgs, queryDatasetArgsSchema, toMetricFilters } from './args.js';
7
+ export async function queryDatasetTool(datasets, analytics, args, options = {}) {
8
+ const validatedArgs = parseToolArgs(queryDatasetArgsSchema, 'query_dataset', args);
9
+ const { dataset: datasetName, dimensions, measures, filters, grain, orderBy, limit, offset } = validatedArgs;
11
10
  if (!datasetName) {
12
11
  throw new Error('dataset parameter is required');
13
12
  }
@@ -15,30 +14,28 @@ export async function queryDatasetTool(datasets, executor, args) {
15
14
  if (!dataset) {
16
15
  throw new Error(`Dataset not found: ${datasetName}`);
17
16
  }
18
- if (!dimensions?.length && !metrics?.length) {
19
- throw new Error('At least one dimension or metric must be specified');
17
+ if (!dimensions?.length && !measures?.length) {
18
+ throw new Error('At least one dimension or measure must be specified');
20
19
  }
21
20
  // Build the query with proper types
22
21
  const query = {
23
22
  dimensions: dimensions || [],
24
- measures: metrics || [],
25
- filters: filters || [],
23
+ measures: measures || [],
24
+ filters: toMetricFilters(filters),
26
25
  orderBy: orderBy || [],
27
26
  };
28
27
  if (grain) {
29
28
  query.by = grain;
30
29
  }
31
- // Apply limit with maximum cap
32
- const MAX_LIMIT = 10000;
33
30
  if (limit !== undefined) {
34
- query.limit = Math.min(limit, MAX_LIMIT);
31
+ query.limit = limit;
35
32
  }
36
- const result = await runDatasetQuery(dataset, query, {
37
- builderFactory: executor.getBuilderFactory(),
38
- context: {
39
- runtime: {
40
- tenant: undefined,
41
- },
33
+ if (offset !== undefined) {
34
+ query.offset = offset;
35
+ }
36
+ const result = await analytics.execute(dataset, query, {
37
+ runtime: {
38
+ tenant: options.tenantId ? { id: options.tenantId } : undefined,
42
39
  },
43
40
  });
44
41
  // Format the response with proper types
@@ -48,6 +45,7 @@ export async function queryDatasetTool(datasets, executor, args) {
48
45
  sql: result.meta?.sql,
49
46
  timingMs: result.meta?.timingMs,
50
47
  rowCount: result.data.length,
48
+ ...(result.meta?.pagination ? { pagination: result.meta.pagination } : {}),
51
49
  },
52
50
  };
53
51
  return {
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Executes a metric query with optional dimensions, filters, grain, and sorting.
5
5
  */
6
- import type { MetricExecutor } from '@hypequery/datasets';
7
- import type { DatasetRegistry, MCPToolResponse } from '../types.js';
8
- export declare function queryMetricTool(datasets: DatasetRegistry, executor: MetricExecutor, args: unknown): Promise<MCPToolResponse>;
6
+ import type { DatasetClient } from '@hypequery/datasets';
7
+ import type { DatasetRegistry, MCPToolResponse, QueryToolOptions } from '../types.js';
8
+ export declare function queryMetricTool(datasets: DatasetRegistry, analytics: DatasetClient, args: unknown, options?: QueryToolOptions): Promise<MCPToolResponse>;
9
9
  //# sourceMappingURL=query-metric.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"query-metric.d.ts","sourceRoot":"","sources":["../../src/tools/query-metric.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAe,MAAM,qBAAqB,CAAC;AACvE,OAAO,KAAK,EAAE,eAAe,EAAmB,eAAe,EAAwC,MAAM,aAAa,CAAC;AAE3H,wBAAsB,eAAe,CACnC,QAAQ,EAAE,eAAe,EACzB,QAAQ,EAAE,cAAc,EACxB,IAAI,EAAE,OAAO,GACZ,OAAO,CAAC,eAAe,CAAC,CAqE1B"}
1
+ {"version":3,"file":"query-metric.d.ts","sourceRoot":"","sources":["../../src/tools/query-metric.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAe,MAAM,qBAAqB,CAAC;AACtE,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAuB,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAG3G,wBAAsB,eAAe,CACnC,QAAQ,EAAE,eAAe,EACzB,SAAS,EAAE,aAAa,EACxB,IAAI,EAAE,OAAO,EACb,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,eAAe,CAAC,CAqE1B"}
@@ -3,10 +3,10 @@
3
3
  *
4
4
  * Executes a metric query with optional dimensions, filters, grain, and sorting.
5
5
  */
6
- export async function queryMetricTool(datasets, executor, args) {
7
- // Parse and validate args
8
- const validatedArgs = args;
9
- const { dataset: datasetName, metric: metricName, dimensions, filters, grain, orderBy, limit } = validatedArgs;
6
+ import { parseToolArgs, queryMetricArgsSchema, toMetricFilters } from './args.js';
7
+ export async function queryMetricTool(datasets, analytics, args, options = {}) {
8
+ const validatedArgs = parseToolArgs(queryMetricArgsSchema, 'query_metric', args);
9
+ const { dataset: datasetName, metric: metricName, dimensions, filters, grain, orderBy, limit, offset } = validatedArgs;
10
10
  if (!datasetName) {
11
11
  throw new Error('dataset parameter is required');
12
12
  }
@@ -25,22 +25,22 @@ export async function queryMetricTool(datasets, executor, args) {
25
25
  // Build the query with proper types
26
26
  const query = {
27
27
  dimensions: dimensions || [],
28
- filters: filters || [],
28
+ filters: toMetricFilters(filters),
29
29
  orderBy: orderBy || [],
30
30
  };
31
31
  if (grain) {
32
32
  query.by = grain;
33
33
  }
34
- // Apply limit with maximum cap
35
- const MAX_LIMIT = 10000;
36
34
  if (limit !== undefined) {
37
- query.limit = Math.min(limit, MAX_LIMIT);
35
+ query.limit = limit;
36
+ }
37
+ if (offset !== undefined) {
38
+ query.offset = offset;
38
39
  }
39
40
  // Execute the query
40
- const result = await executor.run(metric, query, {
41
+ const result = await analytics.execute(metric, query, {
41
42
  runtime: {
42
- builderFactory: executor.getBuilderFactory(),
43
- tenant: undefined,
43
+ tenant: options.tenantId ? { id: options.tenantId } : undefined,
44
44
  },
45
45
  });
46
46
  // Format the response with proper types
@@ -50,6 +50,7 @@ export async function queryMetricTool(datasets, executor, args) {
50
50
  sql: result.meta?.sql,
51
51
  timingMs: result.meta?.timingMs,
52
52
  rowCount: result.data.length,
53
+ ...(result.meta?.pagination ? { pagination: result.meta.pagination } : {}),
53
54
  },
54
55
  };
55
56
  return {
package/dist/types.d.ts CHANGED
@@ -1,12 +1,11 @@
1
1
  /**
2
2
  * Type definitions for MCP Server
3
3
  */
4
- import type { MetricFilter, TimeGrain, MetricOrderBy } from '@hypequery/datasets';
4
+ import type { AnyDatasetInstance, MetricFilter, TimeGrain, MetricOrderBy } from '@hypequery/datasets';
5
5
  /**
6
6
  * Registry of datasets - maps dataset names to dataset instances
7
- * Using flexible type to accommodate actual dataset structure
8
7
  */
9
- export type DatasetRegistry = Record<string, Record<string, unknown>>;
8
+ export type DatasetRegistry = Record<string, AnyDatasetInstance | Record<string, unknown>>;
10
9
  /**
11
10
  * Arguments for query_metric tool
12
11
  */
@@ -18,6 +17,7 @@ export interface QueryMetricArgs {
18
17
  grain?: TimeGrain;
19
18
  orderBy?: MetricOrderBy[];
20
19
  limit?: number;
20
+ offset?: number;
21
21
  }
22
22
  /**
23
23
  * Arguments for query_dataset tool
@@ -25,11 +25,15 @@ export interface QueryMetricArgs {
25
25
  export interface QueryDatasetArgs {
26
26
  dataset: string;
27
27
  dimensions?: string[];
28
- metrics?: string[];
28
+ measures?: string[];
29
29
  filters?: MetricFilter[];
30
30
  grain?: TimeGrain;
31
31
  orderBy?: MetricOrderBy[];
32
32
  limit?: number;
33
+ offset?: number;
34
+ }
35
+ export interface QueryToolOptions {
36
+ tenantId?: string;
33
37
  }
34
38
  /**
35
39
  * Arguments for get_dataset_schema tool
@@ -59,18 +63,48 @@ export interface DatasetSchema {
59
63
  timeKey: string | null;
60
64
  tenantKey: string | null;
61
65
  dimensions: Record<string, DimensionSchema>;
66
+ measures: Record<string, MeasureSchema>;
62
67
  metrics: Record<string, MetricSchema>;
68
+ filters: Record<string, FilterSchema>;
63
69
  relationships: Record<string, RelationshipSchema>;
70
+ limits?: {
71
+ maxDimensions?: number;
72
+ maxMeasures?: number;
73
+ maxFilters?: number;
74
+ maxResultSize?: number;
75
+ };
64
76
  }
65
77
  /**
66
78
  * Dimension schema in response
67
79
  */
68
80
  export interface DimensionSchema {
69
81
  type: string;
70
- column: string;
82
+ column: string | null;
83
+ sql: string | null;
71
84
  label: string;
72
85
  description: string;
73
86
  examples: string[];
87
+ filterable: boolean;
88
+ groupable: boolean;
89
+ }
90
+ /**
91
+ * Measure schema in response
92
+ */
93
+ export interface MeasureSchema {
94
+ aggregation: string;
95
+ field: string;
96
+ sql: string | null;
97
+ label: string;
98
+ description: string;
99
+ }
100
+ /**
101
+ * Filter schema in response
102
+ */
103
+ export interface FilterSchema {
104
+ field: string;
105
+ label: string;
106
+ description: string;
107
+ operators: string[] | null;
74
108
  }
75
109
  /**
76
110
  * Metric schema in response
@@ -88,6 +122,9 @@ export interface MetricSchema {
88
122
  export interface RelationshipSchema {
89
123
  type: string;
90
124
  target: string;
125
+ from?: string;
126
+ to?: string;
127
+ execution?: string;
91
128
  description: string;
92
129
  }
93
130
  /**
@@ -97,6 +134,7 @@ export interface DatasetListItem {
97
134
  name: string;
98
135
  description: string;
99
136
  dimensionCount: number;
137
+ measureCount?: number;
100
138
  metricCount: number;
101
139
  }
102
140
  /**
@@ -113,6 +151,15 @@ export interface QueryResultMeta {
113
151
  sql?: string;
114
152
  timingMs?: number;
115
153
  rowCount: number;
154
+ /**
155
+ * Offset pagination state. Present when the query specified a `limit`.
156
+ * `hasMore` lets callers know whether to request the next `offset` page.
157
+ */
158
+ pagination?: {
159
+ limit: number;
160
+ offset: number;
161
+ hasMore: boolean;
162
+ };
116
163
  }
117
164
  /**
118
165
  * Query result response
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hypequery/mcp",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "Model Context Protocol (MCP) server for Hypequery semantic layer",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -20,9 +20,9 @@
20
20
  "dist"
21
21
  ],
22
22
  "dependencies": {
23
+ "@hypequery/datasets": "^0.2.1",
23
24
  "@modelcontextprotocol/sdk": "^1.29.0",
24
- "zod": "^3.23.8",
25
- "@hypequery/datasets": "0.1.0"
25
+ "zod": "^3.23.8"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@types/node": "^20.11.30",