@duckcodeailabs/dql-mcp 1.2.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/LICENSE +123 -0
- package/dist/context.d.ts +26 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +102 -0
- package/dist/context.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +7 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +34 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/certify.d.ts +31 -0
- package/dist/tools/certify.d.ts.map +1 -0
- package/dist/tools/certify.js +22 -0
- package/dist/tools/certify.js.map +1 -0
- package/dist/tools/get-block.d.ts +55 -0
- package/dist/tools/get-block.d.ts.map +1 -0
- package/dist/tools/get-block.js +46 -0
- package/dist/tools/get-block.js.map +1 -0
- package/dist/tools/lineage-impact.d.ts +15 -0
- package/dist/tools/lineage-impact.d.ts.map +1 -0
- package/dist/tools/lineage-impact.js +45 -0
- package/dist/tools/lineage-impact.js.map +1 -0
- package/dist/tools/query-via-block.d.ts +37 -0
- package/dist/tools/query-via-block.d.ts.map +1 -0
- package/dist/tools/query-via-block.js +56 -0
- package/dist/tools/query-via-block.js.map +1 -0
- package/dist/tools/search-blocks.d.ts +32 -0
- package/dist/tools/search-blocks.d.ts.map +1 -0
- package/dist/tools/search-blocks.js +53 -0
- package/dist/tools/search-blocks.js.map +1 -0
- package/dist/tools/semantic.d.ts +35 -0
- package/dist/tools/semantic.d.ts.map +1 -0
- package/dist/tools/semantic.js +36 -0
- package/dist/tools/semantic.js.map +1 -0
- package/dist/tools/suggest-block.d.ts +48 -0
- package/dist/tools/suggest-block.d.ts.map +1 -0
- package/dist/tools/suggest-block.js +79 -0
- package/dist/tools/suggest-block.js.map +1 -0
- package/dist/tools/util.d.ts +10 -0
- package/dist/tools/util.d.ts.map +1 -0
- package/dist/tools/util.js +28 -0
- package/dist/tools/util.js.map +1 -0
- package/dist/transports/http.d.ts +20 -0
- package/dist/transports/http.d.ts.map +1 -0
- package/dist/transports/http.js +52 -0
- package/dist/transports/http.js.map +1 -0
- package/dist/transports/stdio.d.ts +7 -0
- package/dist/transports/stdio.d.ts.map +1 -0
- package/dist/transports/stdio.js +12 -0
- package/dist/transports/stdio.js.map +1 -0
- package/package.json +46 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-via-block.d.ts","sourceRoot":"","sources":["../../src/tools/query-via-block.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,eAAO,MAAM,kBAAkB;;;;CAS9B,CAAC;AAEF;;;;GAIG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,UAAU,EACf,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE;;;;;;;;;;;;;;cAmChC,MAAM;eAAS,MAAM;;;;GAahD"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export const queryViaBlockInput = {
|
|
3
|
+
name: z.string().describe('Certified block to execute.'),
|
|
4
|
+
limit: z.number().int().min(1).max(10000).optional().describe('Max rows to return.'),
|
|
5
|
+
serverUrl: z
|
|
6
|
+
.string()
|
|
7
|
+
.optional()
|
|
8
|
+
.describe('Base URL of the local DQL runtime (default http://127.0.0.1:3474). Start it with `dql serve`.'),
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Execute a certified block by name. Delegates SQL prep + warehouse execution
|
|
12
|
+
* to the local-runtime HTTP server, so results honor the same semantic resolver
|
|
13
|
+
* and connection config as the notebook UI — the agent never sees raw SQL.
|
|
14
|
+
*/
|
|
15
|
+
export async function queryViaBlock(ctx, args) {
|
|
16
|
+
const block = ctx.manifest.blocks[args.name];
|
|
17
|
+
if (!block)
|
|
18
|
+
return { error: `No block named "${args.name}".` };
|
|
19
|
+
if (block.status !== 'certified') {
|
|
20
|
+
return {
|
|
21
|
+
error: `Block "${args.name}" is "${block.status ?? 'draft'}" — only certified blocks can be executed via MCP.`,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
const base = args.serverUrl ?? process.env.DQL_RUNTIME_URL ?? 'http://127.0.0.1:3474';
|
|
25
|
+
const url = `${base.replace(/\/$/, '')}/api/query`;
|
|
26
|
+
let response;
|
|
27
|
+
try {
|
|
28
|
+
response = await fetch(url, {
|
|
29
|
+
method: 'POST',
|
|
30
|
+
headers: { 'Content-Type': 'application/json' },
|
|
31
|
+
body: JSON.stringify({
|
|
32
|
+
sql: block.sql,
|
|
33
|
+
blockName: args.name,
|
|
34
|
+
limit: args.limit,
|
|
35
|
+
}),
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
return {
|
|
40
|
+
error: `Could not reach DQL runtime at ${base}. Start it with \`dql serve\` in ${ctx.projectRoot}. (${err instanceof Error ? err.message : String(err)})`,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
if (!response.ok) {
|
|
44
|
+
return { error: `Runtime returned ${response.status}: ${await response.text()}` };
|
|
45
|
+
}
|
|
46
|
+
const payload = (await response.json());
|
|
47
|
+
return {
|
|
48
|
+
block: args.name,
|
|
49
|
+
blockPath: block.filePath,
|
|
50
|
+
rowCount: payload.rows?.length ?? 0,
|
|
51
|
+
durationMs: payload.durationMs ?? null,
|
|
52
|
+
columns: payload.columns ?? [],
|
|
53
|
+
rows: payload.rows ?? [],
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=query-via-block.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-via-block.js","sourceRoot":"","sources":["../../src/tools/query-via-block.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6BAA6B,CAAC;IACxD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,qBAAqB,CAAC;IACpF,SAAS,EAAE,CAAC;SACT,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,+FAA+F,CAChG;CACJ,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,GAAe,EACf,IAA0D;IAE1D,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7C,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,KAAK,EAAE,mBAAmB,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;IAC/D,IAAI,KAAK,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;QACjC,OAAO;YACL,KAAK,EAAE,UAAU,IAAI,CAAC,IAAI,SAAS,KAAK,CAAC,MAAM,IAAI,OAAO,oDAAoD;SAC/G,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,uBAAuB,CAAC;IACtF,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC;IAEnD,IAAI,QAAkB,CAAC;IACvB,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAC1B,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,GAAG,EAAE,KAAK,CAAC,GAAG;gBACd,SAAS,EAAE,IAAI,CAAC,IAAI;gBACpB,KAAK,EAAE,IAAI,CAAC,KAAK;aAClB,CAAC;SACH,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,KAAK,EAAE,kCAAkC,IAAI,oCAAoC,GAAG,CAAC,WAAW,MAAM,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG;SAC1J,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,OAAO,EAAE,KAAK,EAAE,oBAAoB,QAAQ,CAAC,MAAM,KAAK,MAAM,QAAQ,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC;IACpF,CAAC;IAED,MAAM,OAAO,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAIrC,CAAC;IAEF,OAAO;QACL,KAAK,EAAE,IAAI,CAAC,IAAI;QAChB,SAAS,EAAE,KAAK,CAAC,QAAQ;QACzB,QAAQ,EAAE,OAAO,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC;QACnC,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,IAAI;QACtC,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,EAAE;QAC9B,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,EAAE;KACzB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { DQLContext } from '../context.js';
|
|
3
|
+
export declare const searchBlocksInput: {
|
|
4
|
+
query: z.ZodOptional<z.ZodString>;
|
|
5
|
+
domain: z.ZodOptional<z.ZodString>;
|
|
6
|
+
status: z.ZodOptional<z.ZodEnum<["draft", "review", "certified", "deprecated", "pending_recertification"]>>;
|
|
7
|
+
limit: z.ZodOptional<z.ZodNumber>;
|
|
8
|
+
};
|
|
9
|
+
export declare function searchBlocks(ctx: DQLContext, args: {
|
|
10
|
+
query?: string;
|
|
11
|
+
domain?: string;
|
|
12
|
+
status?: string;
|
|
13
|
+
limit?: number;
|
|
14
|
+
}): {
|
|
15
|
+
total: number;
|
|
16
|
+
returned: number;
|
|
17
|
+
blocks: {
|
|
18
|
+
name: string;
|
|
19
|
+
path: string;
|
|
20
|
+
domain: string | null;
|
|
21
|
+
owner: string | null;
|
|
22
|
+
status: string;
|
|
23
|
+
description: string | null;
|
|
24
|
+
tags: string[];
|
|
25
|
+
dependencies: string[];
|
|
26
|
+
chartType: string | null;
|
|
27
|
+
llmContext: string | null;
|
|
28
|
+
hasExamples: boolean;
|
|
29
|
+
hasInvariants: boolean;
|
|
30
|
+
}[];
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=search-blocks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-blocks.d.ts","sourceRoot":"","sources":["../../src/tools/search-blocks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAGhD,eAAO,MAAM,iBAAiB;;;;;CAQ7B,CAAC;AAEF,wBAAgB,YAAY,CAC1B,GAAG,EAAE,UAAU,EACf,IAAI,EAAE;IACJ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;;;;;;;;;;;;;;;;;EAuBF"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export const searchBlocksInput = {
|
|
3
|
+
query: z.string().optional().describe('Substring matched against name, description, or tags.'),
|
|
4
|
+
domain: z.string().optional().describe('Filter to a single business domain.'),
|
|
5
|
+
status: z
|
|
6
|
+
.enum(['draft', 'review', 'certified', 'deprecated', 'pending_recertification'])
|
|
7
|
+
.optional()
|
|
8
|
+
.describe('Filter by certification status.'),
|
|
9
|
+
limit: z.number().int().min(1).max(200).optional().describe('Max results (default 50).'),
|
|
10
|
+
};
|
|
11
|
+
export function searchBlocks(ctx, args) {
|
|
12
|
+
const { query, domain, status, limit = 50 } = args;
|
|
13
|
+
const needle = query?.trim().toLowerCase();
|
|
14
|
+
const blocks = Object.values(ctx.manifest.blocks).filter((block) => {
|
|
15
|
+
if (domain && block.domain !== domain)
|
|
16
|
+
return false;
|
|
17
|
+
if (status && block.status !== status)
|
|
18
|
+
return false;
|
|
19
|
+
if (needle) {
|
|
20
|
+
const haystack = [block.name, block.description ?? '', (block.tags ?? []).join(' ')]
|
|
21
|
+
.join(' ')
|
|
22
|
+
.toLowerCase();
|
|
23
|
+
if (!haystack.includes(needle))
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
return true;
|
|
27
|
+
});
|
|
28
|
+
const results = blocks.slice(0, limit).map(summarize);
|
|
29
|
+
return {
|
|
30
|
+
total: blocks.length,
|
|
31
|
+
returned: results.length,
|
|
32
|
+
blocks: results,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function summarize(block) {
|
|
36
|
+
return {
|
|
37
|
+
name: block.name,
|
|
38
|
+
path: block.filePath,
|
|
39
|
+
domain: block.domain ?? null,
|
|
40
|
+
owner: block.owner ?? null,
|
|
41
|
+
status: block.status ?? 'draft',
|
|
42
|
+
description: block.description ?? null,
|
|
43
|
+
tags: block.tags ?? [],
|
|
44
|
+
dependencies: block.allDependencies,
|
|
45
|
+
chartType: block.chartType ?? null,
|
|
46
|
+
// v1.2 Track G — agent-facing metadata. Surfaced so agents can prefer
|
|
47
|
+
// blocks with richer grounding without a second tool round-trip.
|
|
48
|
+
llmContext: block.llmContext ?? null,
|
|
49
|
+
hasExamples: !!(block.examples && block.examples.length > 0),
|
|
50
|
+
hasInvariants: !!(block.invariants && block.invariants.length > 0),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=search-blocks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-blocks.js","sourceRoot":"","sources":["../../src/tools/search-blocks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { DQLContext } from '../context.js';
|
|
3
|
+
export declare const listMetricsInput: {
|
|
4
|
+
domain: z.ZodOptional<z.ZodString>;
|
|
5
|
+
};
|
|
6
|
+
export declare function listMetrics(ctx: DQLContext, args: {
|
|
7
|
+
domain?: string;
|
|
8
|
+
}): {
|
|
9
|
+
domain: string | null;
|
|
10
|
+
total: number;
|
|
11
|
+
metrics: {
|
|
12
|
+
name: string;
|
|
13
|
+
type: "sum" | "count" | "count_distinct" | "avg" | "min" | "max" | "custom";
|
|
14
|
+
table: string;
|
|
15
|
+
domain: string | null;
|
|
16
|
+
description: string;
|
|
17
|
+
sql: string;
|
|
18
|
+
}[];
|
|
19
|
+
};
|
|
20
|
+
export declare const listDimensionsInput: {
|
|
21
|
+
domain: z.ZodOptional<z.ZodString>;
|
|
22
|
+
};
|
|
23
|
+
export declare function listDimensions(ctx: DQLContext, args: {
|
|
24
|
+
domain?: string;
|
|
25
|
+
}): {
|
|
26
|
+
domain: string | null;
|
|
27
|
+
total: number;
|
|
28
|
+
dimensions: {
|
|
29
|
+
name: string;
|
|
30
|
+
table: string;
|
|
31
|
+
type: "string" | "number" | "boolean" | "date";
|
|
32
|
+
description: string;
|
|
33
|
+
}[];
|
|
34
|
+
};
|
|
35
|
+
//# sourceMappingURL=semantic.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"semantic.d.ts","sourceRoot":"","sources":["../../src/tools/semantic.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,eAAO,MAAM,gBAAgB;;CAE5B,CAAC;AAEF,wBAAgB,WAAW,CAAC,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE;;;;;;;;;;;EAcrE;AAED,eAAO,MAAM,mBAAmB;;CAE/B,CAAC;AAEF,wBAAgB,cAAc,CAAC,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE;;;;;;;;;EAYxE"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export const listMetricsInput = {
|
|
3
|
+
domain: z.string().optional().describe('Filter to a single domain.'),
|
|
4
|
+
};
|
|
5
|
+
export function listMetrics(ctx, args) {
|
|
6
|
+
const metrics = ctx.semanticLayer.listMetrics(args.domain);
|
|
7
|
+
return {
|
|
8
|
+
domain: args.domain ?? null,
|
|
9
|
+
total: metrics.length,
|
|
10
|
+
metrics: metrics.map((m) => ({
|
|
11
|
+
name: m.name,
|
|
12
|
+
type: m.type,
|
|
13
|
+
table: m.table,
|
|
14
|
+
domain: m.domain ?? null,
|
|
15
|
+
description: m.description ?? null,
|
|
16
|
+
sql: m.sql ?? null,
|
|
17
|
+
})),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export const listDimensionsInput = {
|
|
21
|
+
domain: z.string().optional().describe('Filter to a single domain.'),
|
|
22
|
+
};
|
|
23
|
+
export function listDimensions(ctx, args) {
|
|
24
|
+
const dims = ctx.semanticLayer.listDimensions(args.domain);
|
|
25
|
+
return {
|
|
26
|
+
domain: args.domain ?? null,
|
|
27
|
+
total: dims.length,
|
|
28
|
+
dimensions: dims.map((d) => ({
|
|
29
|
+
name: d.name,
|
|
30
|
+
table: d.table,
|
|
31
|
+
type: d.type ?? null,
|
|
32
|
+
description: d.description ?? null,
|
|
33
|
+
})),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=semantic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"semantic.js","sourceRoot":"","sources":["../../src/tools/semantic.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,4BAA4B,CAAC;CACrE,CAAC;AAEF,MAAM,UAAU,WAAW,CAAC,GAAe,EAAE,IAAyB;IACpE,MAAM,OAAO,GAAG,GAAG,CAAC,aAAa,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC3D,OAAO;QACL,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,IAAI;QAC3B,KAAK,EAAE,OAAO,CAAC,MAAM;QACrB,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC3B,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,MAAM,EAAG,CAAoC,CAAC,MAAM,IAAI,IAAI;YAC5D,WAAW,EAAE,CAAC,CAAC,WAAW,IAAI,IAAI;YAClC,GAAG,EAAE,CAAC,CAAC,GAAG,IAAI,IAAI;SACnB,CAAC,CAAC;KACJ,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,4BAA4B,CAAC;CACrE,CAAC;AAEF,MAAM,UAAU,cAAc,CAAC,GAAe,EAAE,IAAyB;IACvE,MAAM,IAAI,GAAG,GAAG,CAAC,aAAa,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC3D,OAAO;QACL,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,IAAI;QAC3B,KAAK,EAAE,IAAI,CAAC,MAAM;QAClB,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC3B,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,IAAI;YACpB,WAAW,EAAE,CAAC,CAAC,WAAW,IAAI,IAAI;SACnC,CAAC,CAAC;KACJ,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { DQLContext } from '../context.js';
|
|
3
|
+
export declare const suggestBlockInput: {
|
|
4
|
+
name: z.ZodString;
|
|
5
|
+
domain: z.ZodString;
|
|
6
|
+
owner: z.ZodString;
|
|
7
|
+
description: z.ZodString;
|
|
8
|
+
sql: z.ZodString;
|
|
9
|
+
tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
10
|
+
chartType: z.ZodOptional<z.ZodString>;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Write a proposed block to `blocks/_drafts/<name>.dql` and return the
|
|
14
|
+
* governance-gate result. Never auto-certifies — the human still has to
|
|
15
|
+
* review and move the file.
|
|
16
|
+
*/
|
|
17
|
+
export declare function suggestBlock(ctx: DQLContext, args: {
|
|
18
|
+
name: string;
|
|
19
|
+
domain: string;
|
|
20
|
+
owner: string;
|
|
21
|
+
description: string;
|
|
22
|
+
sql: string;
|
|
23
|
+
tags?: string[];
|
|
24
|
+
chartType?: string;
|
|
25
|
+
}): {
|
|
26
|
+
error: string;
|
|
27
|
+
name?: undefined;
|
|
28
|
+
path?: undefined;
|
|
29
|
+
certified?: undefined;
|
|
30
|
+
errors?: undefined;
|
|
31
|
+
warnings?: undefined;
|
|
32
|
+
nextStep?: undefined;
|
|
33
|
+
} | {
|
|
34
|
+
name: string;
|
|
35
|
+
path: string;
|
|
36
|
+
certified: boolean;
|
|
37
|
+
errors: {
|
|
38
|
+
rule: string;
|
|
39
|
+
message: string;
|
|
40
|
+
}[];
|
|
41
|
+
warnings: {
|
|
42
|
+
rule: string;
|
|
43
|
+
message: string;
|
|
44
|
+
}[];
|
|
45
|
+
nextStep: string;
|
|
46
|
+
error?: undefined;
|
|
47
|
+
};
|
|
48
|
+
//# sourceMappingURL=suggest-block.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"suggest-block.d.ts","sourceRoot":"","sources":["../../src/tools/suggest-block.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,eAAO,MAAM,iBAAiB;;;;;;;;CAQ7B,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,UAAU,EACf,IAAI,EAAE;IACJ,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;;;;;;;;;;;;;;;;;;;;;;EA2CF"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { mkdirSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import { Certifier } from '@duckcodeailabs/dql-governance';
|
|
5
|
+
export const suggestBlockInput = {
|
|
6
|
+
name: z.string().describe('Proposed block name (kebab_case).'),
|
|
7
|
+
domain: z.string().describe('Business domain (finance, product, …).'),
|
|
8
|
+
owner: z.string().describe('Block owner identity (email or team handle).'),
|
|
9
|
+
description: z.string().describe('One-line description of what the block answers.'),
|
|
10
|
+
sql: z.string().describe('The block body SQL.'),
|
|
11
|
+
tags: z.array(z.string()).optional(),
|
|
12
|
+
chartType: z.string().optional().describe('Optional visualization type.'),
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Write a proposed block to `blocks/_drafts/<name>.dql` and return the
|
|
16
|
+
* governance-gate result. Never auto-certifies — the human still has to
|
|
17
|
+
* review and move the file.
|
|
18
|
+
*/
|
|
19
|
+
export function suggestBlock(ctx, args) {
|
|
20
|
+
const safeName = args.name.trim().toLowerCase().replace(/[^a-z0-9_]+/g, '_');
|
|
21
|
+
if (!safeName)
|
|
22
|
+
return { error: 'Invalid block name.' };
|
|
23
|
+
const now = new Date();
|
|
24
|
+
const record = {
|
|
25
|
+
id: safeName,
|
|
26
|
+
name: safeName,
|
|
27
|
+
domain: args.domain,
|
|
28
|
+
type: args.chartType ? 'chart' : 'block',
|
|
29
|
+
version: '0.1.0',
|
|
30
|
+
status: 'draft',
|
|
31
|
+
gitRepo: '',
|
|
32
|
+
gitPath: `blocks/_drafts/${safeName}.dql`,
|
|
33
|
+
gitCommitSha: '',
|
|
34
|
+
description: args.description,
|
|
35
|
+
owner: args.owner,
|
|
36
|
+
tags: args.tags ?? [],
|
|
37
|
+
dependencies: [],
|
|
38
|
+
usedInCount: 0,
|
|
39
|
+
createdAt: now,
|
|
40
|
+
updatedAt: now,
|
|
41
|
+
};
|
|
42
|
+
const certification = new Certifier().evaluate(record);
|
|
43
|
+
const draftsDir = join(ctx.projectRoot, 'blocks', '_drafts');
|
|
44
|
+
mkdirSync(draftsDir, { recursive: true });
|
|
45
|
+
const filePath = join(draftsDir, `${safeName}.dql`);
|
|
46
|
+
writeFileSync(filePath, renderBlock(args, safeName));
|
|
47
|
+
ctx.refresh();
|
|
48
|
+
return {
|
|
49
|
+
name: safeName,
|
|
50
|
+
path: `blocks/_drafts/${safeName}.dql`,
|
|
51
|
+
certified: certification.certified,
|
|
52
|
+
errors: certification.errors,
|
|
53
|
+
warnings: certification.warnings,
|
|
54
|
+
nextStep: certification.certified
|
|
55
|
+
? 'Draft saved and passes governance. Move to the appropriate domain folder and commit.'
|
|
56
|
+
: 'Draft saved but does NOT pass governance. Address errors before promotion.',
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
function renderBlock(args, safeName) {
|
|
60
|
+
const tagsLine = args.tags?.length ? `\n tags = [${args.tags.map((t) => `"${t}"`).join(', ')}]` : '';
|
|
61
|
+
const chartLine = args.chartType
|
|
62
|
+
? `\n\n visualization {\n chart = "${args.chartType}"\n }`
|
|
63
|
+
: '';
|
|
64
|
+
const descEscaped = args.description.replace(/"/g, '\\"');
|
|
65
|
+
return `// dql-format: 1
|
|
66
|
+
block "${safeName}" {
|
|
67
|
+
domain = "${args.domain}"
|
|
68
|
+
owner = "${args.owner}"
|
|
69
|
+
description = "${descEscaped}"${tagsLine}
|
|
70
|
+
|
|
71
|
+
query {
|
|
72
|
+
sql = """
|
|
73
|
+
${args.sql.trimEnd()}
|
|
74
|
+
"""
|
|
75
|
+
}${chartLine}
|
|
76
|
+
}
|
|
77
|
+
`;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=suggest-block.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"suggest-block.js","sourceRoot":"","sources":["../../src/tools/suggest-block.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ManifestBlock } from '@duckcodeailabs/dql-core';
|
|
2
|
+
import type { BlockRecord } from '@duckcodeailabs/dql-project';
|
|
3
|
+
/**
|
|
4
|
+
* Adapt a ManifestBlock (what the compiler produces) into a BlockRecord
|
|
5
|
+
* (what governance rules consume). Fills the registry-only fields with
|
|
6
|
+
* best-effort defaults so the Certifier can score a block discovered on
|
|
7
|
+
* disk — without requiring a populated SQLite registry.
|
|
8
|
+
*/
|
|
9
|
+
export declare function manifestBlockToRecord(block: ManifestBlock): BlockRecord;
|
|
10
|
+
//# sourceMappingURL=util.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../src/tools/util.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,KAAK,EAAE,WAAW,EAAe,MAAM,6BAA6B,CAAC;AAE5E;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,aAAa,GAAG,WAAW,CAoBvE"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapt a ManifestBlock (what the compiler produces) into a BlockRecord
|
|
3
|
+
* (what governance rules consume). Fills the registry-only fields with
|
|
4
|
+
* best-effort defaults so the Certifier can score a block discovered on
|
|
5
|
+
* disk — without requiring a populated SQLite registry.
|
|
6
|
+
*/
|
|
7
|
+
export function manifestBlockToRecord(block) {
|
|
8
|
+
const now = new Date();
|
|
9
|
+
return {
|
|
10
|
+
id: block.name,
|
|
11
|
+
name: block.name,
|
|
12
|
+
domain: block.domain ?? '',
|
|
13
|
+
type: block.blockType ?? 'block',
|
|
14
|
+
version: '0.1.0',
|
|
15
|
+
status: block.status ?? 'draft',
|
|
16
|
+
gitRepo: '',
|
|
17
|
+
gitPath: block.filePath,
|
|
18
|
+
gitCommitSha: '',
|
|
19
|
+
description: block.description,
|
|
20
|
+
owner: block.owner ?? '',
|
|
21
|
+
tags: block.tags ?? [],
|
|
22
|
+
dependencies: block.allDependencies,
|
|
23
|
+
usedInCount: 0,
|
|
24
|
+
createdAt: now,
|
|
25
|
+
updatedAt: now,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=util.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"util.js","sourceRoot":"","sources":["../../src/tools/util.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAoB;IACxD,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,OAAO;QACL,EAAE,EAAE,KAAK,CAAC,IAAI;QACd,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,EAAE;QAC1B,IAAI,EAAE,KAAK,CAAC,SAAS,IAAI,OAAO;QAChC,OAAO,EAAE,OAAO;QAChB,MAAM,EAAG,KAAK,CAAC,MAAsB,IAAI,OAAO;QAChD,OAAO,EAAE,EAAE;QACX,OAAO,EAAE,KAAK,CAAC,QAAQ;QACvB,YAAY,EAAE,EAAE;QAChB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,EAAE;QACxB,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,EAAE;QACtB,YAAY,EAAE,KAAK,CAAC,eAAe;QACnC,WAAW,EAAE,CAAC;QACd,SAAS,EAAE,GAAG;QACd,SAAS,EAAE,GAAG;KACf,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type CreateServerOptions } from '../server.js';
|
|
2
|
+
export interface LoopbackHTTPOptions extends CreateServerOptions {
|
|
3
|
+
/** Explicit port; 0 = pick a free port (default). */
|
|
4
|
+
port?: number;
|
|
5
|
+
/** Pre-generated auth token; a random one is generated when omitted. */
|
|
6
|
+
token?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface LoopbackHTTPHandle {
|
|
9
|
+
url: string;
|
|
10
|
+
token: string;
|
|
11
|
+
close(): Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Run an MCP server over loopback HTTP (127.0.0.1 only). Intended for the
|
|
15
|
+
* VS Code extension, the notebook web UI, and developer-local CLIs that
|
|
16
|
+
* cannot spawn a stdio child. Any non-loopback listener is refused —
|
|
17
|
+
* remote HTTP transport stays in the Cloud build.
|
|
18
|
+
*/
|
|
19
|
+
export declare function runLoopbackHTTP(options?: LoopbackHTTPOptions): Promise<LoopbackHTTPHandle>;
|
|
20
|
+
//# sourceMappingURL=http.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/transports/http.ts"],"names":[],"mappings":"AAGA,OAAO,EAAsB,KAAK,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAE5E,MAAM,WAAW,mBAAoB,SAAQ,mBAAmB;IAC9D,qDAAqD;IACrD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAyCpG"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { createServer } from 'node:http';
|
|
2
|
+
import { randomBytes } from 'node:crypto';
|
|
3
|
+
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
4
|
+
import { createDQLMCPServer } from '../server.js';
|
|
5
|
+
/**
|
|
6
|
+
* Run an MCP server over loopback HTTP (127.0.0.1 only). Intended for the
|
|
7
|
+
* VS Code extension, the notebook web UI, and developer-local CLIs that
|
|
8
|
+
* cannot spawn a stdio child. Any non-loopback listener is refused —
|
|
9
|
+
* remote HTTP transport stays in the Cloud build.
|
|
10
|
+
*/
|
|
11
|
+
export async function runLoopbackHTTP(options = {}) {
|
|
12
|
+
const token = options.token ?? randomBytes(24).toString('hex');
|
|
13
|
+
const server = createDQLMCPServer(options);
|
|
14
|
+
const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: () => randomBytes(12).toString('hex') });
|
|
15
|
+
await server.connect(transport);
|
|
16
|
+
const http = createServer((req, res) => {
|
|
17
|
+
if (req.socket.remoteAddress && !isLoopback(req.socket.remoteAddress)) {
|
|
18
|
+
res.statusCode = 403;
|
|
19
|
+
res.end('dql-mcp: non-loopback connections are refused');
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const header = req.headers['authorization'];
|
|
23
|
+
if (header !== `Bearer ${token}`) {
|
|
24
|
+
res.statusCode = 401;
|
|
25
|
+
res.end('dql-mcp: missing or invalid Authorization header');
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
void transport.handleRequest(req, res);
|
|
29
|
+
});
|
|
30
|
+
await new Promise((resolve, reject) => {
|
|
31
|
+
http.once('error', reject);
|
|
32
|
+
http.listen(options.port ?? 0, '127.0.0.1', resolve);
|
|
33
|
+
});
|
|
34
|
+
const addr = http.address();
|
|
35
|
+
if (!addr || typeof addr === 'string') {
|
|
36
|
+
throw new Error('Failed to resolve HTTP listening address');
|
|
37
|
+
}
|
|
38
|
+
const url = `http://127.0.0.1:${addr.port}/mcp`;
|
|
39
|
+
return {
|
|
40
|
+
url,
|
|
41
|
+
token,
|
|
42
|
+
async close() {
|
|
43
|
+
await new Promise((resolve) => http.close(() => resolve()));
|
|
44
|
+
await transport.close();
|
|
45
|
+
await server.close();
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function isLoopback(address) {
|
|
50
|
+
return address === '127.0.0.1' || address === '::1' || address === '::ffff:127.0.0.1';
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=http.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/transports/http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAA6C,MAAM,WAAW,CAAC;AACpF,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;AACnG,OAAO,EAAE,kBAAkB,EAA4B,MAAM,cAAc,CAAC;AAe5E;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,UAA+B,EAAE;IACrE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC/D,MAAM,MAAM,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAC3C,MAAM,SAAS,GAAG,IAAI,6BAA6B,CAAC,EAAE,kBAAkB,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACnH,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEhC,MAAM,IAAI,GAAG,YAAY,CAAC,CAAC,GAAoB,EAAE,GAAmB,EAAE,EAAE;QACtE,IAAI,GAAG,CAAC,MAAM,CAAC,aAAa,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC;YACtE,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;YACrB,GAAG,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAC;YACzD,OAAO;QACT,CAAC;QACD,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;QAC5C,IAAI,MAAM,KAAK,UAAU,KAAK,EAAE,EAAE,CAAC;YACjC,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;YACrB,GAAG,CAAC,GAAG,CAAC,kDAAkD,CAAC,CAAC;YAC5D,OAAO;QACT,CAAC;QACD,KAAK,SAAS,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC1C,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC3B,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;IAC5B,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtC,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAC9D,CAAC;IACD,MAAM,GAAG,GAAG,oBAAoB,IAAI,CAAC,IAAI,MAAM,CAAC;IAEhD,OAAO;QACL,GAAG;QACH,KAAK;QACL,KAAK,CAAC,KAAK;YACT,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YAClE,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC;YACxB,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACvB,CAAC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,OAAe;IACjC,OAAO,OAAO,KAAK,WAAW,IAAI,OAAO,KAAK,KAAK,IAAI,OAAO,KAAK,kBAAkB,CAAC;AACxF,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type CreateServerOptions } from '../server.js';
|
|
2
|
+
/**
|
|
3
|
+
* Run an MCP server over stdio. Intended for child-process use by
|
|
4
|
+
* Claude Code, Cursor, Claude Desktop, and similar agents.
|
|
5
|
+
*/
|
|
6
|
+
export declare function runStdio(options?: CreateServerOptions): Promise<void>;
|
|
7
|
+
//# sourceMappingURL=stdio.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["../../src/transports/stdio.ts"],"names":[],"mappings":"AACA,OAAO,EAAsB,KAAK,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAE5E;;;GAGG;AACH,wBAAsB,QAAQ,CAAC,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAI/E"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
2
|
+
import { createDQLMCPServer } from '../server.js';
|
|
3
|
+
/**
|
|
4
|
+
* Run an MCP server over stdio. Intended for child-process use by
|
|
5
|
+
* Claude Code, Cursor, Claude Desktop, and similar agents.
|
|
6
|
+
*/
|
|
7
|
+
export async function runStdio(options = {}) {
|
|
8
|
+
const server = createDQLMCPServer(options);
|
|
9
|
+
const transport = new StdioServerTransport();
|
|
10
|
+
await server.connect(transport);
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=stdio.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stdio.js","sourceRoot":"","sources":["../../src/transports/stdio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,kBAAkB,EAA4B,MAAM,cAAc,CAAC;AAE5E;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,UAA+B,EAAE;IAC9D,MAAM,MAAM,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAC3C,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@duckcodeailabs/dql-mcp",
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"description": "DQL MCP server: expose certified blocks, semantic layer, lineage, and governance to LLM agents via the Model Context Protocol",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "https://github.com/duckcode-ai/dql.git",
|
|
21
|
+
"directory": "packages/dql-mcp"
|
|
22
|
+
},
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"access": "public"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@duckcodeailabs/dql-core": "^1.2.0",
|
|
28
|
+
"@duckcodeailabs/dql-governance": "^1.2.0",
|
|
29
|
+
"@duckcodeailabs/dql-project": "^1.2.0",
|
|
30
|
+
"@modelcontextprotocol/sdk": "^1.0.4",
|
|
31
|
+
"zod": "^3.25.0"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@types/node": "^20.0.0",
|
|
35
|
+
"typescript": "^5.7.0",
|
|
36
|
+
"vitest": "^3.0.0"
|
|
37
|
+
},
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=18.0.0"
|
|
40
|
+
},
|
|
41
|
+
"scripts": {
|
|
42
|
+
"build": "rm -rf dist tsconfig.tsbuildinfo && tsc -b",
|
|
43
|
+
"test": "vitest run --passWithNoTests",
|
|
44
|
+
"clean": "rm -rf dist tsconfig.tsbuildinfo"
|
|
45
|
+
}
|
|
46
|
+
}
|