@calebmabry/postgres-mcp-server 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.
Files changed (63) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +223 -0
  3. package/dist/config.d.ts +44 -0
  4. package/dist/config.d.ts.map +1 -0
  5. package/dist/config.js +53 -0
  6. package/dist/config.js.map +1 -0
  7. package/dist/db.d.ts +46 -0
  8. package/dist/db.d.ts.map +1 -0
  9. package/dist/db.js +140 -0
  10. package/dist/db.js.map +1 -0
  11. package/dist/http-server.d.ts +3 -0
  12. package/dist/http-server.d.ts.map +1 -0
  13. package/dist/http-server.js +184 -0
  14. package/dist/http-server.js.map +1 -0
  15. package/dist/index.d.ts +3 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +33 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/logger.d.ts +8 -0
  20. package/dist/logger.d.ts.map +1 -0
  21. package/dist/logger.js +85 -0
  22. package/dist/logger.js.map +1 -0
  23. package/dist/register-tools.d.ts +6 -0
  24. package/dist/register-tools.d.ts.map +1 -0
  25. package/dist/register-tools.js +83 -0
  26. package/dist/register-tools.js.map +1 -0
  27. package/dist/tools/describe.d.ts +31 -0
  28. package/dist/tools/describe.d.ts.map +1 -0
  29. package/dist/tools/describe.js +61 -0
  30. package/dist/tools/describe.js.map +1 -0
  31. package/dist/tools/functions.d.ts +20 -0
  32. package/dist/tools/functions.d.ts.map +1 -0
  33. package/dist/tools/functions.js +65 -0
  34. package/dist/tools/functions.js.map +1 -0
  35. package/dist/tools/indexes.d.ts +17 -0
  36. package/dist/tools/indexes.d.ts.map +1 -0
  37. package/dist/tools/indexes.js +82 -0
  38. package/dist/tools/indexes.js.map +1 -0
  39. package/dist/tools/list.d.ts +22 -0
  40. package/dist/tools/list.d.ts.map +1 -0
  41. package/dist/tools/list.js +64 -0
  42. package/dist/tools/list.js.map +1 -0
  43. package/dist/tools/performance.d.ts +26 -0
  44. package/dist/tools/performance.d.ts.map +1 -0
  45. package/dist/tools/performance.js +125 -0
  46. package/dist/tools/performance.js.map +1 -0
  47. package/dist/tools/query.d.ts +6 -0
  48. package/dist/tools/query.d.ts.map +1 -0
  49. package/dist/tools/query.js +318 -0
  50. package/dist/tools/query.js.map +1 -0
  51. package/dist/tools/schemas.d.ts +10 -0
  52. package/dist/tools/schemas.d.ts.map +1 -0
  53. package/dist/tools/schemas.js +51 -0
  54. package/dist/tools/schemas.js.map +1 -0
  55. package/dist/validation.d.ts +159 -0
  56. package/dist/validation.d.ts.map +1 -0
  57. package/dist/validation.js +90 -0
  58. package/dist/validation.js.map +1 -0
  59. package/dist/version.d.ts +3 -0
  60. package/dist/version.d.ts.map +1 -0
  61. package/dist/version.js +11 -0
  62. package/dist/version.js.map +1 -0
  63. package/package.json +78 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"functions.js","sourceRoot":"","sources":["../../src/tools/functions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AACjC,OAAO,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAC7B,OAAO,EAAE,wBAAwB,EAAE,aAAa,EAA2B,MAAM,kBAAkB,CAAC;AAsBpG,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,KAAc;IACpD,IAAI,CAAC;QACH,iBAAiB;QACjB,MAAM,UAAU,GAAG,aAAa,CAAC,wBAAwB,EAAE,KAAK,CAAC,CAAC;QAClE,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;YACxB,OAAO,EAAE,KAAK,EAAE,4BAA4B,UAAU,CAAC,KAAK,EAAE,EAAE,CAAC;QACnE,CAAC;QAED,MAAM,cAAc,GAAG,UAAU,CAAC,IAAI,CAAC;QACvC,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;QACnB,MAAM,MAAM,GAAG,cAAc,CAAC,MAAM,IAAI,QAAQ,CAAC;QAEjD,MAAM,KAAK,GAAG,GAAG,CAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0BAoCT,MAAM;;;KAG3B,CAAC;QAEF,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAEvC,OAAO;YACL,SAAS,EAAE,MAAM,CAAC,IAAI;SACvB,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,wBAAwB;SACzE,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,17 @@
1
+ export interface IndexInfo {
2
+ schema_name: string;
3
+ table_name: string;
4
+ index_name: string;
5
+ index_type: string;
6
+ is_unique: boolean;
7
+ is_primary: boolean;
8
+ columns: string;
9
+ definition: string;
10
+ size_bytes?: number;
11
+ }
12
+ export interface ListIndexesOutput {
13
+ indexes?: IndexInfo[];
14
+ error?: string;
15
+ }
16
+ export declare function listIndexesTool(input: unknown): Promise<ListIndexesOutput>;
17
+ //# sourceMappingURL=indexes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexes.d.ts","sourceRoot":"","sources":["../../src/tools/indexes.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,SAAS;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,EAAE,SAAS,EAAE,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,eAAe,CACnC,KAAK,EAAE,OAAO,GACb,OAAO,CAAC,iBAAiB,CAAC,CA+E5B"}
@@ -0,0 +1,82 @@
1
+ import { getDb } from "../db.js";
2
+ import { sql } from "kysely";
3
+ import { ListIndexesInputSchema, validateInput } from "../validation.js";
4
+ export async function listIndexesTool(input) {
5
+ try {
6
+ // Validate input
7
+ const validation = validateInput(ListIndexesInputSchema, input);
8
+ if (!validation.success) {
9
+ return { error: `Input validation failed: ${validation.error}` };
10
+ }
11
+ const validatedInput = validation.data;
12
+ const db = getDb();
13
+ let query;
14
+ if (validatedInput.table) {
15
+ query = sql `
16
+ SELECT
17
+ schemaname as schema_name,
18
+ tablename as table_name,
19
+ indexname as index_name,
20
+ CASE
21
+ WHEN indexdef LIKE '%USING btree%' THEN 'btree'
22
+ WHEN indexdef LIKE '%USING hash%' THEN 'hash'
23
+ WHEN indexdef LIKE '%USING gin%' THEN 'gin'
24
+ WHEN indexdef LIKE '%USING gist%' THEN 'gist'
25
+ WHEN indexdef LIKE '%USING spgist%' THEN 'sp-gist'
26
+ WHEN indexdef LIKE '%USING brin%' THEN 'brin'
27
+ ELSE 'unknown'
28
+ END as index_type,
29
+ CASE WHEN indexdef LIKE '%UNIQUE%' THEN true ELSE false END as is_unique,
30
+ CASE WHEN indexname LIKE '%_pkey' THEN true ELSE false END as is_primary,
31
+ regexp_replace(
32
+ regexp_replace(indexdef, '.*\\((.*?)\\).*', '\\1'),
33
+ ' COLLATE [^,)]+', '', 'g'
34
+ ) as columns,
35
+ indexdef as definition,
36
+ pg_relation_size(schemaname||'.'||indexname) as size_bytes
37
+ FROM pg_indexes
38
+ WHERE schemaname = ${validatedInput.schema}
39
+ AND tablename = ${validatedInput.table}
40
+ ORDER BY tablename, indexname
41
+ `;
42
+ }
43
+ else {
44
+ query = sql `
45
+ SELECT
46
+ schemaname as schema_name,
47
+ tablename as table_name,
48
+ indexname as index_name,
49
+ CASE
50
+ WHEN indexdef LIKE '%USING btree%' THEN 'btree'
51
+ WHEN indexdef LIKE '%USING hash%' THEN 'hash'
52
+ WHEN indexdef LIKE '%USING gin%' THEN 'gin'
53
+ WHEN indexdef LIKE '%USING gist%' THEN 'gist'
54
+ WHEN indexdef LIKE '%USING spgist%' THEN 'sp-gist'
55
+ WHEN indexdef LIKE '%USING brin%' THEN 'brin'
56
+ ELSE 'unknown'
57
+ END as index_type,
58
+ CASE WHEN indexdef LIKE '%UNIQUE%' THEN true ELSE false END as is_unique,
59
+ CASE WHEN indexname LIKE '%_pkey' THEN true ELSE false END as is_primary,
60
+ regexp_replace(
61
+ regexp_replace(indexdef, '.*\\((.*?)\\).*', '\\1'),
62
+ ' COLLATE [^,)]+', '', 'g'
63
+ ) as columns,
64
+ indexdef as definition,
65
+ pg_relation_size(schemaname||'.'||indexname) as size_bytes
66
+ FROM pg_indexes
67
+ WHERE schemaname = ${validatedInput.schema}
68
+ ORDER BY tablename, indexname
69
+ `;
70
+ }
71
+ const result = await query.execute(db);
72
+ return {
73
+ indexes: result.rows,
74
+ };
75
+ }
76
+ catch (error) {
77
+ return {
78
+ error: error instanceof Error ? error.message : "Unknown error occurred",
79
+ };
80
+ }
81
+ }
82
+ //# sourceMappingURL=indexes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexes.js","sourceRoot":"","sources":["../../src/tools/indexes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AACjC,OAAO,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAC7B,OAAO,EAAE,sBAAsB,EAAE,aAAa,EAAyB,MAAM,kBAAkB,CAAC;AAmBhG,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,KAAc;IAEd,IAAI,CAAC;QACH,iBAAiB;QACjB,MAAM,UAAU,GAAG,aAAa,CAAC,sBAAsB,EAAE,KAAK,CAAC,CAAC;QAChE,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;YACxB,OAAO,EAAE,KAAK,EAAE,4BAA4B,UAAU,CAAC,KAAK,EAAE,EAAE,CAAC;QACnE,CAAC;QAED,MAAM,cAAc,GAAG,UAAU,CAAC,IAAI,CAAC;QACvC,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;QAEnB,IAAI,KAAK,CAAC;QACV,IAAI,cAAc,CAAC,KAAK,EAAE,CAAC;YACzB,KAAK,GAAG,GAAG,CAAW;;;;;;;;;;;;;;;;;;;;;;;6BAuBC,cAAc,CAAC,MAAM;4BACtB,cAAc,CAAC,KAAK;;OAEzC,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,KAAK,GAAG,GAAG,CAAW;;;;;;;;;;;;;;;;;;;;;;;6BAuBC,cAAc,CAAC,MAAM;;OAE3C,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAEvC,OAAO;YACL,OAAO,EAAE,MAAM,CAAC,IAAI;SACrB,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,wBAAwB;SACzE,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,22 @@
1
+ export interface TableInfo {
2
+ table_name: string;
3
+ table_type: string;
4
+ }
5
+ export interface ListTablesOutput {
6
+ tables?: TableInfo[];
7
+ error?: string;
8
+ }
9
+ export declare function listTablesTool(input: unknown): Promise<ListTablesOutput>;
10
+ export interface ViewInfo {
11
+ schema_name: string;
12
+ view_name: string;
13
+ view_definition: string;
14
+ is_updatable: string;
15
+ check_option: string;
16
+ }
17
+ export interface ListViewsOutput {
18
+ views?: ViewInfo[];
19
+ error?: string;
20
+ }
21
+ export declare function listViewsTool(input: unknown): Promise<ListViewsOutput>;
22
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/tools/list.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,SAAS;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,cAAc,CAClC,KAAK,EAAE,OAAO,GACb,OAAO,CAAC,gBAAgB,CAAC,CA+B3B;AAED,MAAM,WAAW,QAAQ;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,eAAe,CAAC,CAiC5E"}
@@ -0,0 +1,64 @@
1
+ import { getDb } from "../db.js";
2
+ import { sql } from "kysely";
3
+ import { ListTablesInputSchema, ListViewsInputSchema, validateInput, } from "../validation.js";
4
+ export async function listTablesTool(input) {
5
+ try {
6
+ const validation = validateInput(ListTablesInputSchema, input);
7
+ if (!validation.success) {
8
+ return { error: `Input validation failed: ${validation.error}` };
9
+ }
10
+ const validatedInput = validation.data;
11
+ const db = getDb();
12
+ const schema = validatedInput.schema || "public";
13
+ const query = sql `
14
+ SELECT
15
+ table_name,
16
+ table_type
17
+ FROM information_schema.tables
18
+ WHERE table_schema = ${schema}
19
+ AND table_type IN ('BASE TABLE', 'VIEW')
20
+ ORDER BY table_name
21
+ `;
22
+ const result = await query.execute(db);
23
+ return {
24
+ tables: result.rows,
25
+ };
26
+ }
27
+ catch (error) {
28
+ return {
29
+ error: error instanceof Error ? error.message : "Unknown error occurred",
30
+ };
31
+ }
32
+ }
33
+ export async function listViewsTool(input) {
34
+ try {
35
+ const validation = validateInput(ListViewsInputSchema, input);
36
+ if (!validation.success) {
37
+ return { error: `Input validation failed: ${validation.error}` };
38
+ }
39
+ const validatedInput = validation.data;
40
+ const db = getDb();
41
+ const schema = validatedInput.schema || "public";
42
+ const query = sql `
43
+ SELECT
44
+ table_schema as schema_name,
45
+ table_name as view_name,
46
+ view_definition,
47
+ is_updatable,
48
+ check_option
49
+ FROM information_schema.views
50
+ WHERE table_schema = ${schema}
51
+ ORDER BY table_name
52
+ `;
53
+ const result = await query.execute(db);
54
+ return {
55
+ views: result.rows,
56
+ };
57
+ }
58
+ catch (error) {
59
+ return {
60
+ error: error instanceof Error ? error.message : "Unknown error occurred",
61
+ };
62
+ }
63
+ }
64
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/tools/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AACjC,OAAO,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAC7B,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EACpB,aAAa,GACd,MAAM,kBAAkB,CAAC;AAY1B,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,KAAc;IAEd,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,aAAa,CAAC,qBAAqB,EAAE,KAAK,CAAC,CAAC;QAC/D,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;YACxB,OAAO,EAAE,KAAK,EAAE,4BAA4B,UAAU,CAAC,KAAK,EAAE,EAAE,CAAC;QACnE,CAAC;QAED,MAAM,cAAc,GAAG,UAAU,CAAC,IAAI,CAAC;QACvC,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;QACnB,MAAM,MAAM,GAAG,cAAc,CAAC,MAAM,IAAI,QAAQ,CAAC;QAEjD,MAAM,KAAK,GAAG,GAAG,CAAW;;;;;6BAKH,MAAM;;;KAG9B,CAAC;QAEF,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAEvC,OAAO;YACL,MAAM,EAAE,MAAM,CAAC,IAAI;SACpB,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,wBAAwB;SACzE,CAAC;IACJ,CAAC;AACH,CAAC;AAeD,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,KAAc;IAChD,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,aAAa,CAAC,oBAAoB,EAAE,KAAK,CAAC,CAAC;QAC9D,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;YACxB,OAAO,EAAE,KAAK,EAAE,4BAA4B,UAAU,CAAC,KAAK,EAAE,EAAE,CAAC;QACnE,CAAC;QAED,MAAM,cAAc,GAAG,UAAU,CAAC,IAAI,CAAC;QACvC,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;QACnB,MAAM,MAAM,GAAG,cAAc,CAAC,MAAM,IAAI,QAAQ,CAAC;QAEjD,MAAM,KAAK,GAAG,GAAG,CAAU;;;;;;;;6BAQF,MAAM;;KAE9B,CAAC;QAEF,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAEvC,OAAO;YACL,KAAK,EAAE,MAAM,CAAC,IAAI;SACnB,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,wBAAwB;SACzE,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,26 @@
1
+ export interface ExplainQueryOutput {
2
+ plan?: any[];
3
+ error?: string;
4
+ }
5
+ export declare function explainQueryTool(input: unknown): Promise<ExplainQueryOutput>;
6
+ export interface TableStatsInfo {
7
+ schema_name: string;
8
+ table_name: string;
9
+ row_count: number;
10
+ table_size_bytes: number;
11
+ table_size_pretty: string;
12
+ index_size_bytes: number;
13
+ index_size_pretty: string;
14
+ total_size_bytes: number;
15
+ total_size_pretty: string;
16
+ last_vacuum?: string;
17
+ last_autovacuum?: string;
18
+ last_analyze?: string;
19
+ last_autoanalyze?: string;
20
+ }
21
+ export interface GetTableStatsOutput {
22
+ stats?: TableStatsInfo[];
23
+ error?: string;
24
+ }
25
+ export declare function getTableStatsTool(input: unknown): Promise<GetTableStatsOutput>;
26
+ //# sourceMappingURL=performance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"performance.d.ts","sourceRoot":"","sources":["../../src/tools/performance.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,OAAO,GACb,OAAO,CAAC,kBAAkB,CAAC,CAsD7B;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,cAAc,EAAE,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,OAAO,GACb,OAAO,CAAC,mBAAmB,CAAC,CAyE9B"}
@@ -0,0 +1,125 @@
1
+ import { getDb, getPool } from "../db.js";
2
+ import { sql } from "kysely";
3
+ import { ExplainQueryInputSchema, GetTableStatsInputSchema, validateInput, } from "../validation.js";
4
+ export async function explainQueryTool(input) {
5
+ try {
6
+ const validation = validateInput(ExplainQueryInputSchema, input);
7
+ if (!validation.success) {
8
+ return { error: `Input validation failed: ${validation.error}` };
9
+ }
10
+ const validatedInput = validation.data;
11
+ // Safety check - prevent potentially dangerous queries
12
+ const trimmedSql = validatedInput.sql.trim().toUpperCase();
13
+ if (trimmedSql.includes("INSERT") ||
14
+ trimmedSql.includes("UPDATE") ||
15
+ trimmedSql.includes("DELETE") ||
16
+ trimmedSql.includes("DROP") ||
17
+ trimmedSql.includes("CREATE") ||
18
+ trimmedSql.includes("ALTER") ||
19
+ trimmedSql.includes("TRUNCATE")) {
20
+ return {
21
+ error: "EXPLAIN is only allowed for SELECT queries and read-only operations",
22
+ };
23
+ }
24
+ // Build EXPLAIN options safely
25
+ const options = [];
26
+ if (validatedInput.analyze)
27
+ options.push("ANALYZE true");
28
+ if (validatedInput.buffers)
29
+ options.push("BUFFERS true");
30
+ if (validatedInput.costs !== false)
31
+ options.push("COSTS true");
32
+ if (validatedInput.format) {
33
+ // Validate format to prevent injection
34
+ const validFormats = ["TEXT", "JSON", "XML", "YAML"];
35
+ const upperFormat = validatedInput.format.toUpperCase();
36
+ if (validFormats.includes(upperFormat)) {
37
+ options.push(`FORMAT ${upperFormat}`);
38
+ }
39
+ }
40
+ const optionsStr = options.length > 0 ? `(${options.join(", ")})` : "";
41
+ const explainSql = `EXPLAIN ${optionsStr} ${validatedInput.sql}`;
42
+ const pool = getPool();
43
+ const result = await pool.query(explainSql);
44
+ return {
45
+ plan: result.rows,
46
+ };
47
+ }
48
+ catch (error) {
49
+ return {
50
+ error: error instanceof Error ? error.message : "Unknown error occurred",
51
+ };
52
+ }
53
+ }
54
+ export async function getTableStatsTool(input) {
55
+ try {
56
+ // Validate input
57
+ const validation = validateInput(GetTableStatsInputSchema, input);
58
+ if (!validation.success) {
59
+ return { error: `Input validation failed: ${validation.error}` };
60
+ }
61
+ const validatedInput = validation.data;
62
+ const db = getDb();
63
+ let query;
64
+ if (validatedInput.table) {
65
+ query = sql `
66
+ SELECT
67
+ schemaname as schema_name,
68
+ relname as table_name,
69
+ (COALESCE(n_tup_ins, 0) + COALESCE(n_tup_upd, 0) + COALESCE(n_tup_del, 0))::bigint as row_count,
70
+ pg_relation_size(schemaname||'.'||relname) as table_size_bytes,
71
+ pg_size_pretty(pg_relation_size(schemaname||'.'||relname)) as table_size_pretty,
72
+ pg_indexes_size(schemaname||'.'||relname) as index_size_bytes,
73
+ pg_size_pretty(pg_indexes_size(schemaname||'.'||relname)) as index_size_pretty,
74
+ pg_total_relation_size(schemaname||'.'||relname) as total_size_bytes,
75
+ pg_size_pretty(pg_total_relation_size(schemaname||'.'||relname)) as total_size_pretty,
76
+ last_vacuum::text,
77
+ last_autovacuum::text,
78
+ last_analyze::text,
79
+ last_autoanalyze::text
80
+ FROM pg_stat_user_tables
81
+ WHERE schemaname = ${validatedInput.schema}
82
+ AND relname = ${validatedInput.table}
83
+ `;
84
+ }
85
+ else {
86
+ query = sql `
87
+ SELECT
88
+ schemaname as schema_name,
89
+ relname as table_name,
90
+ (COALESCE(n_tup_ins, 0) + COALESCE(n_tup_upd, 0) + COALESCE(n_tup_del, 0))::bigint as row_count,
91
+ pg_relation_size(schemaname||'.'||relname) as table_size_bytes,
92
+ pg_size_pretty(pg_relation_size(schemaname||'.'||relname)) as table_size_pretty,
93
+ pg_indexes_size(schemaname||'.'||relname) as index_size_bytes,
94
+ pg_size_pretty(pg_indexes_size(schemaname||'.'||relname)) as index_size_pretty,
95
+ pg_total_relation_size(schemaname||'.'||relname) as total_size_bytes,
96
+ pg_size_pretty(pg_total_relation_size(schemaname||'.'||relname)) as total_size_pretty,
97
+ last_vacuum::text,
98
+ last_autovacuum::text,
99
+ last_analyze::text,
100
+ last_autoanalyze::text
101
+ FROM pg_stat_user_tables
102
+ WHERE schemaname = ${validatedInput.schema}
103
+ ORDER BY total_size_bytes DESC
104
+ `;
105
+ }
106
+ const result = await query.execute(db);
107
+ // Convert string numbers to actual numbers
108
+ const stats = result.rows.map((row) => ({
109
+ ...row,
110
+ row_count: Number(row.row_count),
111
+ table_size_bytes: Number(row.table_size_bytes),
112
+ index_size_bytes: Number(row.index_size_bytes),
113
+ total_size_bytes: Number(row.total_size_bytes),
114
+ }));
115
+ return {
116
+ stats,
117
+ };
118
+ }
119
+ catch (error) {
120
+ return {
121
+ error: error instanceof Error ? error.message : "Unknown error occurred",
122
+ };
123
+ }
124
+ }
125
+ //# sourceMappingURL=performance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"performance.js","sourceRoot":"","sources":["../../src/tools/performance.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { type QueryOutput } from "../validation.js";
2
+ export declare const MAX_PAGE_SIZE: number;
3
+ export declare const DEFAULT_PAGE_SIZE: number;
4
+ export declare const MAX_PAYLOAD_SIZE: number;
5
+ export declare function queryTool(input: unknown): Promise<QueryOutput>;
6
+ //# sourceMappingURL=query.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/tools/query.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,WAAW,EACjB,MAAM,kBAAkB,CAAC;AAG1B,eAAO,MAAM,aAAa,QAA2B,CAAC;AACtD,eAAO,MAAM,iBAAiB,QAA+B,CAAC;AAI9D,eAAO,MAAM,gBAAgB,QAA8B,CAAC;AAiS5D,wBAAsB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC,CA2FpE"}