db-mcp 3.0.2 → 5.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 +112 -75
- package/dist/.tsbuildinfo +1 -1
- package/dist/adapters/database-adapter.d.ts +11 -1
- package/dist/adapters/database-adapter.d.ts.map +1 -1
- package/dist/adapters/registration/resources.d.ts.map +1 -1
- package/dist/adapters/registration/tools.d.ts.map +1 -1
- package/dist/adapters/sqlite/prompts/analysis.d.ts.map +1 -1
- package/dist/adapters/sqlite/query-executor.d.ts.map +1 -1
- package/dist/adapters/sqlite/read-write-lock.d.ts +49 -0
- package/dist/adapters/sqlite/read-write-lock.d.ts.map +1 -0
- package/dist/adapters/sqlite/resources.d.ts +1 -1
- package/dist/adapters/sqlite/resources.d.ts.map +1 -1
- package/dist/adapters/sqlite/schemas/admin.d.ts +33 -19
- package/dist/adapters/sqlite/schemas/admin.d.ts.map +1 -1
- package/dist/adapters/sqlite/schemas/core.d.ts +96 -0
- package/dist/adapters/sqlite/schemas/core.d.ts.map +1 -1
- package/dist/adapters/sqlite/schemas/fts.d.ts +4 -0
- package/dist/adapters/sqlite/schemas/fts.d.ts.map +1 -1
- package/dist/adapters/sqlite/schemas/introspection.d.ts +25 -15
- package/dist/adapters/sqlite/schemas/introspection.d.ts.map +1 -1
- package/dist/adapters/sqlite/schemas/migration.d.ts +2 -2
- package/dist/adapters/sqlite/schemas/migration.d.ts.map +1 -1
- package/dist/adapters/sqlite/schemas/spatialite.d.ts +1 -0
- package/dist/adapters/sqlite/schemas/spatialite.d.ts.map +1 -1
- package/dist/adapters/sqlite/schemas/text.d.ts +36 -0
- package/dist/adapters/sqlite/schemas/text.d.ts.map +1 -1
- package/dist/adapters/sqlite/sqlite-adapter.d.ts +6 -0
- package/dist/adapters/sqlite/sqlite-adapter.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/admin/backup/create.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/admin/backup/dump.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/admin/backup/restore.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/admin/index.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/admin/pragma.d.ts +0 -4
- package/dist/adapters/sqlite/tools/admin/pragma.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/admin/verify.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/codemode.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/core/convenience.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/core/index.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/core/queries.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/core/tables.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/core/versioning.d.ts +19 -0
- package/dist/adapters/sqlite/tools/core/versioning.d.ts.map +1 -0
- package/dist/adapters/sqlite/tools/fts.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/introspection/diagnostics/indexes.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/introspection/graph/tools.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/json-helpers/read.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/json-operations/crud.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/json-operations/query.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/migration/helpers.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/text/helpers.d.ts +9 -0
- package/dist/adapters/sqlite/tools/text/helpers.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/text/index.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/text/search.d.ts +4 -0
- package/dist/adapters/sqlite/tools/text/search.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/vector/metadata.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/vector/search.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/vector/storage.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/virtual/vtable/analyze-csv.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/virtual/vtable/csv.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/virtual/vtable/info.d.ts.map +1 -1
- package/dist/adapters/sqlite/types.d.ts +5 -1
- package/dist/adapters/sqlite/types.d.ts.map +1 -1
- package/dist/adapters/sqlite-native/index.d.ts +1 -1
- package/dist/adapters/sqlite-native/index.d.ts.map +1 -1
- package/dist/adapters/sqlite-native/native-sqlite-adapter.d.ts.map +1 -1
- package/dist/adapters/sqlite-native/tools/spatialite/tools.d.ts.map +1 -1
- package/dist/adapters/sqlite-native/tools/window/helpers.d.ts +52 -0
- package/dist/adapters/sqlite-native/tools/window/helpers.d.ts.map +1 -0
- package/dist/adapters/sqlite-native/tools/window/index.d.ts +7 -0
- package/dist/adapters/sqlite-native/tools/window/index.d.ts.map +1 -0
- package/dist/adapters/sqlite-native/tools/window/lag-lead.d.ts +7 -0
- package/dist/adapters/sqlite-native/tools/window/lag-lead.d.ts.map +1 -0
- package/dist/adapters/sqlite-native/tools/window/moving-average.d.ts +7 -0
- package/dist/adapters/sqlite-native/tools/window/moving-average.d.ts.map +1 -0
- package/dist/adapters/sqlite-native/tools/window/ntile.d.ts +7 -0
- package/dist/adapters/sqlite-native/tools/window/ntile.d.ts.map +1 -0
- package/dist/adapters/sqlite-native/tools/window/rank.d.ts +7 -0
- package/dist/adapters/sqlite-native/tools/window/rank.d.ts.map +1 -0
- package/dist/adapters/sqlite-native/tools/window/row-number.d.ts +7 -0
- package/dist/adapters/sqlite-native/tools/window/row-number.d.ts.map +1 -0
- package/dist/adapters/sqlite-native/tools/window/running-total.d.ts +7 -0
- package/dist/adapters/sqlite-native/tools/window/running-total.d.ts.map +1 -0
- package/dist/adapters/sqlite-native/tools/window/schemas.d.ts +159 -0
- package/dist/adapters/sqlite-native/tools/window/schemas.d.ts.map +1 -0
- package/dist/adapters/sqlite-native/transaction-methods.d.ts.map +1 -1
- package/dist/audit/interceptor.d.ts.map +1 -1
- package/dist/audit/logger.d.ts +26 -25
- package/dist/audit/logger.d.ts.map +1 -1
- package/dist/auth/authorization-server-discovery.d.ts.map +1 -1
- package/dist/auth/scopes/mapping.d.ts.map +1 -1
- package/dist/auth/token-validator.d.ts.map +1 -1
- package/dist/{chunk-W5WQVNVX.js → chunk-27C5EE6U.js} +23 -17
- package/dist/chunk-2TYICG7B.js +1183 -0
- package/dist/{chunk-37G4DLL6.js → chunk-LLIAIJPO.js} +1146 -539
- package/dist/{chunk-NV34JSQM.js → chunk-UE7GVOBV.js} +1757 -1331
- package/dist/{chunk-L552U3QS.js → chunk-XLIYO3YA.js} +401 -77
- package/dist/cli.js +116 -11
- package/dist/codemode/api-constants.d.ts.map +1 -1
- package/dist/codemode/api.d.ts.map +1 -1
- package/dist/codemode/sandbox-factory.d.ts.map +1 -1
- package/dist/codemode/sandbox.d.ts +0 -3
- package/dist/codemode/sandbox.d.ts.map +1 -1
- package/dist/codemode/security.d.ts.map +1 -1
- package/dist/codemode/types.d.ts +2 -0
- package/dist/codemode/types.d.ts.map +1 -1
- package/dist/constants/server-instructions.d.ts +1 -1
- package/dist/constants/server-instructions.d.ts.map +1 -1
- package/dist/filtering/tool-constants.d.ts +11 -11
- package/dist/filtering/tool-constants.d.ts.map +1 -1
- package/dist/{http-HWTUVFIA.js → http-ZDMK46QU.js} +195 -32
- package/dist/index.js +4 -4
- package/dist/observability/metrics.d.ts +36 -0
- package/dist/observability/metrics.d.ts.map +1 -0
- package/dist/observability/system-db.d.ts +13 -0
- package/dist/observability/system-db.d.ts.map +1 -0
- package/dist/server/mcp-server.d.ts +3 -0
- package/dist/server/mcp-server.d.ts.map +1 -1
- package/dist/server/registration/admin-tools.d.ts +6 -0
- package/dist/server/registration/admin-tools.d.ts.map +1 -0
- package/dist/server/registration/audit-tools/backup.d.ts +8 -0
- package/dist/server/registration/audit-tools/backup.d.ts.map +1 -0
- package/dist/server/registration/audit-tools/helpers.d.ts +11 -0
- package/dist/server/registration/audit-tools/helpers.d.ts.map +1 -0
- package/dist/server/registration/audit-tools/index.d.ts +4 -0
- package/dist/server/registration/audit-tools/index.d.ts.map +1 -0
- package/dist/server/registration/audit-tools/resource.d.ts +8 -0
- package/dist/server/registration/audit-tools/resource.d.ts.map +1 -0
- package/dist/server/registration/audit-tools/search.d.ts +7 -0
- package/dist/server/registration/audit-tools/search.d.ts.map +1 -0
- package/dist/server/registration/help-resources.d.ts.map +1 -1
- package/dist/server/registration/index.d.ts +3 -1
- package/dist/server/registration/index.d.ts.map +1 -1
- package/dist/server/registration/observability-resources.d.ts +11 -0
- package/dist/server/registration/observability-resources.d.ts.map +1 -0
- package/dist/server/subscription-manager.d.ts +35 -0
- package/dist/server/subscription-manager.d.ts.map +1 -0
- package/dist/{sqlite-TB56Z7G3.js → sqlite-XWZPEZJO.js} +195 -19
- package/dist/{sqlite-native-IF75BB3O.js → sqlite-native-5GQ3WKCZ.js} +311 -147
- package/dist/transports/http/middleware.d.ts.map +1 -1
- package/dist/transports/http/oauth.d.ts.map +1 -1
- package/dist/transports/http/sessions/legacy-sse.d.ts.map +1 -1
- package/dist/transports/http/sessions/stateful.d.ts +5 -1
- package/dist/transports/http/sessions/stateful.d.ts.map +1 -1
- package/dist/transports/http/transport.d.ts +2 -0
- package/dist/transports/http/transport.d.ts.map +1 -1
- package/dist/transports/http/types.d.ts +11 -0
- package/dist/transports/http/types.d.ts.map +1 -1
- package/dist/types/auth.d.ts +4 -0
- package/dist/types/auth.d.ts.map +1 -1
- package/dist/types/server.d.ts +5 -0
- package/dist/types/server.d.ts.map +1 -1
- package/dist/utils/annotations.d.ts +8 -0
- package/dist/utils/annotations.d.ts.map +1 -1
- package/dist/utils/errors/categories.d.ts +16 -11
- package/dist/utils/errors/categories.d.ts.map +1 -1
- package/dist/utils/errors/classes.d.ts +37 -0
- package/dist/utils/errors/classes.d.ts.map +1 -1
- package/dist/utils/errors/format.d.ts +2 -2
- package/dist/utils/errors/format.d.ts.map +1 -1
- package/dist/utils/errors/index.d.ts +1 -1
- package/dist/utils/errors/index.d.ts.map +1 -1
- package/dist/utils/errors/suggestions.d.ts +1 -0
- package/dist/utils/errors/suggestions.d.ts.map +1 -1
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/logger/types.d.ts +1 -1
- package/dist/utils/logger/types.d.ts.map +1 -1
- package/dist/utils/security-utils.d.ts +29 -0
- package/dist/utils/security-utils.d.ts.map +1 -0
- package/dist/utils/stream-utils.d.ts +14 -0
- package/dist/utils/stream-utils.d.ts.map +1 -0
- package/dist/utils/tokens.d.ts +15 -0
- package/dist/utils/tokens.d.ts.map +1 -0
- package/dist/utils/where-clause.d.ts +0 -13
- package/dist/utils/where-clause.d.ts.map +1 -1
- package/package.json +43 -44
- package/dist/adapters/sqlite-native/tools/window.d.ts +0 -7
- package/dist/adapters/sqlite-native/tools/window.d.ts.map +0 -1
- package/dist/chunk-E5IESRTK.js +0 -489
- package/dist/server/registration/audit-tools.d.ts +0 -13
- package/dist/server/registration/audit-tools.d.ts.map +0 -1
- package/dist/utils/insights-manager.d.ts +0 -39
- package/dist/utils/insights-manager.d.ts.map +0 -1
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { RowRecordSchema, WhereConditionSchema,
|
|
2
|
-
import { DatabaseAdapter } from './chunk-
|
|
3
|
-
import { ErrorResponseFields, write, readOnly, VERSION, admin, writeFs, getToolGroupIcon, idempotent } from './chunk-
|
|
4
|
-
import { logger, formatHandlerError, ValidationError, ConfigurationError, ERROR_CODES, ConnectionError, DbMcpError, ResourceNotFoundError, ExtensionNotAvailableError } from './chunk-
|
|
5
|
-
import Database from 'better-sqlite3';
|
|
1
|
+
import { RowRecordSchema, WhereConditionSchema, autoEnableWal, detectAndSetJsonbSupport, SchemaManager, applyCommonPragmas, isDDL, getResourceDefinitions, getPromptDefinitions, resolveAliases, normalizeSqliteParams, translateSqliteError, getCoreTools, getJsonOperationTools, getJsonHelperTools, getTextTools, getStatsTools, getVirtualTools, getVectorTools, getGeoTools, getAdminTools, getIntrospectionTools, getMigrationTools, getCodeModeTools, validateTableExists, sanitizeFtsQuery, FtsHeadlineSchema } from './chunk-UE7GVOBV.js';
|
|
2
|
+
import { DatabaseAdapter } from './chunk-27C5EE6U.js';
|
|
3
|
+
import { ErrorResponseFields, write, readOnly, VERSION, sanitizeIdentifier, buildWhereClause, admin, validateIdentifier, writeFs, getToolGroupIcon, idempotent } from './chunk-2TYICG7B.js';
|
|
4
|
+
import { logger, formatHandlerError, ValidationError, ConfigurationError, ERROR_CODES, ConnectionError, DbMcpError, ErrorCategory, ResourceNotFoundError, ExtensionNotAvailableError } from './chunk-XLIYO3YA.js';
|
|
6
5
|
import { z } from 'zod';
|
|
7
6
|
import { createRequire } from 'module';
|
|
8
7
|
import { fileURLToPath } from 'url';
|
|
@@ -22,7 +21,9 @@ var FtsResultSchema = z.object({
|
|
|
22
21
|
var FtsSearchOutputSchema = z.object({
|
|
23
22
|
success: z.boolean(),
|
|
24
23
|
rowCount: z.number().optional(),
|
|
25
|
-
results: z.array(FtsResultSchema).optional()
|
|
24
|
+
results: z.array(FtsResultSchema).optional(),
|
|
25
|
+
nextCursor: z.string().optional(),
|
|
26
|
+
facets: z.record(z.string(), z.number()).optional()
|
|
26
27
|
}).extend(ErrorResponseFields.shape);
|
|
27
28
|
var FtsRebuildOutputSchema = z.object({
|
|
28
29
|
success: z.boolean(),
|
|
@@ -65,7 +66,11 @@ var FtsSearchSchema = z.object({
|
|
|
65
66
|
return val;
|
|
66
67
|
}, z.number().optional().default(100)),
|
|
67
68
|
highlight: z.boolean().optional().default(false).describe("Include highlighted snippets"),
|
|
68
|
-
includeRowData: z.boolean().optional().default(true).describe("Include full row data in results")
|
|
69
|
+
includeRowData: z.boolean().optional().default(true).describe("Include full row data in results"),
|
|
70
|
+
cursor: z.string().optional().describe("Opaque cursor for pagination"),
|
|
71
|
+
includeFacets: z.boolean().optional().default(false).describe(
|
|
72
|
+
"Return match counts per column (distribution by matched column)"
|
|
73
|
+
)
|
|
69
74
|
});
|
|
70
75
|
var FtsRebuildSchema = z.object({
|
|
71
76
|
table: z.string().describe("FTS table name to rebuild")
|
|
@@ -224,20 +229,46 @@ function createFtsSearchTool(adapter) {
|
|
|
224
229
|
}
|
|
225
230
|
sanitizeIdentifier(input.table);
|
|
226
231
|
await validateTableExists(adapter, input.table);
|
|
232
|
+
let offset = 0;
|
|
233
|
+
if (input.cursor) {
|
|
234
|
+
try {
|
|
235
|
+
const cursorData = JSON.parse(
|
|
236
|
+
Buffer.from(input.cursor, "base64").toString("utf8")
|
|
237
|
+
);
|
|
238
|
+
if (typeof cursorData["offset"] === "number")
|
|
239
|
+
offset = cursorData["offset"];
|
|
240
|
+
} catch {
|
|
241
|
+
}
|
|
242
|
+
}
|
|
227
243
|
let selectClause = input.includeRowData ? "*" : "rowid";
|
|
228
244
|
if (input.highlight) {
|
|
229
245
|
selectClause += `, highlight("${input.table}", 0, '<b>', '</b>') as snippet`;
|
|
230
246
|
}
|
|
231
247
|
if (input.query === "*" || input.query.trim() === "") {
|
|
232
|
-
const sql2 = `SELECT ${selectClause}, NULL as rank FROM "${input.table}" ORDER BY rowid LIMIT ${input.limit}`;
|
|
248
|
+
const sql2 = `SELECT ${selectClause}, NULL as rank FROM "${input.table}" ORDER BY rowid LIMIT ${input.limit} OFFSET ${offset}`;
|
|
233
249
|
const result2 = await adapter.executeReadQuery(sql2, queryParams);
|
|
250
|
+
let nextCursor2;
|
|
251
|
+
if (result2.rows?.length === input.limit) {
|
|
252
|
+
nextCursor2 = Buffer.from(
|
|
253
|
+
JSON.stringify({ offset: offset + input.limit })
|
|
254
|
+
).toString("base64");
|
|
255
|
+
}
|
|
234
256
|
return {
|
|
235
257
|
success: true,
|
|
236
258
|
rowCount: result2.rows?.length ?? 0,
|
|
237
|
-
results: result2.rows
|
|
259
|
+
results: result2.rows,
|
|
260
|
+
nextCursor: nextCursor2
|
|
238
261
|
};
|
|
239
262
|
}
|
|
240
|
-
const
|
|
263
|
+
const sanitizedQuery = sanitizeFtsQuery(input.query);
|
|
264
|
+
if (!sanitizedQuery) {
|
|
265
|
+
return {
|
|
266
|
+
success: true,
|
|
267
|
+
rowCount: 0,
|
|
268
|
+
results: []
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
const queryEscaped = sanitizedQuery.replace(/'/g, "''");
|
|
241
272
|
let matchExpr = `"${input.table}" MATCH '${queryEscaped}'`;
|
|
242
273
|
if (input.columns && input.columns.length > 0) {
|
|
243
274
|
for (const col of input.columns) {
|
|
@@ -246,12 +277,58 @@ function createFtsSearchTool(adapter) {
|
|
|
246
277
|
const colFilter = input.columns.map((c) => `${c}:${queryEscaped}`).join(" OR ");
|
|
247
278
|
matchExpr = `"${input.table}" MATCH '${colFilter}'`;
|
|
248
279
|
}
|
|
249
|
-
|
|
280
|
+
let columnsToFacet = [];
|
|
281
|
+
if (input.includeFacets) {
|
|
282
|
+
const colResult = await adapter.executeReadQuery(
|
|
283
|
+
`PRAGMA table_info("${input.table}")`,
|
|
284
|
+
[]
|
|
285
|
+
);
|
|
286
|
+
const allCols = (colResult.rows ?? []).map((r, i) => ({
|
|
287
|
+
name: String(r["name"]),
|
|
288
|
+
index: i
|
|
289
|
+
}));
|
|
290
|
+
if (input.columns && input.columns.length > 0) {
|
|
291
|
+
columnsToFacet = allCols.filter(
|
|
292
|
+
(c) => input.columns?.includes(c.name)
|
|
293
|
+
);
|
|
294
|
+
} else {
|
|
295
|
+
columnsToFacet = allCols.filter(
|
|
296
|
+
(c) => c.name !== input.table && c.name !== "rank"
|
|
297
|
+
);
|
|
298
|
+
}
|
|
299
|
+
for (const col of columnsToFacet) {
|
|
300
|
+
selectClause += `, highlight("${input.table}", ${col.index}, '', '') as _facet_${col.index}`;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
const sql = `SELECT ${selectClause}, rank FROM "${input.table}" WHERE ${matchExpr} ORDER BY rank LIMIT ${input.limit} OFFSET ${offset}`;
|
|
250
304
|
const result = await adapter.executeReadQuery(sql, queryParams);
|
|
305
|
+
let nextCursor;
|
|
306
|
+
if (result.rows?.length === input.limit) {
|
|
307
|
+
nextCursor = Buffer.from(
|
|
308
|
+
JSON.stringify({ offset: offset + input.limit })
|
|
309
|
+
).toString("base64");
|
|
310
|
+
}
|
|
311
|
+
const facets = {};
|
|
312
|
+
if (input.includeFacets && result.rows) {
|
|
313
|
+
for (const col of columnsToFacet) {
|
|
314
|
+
facets[col.name] = 0;
|
|
315
|
+
}
|
|
316
|
+
for (const row of result.rows) {
|
|
317
|
+
for (const col of columnsToFacet) {
|
|
318
|
+
const val = row[`_facet_${col.index}`];
|
|
319
|
+
if (typeof val === "string" && val.includes("")) {
|
|
320
|
+
facets[col.name] = (facets[col.name] ?? 0) + 1;
|
|
321
|
+
}
|
|
322
|
+
Reflect.deleteProperty(row, `_facet_${col.index}`);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
251
326
|
return {
|
|
252
327
|
success: true,
|
|
253
328
|
rowCount: result.rows?.length ?? 0,
|
|
254
|
-
results: result.rows
|
|
329
|
+
results: result.rows,
|
|
330
|
+
nextCursor,
|
|
331
|
+
...input.includeFacets ? { facets } : {}
|
|
255
332
|
};
|
|
256
333
|
} catch (error) {
|
|
257
334
|
if (isFts5UnavailableError(error)) {
|
|
@@ -315,7 +392,15 @@ function createFtsMatchInfoTool(adapter) {
|
|
|
315
392
|
}
|
|
316
393
|
sanitizeIdentifier(input.table);
|
|
317
394
|
await validateTableExists(adapter, input.table);
|
|
318
|
-
const
|
|
395
|
+
const sanitizedQuery = sanitizeFtsQuery(input.query);
|
|
396
|
+
if (!sanitizedQuery) {
|
|
397
|
+
return {
|
|
398
|
+
success: true,
|
|
399
|
+
rowCount: 0,
|
|
400
|
+
results: []
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
const queryEscaped = sanitizedQuery.replace(/'/g, "''");
|
|
319
404
|
let rankExpr;
|
|
320
405
|
if (input.format === "bm25") {
|
|
321
406
|
rankExpr = `bm25("${input.table}")`;
|
|
@@ -357,8 +442,17 @@ function createFtsHeadlineTool(adapter) {
|
|
|
357
442
|
}
|
|
358
443
|
sanitizeIdentifier(input.table);
|
|
359
444
|
await validateTableExists(adapter, input.table);
|
|
360
|
-
const
|
|
445
|
+
const sanitizedQuery = sanitizeFtsQuery(input.query);
|
|
446
|
+
if (!sanitizedQuery && input.query !== "*" && input.query.trim() !== "") {
|
|
447
|
+
return {
|
|
448
|
+
success: true,
|
|
449
|
+
rowCount: 0,
|
|
450
|
+
results: []
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
const queryEscaped = sanitizedQuery.replace(/'/g, "''");
|
|
361
454
|
let columnIndex = 0;
|
|
455
|
+
let snippetColumnIndex = -1;
|
|
362
456
|
if (input.column) {
|
|
363
457
|
const colResult = await adapter.executeReadQuery(
|
|
364
458
|
`PRAGMA table_info("${input.table}")`,
|
|
@@ -370,12 +464,13 @@ function createFtsHeadlineTool(adapter) {
|
|
|
370
464
|
);
|
|
371
465
|
if (found >= 0) {
|
|
372
466
|
columnIndex = found;
|
|
467
|
+
snippetColumnIndex = found;
|
|
373
468
|
}
|
|
374
469
|
}
|
|
375
470
|
const startSel = input.startSel.replace(/'/g, "''");
|
|
376
471
|
const stopSel = input.stopSel.replace(/'/g, "''");
|
|
377
472
|
const highlightExpr = `highlight("${input.table}", ${String(columnIndex)}, '${startSel}', '${stopSel}')`;
|
|
378
|
-
const snippetExpr = `snippet("${input.table}", ${String(
|
|
473
|
+
const snippetExpr = `snippet("${input.table}", ${String(snippetColumnIndex)}, '${startSel}', '${stopSel}', '...', ${String(input.snippetWords)})`;
|
|
379
474
|
if (input.query === "*" || input.query.trim() === "") {
|
|
380
475
|
const sql2 = `SELECT *, NULL as headline, NULL as snippet, NULL as rank FROM "${input.table}" ORDER BY rowid LIMIT ${String(input.limit)}`;
|
|
381
476
|
const result2 = await adapter.executeReadQuery(sql2, queryParams);
|
|
@@ -515,7 +610,8 @@ var SpatialiteLoadOutputSchema = z.object({
|
|
|
515
610
|
message: z.string().optional(),
|
|
516
611
|
alreadyLoaded: z.boolean().optional(),
|
|
517
612
|
extensionPath: z.string().optional(),
|
|
518
|
-
searchedPaths: z.array(z.string()).optional()
|
|
613
|
+
searchedPaths: z.array(z.string()).optional(),
|
|
614
|
+
version: z.string().optional()
|
|
519
615
|
}).extend(ErrorResponseFields.shape);
|
|
520
616
|
var SpatialiteCreateTableOutputSchema = z.object({
|
|
521
617
|
success: z.boolean(),
|
|
@@ -562,14 +658,14 @@ var BeginTransactionSchema = z.object({
|
|
|
562
658
|
mode: z.enum(["deferred", "immediate", "exclusive"]).optional().default("deferred").describe(
|
|
563
659
|
"Transaction mode: deferred waits for first write, immediate acquires lock immediately, exclusive blocks all access"
|
|
564
660
|
)
|
|
565
|
-
});
|
|
661
|
+
}).strict();
|
|
566
662
|
var SavepointSchema = z.object({
|
|
567
663
|
name: z.string().describe("Savepoint name")
|
|
568
|
-
});
|
|
664
|
+
}).strict();
|
|
569
665
|
var ExecuteInTransactionSchema = z.object({
|
|
570
666
|
statements: z.array(z.string()).describe("Array of SQL statements to execute in order"),
|
|
571
667
|
rollbackOnError: z.boolean().optional().default(true).describe("If true, rollback all changes when any statement fails")
|
|
572
|
-
});
|
|
668
|
+
}).strict();
|
|
573
669
|
function getTransactionTools(adapter) {
|
|
574
670
|
return [
|
|
575
671
|
createBeginTransactionTool(adapter),
|
|
@@ -612,7 +708,7 @@ function createTransactionStatusTool(adapter) {
|
|
|
612
708
|
name: "sqlite_transaction_status",
|
|
613
709
|
description: "Check whether a transaction is currently active. Returns status and a boolean flag. Read-only \u2014 does not alter transaction state.",
|
|
614
710
|
group: "transactions",
|
|
615
|
-
inputSchema: z.object({}),
|
|
711
|
+
inputSchema: z.object({}).strict(),
|
|
616
712
|
outputSchema: TransactionStatusOutputSchema,
|
|
617
713
|
annotations: readOnly("Transaction Status"),
|
|
618
714
|
requiredScopes: ["read"],
|
|
@@ -637,7 +733,7 @@ function createCommitTransactionTool(adapter) {
|
|
|
637
733
|
name: "sqlite_transaction_commit",
|
|
638
734
|
description: "Commit the current transaction, making all changes permanent.",
|
|
639
735
|
group: "transactions",
|
|
640
|
-
inputSchema: z.object({}),
|
|
736
|
+
inputSchema: z.object({}).strict(),
|
|
641
737
|
outputSchema: TransactionCommitOutputSchema,
|
|
642
738
|
annotations: write("Commit Transaction"),
|
|
643
739
|
requiredScopes: ["write"],
|
|
@@ -660,7 +756,7 @@ function createRollbackTransactionTool(adapter) {
|
|
|
660
756
|
description: "Rollback the current transaction, discarding all changes.",
|
|
661
757
|
group: "transactions",
|
|
662
758
|
outputSchema: TransactionRollbackOutputSchema,
|
|
663
|
-
inputSchema: z.object({}),
|
|
759
|
+
inputSchema: z.object({}).strict(),
|
|
664
760
|
annotations: write("Rollback Transaction"),
|
|
665
761
|
requiredScopes: ["write"],
|
|
666
762
|
handler: (_params, _context) => {
|
|
@@ -858,6 +954,14 @@ function createExecuteInTransactionTool(adapter) {
|
|
|
858
954
|
if (transactionStarted) {
|
|
859
955
|
adapter.commitTransaction();
|
|
860
956
|
}
|
|
957
|
+
if (results.length > 50) {
|
|
958
|
+
const omitted = results.length - 50;
|
|
959
|
+
results.splice(50);
|
|
960
|
+
results.push({
|
|
961
|
+
statement: "TRUNCATED",
|
|
962
|
+
error: `Results array truncated. Omitted ${omitted} results to conserve payload size.`
|
|
963
|
+
});
|
|
964
|
+
}
|
|
861
965
|
return {
|
|
862
966
|
success,
|
|
863
967
|
error: success ? void 0 : "Transaction completed with errors",
|
|
@@ -888,17 +992,28 @@ function createExecuteInTransactionTool(adapter) {
|
|
|
888
992
|
} else if (!transactionStarted && !originallyInTransaction) {
|
|
889
993
|
rollbackMessage = `Transaction failed to start: ${message}`;
|
|
890
994
|
}
|
|
995
|
+
const totalExecuted = results.length;
|
|
996
|
+
if (results.length > 50) {
|
|
997
|
+
const omitted = results.length - 50;
|
|
998
|
+
results.splice(50);
|
|
999
|
+
results.push({
|
|
1000
|
+
statement: "TRUNCATED",
|
|
1001
|
+
error: `Results array truncated. Omitted ${omitted} results to conserve payload size.`
|
|
1002
|
+
});
|
|
1003
|
+
}
|
|
891
1004
|
return {
|
|
892
1005
|
...formatted,
|
|
893
1006
|
error: formatted.error ?? rollbackMessage,
|
|
894
1007
|
message: rollbackMessage,
|
|
895
|
-
statementsExecuted:
|
|
1008
|
+
statementsExecuted: totalExecuted,
|
|
896
1009
|
results
|
|
897
1010
|
};
|
|
898
1011
|
}
|
|
899
1012
|
}
|
|
900
1013
|
};
|
|
901
1014
|
}
|
|
1015
|
+
|
|
1016
|
+
// src/adapters/sqlite-native/tools/window/helpers.ts
|
|
902
1017
|
var coerceNumber = (val) => {
|
|
903
1018
|
if (typeof val === "string") {
|
|
904
1019
|
if (val.trim() === "") return void 0;
|
|
@@ -909,93 +1024,6 @@ var coerceNumber = (val) => {
|
|
|
909
1024
|
};
|
|
910
1025
|
var coerceEnumValues2 = (allowed) => (val) => typeof val === "string" && allowed.includes(val) ? val : void 0;
|
|
911
1026
|
var VALID_DIRECTIONS = ["lag", "lead"];
|
|
912
|
-
var RowNumberSchema = z.object({
|
|
913
|
-
table: z.string().describe("Table name"),
|
|
914
|
-
orderBy: z.string().describe("Column(s) to order by"),
|
|
915
|
-
partitionBy: z.string().optional().describe("Column(s) to partition by"),
|
|
916
|
-
selectColumns: z.array(z.string()).optional().describe("Columns to include in result"),
|
|
917
|
-
conditions: z.array(WhereConditionSchema).optional().describe("Optional WHERE clause conditions"),
|
|
918
|
-
limit: z.preprocess(
|
|
919
|
-
coerceNumber,
|
|
920
|
-
z.number().optional().default(20).describe("Maximum rows to return")
|
|
921
|
-
)
|
|
922
|
-
});
|
|
923
|
-
var RankSchema = z.object({
|
|
924
|
-
table: z.string().describe("Table name"),
|
|
925
|
-
orderBy: z.string().describe("Column(s) to order by (determines rank)"),
|
|
926
|
-
partitionBy: z.string().optional().describe("Column(s) to partition by"),
|
|
927
|
-
selectColumns: z.array(z.string()).optional().describe("Columns to include in result"),
|
|
928
|
-
rankType: z.preprocess(
|
|
929
|
-
coerceEnumValues2(["rank", "dense_rank", "percent_rank"]),
|
|
930
|
-
z.enum(["rank", "dense_rank", "percent_rank"]).optional().default("rank").describe("Rank function type")
|
|
931
|
-
),
|
|
932
|
-
conditions: z.array(WhereConditionSchema).optional().describe("Optional WHERE clause conditions"),
|
|
933
|
-
limit: z.preprocess(
|
|
934
|
-
coerceNumber,
|
|
935
|
-
z.number().optional().default(20).describe("Maximum rows to return")
|
|
936
|
-
)
|
|
937
|
-
});
|
|
938
|
-
var LagLeadSchema = z.object({
|
|
939
|
-
table: z.string().describe("Table name"),
|
|
940
|
-
column: z.string().describe("Column to get lag/lead value from"),
|
|
941
|
-
orderBy: z.string().describe("Column(s) to order by"),
|
|
942
|
-
direction: z.string().describe("LAG (previous) or LEAD (next) row"),
|
|
943
|
-
offset: z.preprocess(
|
|
944
|
-
coerceNumber,
|
|
945
|
-
z.number().optional().default(1).describe("Number of rows to look back/ahead")
|
|
946
|
-
),
|
|
947
|
-
defaultValue: z.string().optional().describe("Default value if no row exists"),
|
|
948
|
-
partitionBy: z.string().optional().describe("Column(s) to partition by"),
|
|
949
|
-
selectColumns: z.array(z.string()).optional().describe("Columns to include in result"),
|
|
950
|
-
conditions: z.array(WhereConditionSchema).optional().describe("Optional WHERE clause conditions"),
|
|
951
|
-
limit: z.preprocess(
|
|
952
|
-
coerceNumber,
|
|
953
|
-
z.number().optional().default(20).describe("Maximum rows to return")
|
|
954
|
-
)
|
|
955
|
-
});
|
|
956
|
-
var RunningTotalSchema = z.object({
|
|
957
|
-
table: z.string().describe("Table name"),
|
|
958
|
-
column: z.string().describe("Column to sum"),
|
|
959
|
-
orderBy: z.string().describe("Column(s) to order by"),
|
|
960
|
-
partitionBy: z.string().optional().describe("Reset running total for each partition"),
|
|
961
|
-
selectColumns: z.array(z.string()).optional().describe("Columns to include in result"),
|
|
962
|
-
conditions: z.array(WhereConditionSchema).optional().describe("Optional WHERE clause conditions"),
|
|
963
|
-
limit: z.preprocess(
|
|
964
|
-
coerceNumber,
|
|
965
|
-
z.number().optional().default(20).describe("Maximum rows to return")
|
|
966
|
-
)
|
|
967
|
-
});
|
|
968
|
-
var MovingAverageSchema = z.object({
|
|
969
|
-
table: z.string().describe("Table name"),
|
|
970
|
-
column: z.string().describe("Column to average"),
|
|
971
|
-
orderBy: z.string().describe("Column(s) to order by"),
|
|
972
|
-
windowSize: z.preprocess(
|
|
973
|
-
coerceNumber,
|
|
974
|
-
z.number().describe("Number of rows in the moving window")
|
|
975
|
-
),
|
|
976
|
-
partitionBy: z.string().optional().describe("Column(s) to partition by"),
|
|
977
|
-
selectColumns: z.array(z.string()).optional().describe("Columns to include in result"),
|
|
978
|
-
conditions: z.array(WhereConditionSchema).optional().describe("Optional WHERE clause conditions"),
|
|
979
|
-
limit: z.preprocess(
|
|
980
|
-
coerceNumber,
|
|
981
|
-
z.number().optional().default(20).describe("Maximum rows to return")
|
|
982
|
-
)
|
|
983
|
-
});
|
|
984
|
-
var NtileSchema = z.object({
|
|
985
|
-
table: z.string().describe("Table name"),
|
|
986
|
-
orderBy: z.string().describe("Column(s) to order by"),
|
|
987
|
-
buckets: z.preprocess(
|
|
988
|
-
coerceNumber,
|
|
989
|
-
z.number().describe("Number of buckets (e.g., 4 for quartiles)")
|
|
990
|
-
),
|
|
991
|
-
partitionBy: z.string().optional().describe("Column(s) to partition by"),
|
|
992
|
-
selectColumns: z.array(z.string()).optional().describe("Columns to include in result"),
|
|
993
|
-
conditions: z.array(WhereConditionSchema).optional().describe("Optional WHERE clause conditions"),
|
|
994
|
-
limit: z.preprocess(
|
|
995
|
-
coerceNumber,
|
|
996
|
-
z.number().optional().default(20).describe("Maximum rows to return")
|
|
997
|
-
)
|
|
998
|
-
});
|
|
999
1027
|
async function validateTableExists2(adapter, table) {
|
|
1000
1028
|
validateIdentifier(table);
|
|
1001
1029
|
const result = await adapter.executeReadQuery(
|
|
@@ -1041,7 +1069,7 @@ async function validateOrderByColumns(adapter, table, orderBy) {
|
|
|
1041
1069
|
throw new DbMcpError(
|
|
1042
1070
|
`Invalid ORDER BY expression: '${colName}' contains disallowed characters. Only column names with optional ASC/DESC are permitted.`,
|
|
1043
1071
|
"NATIVE_WINDOW_INVALID_ORDERBY",
|
|
1044
|
-
|
|
1072
|
+
ErrorCategory.VALIDATION
|
|
1045
1073
|
);
|
|
1046
1074
|
}
|
|
1047
1075
|
if (/^(ASC|DESC)$/i.test(colName)) continue;
|
|
@@ -1157,19 +1185,100 @@ function validateDefaultValue(value) {
|
|
|
1157
1185
|
throw new DbMcpError(
|
|
1158
1186
|
`Invalid default value: '${value}'. Only numeric literals, single-quoted strings, or NULL are permitted.`,
|
|
1159
1187
|
"NATIVE_WINDOW_INVALID_DEFAULT",
|
|
1160
|
-
|
|
1188
|
+
ErrorCategory.VALIDATION
|
|
1161
1189
|
);
|
|
1162
1190
|
}
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1191
|
+
|
|
1192
|
+
// src/adapters/sqlite-native/tools/window/schemas.ts
|
|
1193
|
+
var RowNumberSchema = z.object({
|
|
1194
|
+
table: z.string().describe("Table name"),
|
|
1195
|
+
orderBy: z.string().describe("Column(s) to order by"),
|
|
1196
|
+
partitionBy: z.string().optional().describe("Column(s) to partition by"),
|
|
1197
|
+
selectColumns: z.array(z.string()).optional().describe("Columns to include in result"),
|
|
1198
|
+
conditions: z.array(WhereConditionSchema).optional().describe("Optional WHERE clause conditions"),
|
|
1199
|
+
limit: z.preprocess(
|
|
1200
|
+
coerceNumber,
|
|
1201
|
+
z.number().optional().default(20).describe("Maximum rows to return")
|
|
1202
|
+
)
|
|
1203
|
+
});
|
|
1204
|
+
var RankSchema = z.object({
|
|
1205
|
+
table: z.string().describe("Table name"),
|
|
1206
|
+
orderBy: z.string().describe("Column(s) to order by (determines rank)"),
|
|
1207
|
+
partitionBy: z.string().optional().describe("Column(s) to partition by"),
|
|
1208
|
+
selectColumns: z.array(z.string()).optional().describe("Columns to include in result"),
|
|
1209
|
+
rankType: z.preprocess(
|
|
1210
|
+
coerceEnumValues2(["rank", "dense_rank", "percent_rank"]),
|
|
1211
|
+
z.enum(["rank", "dense_rank", "percent_rank"]).optional().default("rank").describe("Rank function type")
|
|
1212
|
+
),
|
|
1213
|
+
conditions: z.array(WhereConditionSchema).optional().describe("Optional WHERE clause conditions"),
|
|
1214
|
+
limit: z.preprocess(
|
|
1215
|
+
coerceNumber,
|
|
1216
|
+
z.number().optional().default(20).describe("Maximum rows to return")
|
|
1217
|
+
)
|
|
1218
|
+
});
|
|
1219
|
+
var LagLeadSchema = z.object({
|
|
1220
|
+
table: z.string().describe("Table name"),
|
|
1221
|
+
column: z.string().describe("Column to get lag/lead value from"),
|
|
1222
|
+
orderBy: z.string().describe("Column(s) to order by"),
|
|
1223
|
+
direction: z.string().describe("LAG (previous) or LEAD (next) row"),
|
|
1224
|
+
offset: z.preprocess(
|
|
1225
|
+
coerceNumber,
|
|
1226
|
+
z.number().optional().default(1).describe("Number of rows to look back/ahead")
|
|
1227
|
+
),
|
|
1228
|
+
defaultValue: z.string().optional().describe("Default value if no row exists"),
|
|
1229
|
+
partitionBy: z.string().optional().describe("Column(s) to partition by"),
|
|
1230
|
+
selectColumns: z.array(z.string()).optional().describe("Columns to include in result"),
|
|
1231
|
+
conditions: z.array(WhereConditionSchema).optional().describe("Optional WHERE clause conditions"),
|
|
1232
|
+
limit: z.preprocess(
|
|
1233
|
+
coerceNumber,
|
|
1234
|
+
z.number().optional().default(20).describe("Maximum rows to return")
|
|
1235
|
+
)
|
|
1236
|
+
});
|
|
1237
|
+
var RunningTotalSchema = z.object({
|
|
1238
|
+
table: z.string().describe("Table name"),
|
|
1239
|
+
column: z.string().describe("Column to sum"),
|
|
1240
|
+
orderBy: z.string().describe("Column(s) to order by"),
|
|
1241
|
+
partitionBy: z.string().optional().describe("Reset running total for each partition"),
|
|
1242
|
+
selectColumns: z.array(z.string()).optional().describe("Columns to include in result"),
|
|
1243
|
+
conditions: z.array(WhereConditionSchema).optional().describe("Optional WHERE clause conditions"),
|
|
1244
|
+
limit: z.preprocess(
|
|
1245
|
+
coerceNumber,
|
|
1246
|
+
z.number().optional().default(20).describe("Maximum rows to return")
|
|
1247
|
+
)
|
|
1248
|
+
});
|
|
1249
|
+
var MovingAverageSchema = z.object({
|
|
1250
|
+
table: z.string().describe("Table name"),
|
|
1251
|
+
column: z.string().describe("Column to average"),
|
|
1252
|
+
orderBy: z.string().describe("Column(s) to order by"),
|
|
1253
|
+
windowSize: z.preprocess(
|
|
1254
|
+
coerceNumber,
|
|
1255
|
+
z.number().describe("Number of rows in the moving window")
|
|
1256
|
+
),
|
|
1257
|
+
partitionBy: z.string().optional().describe("Column(s) to partition by"),
|
|
1258
|
+
selectColumns: z.array(z.string()).optional().describe("Columns to include in result"),
|
|
1259
|
+
conditions: z.array(WhereConditionSchema).optional().describe("Optional WHERE clause conditions"),
|
|
1260
|
+
limit: z.preprocess(
|
|
1261
|
+
coerceNumber,
|
|
1262
|
+
z.number().optional().default(20).describe("Maximum rows to return")
|
|
1263
|
+
)
|
|
1264
|
+
});
|
|
1265
|
+
var NtileSchema = z.object({
|
|
1266
|
+
table: z.string().describe("Table name"),
|
|
1267
|
+
orderBy: z.string().describe("Column(s) to order by"),
|
|
1268
|
+
buckets: z.preprocess(
|
|
1269
|
+
coerceNumber,
|
|
1270
|
+
z.number().describe("Number of buckets (e.g., 4 for quartiles)")
|
|
1271
|
+
),
|
|
1272
|
+
partitionBy: z.string().optional().describe("Column(s) to partition by"),
|
|
1273
|
+
selectColumns: z.array(z.string()).optional().describe("Columns to include in result"),
|
|
1274
|
+
conditions: z.array(WhereConditionSchema).optional().describe("Optional WHERE clause conditions"),
|
|
1275
|
+
limit: z.preprocess(
|
|
1276
|
+
coerceNumber,
|
|
1277
|
+
z.number().optional().default(20).describe("Maximum rows to return")
|
|
1278
|
+
)
|
|
1279
|
+
});
|
|
1280
|
+
|
|
1281
|
+
// src/adapters/sqlite-native/tools/window/row-number.ts
|
|
1173
1282
|
function createRowNumberTool(adapter) {
|
|
1174
1283
|
return {
|
|
1175
1284
|
name: "sqlite_window_row_number",
|
|
@@ -1221,6 +1330,8 @@ function createRowNumberTool(adapter) {
|
|
|
1221
1330
|
}
|
|
1222
1331
|
};
|
|
1223
1332
|
}
|
|
1333
|
+
|
|
1334
|
+
// src/adapters/sqlite-native/tools/window/rank.ts
|
|
1224
1335
|
function createRankTool(adapter) {
|
|
1225
1336
|
return {
|
|
1226
1337
|
name: "sqlite_window_rank",
|
|
@@ -1274,6 +1385,8 @@ function createRankTool(adapter) {
|
|
|
1274
1385
|
}
|
|
1275
1386
|
};
|
|
1276
1387
|
}
|
|
1388
|
+
|
|
1389
|
+
// src/adapters/sqlite-native/tools/window/lag-lead.ts
|
|
1277
1390
|
function createLagLeadTool(adapter) {
|
|
1278
1391
|
return {
|
|
1279
1392
|
name: "sqlite_window_lag_lead",
|
|
@@ -1349,6 +1462,8 @@ function createLagLeadTool(adapter) {
|
|
|
1349
1462
|
}
|
|
1350
1463
|
};
|
|
1351
1464
|
}
|
|
1465
|
+
|
|
1466
|
+
// src/adapters/sqlite-native/tools/window/running-total.ts
|
|
1352
1467
|
function createRunningTotalTool(adapter) {
|
|
1353
1468
|
return {
|
|
1354
1469
|
name: "sqlite_window_running_total",
|
|
@@ -1405,6 +1520,8 @@ function createRunningTotalTool(adapter) {
|
|
|
1405
1520
|
}
|
|
1406
1521
|
};
|
|
1407
1522
|
}
|
|
1523
|
+
|
|
1524
|
+
// src/adapters/sqlite-native/tools/window/moving-average.ts
|
|
1408
1525
|
function createMovingAverageTool(adapter) {
|
|
1409
1526
|
return {
|
|
1410
1527
|
name: "sqlite_window_moving_avg",
|
|
@@ -1463,6 +1580,8 @@ function createMovingAverageTool(adapter) {
|
|
|
1463
1580
|
}
|
|
1464
1581
|
};
|
|
1465
1582
|
}
|
|
1583
|
+
|
|
1584
|
+
// src/adapters/sqlite-native/tools/window/ntile.ts
|
|
1466
1585
|
function createNtileTool(adapter) {
|
|
1467
1586
|
return {
|
|
1468
1587
|
name: "sqlite_window_ntile",
|
|
@@ -1515,6 +1634,18 @@ function createNtileTool(adapter) {
|
|
|
1515
1634
|
}
|
|
1516
1635
|
};
|
|
1517
1636
|
}
|
|
1637
|
+
|
|
1638
|
+
// src/adapters/sqlite-native/tools/window/index.ts
|
|
1639
|
+
function getWindowTools(adapter) {
|
|
1640
|
+
return [
|
|
1641
|
+
createRowNumberTool(adapter),
|
|
1642
|
+
createRankTool(adapter),
|
|
1643
|
+
createLagLeadTool(adapter),
|
|
1644
|
+
createRunningTotalTool(adapter),
|
|
1645
|
+
createMovingAverageTool(adapter),
|
|
1646
|
+
createNtileTool(adapter)
|
|
1647
|
+
];
|
|
1648
|
+
}
|
|
1518
1649
|
var coerceNumber2 = (val) => {
|
|
1519
1650
|
if (typeof val === "string") {
|
|
1520
1651
|
if (val.trim() === "") return void 0;
|
|
@@ -1755,34 +1886,44 @@ function createLoadSpatialiteTool(adapter) {
|
|
|
1755
1886
|
outputSchema: SpatialiteLoadOutputSchema,
|
|
1756
1887
|
requiredScopes: ["admin"],
|
|
1757
1888
|
annotations: admin("SpatiaLite Load"),
|
|
1758
|
-
handler: (_params, _context) => {
|
|
1889
|
+
handler: async (_params, _context) => {
|
|
1759
1890
|
try {
|
|
1760
1891
|
const input = LoadSpatialiteSchema.parse(_params);
|
|
1761
1892
|
if (!input.forceReload && isSpatialiteLoaded(adapter)) {
|
|
1762
|
-
|
|
1893
|
+
const versionResult = await adapter.executeReadQuery(
|
|
1894
|
+
"SELECT spatialite_version() as v"
|
|
1895
|
+
);
|
|
1896
|
+
const version = versionResult.rows?.[0]?.["v"];
|
|
1897
|
+
return {
|
|
1763
1898
|
success: true,
|
|
1764
1899
|
message: "SpatiaLite already loaded",
|
|
1765
|
-
alreadyLoaded: true
|
|
1766
|
-
|
|
1900
|
+
alreadyLoaded: true,
|
|
1901
|
+
version
|
|
1902
|
+
};
|
|
1767
1903
|
}
|
|
1768
1904
|
const result = tryLoadSpatialite(adapter);
|
|
1769
1905
|
if (result.success) {
|
|
1770
|
-
|
|
1906
|
+
const versionResult = await adapter.executeReadQuery(
|
|
1907
|
+
"SELECT spatialite_version() as v"
|
|
1908
|
+
);
|
|
1909
|
+
const version = versionResult.rows?.[0]?.["v"];
|
|
1910
|
+
return {
|
|
1771
1911
|
success: true,
|
|
1772
1912
|
message: "SpatiaLite loaded successfully",
|
|
1773
|
-
extensionPath: result.path
|
|
1774
|
-
|
|
1913
|
+
extensionPath: result.path,
|
|
1914
|
+
version
|
|
1915
|
+
};
|
|
1775
1916
|
}
|
|
1776
|
-
return
|
|
1917
|
+
return {
|
|
1777
1918
|
success: false,
|
|
1778
1919
|
error: result.error,
|
|
1779
1920
|
code: "SPATIALITE_LOAD_FAILED",
|
|
1780
1921
|
category: "internal",
|
|
1781
1922
|
recoverable: false,
|
|
1782
1923
|
searchedPaths: SPATIALITE_PATHS
|
|
1783
|
-
}
|
|
1924
|
+
};
|
|
1784
1925
|
} catch (error) {
|
|
1785
|
-
return
|
|
1926
|
+
return formatHandlerError(error);
|
|
1786
1927
|
}
|
|
1787
1928
|
}
|
|
1788
1929
|
};
|
|
@@ -2636,16 +2777,18 @@ function savepoint(db, name) {
|
|
|
2636
2777
|
}
|
|
2637
2778
|
function releaseSavepoint(db, name) {
|
|
2638
2779
|
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name)) {
|
|
2639
|
-
throw new
|
|
2640
|
-
"Invalid savepoint name. Must start with a letter/underscore and contain only alphanumeric chars."
|
|
2780
|
+
throw new ValidationError(
|
|
2781
|
+
"Invalid savepoint name. Must start with a letter/underscore and contain only alphanumeric chars.",
|
|
2782
|
+
"INVALID_SAVEPOINT_NAME"
|
|
2641
2783
|
);
|
|
2642
2784
|
}
|
|
2643
2785
|
db.exec(`RELEASE SAVEPOINT "${name}"`);
|
|
2644
2786
|
}
|
|
2645
2787
|
function rollbackToSavepoint(db, name) {
|
|
2646
2788
|
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name)) {
|
|
2647
|
-
throw new
|
|
2648
|
-
"Invalid savepoint name. Must start with a letter/underscore and contain only alphanumeric chars."
|
|
2789
|
+
throw new ValidationError(
|
|
2790
|
+
"Invalid savepoint name. Must start with a letter/underscore and contain only alphanumeric chars.",
|
|
2791
|
+
"INVALID_SAVEPOINT_NAME"
|
|
2649
2792
|
);
|
|
2650
2793
|
}
|
|
2651
2794
|
db.exec(`ROLLBACK TO SAVEPOINT "${name}"`);
|
|
@@ -2724,7 +2867,7 @@ var NativeSqliteAdapter = class extends DatabaseAdapter {
|
|
|
2724
2867
|
/**
|
|
2725
2868
|
* Connect to a SQLite database using better-sqlite3
|
|
2726
2869
|
*/
|
|
2727
|
-
connect(config) {
|
|
2870
|
+
async connect(config) {
|
|
2728
2871
|
if (config.type !== "sqlite") {
|
|
2729
2872
|
throw new ConfigurationError(
|
|
2730
2873
|
`Invalid database type: expected 'sqlite', got '${config.type}'`,
|
|
@@ -2735,13 +2878,33 @@ var NativeSqliteAdapter = class extends DatabaseAdapter {
|
|
|
2735
2878
|
this.config = sqliteConfig;
|
|
2736
2879
|
try {
|
|
2737
2880
|
const filePath = sqliteConfig.filePath ?? sqliteConfig.connectionString ?? ":memory:";
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2881
|
+
if (sqliteConfig.options?.encryptionKey) {
|
|
2882
|
+
const DatabaseDriver = (await import('better-sqlite3-multiple-ciphers')).default;
|
|
2883
|
+
this.db = new DatabaseDriver(filePath, {
|
|
2884
|
+
readonly: false,
|
|
2885
|
+
fileMustExist: false
|
|
2886
|
+
});
|
|
2887
|
+
const escapedKey = sqliteConfig.options.encryptionKey.replace(
|
|
2888
|
+
/"/g,
|
|
2889
|
+
'""'
|
|
2890
|
+
);
|
|
2891
|
+
this.db.pragma(`key = "${escapedKey}"`);
|
|
2892
|
+
log.info(
|
|
2893
|
+
`Connected to SQLite database (native encrypted): ${filePath}`,
|
|
2894
|
+
{
|
|
2895
|
+
code: "SQLITE_CONNECT_ENCRYPTED"
|
|
2896
|
+
}
|
|
2897
|
+
);
|
|
2898
|
+
} else {
|
|
2899
|
+
const DatabaseDriver = (await import('better-sqlite3')).default;
|
|
2900
|
+
this.db = new DatabaseDriver(filePath, {
|
|
2901
|
+
readonly: false,
|
|
2902
|
+
fileMustExist: false
|
|
2903
|
+
});
|
|
2904
|
+
log.info(`Connected to SQLite database (native): ${filePath}`, {
|
|
2905
|
+
code: "SQLITE_CONNECT"
|
|
2906
|
+
});
|
|
2907
|
+
}
|
|
2745
2908
|
this.applyOptions(sqliteConfig.options);
|
|
2746
2909
|
const db = this.db;
|
|
2747
2910
|
autoEnableWal(
|
|
@@ -2780,7 +2943,6 @@ var NativeSqliteAdapter = class extends DatabaseAdapter {
|
|
|
2780
2943
|
}
|
|
2781
2944
|
);
|
|
2782
2945
|
}
|
|
2783
|
-
return Promise.resolve();
|
|
2784
2946
|
}
|
|
2785
2947
|
/**
|
|
2786
2948
|
* Apply SQLite PRAGMA options and load extensions
|
|
@@ -2870,6 +3032,7 @@ var NativeSqliteAdapter = class extends DatabaseAdapter {
|
|
|
2870
3032
|
const result = nativeExecuteWrite(this.ensureDb(), sql, params, log);
|
|
2871
3033
|
if (isDDL(sql)) {
|
|
2872
3034
|
this.clearSchemaCache();
|
|
3035
|
+
this.emit("schemaChanged");
|
|
2873
3036
|
}
|
|
2874
3037
|
return result;
|
|
2875
3038
|
}
|
|
@@ -2896,6 +3059,7 @@ var NativeSqliteAdapter = class extends DatabaseAdapter {
|
|
|
2896
3059
|
this.ensureConnected();
|
|
2897
3060
|
this.ensureDb().exec(sql);
|
|
2898
3061
|
this.clearSchemaCache();
|
|
3062
|
+
this.emit("schemaChanged");
|
|
2899
3063
|
return Promise.resolve();
|
|
2900
3064
|
}
|
|
2901
3065
|
/**
|
|
@@ -2943,7 +3107,7 @@ var NativeSqliteAdapter = class extends DatabaseAdapter {
|
|
|
2943
3107
|
throw new DbMcpError(
|
|
2944
3108
|
"Invalid table name",
|
|
2945
3109
|
"SQLITE_INVALID_TABLE",
|
|
2946
|
-
|
|
3110
|
+
ErrorCategory.VALIDATION
|
|
2947
3111
|
);
|
|
2948
3112
|
}
|
|
2949
3113
|
const result = await this.executeReadQuery(
|
|
@@ -2953,7 +3117,7 @@ var NativeSqliteAdapter = class extends DatabaseAdapter {
|
|
|
2953
3117
|
throw new DbMcpError(
|
|
2954
3118
|
`Table '${tableName}' does not exist`,
|
|
2955
3119
|
"SQLITE_TABLE_NOT_FOUND",
|
|
2956
|
-
|
|
3120
|
+
ErrorCategory.RESOURCE
|
|
2957
3121
|
);
|
|
2958
3122
|
}
|
|
2959
3123
|
return {
|