@neverinfamous/postgres-mcp 1.3.0 → 2.0.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/README.md +177 -129
- package/dist/__tests__/benchmarks/codemode.bench.d.ts +10 -0
- package/dist/__tests__/benchmarks/codemode.bench.d.ts.map +1 -0
- package/dist/__tests__/benchmarks/codemode.bench.js +159 -0
- package/dist/__tests__/benchmarks/codemode.bench.js.map +1 -0
- package/dist/__tests__/benchmarks/connection-pool.bench.d.ts +10 -0
- package/dist/__tests__/benchmarks/connection-pool.bench.d.ts.map +1 -0
- package/dist/__tests__/benchmarks/connection-pool.bench.js +123 -0
- package/dist/__tests__/benchmarks/connection-pool.bench.js.map +1 -0
- package/dist/__tests__/benchmarks/handler-dispatch.bench.d.ts +11 -0
- package/dist/__tests__/benchmarks/handler-dispatch.bench.d.ts.map +1 -0
- package/dist/__tests__/benchmarks/handler-dispatch.bench.js +199 -0
- package/dist/__tests__/benchmarks/handler-dispatch.bench.js.map +1 -0
- package/dist/__tests__/benchmarks/logger-sanitization.bench.d.ts +15 -0
- package/dist/__tests__/benchmarks/logger-sanitization.bench.d.ts.map +1 -0
- package/dist/__tests__/benchmarks/logger-sanitization.bench.js +155 -0
- package/dist/__tests__/benchmarks/logger-sanitization.bench.js.map +1 -0
- package/dist/__tests__/benchmarks/resource-prompts.bench.d.ts +10 -0
- package/dist/__tests__/benchmarks/resource-prompts.bench.d.ts.map +1 -0
- package/dist/__tests__/benchmarks/resource-prompts.bench.js +181 -0
- package/dist/__tests__/benchmarks/resource-prompts.bench.js.map +1 -0
- package/dist/__tests__/benchmarks/schema-parsing.bench.d.ts +11 -0
- package/dist/__tests__/benchmarks/schema-parsing.bench.d.ts.map +1 -0
- package/dist/__tests__/benchmarks/schema-parsing.bench.js +209 -0
- package/dist/__tests__/benchmarks/schema-parsing.bench.js.map +1 -0
- package/dist/__tests__/benchmarks/tool-filtering.bench.d.ts +9 -0
- package/dist/__tests__/benchmarks/tool-filtering.bench.d.ts.map +1 -0
- package/dist/__tests__/benchmarks/tool-filtering.bench.js +83 -0
- package/dist/__tests__/benchmarks/tool-filtering.bench.js.map +1 -0
- package/dist/__tests__/benchmarks/transport-auth.bench.d.ts +10 -0
- package/dist/__tests__/benchmarks/transport-auth.bench.d.ts.map +1 -0
- package/dist/__tests__/benchmarks/transport-auth.bench.js +128 -0
- package/dist/__tests__/benchmarks/transport-auth.bench.js.map +1 -0
- package/dist/__tests__/benchmarks/utilities.bench.d.ts +10 -0
- package/dist/__tests__/benchmarks/utilities.bench.d.ts.map +1 -0
- package/dist/__tests__/benchmarks/utilities.bench.js +164 -0
- package/dist/__tests__/benchmarks/utilities.bench.js.map +1 -0
- package/dist/adapters/DatabaseAdapter.d.ts.map +1 -1
- package/dist/adapters/DatabaseAdapter.js +12 -0
- package/dist/adapters/DatabaseAdapter.js.map +1 -1
- package/dist/adapters/postgresql/PostgresAdapter.d.ts.map +1 -1
- package/dist/adapters/postgresql/PostgresAdapter.js +3 -0
- package/dist/adapters/postgresql/PostgresAdapter.js.map +1 -1
- package/dist/adapters/postgresql/schemas/backup.d.ts +37 -23
- package/dist/adapters/postgresql/schemas/backup.d.ts.map +1 -1
- package/dist/adapters/postgresql/schemas/backup.js +53 -22
- package/dist/adapters/postgresql/schemas/backup.js.map +1 -1
- package/dist/adapters/postgresql/schemas/extensions.d.ts +56 -37
- package/dist/adapters/postgresql/schemas/extensions.d.ts.map +1 -1
- package/dist/adapters/postgresql/schemas/extensions.js +68 -36
- package/dist/adapters/postgresql/schemas/extensions.js.map +1 -1
- package/dist/adapters/postgresql/schemas/index.d.ts +3 -2
- package/dist/adapters/postgresql/schemas/index.d.ts.map +1 -1
- package/dist/adapters/postgresql/schemas/index.js +8 -2
- package/dist/adapters/postgresql/schemas/index.js.map +1 -1
- package/dist/adapters/postgresql/schemas/introspection.d.ts +445 -0
- package/dist/adapters/postgresql/schemas/introspection.d.ts.map +1 -0
- package/dist/adapters/postgresql/schemas/introspection.js +478 -0
- package/dist/adapters/postgresql/schemas/introspection.js.map +1 -0
- package/dist/adapters/postgresql/schemas/jsonb.d.ts +8 -0
- package/dist/adapters/postgresql/schemas/jsonb.d.ts.map +1 -1
- package/dist/adapters/postgresql/schemas/jsonb.js +26 -2
- package/dist/adapters/postgresql/schemas/jsonb.js.map +1 -1
- package/dist/adapters/postgresql/schemas/monitoring.d.ts +41 -25
- package/dist/adapters/postgresql/schemas/monitoring.d.ts.map +1 -1
- package/dist/adapters/postgresql/schemas/monitoring.js +49 -16
- package/dist/adapters/postgresql/schemas/monitoring.js.map +1 -1
- package/dist/adapters/postgresql/schemas/partitioning.d.ts +16 -20
- package/dist/adapters/postgresql/schemas/partitioning.d.ts.map +1 -1
- package/dist/adapters/postgresql/schemas/partitioning.js +21 -10
- package/dist/adapters/postgresql/schemas/partitioning.js.map +1 -1
- package/dist/adapters/postgresql/schemas/partman.d.ts +69 -0
- package/dist/adapters/postgresql/schemas/partman.d.ts.map +1 -1
- package/dist/adapters/postgresql/schemas/partman.js +46 -33
- package/dist/adapters/postgresql/schemas/partman.js.map +1 -1
- package/dist/adapters/postgresql/schemas/performance.d.ts +37 -19
- package/dist/adapters/postgresql/schemas/performance.d.ts.map +1 -1
- package/dist/adapters/postgresql/schemas/performance.js +54 -12
- package/dist/adapters/postgresql/schemas/performance.js.map +1 -1
- package/dist/adapters/postgresql/schemas/postgis.d.ts.map +1 -1
- package/dist/adapters/postgresql/schemas/postgis.js +20 -0
- package/dist/adapters/postgresql/schemas/postgis.js.map +1 -1
- package/dist/adapters/postgresql/schemas/schema-mgmt.d.ts +15 -7
- package/dist/adapters/postgresql/schemas/schema-mgmt.d.ts.map +1 -1
- package/dist/adapters/postgresql/schemas/schema-mgmt.js +36 -7
- package/dist/adapters/postgresql/schemas/schema-mgmt.js.map +1 -1
- package/dist/adapters/postgresql/schemas/text-search.d.ts +26 -14
- package/dist/adapters/postgresql/schemas/text-search.d.ts.map +1 -1
- package/dist/adapters/postgresql/schemas/text-search.js +41 -9
- package/dist/adapters/postgresql/schemas/text-search.js.map +1 -1
- package/dist/adapters/postgresql/tools/admin.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/admin.js +82 -67
- package/dist/adapters/postgresql/tools/admin.js.map +1 -1
- package/dist/adapters/postgresql/tools/backup/dump.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/backup/dump.js +27 -24
- package/dist/adapters/postgresql/tools/backup/dump.js.map +1 -1
- package/dist/adapters/postgresql/tools/citext.js +114 -82
- package/dist/adapters/postgresql/tools/citext.js.map +1 -1
- package/dist/adapters/postgresql/tools/codemode/index.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/codemode/index.js +2 -11
- package/dist/adapters/postgresql/tools/codemode/index.js.map +1 -1
- package/dist/adapters/postgresql/tools/core/convenience.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/core/convenience.js +23 -8
- package/dist/adapters/postgresql/tools/core/convenience.js.map +1 -1
- package/dist/adapters/postgresql/tools/core/indexes.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/core/indexes.js +3 -2
- package/dist/adapters/postgresql/tools/core/indexes.js.map +1 -1
- package/dist/adapters/postgresql/tools/core/tables.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/core/tables.js +4 -4
- package/dist/adapters/postgresql/tools/core/tables.js.map +1 -1
- package/dist/adapters/postgresql/tools/cron.js +59 -27
- package/dist/adapters/postgresql/tools/cron.js.map +1 -1
- package/dist/adapters/postgresql/tools/introspection.d.ts +15 -0
- package/dist/adapters/postgresql/tools/introspection.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/introspection.js +1682 -0
- package/dist/adapters/postgresql/tools/introspection.js.map +1 -0
- package/dist/adapters/postgresql/tools/jsonb/advanced.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/jsonb/advanced.js +26 -17
- package/dist/adapters/postgresql/tools/jsonb/advanced.js.map +1 -1
- package/dist/adapters/postgresql/tools/jsonb/basic.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/jsonb/basic.js +92 -23
- package/dist/adapters/postgresql/tools/jsonb/basic.js.map +1 -1
- package/dist/adapters/postgresql/tools/ltree.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/ltree.js +17 -4
- package/dist/adapters/postgresql/tools/ltree.js.map +1 -1
- package/dist/adapters/postgresql/tools/monitoring.js +32 -21
- package/dist/adapters/postgresql/tools/monitoring.js.map +1 -1
- package/dist/adapters/postgresql/tools/partman/management.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/partman/management.js +32 -52
- package/dist/adapters/postgresql/tools/partman/management.js.map +1 -1
- package/dist/adapters/postgresql/tools/partman/operations.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/partman/operations.js +5 -5
- package/dist/adapters/postgresql/tools/partman/operations.js.map +1 -1
- package/dist/adapters/postgresql/tools/performance/analysis.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/performance/analysis.js +15 -8
- package/dist/adapters/postgresql/tools/performance/analysis.js.map +1 -1
- package/dist/adapters/postgresql/tools/performance/monitoring.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/performance/monitoring.js +10 -7
- package/dist/adapters/postgresql/tools/performance/monitoring.js.map +1 -1
- package/dist/adapters/postgresql/tools/performance/stats.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/performance/stats.js +62 -28
- package/dist/adapters/postgresql/tools/performance/stats.js.map +1 -1
- package/dist/adapters/postgresql/tools/pgcrypto.js +31 -11
- package/dist/adapters/postgresql/tools/pgcrypto.js.map +1 -1
- package/dist/adapters/postgresql/tools/postgis/advanced.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/postgis/advanced.js +30 -25
- package/dist/adapters/postgresql/tools/postgis/advanced.js.map +1 -1
- package/dist/adapters/postgresql/tools/postgis/basic.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/postgis/basic.js +24 -15
- package/dist/adapters/postgresql/tools/postgis/basic.js.map +1 -1
- package/dist/adapters/postgresql/tools/schema.js +79 -5
- package/dist/adapters/postgresql/tools/schema.js.map +1 -1
- package/dist/adapters/postgresql/tools/stats/advanced.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/stats/advanced.js +61 -39
- package/dist/adapters/postgresql/tools/stats/advanced.js.map +1 -1
- package/dist/adapters/postgresql/tools/stats/basic.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/stats/basic.js +45 -30
- package/dist/adapters/postgresql/tools/stats/basic.js.map +1 -1
- package/dist/adapters/postgresql/tools/text.js +327 -148
- package/dist/adapters/postgresql/tools/text.js.map +1 -1
- package/dist/auth/auth-context.d.ts +28 -0
- package/dist/auth/auth-context.d.ts.map +1 -0
- package/dist/auth/auth-context.js +37 -0
- package/dist/auth/auth-context.js.map +1 -0
- package/dist/auth/scope-map.d.ts +20 -0
- package/dist/auth/scope-map.d.ts.map +1 -0
- package/dist/auth/scope-map.js +40 -0
- package/dist/auth/scope-map.js.map +1 -0
- package/dist/auth/scopes.d.ts.map +1 -1
- package/dist/auth/scopes.js +2 -0
- package/dist/auth/scopes.js.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/codemode/api.d.ts +1 -0
- package/dist/codemode/api.d.ts.map +1 -1
- package/dist/codemode/api.js +34 -0
- package/dist/codemode/api.js.map +1 -1
- package/dist/codemode/index.d.ts +0 -2
- package/dist/codemode/index.d.ts.map +1 -1
- package/dist/codemode/index.js +0 -4
- package/dist/codemode/index.js.map +1 -1
- package/dist/codemode/sandbox.d.ts +14 -1
- package/dist/codemode/sandbox.d.ts.map +1 -1
- package/dist/codemode/sandbox.js +58 -19
- package/dist/codemode/sandbox.js.map +1 -1
- package/dist/codemode/types.d.ts.map +1 -1
- package/dist/codemode/types.js +3 -0
- package/dist/codemode/types.js.map +1 -1
- package/dist/constants/ServerInstructions.d.ts +5 -1
- package/dist/constants/ServerInstructions.d.ts.map +1 -1
- package/dist/constants/ServerInstructions.js +91 -43
- package/dist/constants/ServerInstructions.js.map +1 -1
- package/dist/filtering/ToolConstants.d.ts +22 -19
- package/dist/filtering/ToolConstants.d.ts.map +1 -1
- package/dist/filtering/ToolConstants.js +48 -37
- package/dist/filtering/ToolConstants.js.map +1 -1
- package/dist/filtering/ToolFilter.d.ts.map +1 -1
- package/dist/filtering/ToolFilter.js +10 -13
- package/dist/filtering/ToolFilter.js.map +1 -1
- package/dist/pool/ConnectionPool.js +1 -1
- package/dist/pool/ConnectionPool.js.map +1 -1
- package/dist/transports/http.d.ts +1 -0
- package/dist/transports/http.d.ts.map +1 -1
- package/dist/transports/http.js +75 -21
- package/dist/transports/http.js.map +1 -1
- package/dist/types/filtering.d.ts +2 -2
- package/dist/types/filtering.d.ts.map +1 -1
- package/dist/utils/icons.d.ts.map +1 -1
- package/dist/utils/icons.js +5 -0
- package/dist/utils/icons.js.map +1 -1
- package/dist/utils/where-clause.d.ts.map +1 -1
- package/dist/utils/where-clause.js +24 -0
- package/dist/utils/where-clause.js.map +1 -1
- package/package.json +15 -12
- package/dist/codemode/sandbox-factory.d.ts +0 -72
- package/dist/codemode/sandbox-factory.d.ts.map +0 -1
- package/dist/codemode/sandbox-factory.js +0 -88
- package/dist/codemode/sandbox-factory.js.map +0 -1
- package/dist/codemode/worker-sandbox.d.ts +0 -82
- package/dist/codemode/worker-sandbox.d.ts.map +0 -1
- package/dist/codemode/worker-sandbox.js +0 -244
- package/dist/codemode/worker-sandbox.js.map +0 -1
- package/dist/codemode/worker-script.d.ts +0 -8
- package/dist/codemode/worker-script.d.ts.map +0 -1
- package/dist/codemode/worker-script.js +0 -113
- package/dist/codemode/worker-script.js.map +0 -1
|
@@ -79,15 +79,30 @@ function createTextSearchTool(adapter) {
|
|
|
79
79
|
const tsvector = sanitizedCols
|
|
80
80
|
.map((c) => `coalesce(${c}, '')`)
|
|
81
81
|
.join(" || ' ' || ");
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
82
|
+
// Default limit to 100 to prevent large payloads; limit: 0 means no limit
|
|
83
|
+
const limitVal = parsed.limit === 0
|
|
84
|
+
? null
|
|
85
|
+
: parsed.limit !== undefined && parsed.limit > 0
|
|
86
|
+
? parsed.limit
|
|
87
|
+
: 100;
|
|
88
|
+
const limitClause = limitVal !== null ? ` LIMIT ${String(limitVal)}` : "";
|
|
85
89
|
const sql = `SELECT ${selectCols}, ts_rank_cd(to_tsvector('${cfg}', ${tsvector}), plainto_tsquery('${cfg}', $1)) as rank
|
|
86
90
|
FROM ${tableName}
|
|
87
91
|
WHERE to_tsvector('${cfg}', ${tsvector}) @@ plainto_tsquery('${cfg}', $1)
|
|
88
92
|
ORDER BY rank DESC${limitClause}`;
|
|
89
93
|
const result = await adapter.executeQuery(sql, [parsed.query]);
|
|
90
|
-
|
|
94
|
+
const count = result.rows?.length ?? 0;
|
|
95
|
+
const truncated = limitVal !== null && count === limitVal;
|
|
96
|
+
return {
|
|
97
|
+
rows: result.rows,
|
|
98
|
+
count,
|
|
99
|
+
...(truncated
|
|
100
|
+
? {
|
|
101
|
+
truncated: true,
|
|
102
|
+
hint: `Results limited to ${String(limitVal)}. Use limit: 0 for all rows.`,
|
|
103
|
+
}
|
|
104
|
+
: {}),
|
|
105
|
+
};
|
|
91
106
|
}
|
|
92
107
|
catch (error) {
|
|
93
108
|
if (error instanceof ZodError) {
|
|
@@ -172,15 +187,30 @@ function createTextRankTool(adapter) {
|
|
|
172
187
|
const tsvector = sanitizedCols
|
|
173
188
|
.map((c) => `coalesce(${c}, '')`)
|
|
174
189
|
.join(" || ' ' || ");
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
190
|
+
// Default limit to 100 to prevent large payloads; limit: 0 means no limit
|
|
191
|
+
const limitVal = parsed.limit === 0
|
|
192
|
+
? null
|
|
193
|
+
: parsed.limit !== undefined && parsed.limit > 0
|
|
194
|
+
? parsed.limit
|
|
195
|
+
: 100;
|
|
196
|
+
const limitClause = limitVal !== null ? ` LIMIT ${String(limitVal)}` : "";
|
|
178
197
|
const sql = `SELECT ${selectCols}, ts_rank_cd(to_tsvector('${cfg}', ${tsvector}), plainto_tsquery('${cfg}', $1), ${String(norm)}) as rank
|
|
179
198
|
FROM ${tableName}
|
|
180
199
|
WHERE to_tsvector('${cfg}', ${tsvector}) @@ plainto_tsquery('${cfg}', $1)
|
|
181
200
|
ORDER BY rank DESC${limitClause}`;
|
|
182
201
|
const result = await adapter.executeQuery(sql, [parsed.query]);
|
|
183
|
-
|
|
202
|
+
const count = result.rows?.length ?? 0;
|
|
203
|
+
const truncated = limitVal !== null && count === limitVal;
|
|
204
|
+
return {
|
|
205
|
+
rows: result.rows,
|
|
206
|
+
count,
|
|
207
|
+
...(truncated
|
|
208
|
+
? {
|
|
209
|
+
truncated: true,
|
|
210
|
+
hint: `Results limited to ${String(limitVal)}. Use limit: 0 for all rows.`,
|
|
211
|
+
}
|
|
212
|
+
: {}),
|
|
213
|
+
};
|
|
184
214
|
}
|
|
185
215
|
catch (error) {
|
|
186
216
|
if (error instanceof ZodError) {
|
|
@@ -212,8 +242,13 @@ function createTrigramSimilarityTool(adapter) {
|
|
|
212
242
|
try {
|
|
213
243
|
const parsed = TrigramSimilaritySchema.parse(params);
|
|
214
244
|
const thresh = parsed.threshold ?? 0.3;
|
|
215
|
-
// Default limit to 100 to prevent large payloads
|
|
216
|
-
const limitVal = parsed.limit
|
|
245
|
+
// Default limit to 100 to prevent large payloads; limit: 0 means no limit
|
|
246
|
+
const limitVal = parsed.limit === 0
|
|
247
|
+
? null
|
|
248
|
+
: parsed.limit !== undefined && parsed.limit > 0
|
|
249
|
+
? parsed.limit
|
|
250
|
+
: 100;
|
|
251
|
+
const limitClause = limitVal !== null ? ` LIMIT ${String(limitVal)}` : "";
|
|
217
252
|
// The preprocessor guarantees table is set (converts tableName → table)
|
|
218
253
|
const resolvedTable = parsed.table ?? parsed.tableName;
|
|
219
254
|
if (!resolvedTable) {
|
|
@@ -233,9 +268,20 @@ function createTrigramSimilarityTool(adapter) {
|
|
|
233
268
|
const sql = `SELECT ${selectCols}, similarity(${columnName}, $1) as similarity
|
|
234
269
|
FROM ${tableName}
|
|
235
270
|
WHERE similarity(${columnName}, $1) > ${String(thresh)}${additionalWhere}
|
|
236
|
-
ORDER BY similarity DESC
|
|
271
|
+
ORDER BY similarity DESC${limitClause}`;
|
|
237
272
|
const result = await adapter.executeQuery(sql, [parsed.value]);
|
|
238
|
-
|
|
273
|
+
const count = result.rows?.length ?? 0;
|
|
274
|
+
const truncated = limitVal !== null && count === limitVal;
|
|
275
|
+
return {
|
|
276
|
+
rows: result.rows,
|
|
277
|
+
count,
|
|
278
|
+
...(truncated
|
|
279
|
+
? {
|
|
280
|
+
truncated: true,
|
|
281
|
+
hint: `Results limited to ${String(limitVal)}. Use limit: 0 for all rows.`,
|
|
282
|
+
}
|
|
283
|
+
: {}),
|
|
284
|
+
};
|
|
239
285
|
}
|
|
240
286
|
catch (error) {
|
|
241
287
|
if (error instanceof ZodError) {
|
|
@@ -309,8 +355,13 @@ function createFuzzyMatchTool(adapter) {
|
|
|
309
355
|
}
|
|
310
356
|
const method = rawMethod;
|
|
311
357
|
const maxDist = parsed.maxDistance ?? 3;
|
|
312
|
-
// Default limit to 100 to prevent large payloads
|
|
313
|
-
const limitVal = parsed.limit
|
|
358
|
+
// Default limit to 100 to prevent large payloads; limit: 0 means no limit
|
|
359
|
+
const limitVal = parsed.limit === 0
|
|
360
|
+
? null
|
|
361
|
+
: parsed.limit !== undefined && parsed.limit > 0
|
|
362
|
+
? parsed.limit
|
|
363
|
+
: 100;
|
|
364
|
+
const limitClause = limitVal !== null ? ` LIMIT ${String(limitVal)}` : "";
|
|
314
365
|
// The preprocessor guarantees table is set (converts tableName → table)
|
|
315
366
|
const resolvedTable = parsed.table ?? parsed.tableName;
|
|
316
367
|
if (!resolvedTable) {
|
|
@@ -329,16 +380,27 @@ function createFuzzyMatchTool(adapter) {
|
|
|
329
380
|
: "";
|
|
330
381
|
let sql;
|
|
331
382
|
if (method === "soundex") {
|
|
332
|
-
sql = `SELECT ${selectCols}, soundex(${columnName}) as code FROM ${tableName} WHERE soundex(${columnName}) = soundex($1)${additionalWhere}
|
|
383
|
+
sql = `SELECT ${selectCols}, soundex(${columnName}) as code FROM ${tableName} WHERE soundex(${columnName}) = soundex($1)${additionalWhere}${limitClause}`;
|
|
333
384
|
}
|
|
334
385
|
else if (method === "metaphone") {
|
|
335
|
-
sql = `SELECT ${selectCols}, metaphone(${columnName}, 10) as code FROM ${tableName} WHERE metaphone(${columnName}, 10) = metaphone($1, 10)${additionalWhere}
|
|
386
|
+
sql = `SELECT ${selectCols}, metaphone(${columnName}, 10) as code FROM ${tableName} WHERE metaphone(${columnName}, 10) = metaphone($1, 10)${additionalWhere}${limitClause}`;
|
|
336
387
|
}
|
|
337
388
|
else {
|
|
338
|
-
sql = `SELECT ${selectCols}, levenshtein(${columnName}, $1) as distance FROM ${tableName} WHERE levenshtein(${columnName}, $1) <= ${String(maxDist)}${additionalWhere} ORDER BY distance
|
|
389
|
+
sql = `SELECT ${selectCols}, levenshtein(${columnName}, $1) as distance FROM ${tableName} WHERE levenshtein(${columnName}, $1) <= ${String(maxDist)}${additionalWhere} ORDER BY distance${limitClause}`;
|
|
339
390
|
}
|
|
340
391
|
const result = await adapter.executeQuery(sql, [parsed.value]);
|
|
341
|
-
|
|
392
|
+
const count = result.rows?.length ?? 0;
|
|
393
|
+
const truncated = limitVal !== null && count === limitVal;
|
|
394
|
+
return {
|
|
395
|
+
rows: result.rows,
|
|
396
|
+
count,
|
|
397
|
+
...(truncated
|
|
398
|
+
? {
|
|
399
|
+
truncated: true,
|
|
400
|
+
hint: `Results limited to ${String(limitVal)}. Use limit: 0 for all rows.`,
|
|
401
|
+
}
|
|
402
|
+
: {}),
|
|
403
|
+
};
|
|
342
404
|
}
|
|
343
405
|
catch (error) {
|
|
344
406
|
if (error instanceof ZodError) {
|
|
@@ -386,12 +448,27 @@ function createRegexpMatchTool(adapter) {
|
|
|
386
448
|
const additionalWhere = parsed.where
|
|
387
449
|
? ` AND (${sanitizeWhereClause(parsed.where)})`
|
|
388
450
|
: "";
|
|
389
|
-
// Default limit to 100 to prevent large payloads
|
|
390
|
-
const limitVal = parsed.limit
|
|
391
|
-
|
|
451
|
+
// Default limit to 100 to prevent large payloads; limit: 0 means no limit
|
|
452
|
+
const limitVal = parsed.limit === 0
|
|
453
|
+
? null
|
|
454
|
+
: parsed.limit !== undefined && parsed.limit > 0
|
|
455
|
+
? parsed.limit
|
|
456
|
+
: 100;
|
|
457
|
+
const limitClause = limitVal !== null ? ` LIMIT ${String(limitVal)}` : "";
|
|
392
458
|
const sql = `SELECT ${selectCols} FROM ${tableName} WHERE ${columnName} ${op} $1${additionalWhere}${limitClause}`;
|
|
393
459
|
const result = await adapter.executeQuery(sql, [parsed.pattern]);
|
|
394
|
-
|
|
460
|
+
const count = result.rows?.length ?? 0;
|
|
461
|
+
const truncated = limitVal !== null && count === limitVal;
|
|
462
|
+
return {
|
|
463
|
+
rows: result.rows,
|
|
464
|
+
count,
|
|
465
|
+
...(truncated
|
|
466
|
+
? {
|
|
467
|
+
truncated: true,
|
|
468
|
+
hint: `Results limited to ${String(limitVal)}. Use limit: 0 for all rows.`,
|
|
469
|
+
}
|
|
470
|
+
: {}),
|
|
471
|
+
};
|
|
395
472
|
}
|
|
396
473
|
catch (error) {
|
|
397
474
|
if (error instanceof ZodError) {
|
|
@@ -463,12 +540,27 @@ function createLikeSearchTool(adapter) {
|
|
|
463
540
|
const additionalWhere = parsed.where
|
|
464
541
|
? ` AND (${sanitizeWhereClause(parsed.where)})`
|
|
465
542
|
: "";
|
|
466
|
-
// Default limit to 100 to prevent large payloads
|
|
467
|
-
const limitVal = parsed.limit
|
|
468
|
-
|
|
543
|
+
// Default limit to 100 to prevent large payloads; limit: 0 means no limit
|
|
544
|
+
const limitVal = parsed.limit === 0
|
|
545
|
+
? null
|
|
546
|
+
: parsed.limit !== undefined && parsed.limit > 0
|
|
547
|
+
? parsed.limit
|
|
548
|
+
: 100;
|
|
549
|
+
const limitClause = limitVal !== null ? ` LIMIT ${String(limitVal)}` : "";
|
|
469
550
|
const sql = `SELECT ${selectCols} FROM ${tableName} WHERE ${columnName} ${op} $1${additionalWhere}${limitClause}`;
|
|
470
551
|
const result = await adapter.executeQuery(sql, [parsed.pattern]);
|
|
471
|
-
|
|
552
|
+
const count = result.rows?.length ?? 0;
|
|
553
|
+
const truncated = limitVal !== null && count === limitVal;
|
|
554
|
+
return {
|
|
555
|
+
rows: result.rows,
|
|
556
|
+
count,
|
|
557
|
+
...(truncated
|
|
558
|
+
? {
|
|
559
|
+
truncated: true,
|
|
560
|
+
hint: `Results limited to ${String(limitVal)}. Use limit: 0 for all rows.`,
|
|
561
|
+
}
|
|
562
|
+
: {}),
|
|
563
|
+
};
|
|
472
564
|
}
|
|
473
565
|
catch (error) {
|
|
474
566
|
if (error instanceof ZodError) {
|
|
@@ -561,14 +653,29 @@ function createTextHeadlineTool(adapter) {
|
|
|
561
653
|
const selectCols = parsed.select !== undefined && parsed.select.length > 0
|
|
562
654
|
? sanitizeIdentifiers(parsed.select).join(", ") + ", "
|
|
563
655
|
: "";
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
656
|
+
// Default limit to 100 to prevent large payloads; limit: 0 means no limit
|
|
657
|
+
const limitVal = parsed.limit === 0
|
|
658
|
+
? null
|
|
659
|
+
: parsed.limit !== undefined && parsed.limit > 0
|
|
660
|
+
? parsed.limit
|
|
661
|
+
: 100;
|
|
662
|
+
const limitClause = limitVal !== null ? ` LIMIT ${String(limitVal)}` : "";
|
|
567
663
|
const sql = `SELECT ${selectCols}ts_headline('${cfg}', ${columnName}, plainto_tsquery('${cfg}', $1), '${opts}') as headline
|
|
568
664
|
FROM ${tableName}
|
|
569
665
|
WHERE to_tsvector('${cfg}', ${columnName}) @@ plainto_tsquery('${cfg}', $1)${limitClause}`;
|
|
570
666
|
const result = await adapter.executeQuery(sql, [parsed.query]);
|
|
571
|
-
|
|
667
|
+
const count = result.rows?.length ?? 0;
|
|
668
|
+
const truncated = limitVal !== null && count === limitVal;
|
|
669
|
+
return {
|
|
670
|
+
rows: result.rows,
|
|
671
|
+
count,
|
|
672
|
+
...(truncated
|
|
673
|
+
? {
|
|
674
|
+
truncated: true,
|
|
675
|
+
hint: `Results limited to ${String(limitVal)}. Use limit: 0 for all rows.`,
|
|
676
|
+
}
|
|
677
|
+
: {}),
|
|
678
|
+
};
|
|
572
679
|
}
|
|
573
680
|
catch (error) {
|
|
574
681
|
if (error instanceof ZodError) {
|
|
@@ -681,11 +788,27 @@ function createTextNormalizeTool(adapter) {
|
|
|
681
788
|
annotations: readOnly("Text Normalize"),
|
|
682
789
|
icons: getToolIcons("text", readOnly("Text Normalize")),
|
|
683
790
|
handler: async (params, _context) => {
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
791
|
+
try {
|
|
792
|
+
const parsed = NormalizeSchema.parse(params ?? {});
|
|
793
|
+
// Ensure unaccent extension is available
|
|
794
|
+
await adapter.executeQuery("CREATE EXTENSION IF NOT EXISTS unaccent");
|
|
795
|
+
const result = await adapter.executeQuery(`SELECT unaccent($1) as normalized`, [parsed.text]);
|
|
796
|
+
return { normalized: result.rows?.[0]?.["normalized"] };
|
|
797
|
+
}
|
|
798
|
+
catch (error) {
|
|
799
|
+
if (error instanceof ZodError) {
|
|
800
|
+
return {
|
|
801
|
+
success: false,
|
|
802
|
+
error: `pg_text_normalize validation error: ${error.issues.map((e) => e.message).join(", ")}`,
|
|
803
|
+
};
|
|
804
|
+
}
|
|
805
|
+
return {
|
|
806
|
+
success: false,
|
|
807
|
+
error: formatPostgresError(error, {
|
|
808
|
+
tool: "pg_text_normalize",
|
|
809
|
+
}),
|
|
810
|
+
};
|
|
811
|
+
}
|
|
689
812
|
},
|
|
690
813
|
};
|
|
691
814
|
}
|
|
@@ -709,95 +832,109 @@ function createTextSentimentTool(_adapter) {
|
|
|
709
832
|
annotations: readOnly("Text Sentiment"),
|
|
710
833
|
icons: getToolIcons("text", readOnly("Text Sentiment")),
|
|
711
834
|
handler: (params, _context) => {
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
835
|
+
try {
|
|
836
|
+
const parsed = SentimentSchema.parse(params ?? {});
|
|
837
|
+
const text = parsed.text.toLowerCase();
|
|
838
|
+
const positiveWords = [
|
|
839
|
+
"good",
|
|
840
|
+
"great",
|
|
841
|
+
"excellent",
|
|
842
|
+
"amazing",
|
|
843
|
+
"wonderful",
|
|
844
|
+
"fantastic",
|
|
845
|
+
"love",
|
|
846
|
+
"happy",
|
|
847
|
+
"positive",
|
|
848
|
+
"best",
|
|
849
|
+
"beautiful",
|
|
850
|
+
"awesome",
|
|
851
|
+
"perfect",
|
|
852
|
+
"nice",
|
|
853
|
+
"helpful",
|
|
854
|
+
"thank",
|
|
855
|
+
"thanks",
|
|
856
|
+
"pleased",
|
|
857
|
+
"satisfied",
|
|
858
|
+
"recommend",
|
|
859
|
+
"enjoy",
|
|
860
|
+
"impressive",
|
|
861
|
+
"brilliant",
|
|
862
|
+
];
|
|
863
|
+
const negativeWords = [
|
|
864
|
+
"bad",
|
|
865
|
+
"terrible",
|
|
866
|
+
"awful",
|
|
867
|
+
"horrible",
|
|
868
|
+
"worst",
|
|
869
|
+
"hate",
|
|
870
|
+
"angry",
|
|
871
|
+
"disappointed",
|
|
872
|
+
"poor",
|
|
873
|
+
"wrong",
|
|
874
|
+
"problem",
|
|
875
|
+
"issue",
|
|
876
|
+
"fail",
|
|
877
|
+
"failed",
|
|
878
|
+
"broken",
|
|
879
|
+
"useless",
|
|
880
|
+
"waste",
|
|
881
|
+
"frustrating",
|
|
882
|
+
"annoyed",
|
|
883
|
+
"unhappy",
|
|
884
|
+
"negative",
|
|
885
|
+
"complaint",
|
|
886
|
+
"slow",
|
|
887
|
+
];
|
|
888
|
+
const words = text.split(/\s+/);
|
|
889
|
+
const matchedPositive = words
|
|
890
|
+
.map((w) => w.replace(/[^a-z]/g, ""))
|
|
891
|
+
.filter((w) => positiveWords.includes(w));
|
|
892
|
+
const matchedNegative = words
|
|
893
|
+
.map((w) => w.replace(/[^a-z]/g, ""))
|
|
894
|
+
.filter((w) => negativeWords.includes(w));
|
|
895
|
+
const positiveScore = matchedPositive.length;
|
|
896
|
+
const negativeScore = matchedNegative.length;
|
|
897
|
+
const totalScore = positiveScore - negativeScore;
|
|
898
|
+
let sentiment;
|
|
899
|
+
if (totalScore > 2)
|
|
900
|
+
sentiment = "very_positive";
|
|
901
|
+
else if (totalScore > 0)
|
|
902
|
+
sentiment = "positive";
|
|
903
|
+
else if (totalScore < -2)
|
|
904
|
+
sentiment = "very_negative";
|
|
905
|
+
else if (totalScore < 0)
|
|
906
|
+
sentiment = "negative";
|
|
907
|
+
else
|
|
908
|
+
sentiment = "neutral";
|
|
909
|
+
const result = {
|
|
910
|
+
sentiment,
|
|
911
|
+
score: totalScore,
|
|
912
|
+
positiveCount: positiveScore,
|
|
913
|
+
negativeCount: negativeScore,
|
|
914
|
+
confidence: positiveScore + negativeScore > 3
|
|
915
|
+
? "high"
|
|
916
|
+
: positiveScore + negativeScore > 1
|
|
917
|
+
? "medium"
|
|
918
|
+
: "low",
|
|
919
|
+
};
|
|
920
|
+
if (parsed.returnWords) {
|
|
921
|
+
result.matchedPositive = matchedPositive;
|
|
922
|
+
result.matchedNegative = matchedNegative;
|
|
923
|
+
}
|
|
924
|
+
return Promise.resolve(result);
|
|
925
|
+
}
|
|
926
|
+
catch (error) {
|
|
927
|
+
if (error instanceof ZodError) {
|
|
928
|
+
return Promise.resolve({
|
|
929
|
+
success: false,
|
|
930
|
+
error: `pg_text_sentiment validation error: ${error.issues.map((e) => e.message).join(", ")}`,
|
|
931
|
+
});
|
|
932
|
+
}
|
|
933
|
+
return Promise.resolve({
|
|
934
|
+
success: false,
|
|
935
|
+
error: error instanceof Error ? error.message : "Unknown error occurred",
|
|
936
|
+
});
|
|
799
937
|
}
|
|
800
|
-
return Promise.resolve(result);
|
|
801
938
|
},
|
|
802
939
|
};
|
|
803
940
|
}
|
|
@@ -821,10 +958,26 @@ function createTextToVectorTool(adapter) {
|
|
|
821
958
|
annotations: readOnly("Text to Vector"),
|
|
822
959
|
icons: getToolIcons("text", readOnly("Text to Vector")),
|
|
823
960
|
handler: async (params, _context) => {
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
961
|
+
try {
|
|
962
|
+
const parsed = ToVectorSchema.parse(params ?? {});
|
|
963
|
+
const cfg = parsed.config ?? "english";
|
|
964
|
+
const result = await adapter.executeQuery(`SELECT to_tsvector($1, $2) as vector`, [cfg, parsed.text]);
|
|
965
|
+
return { vector: result.rows?.[0]?.["vector"] };
|
|
966
|
+
}
|
|
967
|
+
catch (error) {
|
|
968
|
+
if (error instanceof ZodError) {
|
|
969
|
+
return {
|
|
970
|
+
success: false,
|
|
971
|
+
error: `pg_text_to_vector validation error: ${error.issues.map((e) => e.message).join(", ")}`,
|
|
972
|
+
};
|
|
973
|
+
}
|
|
974
|
+
return {
|
|
975
|
+
success: false,
|
|
976
|
+
error: formatPostgresError(error, {
|
|
977
|
+
tool: "pg_text_to_vector",
|
|
978
|
+
}),
|
|
979
|
+
};
|
|
980
|
+
}
|
|
828
981
|
},
|
|
829
982
|
};
|
|
830
983
|
}
|
|
@@ -852,22 +1005,38 @@ function createTextToQueryTool(adapter) {
|
|
|
852
1005
|
annotations: readOnly("Text to Query"),
|
|
853
1006
|
icons: getToolIcons("text", readOnly("Text to Query")),
|
|
854
1007
|
handler: async (params, _context) => {
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
1008
|
+
try {
|
|
1009
|
+
const parsed = ToQuerySchema.parse(params ?? {});
|
|
1010
|
+
const cfg = parsed.config ?? "english";
|
|
1011
|
+
const mode = parsed.mode ?? "plain";
|
|
1012
|
+
let fn;
|
|
1013
|
+
switch (mode) {
|
|
1014
|
+
case "phrase":
|
|
1015
|
+
fn = "phraseto_tsquery";
|
|
1016
|
+
break;
|
|
1017
|
+
case "websearch":
|
|
1018
|
+
fn = "websearch_to_tsquery";
|
|
1019
|
+
break;
|
|
1020
|
+
default:
|
|
1021
|
+
fn = "plainto_tsquery";
|
|
1022
|
+
}
|
|
1023
|
+
const result = await adapter.executeQuery(`SELECT ${fn}($1, $2) as query`, [cfg, parsed.text]);
|
|
1024
|
+
return { query: result.rows?.[0]?.["query"], mode };
|
|
1025
|
+
}
|
|
1026
|
+
catch (error) {
|
|
1027
|
+
if (error instanceof ZodError) {
|
|
1028
|
+
return {
|
|
1029
|
+
success: false,
|
|
1030
|
+
error: `pg_text_to_query validation error: ${error.issues.map((e) => e.message).join(", ")}`,
|
|
1031
|
+
};
|
|
1032
|
+
}
|
|
1033
|
+
return {
|
|
1034
|
+
success: false,
|
|
1035
|
+
error: formatPostgresError(error, {
|
|
1036
|
+
tool: "pg_text_to_query",
|
|
1037
|
+
}),
|
|
1038
|
+
};
|
|
868
1039
|
}
|
|
869
|
-
const result = await adapter.executeQuery(`SELECT ${fn}($1, $2) as query`, [cfg, parsed.text]);
|
|
870
|
-
return { query: result.rows?.[0]?.["query"], mode };
|
|
871
1040
|
},
|
|
872
1041
|
};
|
|
873
1042
|
}
|
|
@@ -884,8 +1053,9 @@ function createTextSearchConfigTool(adapter) {
|
|
|
884
1053
|
annotations: readOnly("Search Configurations"),
|
|
885
1054
|
icons: getToolIcons("text", readOnly("Search Configurations")),
|
|
886
1055
|
handler: async (_params, _context) => {
|
|
887
|
-
|
|
888
|
-
|
|
1056
|
+
try {
|
|
1057
|
+
const result = await adapter.executeQuery(`
|
|
1058
|
+
SELECT
|
|
889
1059
|
c.cfgname as name,
|
|
890
1060
|
n.nspname as schema,
|
|
891
1061
|
obj_description(c.oid, 'pg_ts_config') as description
|
|
@@ -893,10 +1063,19 @@ function createTextSearchConfigTool(adapter) {
|
|
|
893
1063
|
JOIN pg_namespace n ON n.oid = c.cfgnamespace
|
|
894
1064
|
ORDER BY c.cfgname
|
|
895
1065
|
`);
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
1066
|
+
return {
|
|
1067
|
+
configs: result.rows ?? [],
|
|
1068
|
+
count: result.rows?.length ?? 0,
|
|
1069
|
+
};
|
|
1070
|
+
}
|
|
1071
|
+
catch (error) {
|
|
1072
|
+
return {
|
|
1073
|
+
success: false,
|
|
1074
|
+
error: formatPostgresError(error, {
|
|
1075
|
+
tool: "pg_text_search_config",
|
|
1076
|
+
}),
|
|
1077
|
+
};
|
|
1078
|
+
}
|
|
900
1079
|
},
|
|
901
1080
|
};
|
|
902
1081
|
}
|