@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.
- package/LICENSE +15 -0
- package/README.md +223 -0
- package/dist/config.d.ts +44 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +53 -0
- package/dist/config.js.map +1 -0
- package/dist/db.d.ts +46 -0
- package/dist/db.d.ts.map +1 -0
- package/dist/db.js +140 -0
- package/dist/db.js.map +1 -0
- package/dist/http-server.d.ts +3 -0
- package/dist/http-server.d.ts.map +1 -0
- package/dist/http-server.js +184 -0
- package/dist/http-server.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +33 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +8 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +85 -0
- package/dist/logger.js.map +1 -0
- package/dist/register-tools.d.ts +6 -0
- package/dist/register-tools.d.ts.map +1 -0
- package/dist/register-tools.js +83 -0
- package/dist/register-tools.js.map +1 -0
- package/dist/tools/describe.d.ts +31 -0
- package/dist/tools/describe.d.ts.map +1 -0
- package/dist/tools/describe.js +61 -0
- package/dist/tools/describe.js.map +1 -0
- package/dist/tools/functions.d.ts +20 -0
- package/dist/tools/functions.d.ts.map +1 -0
- package/dist/tools/functions.js +65 -0
- package/dist/tools/functions.js.map +1 -0
- package/dist/tools/indexes.d.ts +17 -0
- package/dist/tools/indexes.d.ts.map +1 -0
- package/dist/tools/indexes.js +82 -0
- package/dist/tools/indexes.js.map +1 -0
- package/dist/tools/list.d.ts +22 -0
- package/dist/tools/list.d.ts.map +1 -0
- package/dist/tools/list.js +64 -0
- package/dist/tools/list.js.map +1 -0
- package/dist/tools/performance.d.ts +26 -0
- package/dist/tools/performance.d.ts.map +1 -0
- package/dist/tools/performance.js +125 -0
- package/dist/tools/performance.js.map +1 -0
- package/dist/tools/query.d.ts +6 -0
- package/dist/tools/query.d.ts.map +1 -0
- package/dist/tools/query.js +318 -0
- package/dist/tools/query.js.map +1 -0
- package/dist/tools/schemas.d.ts +10 -0
- package/dist/tools/schemas.d.ts.map +1 -0
- package/dist/tools/schemas.js +51 -0
- package/dist/tools/schemas.js.map +1 -0
- package/dist/validation.d.ts +159 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +90 -0
- package/dist/validation.js.map +1 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +11 -0
- package/dist/version.js.map +1 -0
- package/package.json +78 -0
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
import { getPool } from "../db.js";
|
|
2
|
+
import { config } from "../config.js";
|
|
3
|
+
import { QueryInputSchema, validateInput, } from "../validation.js";
|
|
4
|
+
import NodeSQL from "node-sql-parser/build/postgresql.js";
|
|
5
|
+
export const MAX_PAGE_SIZE = config.query.maxPageSize;
|
|
6
|
+
export const DEFAULT_PAGE_SIZE = config.query.defaultPageSize;
|
|
7
|
+
// Set to 'false' to disable automatic LIMIT application
|
|
8
|
+
const AUTO_LIMIT = config.query.autoLimit;
|
|
9
|
+
// Maximum payload size in bytes (default 5MB)
|
|
10
|
+
export const MAX_PAYLOAD_SIZE = config.query.maxPayloadSize;
|
|
11
|
+
const sqlParser = new NodeSQL.Parser();
|
|
12
|
+
function isReadOnlyMode() {
|
|
13
|
+
// Check environment variable directly to support test configuration changes
|
|
14
|
+
return process.env.READ_ONLY !== "false";
|
|
15
|
+
}
|
|
16
|
+
// Dangerous operations that are never allowed
|
|
17
|
+
const DANGEROUS_OPERATIONS = [
|
|
18
|
+
"DROP",
|
|
19
|
+
"CREATE",
|
|
20
|
+
"ALTER",
|
|
21
|
+
"TRUNCATE",
|
|
22
|
+
"GRANT",
|
|
23
|
+
"REVOKE",
|
|
24
|
+
"VACUUM",
|
|
25
|
+
"ANALYZE",
|
|
26
|
+
"CLUSTER",
|
|
27
|
+
"REINDEX",
|
|
28
|
+
"COPY",
|
|
29
|
+
"BACKUP",
|
|
30
|
+
"RESTORE",
|
|
31
|
+
"ATTACH",
|
|
32
|
+
"DETACH",
|
|
33
|
+
"PRAGMA",
|
|
34
|
+
];
|
|
35
|
+
function validateSqlSafety(sqlString) {
|
|
36
|
+
if (!sqlString || typeof sqlString !== "string") {
|
|
37
|
+
return {
|
|
38
|
+
isValid: false,
|
|
39
|
+
error: "SQL query is required and must be a string",
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
const trimmedSql = sqlString.trim();
|
|
43
|
+
if (!trimmedSql) {
|
|
44
|
+
return { isValid: false, error: "SQL query cannot be empty" };
|
|
45
|
+
}
|
|
46
|
+
// Check for dangerous operations BEFORE parsing (since parser may not support them)
|
|
47
|
+
const upperSql = trimmedSql.toUpperCase();
|
|
48
|
+
const sqlWords = upperSql.split(/\s+/);
|
|
49
|
+
const firstWord = sqlWords[0];
|
|
50
|
+
if (DANGEROUS_OPERATIONS.includes(firstWord)) {
|
|
51
|
+
return {
|
|
52
|
+
isValid: false,
|
|
53
|
+
error: `Dangerous operation '${firstWord}' is not allowed`,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
// Handle EXPLAIN queries - they're read-only and don't need parsing
|
|
57
|
+
if (firstWord === 'EXPLAIN') {
|
|
58
|
+
// EXPLAIN is allowed in both read-only and write modes
|
|
59
|
+
return { isValid: true };
|
|
60
|
+
}
|
|
61
|
+
// Handle MERGE and UPSERT - not allowed in read-only mode
|
|
62
|
+
if (firstWord === 'MERGE' || firstWord === 'UPSERT') {
|
|
63
|
+
if (isReadOnlyMode()) {
|
|
64
|
+
return {
|
|
65
|
+
isValid: false,
|
|
66
|
+
error: "Only SELECT, WITH, and EXPLAIN queries are allowed in read-only mode",
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
// These operations require WHERE clauses in write mode, but parser can't handle them
|
|
70
|
+
// For now, we'll reject them since we can't safely validate them
|
|
71
|
+
return {
|
|
72
|
+
isValid: false,
|
|
73
|
+
error: "MERGE and UPSERT operations are not currently supported",
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
// Parse SQL to understand its structure
|
|
77
|
+
let ast;
|
|
78
|
+
try {
|
|
79
|
+
ast = sqlParser.astify(trimmedSql);
|
|
80
|
+
}
|
|
81
|
+
catch (parseError) {
|
|
82
|
+
return {
|
|
83
|
+
isValid: false,
|
|
84
|
+
error: "Invalid SQL syntax - unable to parse query",
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
// Convert to array if single statement
|
|
88
|
+
const statements = Array.isArray(ast) ? ast : [ast];
|
|
89
|
+
// Validate each statement
|
|
90
|
+
for (const statement of statements) {
|
|
91
|
+
const statementType = statement.type?.toUpperCase();
|
|
92
|
+
// Check for dangerous operations
|
|
93
|
+
if (DANGEROUS_OPERATIONS.includes(statementType)) {
|
|
94
|
+
return {
|
|
95
|
+
isValid: false,
|
|
96
|
+
error: `Dangerous operation '${statementType}' is not allowed`,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
// In read-only mode, only allow SELECT, WITH (CTE), and EXPLAIN
|
|
100
|
+
if (isReadOnlyMode()) {
|
|
101
|
+
const allowedTypes = ["SELECT", "WITH", "EXPLAIN"];
|
|
102
|
+
if (!allowedTypes.includes(statementType)) {
|
|
103
|
+
return {
|
|
104
|
+
isValid: false,
|
|
105
|
+
error: "Only SELECT, WITH, and EXPLAIN queries are allowed in read-only mode",
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
// Even in write mode, validate UPDATE and DELETE have WHERE clauses
|
|
111
|
+
if (statementType === "UPDATE" || statementType === "DELETE") {
|
|
112
|
+
// Type guard to check if statement has a where property
|
|
113
|
+
if (!("where" in statement) || !statement.where) {
|
|
114
|
+
return {
|
|
115
|
+
isValid: false,
|
|
116
|
+
error: `${statementType} operations must include a WHERE clause`,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
// Check for dangerous WHERE patterns that effectively disable the clause
|
|
120
|
+
// These are patterns like WHERE 1=1, WHERE TRUE, WHERE 1, WHERE '1'='1'
|
|
121
|
+
const where = statement.where;
|
|
122
|
+
// Check for WHERE TRUE
|
|
123
|
+
if (where && where.type === 'bool' && where.value === true) {
|
|
124
|
+
return {
|
|
125
|
+
isValid: false,
|
|
126
|
+
error: `${statementType} operations cannot use trivial WHERE clauses like WHERE 1=1 or WHERE TRUE`,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
// Check for WHERE 1 (just a constant value)
|
|
130
|
+
if (where && where.type === 'number') {
|
|
131
|
+
return {
|
|
132
|
+
isValid: false,
|
|
133
|
+
error: `${statementType} operations cannot use trivial WHERE clauses like WHERE 1=1 or WHERE TRUE`,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
// Check for WHERE 1=1 pattern (binary expression comparing same constants)
|
|
137
|
+
if (where && where.type === 'binary_expr' && where.operator === '=') {
|
|
138
|
+
const left = where.left;
|
|
139
|
+
const right = where.right;
|
|
140
|
+
// Both sides are the same constant number
|
|
141
|
+
if (left && right && left.type === 'number' && right.type === 'number' && left.value === right.value) {
|
|
142
|
+
return {
|
|
143
|
+
isValid: false,
|
|
144
|
+
error: `${statementType} operations cannot use trivial WHERE clauses like WHERE 1=1 or WHERE TRUE`,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
// Both sides are the same string literal
|
|
148
|
+
if (left && right && left.type === 'single_quote_string' && right.type === 'single_quote_string' && left.value === right.value) {
|
|
149
|
+
return {
|
|
150
|
+
isValid: false,
|
|
151
|
+
error: `${statementType} operations cannot use trivial WHERE clauses like WHERE 1=1 or WHERE TRUE`,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
// Both sides are the same identifier (double-quoted or column reference)
|
|
155
|
+
// In PostgreSQL, "1"="1" would be comparing column "1" to column "1"
|
|
156
|
+
if (left && right && left.type === 'column_ref' && right.type === 'column_ref') {
|
|
157
|
+
// Extract values from nested structure
|
|
158
|
+
const leftExpr = left.column?.expr || left.column;
|
|
159
|
+
const rightExpr = right.column?.expr || right.column;
|
|
160
|
+
// Check if both are double_quote_string with same value
|
|
161
|
+
if (leftExpr && rightExpr &&
|
|
162
|
+
leftExpr.type === 'double_quote_string' &&
|
|
163
|
+
rightExpr.type === 'double_quote_string' &&
|
|
164
|
+
leftExpr.value === rightExpr.value) {
|
|
165
|
+
return {
|
|
166
|
+
isValid: false,
|
|
167
|
+
error: `${statementType} operations cannot use trivial WHERE clauses like WHERE 1=1 or WHERE TRUE`,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
// Check if both are the same column name
|
|
171
|
+
if (typeof leftExpr === 'string' && typeof rightExpr === 'string' && leftExpr === rightExpr) {
|
|
172
|
+
return {
|
|
173
|
+
isValid: false,
|
|
174
|
+
error: `${statementType} operations cannot use trivial WHERE clauses like WHERE 1=1 or WHERE TRUE`,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return { isValid: true };
|
|
183
|
+
}
|
|
184
|
+
function isReadOnlyQuery(sqlString) {
|
|
185
|
+
const upperSql = sqlString.trim().toUpperCase();
|
|
186
|
+
return (upperSql.startsWith("SELECT") ||
|
|
187
|
+
upperSql.startsWith("WITH") ||
|
|
188
|
+
upperSql.startsWith("EXPLAIN"));
|
|
189
|
+
}
|
|
190
|
+
function isSingleRowAggregate(upperSql) {
|
|
191
|
+
// Check if it's an aggregate query that should return a single row
|
|
192
|
+
const hasAggregates = upperSql.includes("COUNT(") ||
|
|
193
|
+
upperSql.includes("SUM(") ||
|
|
194
|
+
upperSql.includes("AVG(") ||
|
|
195
|
+
upperSql.includes("MAX(") ||
|
|
196
|
+
upperSql.includes("MIN(");
|
|
197
|
+
const hasGroupBy = upperSql.includes("GROUP BY");
|
|
198
|
+
// Single row aggregate: has aggregates but no GROUP BY
|
|
199
|
+
return hasAggregates && !hasGroupBy;
|
|
200
|
+
}
|
|
201
|
+
function applyPagination(sqlString, pageSize, offset) {
|
|
202
|
+
// Strip trailing semicolons to avoid syntax errors when adding LIMIT/OFFSET
|
|
203
|
+
const cleanedSql = sqlString.trim().replace(/;+$/, '');
|
|
204
|
+
const upperSql = cleanedSql.toUpperCase();
|
|
205
|
+
// Don't modify if already has LIMIT or OFFSET
|
|
206
|
+
if (upperSql.includes("LIMIT") || upperSql.includes("OFFSET")) {
|
|
207
|
+
return {
|
|
208
|
+
sql: cleanedSql,
|
|
209
|
+
actualPageSize: pageSize || DEFAULT_PAGE_SIZE,
|
|
210
|
+
actualOffset: offset || 0,
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
// Use client-specified pageSize or default, capped at MAX_PAGE_SIZE
|
|
214
|
+
const actualPageSize = Math.min(pageSize || DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE);
|
|
215
|
+
const actualOffset = offset || 0;
|
|
216
|
+
// Don't add LIMIT to single-row aggregates
|
|
217
|
+
if (isSingleRowAggregate(upperSql)) {
|
|
218
|
+
return { sql: cleanedSql, actualPageSize, actualOffset };
|
|
219
|
+
}
|
|
220
|
+
// If AUTO_LIMIT is disabled and no pageSize was explicitly provided, don't add LIMIT
|
|
221
|
+
if (!AUTO_LIMIT && !pageSize) {
|
|
222
|
+
return { sql: cleanedSql, actualPageSize, actualOffset };
|
|
223
|
+
}
|
|
224
|
+
let paginatedSql = `${cleanedSql} LIMIT ${actualPageSize}`;
|
|
225
|
+
if (actualOffset > 0) {
|
|
226
|
+
paginatedSql += ` OFFSET ${actualOffset}`;
|
|
227
|
+
}
|
|
228
|
+
return { sql: paginatedSql, actualPageSize, actualOffset };
|
|
229
|
+
}
|
|
230
|
+
function validateParameters(parameters) {
|
|
231
|
+
for (const param of parameters) {
|
|
232
|
+
if (param !== null &&
|
|
233
|
+
typeof param !== "string" &&
|
|
234
|
+
typeof param !== "number" &&
|
|
235
|
+
typeof param !== "boolean") {
|
|
236
|
+
return {
|
|
237
|
+
error: "Invalid parameter type - only string, number, boolean, and null are allowed",
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
if (typeof param === "number" && !Number.isFinite(param)) {
|
|
241
|
+
return { error: "Invalid numeric parameter - must be finite number" };
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
return null;
|
|
245
|
+
}
|
|
246
|
+
export async function queryTool(input) {
|
|
247
|
+
try {
|
|
248
|
+
const inputValidation = validateInput(QueryInputSchema, input);
|
|
249
|
+
if (!inputValidation.success) {
|
|
250
|
+
return { error: `Input validation failed: ${inputValidation.error}` };
|
|
251
|
+
}
|
|
252
|
+
const validatedInput = inputValidation.data;
|
|
253
|
+
const sqlValidation = validateSqlSafety(validatedInput.sql);
|
|
254
|
+
if (!sqlValidation.isValid) {
|
|
255
|
+
return { error: sqlValidation.error };
|
|
256
|
+
}
|
|
257
|
+
const pool = getPool();
|
|
258
|
+
const trimmedSql = validatedInput.sql.trim();
|
|
259
|
+
const params = validatedInput.parameters ?? [];
|
|
260
|
+
if (params.length > 0) {
|
|
261
|
+
const paramError = validateParameters(params);
|
|
262
|
+
if (paramError)
|
|
263
|
+
return paramError;
|
|
264
|
+
}
|
|
265
|
+
if (isReadOnlyQuery(trimmedSql)) {
|
|
266
|
+
const { sql: paginatedSql, actualPageSize, actualOffset, } = applyPagination(trimmedSql, validatedInput.pageSize, validatedInput.offset);
|
|
267
|
+
// Execute the query
|
|
268
|
+
const result = params.length > 0
|
|
269
|
+
? await pool.query(paginatedSql, params)
|
|
270
|
+
: await pool.query(paginatedSql);
|
|
271
|
+
// Check payload size after query execution
|
|
272
|
+
const payloadJson = JSON.stringify(result.rows);
|
|
273
|
+
const payloadSize = Buffer.byteLength(payloadJson, 'utf8');
|
|
274
|
+
if (payloadSize > MAX_PAYLOAD_SIZE) {
|
|
275
|
+
const sizeMB = (payloadSize / (1024 * 1024)).toFixed(2);
|
|
276
|
+
const maxMB = (MAX_PAYLOAD_SIZE / (1024 * 1024)).toFixed(2);
|
|
277
|
+
return {
|
|
278
|
+
error: `Query result payload (${sizeMB}MB) exceeds maximum allowed size (${maxMB}MB). Please reduce pageSize or add more specific WHERE conditions to limit results.`,
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
// Determine if there are more rows available
|
|
282
|
+
const hasMore = result.rows.length === actualPageSize;
|
|
283
|
+
return {
|
|
284
|
+
rows: result.rows,
|
|
285
|
+
rowCount: result.rows.length,
|
|
286
|
+
pagination: {
|
|
287
|
+
hasMore,
|
|
288
|
+
pageSize: actualPageSize,
|
|
289
|
+
offset: actualOffset,
|
|
290
|
+
},
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
else {
|
|
294
|
+
// For write operations (when not in read-only mode)
|
|
295
|
+
const cleanedSql = trimmedSql.replace(/;+$/, '');
|
|
296
|
+
const result = params.length > 0
|
|
297
|
+
? await pool.query(cleanedSql, params)
|
|
298
|
+
: await pool.query(cleanedSql);
|
|
299
|
+
return {
|
|
300
|
+
rowCount: result.rowCount ?? 0,
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
catch (error) {
|
|
305
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
|
|
306
|
+
// Extract PostgreSQL-specific error details if available
|
|
307
|
+
const pgError = error;
|
|
308
|
+
const errorCode = pgError?.code || "UNKNOWN";
|
|
309
|
+
const hint = pgError?.hint;
|
|
310
|
+
const sanitizedError = errorMessage.replace(/\s+/g, " ").trim();
|
|
311
|
+
return {
|
|
312
|
+
error: sanitizedError,
|
|
313
|
+
code: errorCode,
|
|
314
|
+
hint: hint,
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
//# sourceMappingURL=query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query.js","sourceRoot":"","sources":["../../src/tools/query.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface SchemaInfo {
|
|
2
|
+
schema_name: string;
|
|
3
|
+
schema_owner: string;
|
|
4
|
+
}
|
|
5
|
+
export interface ListSchemasOutput {
|
|
6
|
+
schemas?: SchemaInfo[];
|
|
7
|
+
error?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function listSchemasTool(input: unknown): Promise<ListSchemasOutput>;
|
|
10
|
+
//# sourceMappingURL=schemas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../src/tools/schemas.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,EAAE,UAAU,EAAE,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,eAAe,CACnC,KAAK,EAAE,OAAO,GACb,OAAO,CAAC,iBAAiB,CAAC,CAiD5B"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { getDb } from "../db.js";
|
|
2
|
+
import { sql } from "kysely";
|
|
3
|
+
import { ListSchemasInputSchema, validateInput } from "../validation.js";
|
|
4
|
+
export async function listSchemasTool(input) {
|
|
5
|
+
try {
|
|
6
|
+
const validation = validateInput(ListSchemasInputSchema, 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 includeSystem = validatedInput.includeSystemSchemas || false;
|
|
13
|
+
let query = sql `
|
|
14
|
+
SELECT
|
|
15
|
+
schema_name,
|
|
16
|
+
schema_owner
|
|
17
|
+
FROM information_schema.schemata
|
|
18
|
+
`;
|
|
19
|
+
if (!includeSystem) {
|
|
20
|
+
query = sql `
|
|
21
|
+
SELECT
|
|
22
|
+
schema_name,
|
|
23
|
+
schema_owner
|
|
24
|
+
FROM information_schema.schemata
|
|
25
|
+
WHERE schema_name NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
|
|
26
|
+
AND schema_name NOT LIKE 'pg_temp_%'
|
|
27
|
+
AND schema_name NOT LIKE 'pg_toast_temp_%'
|
|
28
|
+
ORDER BY schema_name
|
|
29
|
+
`;
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
query = sql `
|
|
33
|
+
SELECT
|
|
34
|
+
schema_name,
|
|
35
|
+
schema_owner
|
|
36
|
+
FROM information_schema.schemata
|
|
37
|
+
ORDER BY schema_name
|
|
38
|
+
`;
|
|
39
|
+
}
|
|
40
|
+
const result = await query.execute(db);
|
|
41
|
+
return {
|
|
42
|
+
schemas: result.rows,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
return {
|
|
47
|
+
error: error instanceof Error ? error.message : "Unknown error occurred",
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=schemas.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../src/tools/schemas.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,EAAE,MAAM,kBAAkB,CAAC;AAYzE,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,KAAc;IAEd,IAAI,CAAC;QACH,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;QACnB,MAAM,aAAa,GAAG,cAAc,CAAC,oBAAoB,IAAI,KAAK,CAAC;QAEnE,IAAI,KAAK,GAAG,GAAG,CAAY;;;;;KAK1B,CAAC;QAEF,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,KAAK,GAAG,GAAG,CAAY;;;;;;;;;OAStB,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,KAAK,GAAG,GAAG,CAAY;;;;;;OAMtB,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,159 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const QueryInputSchema: z.ZodObject<{
|
|
3
|
+
sql: z.ZodString;
|
|
4
|
+
parameters: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>, "many">>;
|
|
5
|
+
pageSize: z.ZodOptional<z.ZodNumber>;
|
|
6
|
+
offset: z.ZodOptional<z.ZodNumber>;
|
|
7
|
+
}, "strip", z.ZodTypeAny, {
|
|
8
|
+
sql: string;
|
|
9
|
+
parameters?: (string | number | boolean | null)[] | undefined;
|
|
10
|
+
pageSize?: number | undefined;
|
|
11
|
+
offset?: number | undefined;
|
|
12
|
+
}, {
|
|
13
|
+
sql: string;
|
|
14
|
+
parameters?: (string | number | boolean | null)[] | undefined;
|
|
15
|
+
pageSize?: number | undefined;
|
|
16
|
+
offset?: number | undefined;
|
|
17
|
+
}>;
|
|
18
|
+
export declare const QueryOutputSchema: z.ZodObject<{
|
|
19
|
+
rows: z.ZodOptional<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodAny>, "many">>;
|
|
20
|
+
rowCount: z.ZodOptional<z.ZodNumber>;
|
|
21
|
+
error: z.ZodOptional<z.ZodString>;
|
|
22
|
+
code: z.ZodOptional<z.ZodString>;
|
|
23
|
+
hint: z.ZodOptional<z.ZodString>;
|
|
24
|
+
pagination: z.ZodOptional<z.ZodObject<{
|
|
25
|
+
hasMore: z.ZodBoolean;
|
|
26
|
+
pageSize: z.ZodNumber;
|
|
27
|
+
offset: z.ZodNumber;
|
|
28
|
+
totalRows: z.ZodOptional<z.ZodNumber>;
|
|
29
|
+
}, "strip", z.ZodTypeAny, {
|
|
30
|
+
pageSize: number;
|
|
31
|
+
offset: number;
|
|
32
|
+
hasMore: boolean;
|
|
33
|
+
totalRows?: number | undefined;
|
|
34
|
+
}, {
|
|
35
|
+
pageSize: number;
|
|
36
|
+
offset: number;
|
|
37
|
+
hasMore: boolean;
|
|
38
|
+
totalRows?: number | undefined;
|
|
39
|
+
}>>;
|
|
40
|
+
}, "strip", z.ZodTypeAny, {
|
|
41
|
+
error?: string | undefined;
|
|
42
|
+
code?: string | undefined;
|
|
43
|
+
rows?: Record<string, any>[] | undefined;
|
|
44
|
+
rowCount?: number | undefined;
|
|
45
|
+
hint?: string | undefined;
|
|
46
|
+
pagination?: {
|
|
47
|
+
pageSize: number;
|
|
48
|
+
offset: number;
|
|
49
|
+
hasMore: boolean;
|
|
50
|
+
totalRows?: number | undefined;
|
|
51
|
+
} | undefined;
|
|
52
|
+
}, {
|
|
53
|
+
error?: string | undefined;
|
|
54
|
+
code?: string | undefined;
|
|
55
|
+
rows?: Record<string, any>[] | undefined;
|
|
56
|
+
rowCount?: number | undefined;
|
|
57
|
+
hint?: string | undefined;
|
|
58
|
+
pagination?: {
|
|
59
|
+
pageSize: number;
|
|
60
|
+
offset: number;
|
|
61
|
+
hasMore: boolean;
|
|
62
|
+
totalRows?: number | undefined;
|
|
63
|
+
} | undefined;
|
|
64
|
+
}>;
|
|
65
|
+
export declare const DescribeTableInputSchema: z.ZodObject<{
|
|
66
|
+
schema: z.ZodString;
|
|
67
|
+
table: z.ZodString;
|
|
68
|
+
}, "strip", z.ZodTypeAny, {
|
|
69
|
+
schema: string;
|
|
70
|
+
table: string;
|
|
71
|
+
}, {
|
|
72
|
+
schema: string;
|
|
73
|
+
table: string;
|
|
74
|
+
}>;
|
|
75
|
+
export declare const ListTablesInputSchema: z.ZodObject<{
|
|
76
|
+
schema: z.ZodOptional<z.ZodString>;
|
|
77
|
+
}, "strip", z.ZodTypeAny, {
|
|
78
|
+
schema?: string | undefined;
|
|
79
|
+
}, {
|
|
80
|
+
schema?: string | undefined;
|
|
81
|
+
}>;
|
|
82
|
+
export declare const ListSchemasInputSchema: z.ZodObject<{
|
|
83
|
+
includeSystemSchemas: z.ZodOptional<z.ZodBoolean>;
|
|
84
|
+
}, "strip", z.ZodTypeAny, {
|
|
85
|
+
includeSystemSchemas?: boolean | undefined;
|
|
86
|
+
}, {
|
|
87
|
+
includeSystemSchemas?: boolean | undefined;
|
|
88
|
+
}>;
|
|
89
|
+
export declare const ListIndexesInputSchema: z.ZodObject<{
|
|
90
|
+
schema: z.ZodString;
|
|
91
|
+
table: z.ZodOptional<z.ZodString>;
|
|
92
|
+
}, "strip", z.ZodTypeAny, {
|
|
93
|
+
schema: string;
|
|
94
|
+
table?: string | undefined;
|
|
95
|
+
}, {
|
|
96
|
+
schema: string;
|
|
97
|
+
table?: string | undefined;
|
|
98
|
+
}>;
|
|
99
|
+
export declare const ExplainQueryInputSchema: z.ZodObject<{
|
|
100
|
+
sql: z.ZodString;
|
|
101
|
+
analyze: z.ZodOptional<z.ZodBoolean>;
|
|
102
|
+
buffers: z.ZodOptional<z.ZodBoolean>;
|
|
103
|
+
costs: z.ZodOptional<z.ZodBoolean>;
|
|
104
|
+
format: z.ZodOptional<z.ZodEnum<["text", "json", "xml", "yaml"]>>;
|
|
105
|
+
}, "strip", z.ZodTypeAny, {
|
|
106
|
+
sql: string;
|
|
107
|
+
analyze?: boolean | undefined;
|
|
108
|
+
buffers?: boolean | undefined;
|
|
109
|
+
costs?: boolean | undefined;
|
|
110
|
+
format?: "text" | "json" | "xml" | "yaml" | undefined;
|
|
111
|
+
}, {
|
|
112
|
+
sql: string;
|
|
113
|
+
analyze?: boolean | undefined;
|
|
114
|
+
buffers?: boolean | undefined;
|
|
115
|
+
costs?: boolean | undefined;
|
|
116
|
+
format?: "text" | "json" | "xml" | "yaml" | undefined;
|
|
117
|
+
}>;
|
|
118
|
+
export declare const GetTableStatsInputSchema: z.ZodObject<{
|
|
119
|
+
schema: z.ZodString;
|
|
120
|
+
table: z.ZodOptional<z.ZodString>;
|
|
121
|
+
}, "strip", z.ZodTypeAny, {
|
|
122
|
+
schema: string;
|
|
123
|
+
table?: string | undefined;
|
|
124
|
+
}, {
|
|
125
|
+
schema: string;
|
|
126
|
+
table?: string | undefined;
|
|
127
|
+
}>;
|
|
128
|
+
export declare const ListViewsInputSchema: z.ZodObject<{
|
|
129
|
+
schema: z.ZodOptional<z.ZodString>;
|
|
130
|
+
}, "strip", z.ZodTypeAny, {
|
|
131
|
+
schema?: string | undefined;
|
|
132
|
+
}, {
|
|
133
|
+
schema?: string | undefined;
|
|
134
|
+
}>;
|
|
135
|
+
export declare const ListFunctionsInputSchema: z.ZodObject<{
|
|
136
|
+
schema: z.ZodOptional<z.ZodString>;
|
|
137
|
+
}, "strip", z.ZodTypeAny, {
|
|
138
|
+
schema?: string | undefined;
|
|
139
|
+
}, {
|
|
140
|
+
schema?: string | undefined;
|
|
141
|
+
}>;
|
|
142
|
+
export declare function validateInput<T>(schema: z.ZodSchema<T>, input: unknown): {
|
|
143
|
+
success: true;
|
|
144
|
+
data: T;
|
|
145
|
+
} | {
|
|
146
|
+
success: false;
|
|
147
|
+
error: string;
|
|
148
|
+
};
|
|
149
|
+
export type QueryInput = z.infer<typeof QueryInputSchema>;
|
|
150
|
+
export type QueryOutput = z.infer<typeof QueryOutputSchema>;
|
|
151
|
+
export type DescribeTableInput = z.infer<typeof DescribeTableInputSchema>;
|
|
152
|
+
export type ListTablesInput = z.infer<typeof ListTablesInputSchema>;
|
|
153
|
+
export type ListSchemasInput = z.infer<typeof ListSchemasInputSchema>;
|
|
154
|
+
export type ListIndexesInput = z.infer<typeof ListIndexesInputSchema>;
|
|
155
|
+
export type ExplainQueryInput = z.infer<typeof ExplainQueryInputSchema>;
|
|
156
|
+
export type GetTableStatsInput = z.infer<typeof GetTableStatsInputSchema>;
|
|
157
|
+
export type ListViewsInput = z.infer<typeof ListViewsInputSchema>;
|
|
158
|
+
export type ListFunctionsInput = z.infer<typeof ListFunctionsInputSchema>;
|
|
159
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;EAU3B,CAAC;AAEH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAY5B,CAAC;AAEH,eAAO,MAAM,wBAAwB;;;;;;;;;EAKnC,CAAC;AAEH,eAAO,MAAM,qBAAqB;;;;;;EAIhC,CAAC;AAEH,eAAO,MAAM,sBAAsB;;;;;;EAEjC,CAAC;AAEH,eAAO,MAAM,sBAAsB;;;;;;;;;EAMjC,CAAC;AAEH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;EAMlC,CAAC;AAEH,eAAO,MAAM,wBAAwB;;;;;;;;;EAMnC,CAAC;AAEH,eAAO,MAAM,oBAAoB;;;;;;EAI/B,CAAC;AAEH,eAAO,MAAM,wBAAwB;;;;;;EAInC,CAAC;AAEH,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,GAAG;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,CAAC,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAiBvI;AAED,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAC1D,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC5D,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAC1E,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;AACtE,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AACtE,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;AAC1E,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAClE,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export const QueryInputSchema = z.object({
|
|
3
|
+
sql: z.string().min(1, "SQL query cannot be empty").max(50000, "SQL query too long"),
|
|
4
|
+
parameters: z.array(z.union([
|
|
5
|
+
z.string(),
|
|
6
|
+
z.number(),
|
|
7
|
+
z.boolean(),
|
|
8
|
+
z.null()
|
|
9
|
+
])).optional().describe("Optional array of parameters for parameterized queries"),
|
|
10
|
+
pageSize: z.number().min(1).max(500).optional().describe("Number of rows to return (1-500, default: 100)"),
|
|
11
|
+
offset: z.number().min(0).optional().describe("Number of rows to skip for pagination")
|
|
12
|
+
});
|
|
13
|
+
export const QueryOutputSchema = z.object({
|
|
14
|
+
rows: z.array(z.record(z.any())).optional().describe("Query result rows (for SELECT queries)"),
|
|
15
|
+
rowCount: z.number().optional().describe("Number of rows affected/returned"),
|
|
16
|
+
error: z.string().optional().describe("Error message if query failed"),
|
|
17
|
+
code: z.string().optional().describe("Error code for categorized errors"),
|
|
18
|
+
hint: z.string().optional().describe("Helpful hint for resolving errors"),
|
|
19
|
+
pagination: z.object({
|
|
20
|
+
hasMore: z.boolean().describe("Whether more rows are available"),
|
|
21
|
+
pageSize: z.number().describe("Actual page size used"),
|
|
22
|
+
offset: z.number().describe("Offset used for this query"),
|
|
23
|
+
totalRows: z.number().optional().describe("Total rows available (if determinable)")
|
|
24
|
+
}).optional().describe("Pagination metadata for SELECT queries")
|
|
25
|
+
});
|
|
26
|
+
export const DescribeTableInputSchema = z.object({
|
|
27
|
+
schema: z.string().min(1, "Schema name is required").max(63, "Schema name too long")
|
|
28
|
+
.regex(/^[a-zA-Z_][a-zA-Z0-9_]*$/, "Invalid schema name format"),
|
|
29
|
+
table: z.string().min(1, "Table name is required").max(63, "Table name too long")
|
|
30
|
+
.regex(/^[a-zA-Z_][a-zA-Z0-9_]*$/, "Invalid table name format")
|
|
31
|
+
});
|
|
32
|
+
export const ListTablesInputSchema = z.object({
|
|
33
|
+
schema: z.string().min(1).max(63)
|
|
34
|
+
.regex(/^[a-zA-Z_][a-zA-Z0-9_]*$/, "Invalid schema name format")
|
|
35
|
+
.optional()
|
|
36
|
+
});
|
|
37
|
+
export const ListSchemasInputSchema = z.object({
|
|
38
|
+
includeSystemSchemas: z.boolean().optional()
|
|
39
|
+
});
|
|
40
|
+
export const ListIndexesInputSchema = z.object({
|
|
41
|
+
schema: z.string().min(1, "Schema name is required").max(63, "Schema name too long")
|
|
42
|
+
.regex(/^[a-zA-Z_][a-zA-Z0-9_]*$/, "Invalid schema name format"),
|
|
43
|
+
table: z.string().min(1).max(63)
|
|
44
|
+
.regex(/^[a-zA-Z_][a-zA-Z0-9_]*$/, "Invalid table name format")
|
|
45
|
+
.optional()
|
|
46
|
+
});
|
|
47
|
+
export const ExplainQueryInputSchema = z.object({
|
|
48
|
+
sql: z.string().min(1, "SQL query cannot be empty").max(50000, "SQL query too long"),
|
|
49
|
+
analyze: z.boolean().optional(),
|
|
50
|
+
buffers: z.boolean().optional(),
|
|
51
|
+
costs: z.boolean().optional(),
|
|
52
|
+
format: z.enum(['text', 'json', 'xml', 'yaml']).optional()
|
|
53
|
+
});
|
|
54
|
+
export const GetTableStatsInputSchema = z.object({
|
|
55
|
+
schema: z.string().min(1, "Schema name is required").max(63, "Schema name too long")
|
|
56
|
+
.regex(/^[a-zA-Z_][a-zA-Z0-9_]*$/, "Invalid schema name format"),
|
|
57
|
+
table: z.string().min(1).max(63)
|
|
58
|
+
.regex(/^[a-zA-Z_][a-zA-Z0-9_]*$/, "Invalid table name format")
|
|
59
|
+
.optional()
|
|
60
|
+
});
|
|
61
|
+
export const ListViewsInputSchema = z.object({
|
|
62
|
+
schema: z.string().min(1).max(63)
|
|
63
|
+
.regex(/^[a-zA-Z_][a-zA-Z0-9_]*$/, "Invalid schema name format")
|
|
64
|
+
.optional()
|
|
65
|
+
});
|
|
66
|
+
export const ListFunctionsInputSchema = z.object({
|
|
67
|
+
schema: z.string().min(1).max(63)
|
|
68
|
+
.regex(/^[a-zA-Z_][a-zA-Z0-9_]*$/, "Invalid schema name format")
|
|
69
|
+
.optional()
|
|
70
|
+
});
|
|
71
|
+
export function validateInput(schema, input) {
|
|
72
|
+
try {
|
|
73
|
+
const data = schema.parse(input);
|
|
74
|
+
return { success: true, data };
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
if (error instanceof z.ZodError) {
|
|
78
|
+
const firstError = error.errors[0];
|
|
79
|
+
return {
|
|
80
|
+
success: false,
|
|
81
|
+
error: `${firstError.path.join('.')}: ${firstError.message}`
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
success: false,
|
|
86
|
+
error: 'Invalid input format'
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=validation.js.map
|