@kozou/mcp 0.0.1 → 0.1.1
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 +202 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +69 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/schemaCache.d.ts +18 -0
- package/dist/schemaCache.d.ts.map +1 -0
- package/dist/schemaCache.js +43 -0
- package/dist/schemaCache.js.map +1 -0
- package/dist/schemas/describe_table.d.ts +54 -0
- package/dist/schemas/describe_table.d.ts.map +1 -0
- package/dist/schemas/describe_table.js +41 -0
- package/dist/schemas/describe_table.js.map +1 -0
- package/dist/schemas/describe_view.d.ts +29 -0
- package/dist/schemas/describe_view.d.ts.map +1 -0
- package/dist/schemas/describe_view.js +30 -0
- package/dist/schemas/describe_view.js.map +1 -0
- package/dist/schemas/get_concept_context.d.ts +24 -0
- package/dist/schemas/get_concept_context.d.ts.map +1 -0
- package/dist/schemas/get_concept_context.js +24 -0
- package/dist/schemas/get_concept_context.js.map +1 -0
- package/dist/schemas/list_concepts.d.ts +13 -0
- package/dist/schemas/list_concepts.d.ts.map +1 -0
- package/dist/schemas/list_concepts.js +15 -0
- package/dist/schemas/list_concepts.js.map +1 -0
- package/dist/schemas/list_tables.d.ts +16 -0
- package/dist/schemas/list_tables.d.ts.map +1 -0
- package/dist/schemas/list_tables.js +14 -0
- package/dist/schemas/list_tables.js.map +1 -0
- package/dist/schemas/list_views.d.ts +14 -0
- package/dist/schemas/list_views.d.ts.map +1 -0
- package/dist/schemas/list_views.js +12 -0
- package/dist/schemas/list_views.js.map +1 -0
- package/dist/server.d.ts +4 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +114 -0
- package/dist/server.js.map +1 -0
- package/dist/startHttpServer.d.ts +30 -0
- package/dist/startHttpServer.d.ts.map +1 -0
- package/dist/startHttpServer.js +176 -0
- package/dist/startHttpServer.js.map +1 -0
- package/dist/startStdioServer.d.ts +14 -0
- package/dist/startStdioServer.d.ts.map +1 -0
- package/dist/startStdioServer.js +25 -0
- package/dist/startStdioServer.js.map +1 -0
- package/dist/tools/describe_table.d.ts +4 -0
- package/dist/tools/describe_table.d.ts.map +1 -0
- package/dist/tools/describe_table.js +45 -0
- package/dist/tools/describe_table.js.map +1 -0
- package/dist/tools/describe_view.d.ts +4 -0
- package/dist/tools/describe_view.d.ts.map +1 -0
- package/dist/tools/describe_view.js +28 -0
- package/dist/tools/describe_view.js.map +1 -0
- package/dist/tools/get_concept_context.d.ts +4 -0
- package/dist/tools/get_concept_context.d.ts.map +1 -0
- package/dist/tools/get_concept_context.js +29 -0
- package/dist/tools/get_concept_context.js.map +1 -0
- package/dist/tools/list_concepts.d.ts +4 -0
- package/dist/tools/list_concepts.d.ts.map +1 -0
- package/dist/tools/list_concepts.js +13 -0
- package/dist/tools/list_concepts.js.map +1 -0
- package/dist/tools/list_tables.d.ts +4 -0
- package/dist/tools/list_tables.d.ts.map +1 -0
- package/dist/tools/list_tables.js +19 -0
- package/dist/tools/list_tables.js.map +1 -0
- package/dist/tools/list_views.d.ts +4 -0
- package/dist/tools/list_views.d.ts.map +1 -0
- package/dist/tools/list_views.js +15 -0
- package/dist/tools/list_views.js.map +1 -0
- package/package.json +49 -4
- package/README.md +0 -3
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const listConceptsInputSchema: z.ZodObject<{}, z.core.$strict>;
|
|
3
|
+
export declare const listConceptsOutputSchema: z.ZodObject<{
|
|
4
|
+
concepts: z.ZodArray<z.ZodObject<{
|
|
5
|
+
name: z.ZodString;
|
|
6
|
+
label: z.ZodString;
|
|
7
|
+
description: z.ZodNullable<z.ZodString>;
|
|
8
|
+
kind: z.ZodLiteral<"VIEW">;
|
|
9
|
+
}, z.core.$strip>>;
|
|
10
|
+
}, z.core.$strip>;
|
|
11
|
+
export type ListConceptsInput = z.infer<typeof listConceptsInputSchema>;
|
|
12
|
+
export type ListConceptsOutput = z.infer<typeof listConceptsOutputSchema>;
|
|
13
|
+
//# sourceMappingURL=list_concepts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list_concepts.d.ts","sourceRoot":"","sources":["../../src/schemas/list_concepts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,eAAO,MAAM,uBAAuB,iCAAqB,CAAC;AAE1D,eAAO,MAAM,wBAAwB;;;;;;;iBASnC,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AACxE,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
// No inputs; reject any extra fields. zod 4 infers a strict empty object as
|
|
3
|
+
// `Record<string, never>`, so the tool fn takes the raw `Record<string,
|
|
4
|
+
// unknown>` args and validates them through this schema rather than typing
|
|
5
|
+
// its parameter as the inferred (and unassignable) empty-object type.
|
|
6
|
+
export const listConceptsInputSchema = z.strictObject({});
|
|
7
|
+
export const listConceptsOutputSchema = z.object({
|
|
8
|
+
concepts: z.array(z.object({
|
|
9
|
+
name: z.string(),
|
|
10
|
+
label: z.string(),
|
|
11
|
+
description: z.string().nullable(),
|
|
12
|
+
kind: z.literal('VIEW'),
|
|
13
|
+
})),
|
|
14
|
+
});
|
|
15
|
+
//# sourceMappingURL=list_concepts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list_concepts.js","sourceRoot":"","sources":["../../src/schemas/list_concepts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,4EAA4E;AAC5E,wEAAwE;AACxE,2EAA2E;AAC3E,sEAAsE;AACtE,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;AAE1D,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/C,QAAQ,EAAE,CAAC,CAAC,KAAK,CACf,CAAC,CAAC,MAAM,CAAC;QACP,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;QAChB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;QACjB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAClC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;KACxB,CAAC,CACH;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const listTablesInputSchema: z.ZodObject<{
|
|
3
|
+
schema: z.ZodOptional<z.ZodString>;
|
|
4
|
+
includeSystem: z.ZodOptional<z.ZodBoolean>;
|
|
5
|
+
}, z.core.$strip>;
|
|
6
|
+
export declare const listTablesOutputSchema: z.ZodObject<{
|
|
7
|
+
tables: z.ZodArray<z.ZodObject<{
|
|
8
|
+
qualifiedName: z.ZodString;
|
|
9
|
+
label: z.ZodString;
|
|
10
|
+
description: z.ZodNullable<z.ZodString>;
|
|
11
|
+
rowCountEstimate: z.ZodNullable<z.ZodNumber>;
|
|
12
|
+
}, z.core.$strip>>;
|
|
13
|
+
}, z.core.$strip>;
|
|
14
|
+
export type ListTablesInput = z.infer<typeof listTablesInputSchema>;
|
|
15
|
+
export type ListTablesOutput = z.infer<typeof listTablesOutputSchema>;
|
|
16
|
+
//# sourceMappingURL=list_tables.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list_tables.d.ts","sourceRoot":"","sources":["../../src/schemas/list_tables.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,qBAAqB;;;iBAGhC,CAAC;AAEH,eAAO,MAAM,sBAAsB;;;;;;;iBASjC,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AACpE,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export const listTablesInputSchema = z.object({
|
|
3
|
+
schema: z.string().optional(),
|
|
4
|
+
includeSystem: z.boolean().optional(),
|
|
5
|
+
});
|
|
6
|
+
export const listTablesOutputSchema = z.object({
|
|
7
|
+
tables: z.array(z.object({
|
|
8
|
+
qualifiedName: z.string(),
|
|
9
|
+
label: z.string(),
|
|
10
|
+
description: z.string().nullable(),
|
|
11
|
+
rowCountEstimate: z.number().nullable(),
|
|
12
|
+
})),
|
|
13
|
+
});
|
|
14
|
+
//# sourceMappingURL=list_tables.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list_tables.js","sourceRoot":"","sources":["../../src/schemas/list_tables.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7B,aAAa,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;CACtC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,MAAM,EAAE,CAAC,CAAC,KAAK,CACb,CAAC,CAAC,MAAM,CAAC;QACP,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE;QACzB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;QACjB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAClC,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;KACxC,CAAC,CACH;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const listViewsInputSchema: z.ZodObject<{
|
|
3
|
+
schema: z.ZodOptional<z.ZodString>;
|
|
4
|
+
}, z.core.$strip>;
|
|
5
|
+
export declare const listViewsOutputSchema: z.ZodObject<{
|
|
6
|
+
views: z.ZodArray<z.ZodObject<{
|
|
7
|
+
qualifiedName: z.ZodString;
|
|
8
|
+
label: z.ZodString;
|
|
9
|
+
purpose: z.ZodNullable<z.ZodString>;
|
|
10
|
+
}, z.core.$strip>>;
|
|
11
|
+
}, z.core.$strip>;
|
|
12
|
+
export type ListViewsInput = z.infer<typeof listViewsInputSchema>;
|
|
13
|
+
export type ListViewsOutput = z.infer<typeof listViewsOutputSchema>;
|
|
14
|
+
//# sourceMappingURL=list_views.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list_views.d.ts","sourceRoot":"","sources":["../../src/schemas/list_views.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,oBAAoB;;iBAE/B,CAAC;AAEH,eAAO,MAAM,qBAAqB;;;;;;iBAQhC,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAClE,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export const listViewsInputSchema = z.object({
|
|
3
|
+
schema: z.string().optional(),
|
|
4
|
+
});
|
|
5
|
+
export const listViewsOutputSchema = z.object({
|
|
6
|
+
views: z.array(z.object({
|
|
7
|
+
qualifiedName: z.string(),
|
|
8
|
+
label: z.string(),
|
|
9
|
+
purpose: z.string().nullable(),
|
|
10
|
+
})),
|
|
11
|
+
});
|
|
12
|
+
//# sourceMappingURL=list_views.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list_views.js","sourceRoot":"","sources":["../../src/schemas/list_views.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC9B,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,KAAK,EAAE,CAAC,CAAC,KAAK,CACZ,CAAC,CAAC,MAAM,CAAC;QACP,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE;QACzB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;QACjB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;KAC/B,CAAC,CACH;CACF,CAAC,CAAC"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAWnE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AA+EpD,wBAAgB,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAwC1D"}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
4
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
5
|
+
import { listTables } from './tools/list_tables.js';
|
|
6
|
+
import { describeTable } from './tools/describe_table.js';
|
|
7
|
+
import { listViews } from './tools/list_views.js';
|
|
8
|
+
import { describeView } from './tools/describe_view.js';
|
|
9
|
+
import { listConcepts } from './tools/list_concepts.js';
|
|
10
|
+
import { getConceptContext } from './tools/get_concept_context.js';
|
|
11
|
+
// Read the advertised server version from this package's package.json so
|
|
12
|
+
// it tracks a release bump automatically instead of being hardcoded.
|
|
13
|
+
// `../package.json` resolves to packages/mcp/package.json from the
|
|
14
|
+
// compiled dist/server.js; npm always ships package.json in the tarball.
|
|
15
|
+
const require = createRequire(import.meta.url);
|
|
16
|
+
const pkg = JSON.parse(readFileSync(require.resolve('../package.json'), 'utf8'));
|
|
17
|
+
const SERVER_VERSION = pkg.version;
|
|
18
|
+
const TOOL_DEFINITIONS = [
|
|
19
|
+
{
|
|
20
|
+
name: 'list_tables',
|
|
21
|
+
description: 'List tables with their labels and descriptions',
|
|
22
|
+
inputSchema: {
|
|
23
|
+
type: 'object',
|
|
24
|
+
properties: {
|
|
25
|
+
schema: { type: 'string', description: 'Target schema (default: public)' },
|
|
26
|
+
includeSystem: { type: 'boolean', description: 'Include system schemas (ignored in v0.1)' },
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
name: 'describe_table',
|
|
32
|
+
description: 'Return the full schema + COMMENT for the given table',
|
|
33
|
+
inputSchema: {
|
|
34
|
+
type: 'object',
|
|
35
|
+
properties: { qualifiedName: { type: 'string', description: 'e.g. public.users' } },
|
|
36
|
+
required: ['qualifiedName'],
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
name: 'list_views',
|
|
41
|
+
description: 'List views with their labels and purposes',
|
|
42
|
+
inputSchema: {
|
|
43
|
+
type: 'object',
|
|
44
|
+
properties: { schema: { type: 'string', description: 'Target schema (default: public)' } },
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
name: 'describe_view',
|
|
49
|
+
description: 'Return columns + purpose + underlying tables + definition for the given view',
|
|
50
|
+
inputSchema: {
|
|
51
|
+
type: 'object',
|
|
52
|
+
properties: { qualifiedName: { type: 'string', description: 'e.g. public.vw_active_users' } },
|
|
53
|
+
required: ['qualifiedName'],
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: 'list_concepts',
|
|
58
|
+
description: 'List domain concepts (each backed by a VIEW)',
|
|
59
|
+
inputSchema: { type: 'object', properties: {} },
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
name: 'get_concept_context',
|
|
63
|
+
description: 'Return related tables + recommended query path for the given concept',
|
|
64
|
+
inputSchema: {
|
|
65
|
+
type: 'object',
|
|
66
|
+
properties: { name: { type: 'string', description: 'Matches the VIEW name' } },
|
|
67
|
+
required: ['name'],
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
];
|
|
71
|
+
function successResult(payload) {
|
|
72
|
+
return { content: [{ type: 'text', text: JSON.stringify(payload, null, 2) }] };
|
|
73
|
+
}
|
|
74
|
+
function errorResult(message) {
|
|
75
|
+
return {
|
|
76
|
+
isError: true,
|
|
77
|
+
content: [{ type: 'text', text: message }],
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
export function createMcpServer(cache) {
|
|
81
|
+
const server = new Server({ name: 'kozou', version: SERVER_VERSION }, { capabilities: { tools: {} } });
|
|
82
|
+
server.setRequestHandler(ListToolsRequestSchema, () => Promise.resolve({ tools: TOOL_DEFINITIONS.map((t) => ({ ...t })) }));
|
|
83
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
84
|
+
const name = request.params.name;
|
|
85
|
+
const args = (request.params.arguments ?? {});
|
|
86
|
+
try {
|
|
87
|
+
const ctx = await cache.get();
|
|
88
|
+
switch (name) {
|
|
89
|
+
case 'list_tables':
|
|
90
|
+
return successResult(listTables(args, ctx));
|
|
91
|
+
case 'describe_table':
|
|
92
|
+
return successResult(describeTable(args, ctx));
|
|
93
|
+
case 'list_views':
|
|
94
|
+
return successResult(listViews(args, ctx));
|
|
95
|
+
case 'describe_view':
|
|
96
|
+
return successResult(describeView(args, ctx));
|
|
97
|
+
case 'list_concepts':
|
|
98
|
+
return successResult(listConcepts(args, ctx));
|
|
99
|
+
case 'get_concept_context':
|
|
100
|
+
return successResult(getConceptContext(args, ctx));
|
|
101
|
+
default:
|
|
102
|
+
return errorResult(`Unknown tool: ${name}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
catch (err) {
|
|
106
|
+
const dev = process.env.KOZOU_DEV === '1';
|
|
107
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
108
|
+
const detail = dev && err instanceof Error && err.stack ? `\n${err.stack}` : '';
|
|
109
|
+
return errorResult(`${msg}${detail}`);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
return server;
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { SchemaCache } from './schemaCache.js';
|
|
2
|
+
export type StartHttpServerOptions = {
|
|
3
|
+
/** TCP port to listen on. Default: 3334 (Kozou v0.1 spec §7.1). */
|
|
4
|
+
port?: number;
|
|
5
|
+
/** Host/interface to bind. Default: 127.0.0.1 (loopback only). */
|
|
6
|
+
host?: string;
|
|
7
|
+
/** Path that serves the MCP Streamable HTTP endpoint. Default: '/mcp'. */
|
|
8
|
+
mcpPath?: string;
|
|
9
|
+
/** Prefix used in stderr log lines. Default: '[@kozou/mcp]'. */
|
|
10
|
+
logPrefix?: string;
|
|
11
|
+
};
|
|
12
|
+
export type HttpServerHandle = {
|
|
13
|
+
/** The actual bound port (resolves an ephemeral `0` to the real port). */
|
|
14
|
+
port: number;
|
|
15
|
+
/** The host the server is bound to. */
|
|
16
|
+
host: string;
|
|
17
|
+
/** Stop accepting connections and resolve once the server has closed. */
|
|
18
|
+
close: () => Promise<void>;
|
|
19
|
+
};
|
|
20
|
+
export declare function isLoopbackHost(host: string): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Start the MCP server over Streamable HTTP, bound to the given
|
|
23
|
+
* SchemaCache. Resolves once the server is listening.
|
|
24
|
+
*
|
|
25
|
+
* Routes:
|
|
26
|
+
* - `<mcpPath>` (default `/mcp`) — MCP Streamable HTTP endpoint
|
|
27
|
+
* - `POST /admin/refresh` — invalidate the schema cache
|
|
28
|
+
*/
|
|
29
|
+
export declare function startHttpServer(cache: SchemaCache, opts?: StartHttpServerOptions): Promise<HttpServerHandle>;
|
|
30
|
+
//# sourceMappingURL=startHttpServer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"startHttpServer.d.ts","sourceRoot":"","sources":["../src/startHttpServer.ts"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,MAAM,MAAM,sBAAsB,GAAG;IACnC,mEAAmE;IACnE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0EAA0E;IAC1E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gEAAgE;IAChE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,uCAAuC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,yEAAyE;IACzE,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B,CAAC;AASF,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEpD;AAYD;;;;;;;GAOG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,WAAW,EAClB,IAAI,GAAE,sBAA2B,GAChC,OAAO,CAAC,gBAAgB,CAAC,CA6C3B"}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
// Convenience helper to start an MCP server with the Streamable HTTP
|
|
2
|
+
// transport (Kozou v0.1 spec §7.1). Mirrors startStdioServer so callers
|
|
3
|
+
// (the bundled kozou CLI and adopters embedding the server) do not need
|
|
4
|
+
// to depend on @modelcontextprotocol/sdk or node:http directly.
|
|
5
|
+
//
|
|
6
|
+
// Design notes:
|
|
7
|
+
// - The server is *stateful*: an MCP client initialises a session, the
|
|
8
|
+
// transport issues an `mcp-session-id`, and subsequent requests reuse
|
|
9
|
+
// the matching transport. This is the transport mode the standard MCP
|
|
10
|
+
// client (Claude Desktop / Claude Code) speaks. Sessions are torn
|
|
11
|
+
// down on transport close so nothing accumulates.
|
|
12
|
+
// - Cache invalidation is exposed over HTTP via `POST /admin/refresh`
|
|
13
|
+
// (Kozou v0.1 spec §7.5), the HTTP-mode counterpart to the stdio
|
|
14
|
+
// server's SIGHUP handler.
|
|
15
|
+
// - v0.1 MCP HTTP ships with **no authentication** (spec §18.5), so the
|
|
16
|
+
// server binds to localhost by default and prints a loud warning when
|
|
17
|
+
// bound to a non-loopback host. The tools only expose schema
|
|
18
|
+
// metadata (no SQL execution, no data access), which bounds the blast
|
|
19
|
+
// radius, but operators must still avoid exposing it on a public
|
|
20
|
+
// interface.
|
|
21
|
+
import { randomUUID } from 'node:crypto';
|
|
22
|
+
import { createServer } from 'node:http';
|
|
23
|
+
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
24
|
+
import { isInitializeRequest } from '@modelcontextprotocol/sdk/types.js';
|
|
25
|
+
import { createMcpServer } from './server.js';
|
|
26
|
+
const DEFAULT_PORT = 3334;
|
|
27
|
+
const DEFAULT_HOST = '127.0.0.1';
|
|
28
|
+
const DEFAULT_MCP_PATH = '/mcp';
|
|
29
|
+
const REFRESH_PATH = '/admin/refresh';
|
|
30
|
+
const LOOPBACK_HOSTS = new Set(['127.0.0.1', '::1', 'localhost', '::ffff:127.0.0.1']);
|
|
31
|
+
export function isLoopbackHost(host) {
|
|
32
|
+
return LOOPBACK_HOSTS.has(host);
|
|
33
|
+
}
|
|
34
|
+
function nonLoopbackWarning(host, prefix) {
|
|
35
|
+
return (`${prefix} WARNING: MCP HTTP server bound to non-loopback host "${host}".\n` +
|
|
36
|
+
`${prefix} v0.1 MCP HTTP has NO authentication (spec §18.5). Anyone who can\n` +
|
|
37
|
+
`${prefix} reach ${host} can read this database's schema metadata. Bind to\n` +
|
|
38
|
+
`${prefix} 127.0.0.1 (the default) unless you have a trusted network and an\n` +
|
|
39
|
+
`${prefix} external auth/proxy layer in front.\n`);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Start the MCP server over Streamable HTTP, bound to the given
|
|
43
|
+
* SchemaCache. Resolves once the server is listening.
|
|
44
|
+
*
|
|
45
|
+
* Routes:
|
|
46
|
+
* - `<mcpPath>` (default `/mcp`) — MCP Streamable HTTP endpoint
|
|
47
|
+
* - `POST /admin/refresh` — invalidate the schema cache
|
|
48
|
+
*/
|
|
49
|
+
export async function startHttpServer(cache, opts = {}) {
|
|
50
|
+
const prefix = opts.logPrefix ?? '[@kozou/mcp]';
|
|
51
|
+
const host = opts.host ?? DEFAULT_HOST;
|
|
52
|
+
const port = opts.port ?? DEFAULT_PORT;
|
|
53
|
+
const mcpPath = opts.mcpPath ?? DEFAULT_MCP_PATH;
|
|
54
|
+
if (!isLoopbackHost(host)) {
|
|
55
|
+
process.stderr.write(nonLoopbackWarning(host, prefix));
|
|
56
|
+
}
|
|
57
|
+
// Active MCP sessions, keyed by the transport-issued session id.
|
|
58
|
+
const transports = new Map();
|
|
59
|
+
const httpServer = createServer((req, res) => {
|
|
60
|
+
handleRequest(req, res, cache, mcpPath, transports).catch((err) => {
|
|
61
|
+
respondError(res, 500, err instanceof Error ? err.message : String(err));
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
await new Promise((resolve, reject) => {
|
|
65
|
+
const onError = (err) => reject(err);
|
|
66
|
+
httpServer.once('error', onError);
|
|
67
|
+
httpServer.listen(port, host, () => {
|
|
68
|
+
httpServer.removeListener('error', onError);
|
|
69
|
+
resolve();
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
const boundPort = httpServer.address().port;
|
|
73
|
+
process.stderr.write(`${prefix} MCP HTTP listening on http://${host}:${boundPort}` +
|
|
74
|
+
` (MCP: ${mcpPath}, refresh: POST ${REFRESH_PATH})\n`);
|
|
75
|
+
return {
|
|
76
|
+
port: boundPort,
|
|
77
|
+
host,
|
|
78
|
+
close: async () => {
|
|
79
|
+
for (const transport of transports.values()) {
|
|
80
|
+
await transport.close();
|
|
81
|
+
}
|
|
82
|
+
transports.clear();
|
|
83
|
+
await closeServer(httpServer);
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
async function handleRequest(req, res, cache, mcpPath, transports) {
|
|
88
|
+
const url = new URL(req.url ?? '/', 'http://localhost');
|
|
89
|
+
if (url.pathname === REFRESH_PATH) {
|
|
90
|
+
if (req.method !== 'POST') {
|
|
91
|
+
respondError(res, 405, 'Method Not Allowed: use POST /admin/refresh');
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
cache.invalidate();
|
|
95
|
+
res.writeHead(200, { 'content-type': 'application/json' });
|
|
96
|
+
res.end(JSON.stringify({ ok: true }));
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
if (url.pathname === mcpPath) {
|
|
100
|
+
await handleMcp(req, res, cache, transports);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
respondError(res, 404, `Not Found: ${url.pathname}`);
|
|
104
|
+
}
|
|
105
|
+
async function handleMcp(req, res, cache, transports) {
|
|
106
|
+
const sessionId = headerValue(req.headers['mcp-session-id']);
|
|
107
|
+
// Existing session: reuse its transport (and the MCP server bound to it).
|
|
108
|
+
if (sessionId !== undefined) {
|
|
109
|
+
const existing = transports.get(sessionId);
|
|
110
|
+
if (existing === undefined) {
|
|
111
|
+
respondError(res, 404, `Unknown MCP session: ${sessionId}`);
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
await existing.handleRequest(req, res);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
// No session id: this must be an initialize request that opens a new
|
|
118
|
+
// session. The body is read once here so we can both classify it and
|
|
119
|
+
// hand it to the transport (which would otherwise consume the stream).
|
|
120
|
+
const body = await readJsonBody(req);
|
|
121
|
+
if (!isInitializeRequest(body)) {
|
|
122
|
+
respondError(res, 400, 'Bad Request: missing mcp-session-id header (no active session)');
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
const transport = new StreamableHTTPServerTransport({
|
|
126
|
+
sessionIdGenerator: () => randomUUID(),
|
|
127
|
+
enableJsonResponse: true,
|
|
128
|
+
onsessioninitialized: (sid) => {
|
|
129
|
+
transports.set(sid, transport);
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
transport.onclose = () => {
|
|
133
|
+
if (transport.sessionId !== undefined) {
|
|
134
|
+
transports.delete(transport.sessionId);
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
const server = createMcpServer(cache);
|
|
138
|
+
await server.connect(transport);
|
|
139
|
+
await transport.handleRequest(req, res, body);
|
|
140
|
+
}
|
|
141
|
+
function headerValue(value) {
|
|
142
|
+
if (Array.isArray(value))
|
|
143
|
+
return value[0];
|
|
144
|
+
return value;
|
|
145
|
+
}
|
|
146
|
+
async function readJsonBody(req) {
|
|
147
|
+
const chunks = [];
|
|
148
|
+
for await (const chunk of req) {
|
|
149
|
+
chunks.push(chunk);
|
|
150
|
+
}
|
|
151
|
+
if (chunks.length === 0)
|
|
152
|
+
return undefined;
|
|
153
|
+
const raw = Buffer.concat(chunks).toString('utf8');
|
|
154
|
+
if (raw.length === 0)
|
|
155
|
+
return undefined;
|
|
156
|
+
try {
|
|
157
|
+
return JSON.parse(raw);
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
return undefined;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
function respondError(res, status, message) {
|
|
164
|
+
if (res.headersSent) {
|
|
165
|
+
res.end();
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
res.writeHead(status, { 'content-type': 'application/json' });
|
|
169
|
+
res.end(JSON.stringify({ error: message }));
|
|
170
|
+
}
|
|
171
|
+
function closeServer(httpServer) {
|
|
172
|
+
return new Promise((resolve, reject) => {
|
|
173
|
+
httpServer.close((err) => (err ? reject(err) : resolve()));
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
//# sourceMappingURL=startHttpServer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"startHttpServer.js","sourceRoot":"","sources":["../src/startHttpServer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { SchemaCache } from './schemaCache.js';
|
|
2
|
+
export type StartStdioServerOptions = {
|
|
3
|
+
/** Prefix used in stderr log lines. Default: '[@kozou/mcp]'. */
|
|
4
|
+
logPrefix?: string;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Start the MCP server bound to the given SchemaCache, using a stdio
|
|
8
|
+
* transport. Installs a SIGHUP handler that invalidates the cache, so
|
|
9
|
+
* adopters can refresh the schema without restarting the process.
|
|
10
|
+
*
|
|
11
|
+
* Resolves once the underlying transport finishes connecting.
|
|
12
|
+
*/
|
|
13
|
+
export declare function startStdioServer(cache: SchemaCache, opts?: StartStdioServerOptions): Promise<void>;
|
|
14
|
+
//# sourceMappingURL=startStdioServer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"startStdioServer.d.ts","sourceRoot":"","sources":["../src/startStdioServer.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,MAAM,MAAM,uBAAuB,GAAG;IACpC,gEAAgE;IAChE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,WAAW,EAClB,IAAI,GAAE,uBAA4B,GACjC,OAAO,CAAC,IAAI,CAAC,CASf"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// Convenience helper to start an MCP server with the stdio transport.
|
|
2
|
+
//
|
|
3
|
+
// This lives in @kozou/mcp so callers (the bundled kozou CLI as well as
|
|
4
|
+
// adopters embedding the MCP server in their own scripts) do not need to
|
|
5
|
+
// depend on @modelcontextprotocol/sdk directly.
|
|
6
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
7
|
+
import { createMcpServer } from './server.js';
|
|
8
|
+
/**
|
|
9
|
+
* Start the MCP server bound to the given SchemaCache, using a stdio
|
|
10
|
+
* transport. Installs a SIGHUP handler that invalidates the cache, so
|
|
11
|
+
* adopters can refresh the schema without restarting the process.
|
|
12
|
+
*
|
|
13
|
+
* Resolves once the underlying transport finishes connecting.
|
|
14
|
+
*/
|
|
15
|
+
export async function startStdioServer(cache, opts = {}) {
|
|
16
|
+
const prefix = opts.logPrefix ?? '[@kozou/mcp]';
|
|
17
|
+
const server = createMcpServer(cache);
|
|
18
|
+
process.on('SIGHUP', () => {
|
|
19
|
+
cache.invalidate();
|
|
20
|
+
process.stderr.write(`${prefix} SIGHUP received, cache invalidated\n`);
|
|
21
|
+
});
|
|
22
|
+
const transport = new StdioServerTransport();
|
|
23
|
+
await server.connect(transport);
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=startStdioServer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"startStdioServer.js","sourceRoot":"","sources":["../src/startStdioServer.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,EAAE;AACF,wEAAwE;AACxE,yEAAyE;AACzE,gDAAgD;AAEhD,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAQ9C;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,KAAkB,EAClB,OAAgC,EAAE;IAElC,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,IAAI,cAAc,CAAC;IAChD,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;IACtC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;QACxB,KAAK,CAAC,UAAU,EAAE,CAAC;QACnB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,uCAAuC,CAAC,CAAC;IACzE,CAAC,CAAC,CAAC;IACH,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { SchemaContext } from '@kozou/core';
|
|
2
|
+
import { type DescribeTableInput, type DescribeTableOutput } from '../schemas/describe_table.js';
|
|
3
|
+
export declare function describeTable(input: DescribeTableInput, ctx: SchemaContext): DescribeTableOutput;
|
|
4
|
+
//# sourceMappingURL=describe_table.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"describe_table.d.ts","sourceRoot":"","sources":["../../src/tools/describe_table.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EAEzB,MAAM,8BAA8B,CAAC;AAEtC,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,EAAE,GAAG,EAAE,aAAa,GAAG,mBAAmB,CA6ChG"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { describeTableInputSchema, } from '../schemas/describe_table.js';
|
|
2
|
+
export function describeTable(input, ctx) {
|
|
3
|
+
const parsed = describeTableInputSchema.parse(input);
|
|
4
|
+
const table = ctx.tables.find((t) => t.qualifiedName === parsed.qualifiedName);
|
|
5
|
+
if (!table) {
|
|
6
|
+
throw new Error(`Table not found: ${parsed.qualifiedName}`);
|
|
7
|
+
}
|
|
8
|
+
const referencesByField = new Map();
|
|
9
|
+
for (const rel of table.relations) {
|
|
10
|
+
referencesByField.set(rel.field, {
|
|
11
|
+
table: `${rel.references.schema}.${rel.references.table}`,
|
|
12
|
+
column: rel.references.column,
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
const columns = table.columns.map((c) => ({
|
|
16
|
+
name: c.name,
|
|
17
|
+
dataType: c.dataType,
|
|
18
|
+
nullable: c.nullable,
|
|
19
|
+
defaultExpr: c.defaultExpr,
|
|
20
|
+
description: c.description,
|
|
21
|
+
aiDescription: c.aiDescription,
|
|
22
|
+
enumValues: c.enumValues,
|
|
23
|
+
isForeignKey: c.isForeignKey,
|
|
24
|
+
references: referencesByField.get(c.name) ?? null,
|
|
25
|
+
}));
|
|
26
|
+
return {
|
|
27
|
+
qualifiedName: table.qualifiedName,
|
|
28
|
+
label: table.label,
|
|
29
|
+
description: table.description,
|
|
30
|
+
aiDescription: table.aiDescription,
|
|
31
|
+
primaryKey: table.primaryKey,
|
|
32
|
+
columns,
|
|
33
|
+
relations: table.relations.map((r) => ({
|
|
34
|
+
field: r.field,
|
|
35
|
+
referencesTable: `${r.references.schema}.${r.references.table}`,
|
|
36
|
+
referencesColumn: r.references.column,
|
|
37
|
+
meaning: r.meaning,
|
|
38
|
+
})),
|
|
39
|
+
checkConstraints: table.rawTable.checks.map((c) => ({
|
|
40
|
+
name: c.name,
|
|
41
|
+
expression: c.expression,
|
|
42
|
+
})),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=describe_table.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"describe_table.js","sourceRoot":"","sources":["../../src/tools/describe_table.ts"],"names":[],"mappings":"AACA,OAAO,EACL,wBAAwB,GAIzB,MAAM,8BAA8B,CAAC;AAEtC,MAAM,UAAU,aAAa,CAAC,KAAyB,EAAE,GAAkB;IACzE,MAAM,MAAM,GAAG,wBAAwB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACrD,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,KAAK,MAAM,CAAC,aAAa,CAAC,CAAC;IAC/E,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,oBAAoB,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAA6C,CAAC;IAC/E,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;QAClC,iBAAiB,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE;YAC/B,KAAK,EAAE,GAAG,GAAG,CAAC,UAAU,CAAC,MAAM,IAAI,GAAG,CAAC,UAAU,CAAC,KAAK,EAAE;YACzD,MAAM,EAAE,GAAG,CAAC,UAAU,CAAC,MAAM;SAC9B,CAAC,CAAC;IACL,CAAC;IAED,MAAM,OAAO,GAA0B,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC/D,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,QAAQ,EAAE,CAAC,CAAC,QAAQ;QACpB,QAAQ,EAAE,CAAC,CAAC,QAAQ;QACpB,WAAW,EAAE,CAAC,CAAC,WAAW;QAC1B,WAAW,EAAE,CAAC,CAAC,WAAW;QAC1B,aAAa,EAAE,CAAC,CAAC,aAAa;QAC9B,UAAU,EAAE,CAAC,CAAC,UAAU;QACxB,YAAY,EAAE,CAAC,CAAC,YAAY;QAC5B,UAAU,EAAE,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,IAAI;KAClD,CAAC,CAAC,CAAC;IAEJ,OAAO;QACL,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,OAAO;QACP,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACrC,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,eAAe,EAAE,GAAG,CAAC,CAAC,UAAU,CAAC,MAAM,IAAI,CAAC,CAAC,UAAU,CAAC,KAAK,EAAE;YAC/D,gBAAgB,EAAE,CAAC,CAAC,UAAU,CAAC,MAAM;YACrC,OAAO,EAAE,CAAC,CAAC,OAAO;SACnB,CAAC,CAAC;QACH,gBAAgB,EAAE,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAClD,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,UAAU,EAAE,CAAC,CAAC,UAAU;SACzB,CAAC,CAAC;KACJ,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { SchemaContext } from '@kozou/core';
|
|
2
|
+
import { type DescribeViewInput, type DescribeViewOutput } from '../schemas/describe_view.js';
|
|
3
|
+
export declare function describeView(input: DescribeViewInput, ctx: SchemaContext): DescribeViewOutput;
|
|
4
|
+
//# sourceMappingURL=describe_view.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"describe_view.d.ts","sourceRoot":"","sources":["../../src/tools/describe_view.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACxB,MAAM,6BAA6B,CAAC;AAErC,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,EAAE,GAAG,EAAE,aAAa,GAAG,kBAAkB,CAyB7F"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { describeViewInputSchema, } from '../schemas/describe_view.js';
|
|
2
|
+
export function describeView(input, ctx) {
|
|
3
|
+
const parsed = describeViewInputSchema.parse(input);
|
|
4
|
+
const view = ctx.views.find((v) => v.qualifiedName === parsed.qualifiedName);
|
|
5
|
+
if (!view) {
|
|
6
|
+
throw new Error(`View not found: ${parsed.qualifiedName}`);
|
|
7
|
+
}
|
|
8
|
+
return {
|
|
9
|
+
qualifiedName: view.qualifiedName,
|
|
10
|
+
label: view.label,
|
|
11
|
+
description: view.description,
|
|
12
|
+
aiDescription: view.aiDescription,
|
|
13
|
+
columns: view.columns.map((c) => ({
|
|
14
|
+
name: c.name,
|
|
15
|
+
dataType: c.dataType,
|
|
16
|
+
nullable: c.nullable,
|
|
17
|
+
defaultExpr: c.defaultExpr,
|
|
18
|
+
description: c.description,
|
|
19
|
+
aiDescription: c.aiDescription,
|
|
20
|
+
enumValues: c.enumValues,
|
|
21
|
+
isForeignKey: c.isForeignKey,
|
|
22
|
+
references: null,
|
|
23
|
+
})),
|
|
24
|
+
underlyingTables: view.underlyingTables.map((t) => `${t.schema}.${t.name}`),
|
|
25
|
+
definition: view.rawView.definition,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=describe_view.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"describe_view.js","sourceRoot":"","sources":["../../src/tools/describe_view.ts"],"names":[],"mappings":"AACA,OAAO,EACL,uBAAuB,GAGxB,MAAM,6BAA6B,CAAC;AAErC,MAAM,UAAU,YAAY,CAAC,KAAwB,EAAE,GAAkB;IACvE,MAAM,MAAM,GAAG,uBAAuB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACpD,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,KAAK,MAAM,CAAC,aAAa,CAAC,CAAC;IAC7E,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,mBAAmB,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC;IAC7D,CAAC;IACD,OAAO;QACL,aAAa,EAAE,IAAI,CAAC,aAAa;QACjC,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,aAAa,EAAE,IAAI,CAAC,aAAa;QACjC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAChC,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,WAAW,EAAE,CAAC,CAAC,WAAW;YAC1B,WAAW,EAAE,CAAC,CAAC,WAAW;YAC1B,aAAa,EAAE,CAAC,CAAC,aAAa;YAC9B,UAAU,EAAE,CAAC,CAAC,UAAU;YACxB,YAAY,EAAE,CAAC,CAAC,YAAY;YAC5B,UAAU,EAAE,IAAI;SACjB,CAAC,CAAC;QACH,gBAAgB,EAAE,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;QAC3E,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU;KACpC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { SchemaContext } from '@kozou/core';
|
|
2
|
+
import { type GetConceptContextInput, type GetConceptContextOutput } from '../schemas/get_concept_context.js';
|
|
3
|
+
export declare function getConceptContext(input: GetConceptContextInput, ctx: SchemaContext): GetConceptContextOutput;
|
|
4
|
+
//# sourceMappingURL=get_concept_context.d.ts.map
|