@hypequery/mcp 0.1.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.
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Query Metric Tool
3
+ *
4
+ * Executes a metric query with optional dimensions, filters, grain, and sorting.
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;
10
+ if (!datasetName) {
11
+ throw new Error('dataset parameter is required');
12
+ }
13
+ if (!metricName) {
14
+ throw new Error('metric parameter is required');
15
+ }
16
+ const dataset = datasets[datasetName];
17
+ if (!dataset) {
18
+ throw new Error(`Dataset not found: ${datasetName}`);
19
+ }
20
+ // Get the metric from the dataset
21
+ const metric = dataset[metricName] || dataset.metrics?.[metricName];
22
+ if (!metric) {
23
+ throw new Error(`Metric not found: ${metricName} in dataset ${datasetName}`);
24
+ }
25
+ // Build the query with proper types
26
+ const query = {
27
+ dimensions: dimensions || [],
28
+ filters: filters || [],
29
+ orderBy: orderBy || [],
30
+ };
31
+ if (grain) {
32
+ query.by = grain;
33
+ }
34
+ // Apply limit with maximum cap
35
+ const MAX_LIMIT = 10000;
36
+ if (limit !== undefined) {
37
+ query.limit = Math.min(limit, MAX_LIMIT);
38
+ }
39
+ // Execute the query
40
+ const result = await executor.run(metric, query, {
41
+ runtime: {
42
+ builderFactory: executor.getBuilderFactory(),
43
+ tenant: undefined,
44
+ },
45
+ });
46
+ // Format the response with proper types
47
+ const response = {
48
+ data: result.data,
49
+ meta: {
50
+ sql: result.meta?.sql,
51
+ timingMs: result.meta?.timingMs,
52
+ rowCount: result.data.length,
53
+ },
54
+ };
55
+ return {
56
+ content: [
57
+ {
58
+ type: 'text',
59
+ text: JSON.stringify(response, null, 2),
60
+ },
61
+ ],
62
+ };
63
+ }
@@ -0,0 +1,129 @@
1
+ /**
2
+ * Type definitions for MCP Server
3
+ */
4
+ import type { MetricFilter, TimeGrain, MetricOrderBy } from '@hypequery/datasets';
5
+ /**
6
+ * Registry of datasets - maps dataset names to dataset instances
7
+ * Using flexible type to accommodate actual dataset structure
8
+ */
9
+ export type DatasetRegistry = Record<string, Record<string, unknown>>;
10
+ /**
11
+ * Arguments for query_metric tool
12
+ */
13
+ export interface QueryMetricArgs {
14
+ dataset: string;
15
+ metric: string;
16
+ dimensions?: string[];
17
+ filters?: MetricFilter[];
18
+ grain?: TimeGrain;
19
+ orderBy?: MetricOrderBy[];
20
+ limit?: number;
21
+ }
22
+ /**
23
+ * Arguments for query_dataset tool
24
+ */
25
+ export interface QueryDatasetArgs {
26
+ dataset: string;
27
+ dimensions?: string[];
28
+ metrics?: string[];
29
+ filters?: MetricFilter[];
30
+ grain?: TimeGrain;
31
+ orderBy?: MetricOrderBy[];
32
+ limit?: number;
33
+ }
34
+ /**
35
+ * Arguments for get_dataset_schema tool
36
+ */
37
+ export interface GetDatasetSchemaArgs {
38
+ dataset: string;
39
+ }
40
+ /**
41
+ * MCP tool response format
42
+ * Matches the MCP SDK CallToolResult type
43
+ */
44
+ export interface MCPToolResponse {
45
+ content: Array<{
46
+ type: 'text';
47
+ text: string;
48
+ }>;
49
+ isError?: boolean;
50
+ [key: string]: unknown;
51
+ }
52
+ /**
53
+ * Dataset schema response structure
54
+ */
55
+ export interface DatasetSchema {
56
+ name: string;
57
+ description: string;
58
+ source: string;
59
+ timeKey: string | null;
60
+ tenantKey: string | null;
61
+ dimensions: Record<string, DimensionSchema>;
62
+ metrics: Record<string, MetricSchema>;
63
+ relationships: Record<string, RelationshipSchema>;
64
+ }
65
+ /**
66
+ * Dimension schema in response
67
+ */
68
+ export interface DimensionSchema {
69
+ type: string;
70
+ column: string;
71
+ label: string;
72
+ description: string;
73
+ examples: string[];
74
+ }
75
+ /**
76
+ * Metric schema in response
77
+ */
78
+ export interface MetricSchema {
79
+ type: string;
80
+ aggregation: string;
81
+ label: string;
82
+ description: string;
83
+ format: string | null;
84
+ }
85
+ /**
86
+ * Relationship schema in response
87
+ */
88
+ export interface RelationshipSchema {
89
+ type: string;
90
+ target: string;
91
+ description: string;
92
+ }
93
+ /**
94
+ * Dataset list item
95
+ */
96
+ export interface DatasetListItem {
97
+ name: string;
98
+ description: string;
99
+ dimensionCount: number;
100
+ metricCount: number;
101
+ }
102
+ /**
103
+ * Datasets list response
104
+ */
105
+ export interface DatasetsListResponse {
106
+ datasets: DatasetListItem[];
107
+ total: number;
108
+ }
109
+ /**
110
+ * Query result metadata
111
+ */
112
+ export interface QueryResultMeta {
113
+ sql?: string;
114
+ timingMs?: number;
115
+ rowCount: number;
116
+ }
117
+ /**
118
+ * Query result response
119
+ */
120
+ export interface QueryResultResponse {
121
+ data: Record<string, unknown>[];
122
+ meta: QueryResultMeta;
123
+ }
124
+ /**
125
+ * Constants
126
+ */
127
+ export declare const MAX_QUERY_LIMIT = 10000;
128
+ export declare const DEFAULT_QUERY_LIMIT = 100;
129
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Type definitions for MCP Server
3
+ */
4
+ /**
5
+ * Constants
6
+ */
7
+ export const MAX_QUERY_LIMIT = 10000;
8
+ export const DEFAULT_QUERY_LIMIT = 100;
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@hypequery/mcp",
3
+ "version": "0.1.0",
4
+ "description": "Model Context Protocol (MCP) server for Hypequery semantic layer",
5
+ "license": "Apache-2.0",
6
+ "type": "module",
7
+ "main": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "bin": {
10
+ "hypequery-mcp": "./dist/bin.js"
11
+ },
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "import": "./dist/index.js",
16
+ "require": "./dist/index.js"
17
+ }
18
+ },
19
+ "files": [
20
+ "dist"
21
+ ],
22
+ "dependencies": {
23
+ "@modelcontextprotocol/sdk": "^1.29.0",
24
+ "zod": "^3.23.8",
25
+ "@hypequery/datasets": "0.1.0"
26
+ },
27
+ "devDependencies": {
28
+ "@types/node": "^20.11.30",
29
+ "typescript": "^5.7.3",
30
+ "vitest": "^2.1.6"
31
+ },
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "https://github.com/hypequery/hypequery.git"
35
+ },
36
+ "homepage": "https://hypequery.com",
37
+ "bugs": {
38
+ "url": "https://github.com/hypequery/hypequery/issues"
39
+ },
40
+ "publishConfig": {
41
+ "access": "public"
42
+ },
43
+ "scripts": {
44
+ "build": "tsc --project tsconfig.json",
45
+ "dev": "tsc --project tsconfig.json --watch",
46
+ "test": "npm run test:types && npm run test:unit",
47
+ "test:unit": "vitest run",
48
+ "test:types": "tsc --project tsconfig.json --noEmit",
49
+ "start": "node dist/bin.js"
50
+ }
51
+ }