schema-navigator-mcp 0.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.
Files changed (48) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +215 -0
  3. package/dist/db/pg-adapter.d.ts +17 -0
  4. package/dist/db/pg-adapter.js +74 -0
  5. package/dist/db/pg-adapter.js.map +1 -0
  6. package/dist/db/postgres.d.ts +19 -0
  7. package/dist/db/postgres.js +34 -0
  8. package/dist/db/postgres.js.map +1 -0
  9. package/dist/db/supabase-adapter.d.ts +45 -0
  10. package/dist/db/supabase-adapter.js +148 -0
  11. package/dist/db/supabase-adapter.js.map +1 -0
  12. package/dist/db/types.d.ts +25 -0
  13. package/dist/db/types.js +2 -0
  14. package/dist/db/types.js.map +1 -0
  15. package/dist/index.d.ts +2 -0
  16. package/dist/index.js +80 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/server.d.ts +4 -0
  19. package/dist/server.js +129 -0
  20. package/dist/server.js.map +1 -0
  21. package/dist/tools/constraints.d.ts +22 -0
  22. package/dist/tools/constraints.js +80 -0
  23. package/dist/tools/constraints.js.map +1 -0
  24. package/dist/tools/functions.d.ts +20 -0
  25. package/dist/tools/functions.js +118 -0
  26. package/dist/tools/functions.js.map +1 -0
  27. package/dist/tools/overview.d.ts +29 -0
  28. package/dist/tools/overview.js +142 -0
  29. package/dist/tools/overview.js.map +1 -0
  30. package/dist/tools/policies.d.ts +29 -0
  31. package/dist/tools/policies.js +96 -0
  32. package/dist/tools/policies.js.map +1 -0
  33. package/dist/tools/relations.d.ts +18 -0
  34. package/dist/tools/relations.js +72 -0
  35. package/dist/tools/relations.js.map +1 -0
  36. package/dist/tools/search.d.ts +13 -0
  37. package/dist/tools/search.js +77 -0
  38. package/dist/tools/search.js.map +1 -0
  39. package/dist/tools/table-profile.d.ts +68 -0
  40. package/dist/tools/table-profile.js +477 -0
  41. package/dist/tools/table-profile.js.map +1 -0
  42. package/dist/utils/check-parser.d.ts +17 -0
  43. package/dist/utils/check-parser.js +61 -0
  44. package/dist/utils/check-parser.js.map +1 -0
  45. package/dist/utils/pg-array.d.ts +6 -0
  46. package/dist/utils/pg-array.js +42 -0
  47. package/dist/utils/pg-array.js.map +1 -0
  48. package/package.json +67 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overview.js","sourceRoot":"","sources":["../../src/tools/overview.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ interface PolicyInfo {
2
+ name: string;
3
+ command: string;
4
+ permissive: boolean;
5
+ roles: string[];
6
+ using: string | null;
7
+ with_check: string | null;
8
+ }
9
+ interface AccessMatrix {
10
+ [role: string]: {
11
+ select: boolean;
12
+ insert: boolean;
13
+ update: boolean;
14
+ delete: boolean;
15
+ };
16
+ }
17
+ interface PoliciesResult {
18
+ table: string;
19
+ schema: string;
20
+ rls_enabled: boolean | null;
21
+ force_rls: boolean | null;
22
+ policies: PolicyInfo[];
23
+ matrix: AccessMatrix;
24
+ note?: string;
25
+ }
26
+ export declare function schemaPolicies(tableName: string, schema: string): Promise<PoliciesResult | {
27
+ error: string;
28
+ }>;
29
+ export {};
@@ -0,0 +1,96 @@
1
+ import { readOnlyMultiQuery, getIsPostgres } from "../db/postgres.js";
2
+ import { parsePgArray } from "../utils/pg-array.js";
3
+ export async function schemaPolicies(tableName, schema) {
4
+ const isPg = getIsPostgres();
5
+ if (!isPg) {
6
+ return {
7
+ table: tableName,
8
+ schema,
9
+ rls_enabled: null,
10
+ force_rls: null,
11
+ policies: [],
12
+ matrix: {},
13
+ note: "RLS is PostgreSQL-specific. Not available on this database.",
14
+ };
15
+ }
16
+ const results = await readOnlyMultiQuery([
17
+ // Check existence + RLS status
18
+ {
19
+ sql: `
20
+ SELECT c.relrowsecurity AS rls_enabled, c.relforcerowsecurity AS force_rls
21
+ FROM pg_class c
22
+ JOIN pg_namespace n ON n.oid = c.relnamespace
23
+ WHERE n.nspname = $1 AND c.relname = $2 AND c.relkind IN ('r', 'p')
24
+ `,
25
+ params: [schema, tableName],
26
+ },
27
+ // Policies
28
+ {
29
+ sql: `
30
+ SELECT
31
+ pol.polname AS name,
32
+ CASE pol.polcmd
33
+ WHEN 'r' THEN 'SELECT'
34
+ WHEN 'a' THEN 'INSERT'
35
+ WHEN 'w' THEN 'UPDATE'
36
+ WHEN 'd' THEN 'DELETE'
37
+ WHEN '*' THEN 'ALL'
38
+ END AS command,
39
+ pol.polpermissive AS permissive,
40
+ CASE
41
+ WHEN pol.polroles = '{0}' THEN ARRAY['public']
42
+ ELSE ARRAY(SELECT rolname FROM pg_roles WHERE oid = ANY(pol.polroles))
43
+ END AS roles,
44
+ pg_get_expr(pol.polqual, pol.polrelid) AS using_expr,
45
+ pg_get_expr(pol.polwithcheck, pol.polrelid) AS with_check
46
+ FROM pg_policy pol
47
+ JOIN pg_class c ON c.oid = pol.polrelid
48
+ JOIN pg_namespace n ON n.oid = c.relnamespace
49
+ WHERE n.nspname = $1 AND c.relname = $2
50
+ ORDER BY pol.polname
51
+ `,
52
+ params: [schema, tableName],
53
+ },
54
+ ]);
55
+ if (results[0].rows.length === 0) {
56
+ return { error: `Table '${tableName}' not found in schema '${schema}'` };
57
+ }
58
+ const meta = results[0].rows[0];
59
+ const rlsEnabled = meta.rls_enabled;
60
+ const forceRls = meta.force_rls;
61
+ const policies = results[1].rows.map((r) => ({
62
+ name: r.name,
63
+ command: r.command,
64
+ permissive: r.permissive,
65
+ roles: parsePgArray(r.roles),
66
+ using: r.using_expr ?? null,
67
+ with_check: r.with_check ?? null,
68
+ }));
69
+ // Build access matrix
70
+ const matrix = {};
71
+ for (const policy of policies) {
72
+ for (const role of policy.roles) {
73
+ if (!matrix[role]) {
74
+ matrix[role] = { select: false, insert: false, update: false, delete: false };
75
+ }
76
+ const cmd = policy.command;
77
+ if (cmd === "ALL" || cmd === "SELECT")
78
+ matrix[role].select = true;
79
+ if (cmd === "ALL" || cmd === "INSERT")
80
+ matrix[role].insert = true;
81
+ if (cmd === "ALL" || cmd === "UPDATE")
82
+ matrix[role].update = true;
83
+ if (cmd === "ALL" || cmd === "DELETE")
84
+ matrix[role].delete = true;
85
+ }
86
+ }
87
+ return {
88
+ table: tableName,
89
+ schema,
90
+ rls_enabled: rlsEnabled,
91
+ force_rls: forceRls,
92
+ policies,
93
+ matrix,
94
+ };
95
+ }
96
+ //# sourceMappingURL=policies.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policies.js","sourceRoot":"","sources":["../../src/tools/policies.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ interface FKRelation {
2
+ constraint_name: string;
3
+ column: string;
4
+ foreign_table: string;
5
+ foreign_column: string;
6
+ on_delete: string;
7
+ on_update: string;
8
+ }
9
+ interface RelationsResult {
10
+ table: string;
11
+ schema: string;
12
+ outbound: FKRelation[];
13
+ inbound: FKRelation[];
14
+ }
15
+ export declare function schemaRelations(tableName: string, schema: string): Promise<RelationsResult | {
16
+ error: string;
17
+ }>;
18
+ export {};
@@ -0,0 +1,72 @@
1
+ import { readOnlyMultiQuery } from "../db/postgres.js";
2
+ export async function schemaRelations(tableName, schema) {
3
+ // Check existence first
4
+ const results = await readOnlyMultiQuery([
5
+ {
6
+ sql: `SELECT 1 FROM information_schema.tables WHERE table_schema = $1 AND table_name = $2`,
7
+ params: [schema, tableName],
8
+ },
9
+ // Outbound FKs (this table references others)
10
+ {
11
+ sql: `
12
+ SELECT
13
+ tc.constraint_name,
14
+ kcu.column_name AS column,
15
+ ccu.table_name AS foreign_table,
16
+ ccu.column_name AS foreign_column,
17
+ rc.delete_rule AS on_delete,
18
+ rc.update_rule AS on_update
19
+ FROM information_schema.table_constraints tc
20
+ JOIN information_schema.key_column_usage kcu
21
+ ON kcu.constraint_name = tc.constraint_name AND kcu.constraint_schema = tc.constraint_schema
22
+ JOIN information_schema.constraint_column_usage ccu
23
+ ON ccu.constraint_name = tc.constraint_name AND ccu.constraint_schema = tc.constraint_schema
24
+ JOIN information_schema.referential_constraints rc
25
+ ON rc.constraint_name = tc.constraint_name AND rc.constraint_schema = tc.constraint_schema
26
+ WHERE tc.table_schema = $1 AND tc.table_name = $2 AND tc.constraint_type = 'FOREIGN KEY'
27
+ ORDER BY tc.constraint_name
28
+ `,
29
+ params: [schema, tableName],
30
+ },
31
+ // Inbound FKs (others reference this table)
32
+ {
33
+ sql: `
34
+ SELECT
35
+ tc.constraint_name,
36
+ ccu.column_name AS column,
37
+ kcu.table_name AS foreign_table,
38
+ kcu.column_name AS foreign_column,
39
+ rc.delete_rule AS on_delete,
40
+ rc.update_rule AS on_update
41
+ FROM information_schema.table_constraints tc
42
+ JOIN information_schema.key_column_usage kcu
43
+ ON kcu.constraint_name = tc.constraint_name AND kcu.constraint_schema = tc.constraint_schema
44
+ JOIN information_schema.constraint_column_usage ccu
45
+ ON ccu.constraint_name = tc.constraint_name AND ccu.constraint_schema = tc.constraint_schema
46
+ JOIN information_schema.referential_constraints rc
47
+ ON rc.constraint_name = tc.constraint_name AND rc.constraint_schema = tc.constraint_schema
48
+ WHERE ccu.table_schema = $1 AND ccu.table_name = $2 AND tc.constraint_type = 'FOREIGN KEY'
49
+ ORDER BY tc.constraint_name
50
+ `,
51
+ params: [schema, tableName],
52
+ },
53
+ ]);
54
+ if (results[0].rows.length === 0) {
55
+ return { error: `Table '${tableName}' not found in schema '${schema}'` };
56
+ }
57
+ const mapRow = (r) => ({
58
+ constraint_name: r.constraint_name,
59
+ column: r.column,
60
+ foreign_table: r.foreign_table,
61
+ foreign_column: r.foreign_column,
62
+ on_delete: r.on_delete,
63
+ on_update: r.on_update,
64
+ });
65
+ return {
66
+ table: tableName,
67
+ schema,
68
+ outbound: results[1].rows.map(mapRow),
69
+ inbound: results[2].rows.map(mapRow),
70
+ };
71
+ }
72
+ //# sourceMappingURL=relations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relations.js","sourceRoot":"","sources":["../../src/tools/relations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAkBvD,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,SAAiB,EACjB,MAAc;IAEd,wBAAwB;IACxB,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC;QACvC;YACE,GAAG,EAAE,qFAAqF;YAC1F,MAAM,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC;SAC5B;QACD,8CAA8C;QAC9C;YACE,GAAG,EAAE;;;;;;;;;;;;;;;;;OAiBJ;YACD,MAAM,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC;SAC5B;QACD,4CAA4C;QAC5C;YACE,GAAG,EAAE;;;;;;;;;;;;;;;;;OAiBJ;YACD,MAAM,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC;SAC5B;KACF,CAAC,CAAC;IAEH,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjC,OAAO,EAAE,KAAK,EAAE,UAAU,SAAS,0BAA0B,MAAM,GAAG,EAAE,CAAC;IAC3E,CAAC;IAED,MAAM,MAAM,GAAG,CAAC,CAA0B,EAAc,EAAE,CAAC,CAAC;QAC1D,eAAe,EAAE,CAAC,CAAC,eAAyB;QAC5C,MAAM,EAAE,CAAC,CAAC,MAAgB;QAC1B,aAAa,EAAE,CAAC,CAAC,aAAuB;QACxC,cAAc,EAAE,CAAC,CAAC,cAAwB;QAC1C,SAAS,EAAE,CAAC,CAAC,SAAmB;QAChC,SAAS,EAAE,CAAC,CAAC,SAAmB;KACjC,CAAC,CAAC;IAEH,OAAO;QACL,KAAK,EAAE,SAAS;QAChB,MAAM;QACN,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC;QACrC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC;KACrC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,13 @@
1
+ interface SearchMatch {
2
+ type: string;
3
+ name: string;
4
+ context: string;
5
+ }
6
+ interface SearchResult {
7
+ term: string;
8
+ schema: string;
9
+ matches: SearchMatch[];
10
+ truncated: boolean;
11
+ }
12
+ export declare function schemaFind(term: string, schema: string): Promise<SearchResult>;
13
+ export {};
@@ -0,0 +1,77 @@
1
+ import { readOnlyQuery, getIsPostgres } from "../db/postgres.js";
2
+ const MAX_RESULTS = 50;
3
+ export async function schemaFind(term, schema) {
4
+ const isPg = getIsPostgres();
5
+ // Escape ILIKE special characters so % and _ are treated as literals
6
+ const escaped = term.replace(/[%_\\]/g, "\\$&");
7
+ const pattern = `%${escaped}%`;
8
+ // Build UNION ALL search across object types
9
+ const parts = [];
10
+ const params = [schema, pattern];
11
+ // Tables
12
+ parts.push(`
13
+ SELECT 'table' AS type, table_name AS name, table_type AS context
14
+ FROM information_schema.tables
15
+ WHERE table_schema = $1 AND table_name ILIKE $2
16
+ `);
17
+ // Columns
18
+ parts.push(`
19
+ SELECT 'column' AS type, column_name AS name, table_name || '.' || column_name || ' (' || data_type || ')' AS context
20
+ FROM information_schema.columns
21
+ WHERE table_schema = $1 AND column_name ILIKE $2
22
+ `);
23
+ // Functions
24
+ parts.push(`
25
+ SELECT 'function' AS type, routine_name AS name, routine_type || ' → ' || COALESCE(data_type, 'void') AS context
26
+ FROM information_schema.routines
27
+ WHERE routine_schema = $1 AND routine_name ILIKE $2
28
+ `);
29
+ // Views
30
+ parts.push(`
31
+ SELECT 'view' AS type, table_name AS name, 'view' AS context
32
+ FROM information_schema.views
33
+ WHERE table_schema = $1 AND table_name ILIKE $2
34
+ `);
35
+ if (isPg) {
36
+ // Materialized views
37
+ parts.push(`
38
+ SELECT 'materialized_view' AS type, matviewname AS name, 'materialized view' AS context
39
+ FROM pg_matviews
40
+ WHERE schemaname = $1 AND matviewname ILIKE $2
41
+ `);
42
+ // RLS Policies
43
+ parts.push(`
44
+ SELECT 'policy' AS type, policyname AS name, 'on ' || tablename || ' (' || cmd || ')' AS context
45
+ FROM pg_policies
46
+ WHERE schemaname = $1 AND policyname ILIKE $2
47
+ `);
48
+ // ENUMs
49
+ parts.push(`
50
+ SELECT 'enum' AS type, t.typname AS name, 'enum type' AS context
51
+ FROM pg_type t
52
+ JOIN pg_namespace n ON n.oid = t.typnamespace
53
+ WHERE n.nspname = $1 AND t.typname ILIKE $2 AND t.typtype = 'e'
54
+ `);
55
+ // Column comments
56
+ parts.push(`
57
+ SELECT 'comment' AS type, a.attname AS name,
58
+ c.relname || '.' || a.attname || ': ' || d.description AS context
59
+ FROM pg_description d
60
+ JOIN pg_class c ON c.oid = d.objoid
61
+ JOIN pg_namespace n ON n.oid = c.relnamespace
62
+ JOIN pg_attribute a ON a.attrelid = c.oid AND a.attnum = d.objsubid
63
+ WHERE n.nspname = $1 AND d.description ILIKE $2 AND d.objsubid > 0
64
+ `);
65
+ }
66
+ const sql = parts.join("\nUNION ALL\n") + "\nLIMIT $3";
67
+ params.push(MAX_RESULTS + 1);
68
+ const result = await readOnlyQuery(sql, params);
69
+ const truncated = result.rows.length > MAX_RESULTS;
70
+ const matches = result.rows.slice(0, MAX_RESULTS).map((r) => ({
71
+ type: r.type,
72
+ name: r.name,
73
+ context: r.context,
74
+ }));
75
+ return { term, schema, matches, truncated };
76
+ }
77
+ //# sourceMappingURL=search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/tools/search.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAejE,MAAM,WAAW,GAAG,EAAE,CAAC;AAEvB,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,IAAY,EACZ,MAAc;IAEd,MAAM,IAAI,GAAG,aAAa,EAAE,CAAC;IAC7B,qEAAqE;IACrE,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAChD,MAAM,OAAO,GAAG,IAAI,OAAO,GAAG,CAAC;IAE/B,6CAA6C;IAC7C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,MAAM,GAAc,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAE5C,SAAS;IACT,KAAK,CAAC,IAAI,CAAC;;;;GAIV,CAAC,CAAC;IAEH,UAAU;IACV,KAAK,CAAC,IAAI,CAAC;;;;GAIV,CAAC,CAAC;IAEH,YAAY;IACZ,KAAK,CAAC,IAAI,CAAC;;;;GAIV,CAAC,CAAC;IAEH,QAAQ;IACR,KAAK,CAAC,IAAI,CAAC;;;;GAIV,CAAC,CAAC;IAEH,IAAI,IAAI,EAAE,CAAC;QACT,qBAAqB;QACrB,KAAK,CAAC,IAAI,CAAC;;;;KAIV,CAAC,CAAC;QAEH,eAAe;QACf,KAAK,CAAC,IAAI,CAAC;;;;KAIV,CAAC,CAAC;QAEH,QAAQ;QACR,KAAK,CAAC,IAAI,CAAC;;;;;KAKV,CAAC,CAAC;QAEH,kBAAkB;QAClB,KAAK,CAAC,IAAI,CAAC;;;;;;;;KAQV,CAAC,CAAC;IACL,CAAC;IAED,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,YAAY,CAAC;IACvD,MAAM,CAAC,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC;IAC7B,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAEhD,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,GAAG,WAAW,CAAC;IACnD,MAAM,OAAO,GAAkB,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC3E,IAAI,EAAE,CAAC,CAAC,IAAc;QACtB,IAAI,EAAE,CAAC,CAAC,IAAc;QACtB,OAAO,EAAE,CAAC,CAAC,OAAiB;KAC7B,CAAC,CAAC,CAAC;IAEJ,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;AAC9C,CAAC"}
@@ -0,0 +1,68 @@
1
+ interface ColumnInfo {
2
+ name: string;
3
+ type: string;
4
+ nullable: boolean;
5
+ default: string | null;
6
+ comment: string | null;
7
+ }
8
+ interface ConstraintInfo {
9
+ name: string;
10
+ type: string;
11
+ columns: string[];
12
+ definition?: string;
13
+ allowed_values?: string[];
14
+ }
15
+ interface ForeignKey {
16
+ constraint_name: string;
17
+ column: string;
18
+ foreign_table: string;
19
+ foreign_column: string;
20
+ on_delete: string;
21
+ on_update: string;
22
+ }
23
+ interface IndexInfo {
24
+ name: string;
25
+ columns: string;
26
+ unique: boolean;
27
+ definition: string;
28
+ }
29
+ interface TriggerInfo {
30
+ name: string;
31
+ event: string;
32
+ timing: string;
33
+ function: string;
34
+ }
35
+ interface PolicyInfo {
36
+ name: string;
37
+ command: string;
38
+ roles: string[];
39
+ using: string | null;
40
+ with_check: string | null;
41
+ }
42
+ interface GrantInfo {
43
+ grantee: string;
44
+ privileges: string[];
45
+ }
46
+ interface TableProfileResult {
47
+ object_type: string;
48
+ schema: string;
49
+ name: string;
50
+ columns: ColumnInfo[];
51
+ constraints: ConstraintInfo[];
52
+ fks_out: ForeignKey[];
53
+ fks_in: ForeignKey[];
54
+ indexes: IndexInfo[];
55
+ triggers: TriggerInfo[];
56
+ policies: PolicyInfo[];
57
+ rls_enabled: boolean | null;
58
+ grants: GrantInfo[];
59
+ size: string | null;
60
+ row_count: number | null;
61
+ view_definition?: string;
62
+ is_updatable?: boolean;
63
+ is_populated?: boolean;
64
+ }
65
+ export declare function schemaTable(tableName: string, schema: string): Promise<TableProfileResult | {
66
+ error: string;
67
+ }>;
68
+ export {};