db-mcp 3.0.1 → 4.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 +92 -75
- package/dist/.tsbuildinfo +1 -1
- package/dist/adapters/database-adapter.d.ts +2 -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/resources.d.ts +1 -1
- package/dist/adapters/sqlite/resources.d.ts.map +1 -1
- package/dist/adapters/sqlite/schemas/admin.d.ts +29 -15
- package/dist/adapters/sqlite/schemas/admin.d.ts.map +1 -1
- package/dist/adapters/sqlite/schemas/core.d.ts +2 -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 +20 -11
- package/dist/adapters/sqlite/schemas/introspection.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.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/core/queries.d.ts.map +1 -1
- package/dist/adapters/sqlite/tools/core/tables.d.ts.map +1 -1
- 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/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/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/types.d.ts +4 -0
- package/dist/adapters/sqlite/types.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/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/{chunk-W5WQVNVX.js → chunk-EQF3WZHX.js} +10 -17
- package/dist/{chunk-37G4DLL6.js → chunk-NIC5Z2CA.js} +732 -138
- package/dist/chunk-R5M4WKDM.js +987 -0
- package/dist/{chunk-NV34JSQM.js → chunk-TGE7LFAR.js} +708 -996
- package/dist/{chunk-L552U3QS.js → chunk-Y57WFKAP.js} +227 -9
- package/dist/cli.js +103 -10
- package/dist/codemode/sandbox.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 +9 -9
- package/dist/{http-HWTUVFIA.js → http-2WGR3E5K.js} +13 -1
- 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.d.ts +4 -0
- package/dist/server/registration/audit-tools.d.ts.map +1 -1
- 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-D4WCNPU4.js} +8 -5
- package/dist/{sqlite-native-IF75BB3O.js → sqlite-native-DLVS2T52.js} +159 -34
- package/dist/transports/http/sessions/legacy-sse.d.ts.map +1 -1
- package/dist/transports/http/sessions/stateful.d.ts.map +1 -1
- package/dist/transports/http/transport.d.ts.map +1 -1
- package/dist/transports/http/types.d.ts +2 -0
- package/dist/transports/http/types.d.ts.map +1 -1
- package/dist/types/server.d.ts +2 -0
- package/dist/types/server.d.ts.map +1 -1
- package/dist/utils/index.d.ts +1 -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/tokens.d.ts +15 -0
- package/dist/utils/tokens.d.ts.map +1 -0
- package/package.json +10 -7
- package/dist/chunk-E5IESRTK.js +0 -489
- package/dist/utils/insights-manager.d.ts +0 -39
- package/dist/utils/insights-manager.d.ts.map +0 -1
|
@@ -0,0 +1,987 @@
|
|
|
1
|
+
import { ValidationError, SCOPES } from './chunk-Y57WFKAP.js';
|
|
2
|
+
import { createRequire } from 'module';
|
|
3
|
+
import { dirname, resolve, basename, normalize, relative } from 'path';
|
|
4
|
+
import { realpathSync } from 'fs';
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
|
|
7
|
+
var _require = createRequire(import.meta.url);
|
|
8
|
+
var pkg = _require("../package.json");
|
|
9
|
+
var VERSION = pkg.version;
|
|
10
|
+
var NAME = pkg.name;
|
|
11
|
+
|
|
12
|
+
// src/utils/where-clause.ts
|
|
13
|
+
var UnsafeWhereClauseError = class extends Error {
|
|
14
|
+
constructor(reason) {
|
|
15
|
+
super(`Unsafe WHERE clause: ${reason}`);
|
|
16
|
+
this.name = "UnsafeWhereClauseError";
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
var DANGEROUS_PATTERNS = [
|
|
20
|
+
// Statement terminators and new statements
|
|
21
|
+
// Comprehensive keyword list including statements missed in earlier versions:
|
|
22
|
+
// REPLACE, VACUUM, ANALYZE, BEGIN, COMMIT, ROLLBACK, SAVEPOINT, RELEASE
|
|
23
|
+
{
|
|
24
|
+
pattern: /;\s*(DROP|DELETE|TRUNCATE|INSERT|UPDATE|CREATE|ALTER|ATTACH|DETACH|SELECT|REPLACE|VACUUM|ANALYZE|BEGIN|COMMIT|ROLLBACK|SAVEPOINT|RELEASE|REINDEX|EXPLAIN)\b/i,
|
|
25
|
+
reason: "contains statement terminator followed by SQL keyword"
|
|
26
|
+
},
|
|
27
|
+
// Trailing semicolons (potential statement injection)
|
|
28
|
+
{
|
|
29
|
+
pattern: /;\s*$/,
|
|
30
|
+
reason: "contains trailing semicolon"
|
|
31
|
+
},
|
|
32
|
+
// SQL comments (can be used to comment out security checks)
|
|
33
|
+
{
|
|
34
|
+
pattern: /--/,
|
|
35
|
+
reason: "contains SQL line comment"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
pattern: /\/\*/,
|
|
39
|
+
reason: "contains SQL block comment"
|
|
40
|
+
},
|
|
41
|
+
// REGEXP and MATCH injection (blind extraction oracles)
|
|
42
|
+
{
|
|
43
|
+
pattern: /\bREGEXP\s+/i,
|
|
44
|
+
reason: "contains REGEXP (potential blind extraction oracle)"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
pattern: /\bMATCH\s+/i,
|
|
48
|
+
reason: "contains MATCH (potential blind extraction oracle)"
|
|
49
|
+
},
|
|
50
|
+
// UNION injection (data exfiltration)
|
|
51
|
+
{
|
|
52
|
+
pattern: /\bUNION\s+(ALL\s+)?SELECT\b/i,
|
|
53
|
+
reason: "contains UNION SELECT"
|
|
54
|
+
},
|
|
55
|
+
// SQLite-specific: Extension loading (code execution)
|
|
56
|
+
{
|
|
57
|
+
pattern: /\bload_extension\s*\(/i,
|
|
58
|
+
reason: "contains load_extension (code execution)"
|
|
59
|
+
},
|
|
60
|
+
// SQLite-specific: ATTACH database (file system access)
|
|
61
|
+
{
|
|
62
|
+
pattern: /\bATTACH\s+(DATABASE\s+)?['"`]/i,
|
|
63
|
+
reason: "contains ATTACH DATABASE (file system access)"
|
|
64
|
+
},
|
|
65
|
+
// SQLite-specific: Pragma manipulation
|
|
66
|
+
{
|
|
67
|
+
pattern: /\bPRAGMA\s+/i,
|
|
68
|
+
reason: "contains PRAGMA statement"
|
|
69
|
+
},
|
|
70
|
+
// SQLite-specific: writefile/readfile (if using fileio extension)
|
|
71
|
+
{
|
|
72
|
+
pattern: /\b(writefile|readfile)\s*\(/i,
|
|
73
|
+
reason: "contains file I/O function"
|
|
74
|
+
},
|
|
75
|
+
// SQLite-specific: fts3_tokenizer (potential code execution)
|
|
76
|
+
{
|
|
77
|
+
pattern: /\bfts3_tokenizer\s*\(/i,
|
|
78
|
+
reason: "contains FTS tokenizer function"
|
|
79
|
+
},
|
|
80
|
+
// Subquery injection (data exfiltration via boolean-based blind)
|
|
81
|
+
{
|
|
82
|
+
pattern: /\(\s*SELECT\b/i,
|
|
83
|
+
reason: "contains subquery (potential data exfiltration)"
|
|
84
|
+
},
|
|
85
|
+
// Generic: Hexadecimal string injection
|
|
86
|
+
{
|
|
87
|
+
pattern: /\bX'[0-9A-Fa-f]+'/,
|
|
88
|
+
reason: "contains hex string literal (potential binary injection)"
|
|
89
|
+
},
|
|
90
|
+
// CASE WHEN (potential blind injection without subqueries)
|
|
91
|
+
{
|
|
92
|
+
pattern: /\bCASE\s+WHEN\b/i,
|
|
93
|
+
reason: "contains CASE WHEN (potential blind injection)"
|
|
94
|
+
},
|
|
95
|
+
// IIF() — conditional bypass alternative to CASE WHEN
|
|
96
|
+
{
|
|
97
|
+
pattern: /\bIIF\s*\(/i,
|
|
98
|
+
reason: "contains IIF() (potential blind injection)"
|
|
99
|
+
},
|
|
100
|
+
// GROUP_CONCAT() — data aggregation for exfiltration
|
|
101
|
+
{
|
|
102
|
+
pattern: /\bGROUP_CONCAT\s*\(/i,
|
|
103
|
+
reason: "contains GROUP_CONCAT() (potential data exfiltration)"
|
|
104
|
+
},
|
|
105
|
+
// GLOB — case-sensitive wildcard operator usable for character extraction oracles
|
|
106
|
+
{
|
|
107
|
+
pattern: /\bGLOB\b/i,
|
|
108
|
+
reason: "contains GLOB (potential case-sensitive oracle)"
|
|
109
|
+
},
|
|
110
|
+
// Conditional functions — blind injection oracles (bypass for CASE WHEN / IIF)
|
|
111
|
+
{
|
|
112
|
+
pattern: /\bCOALESCE\s*\(/i,
|
|
113
|
+
reason: "contains COALESCE() (potential blind injection oracle)"
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
pattern: /\bNULLIF\s*\(/i,
|
|
117
|
+
reason: "contains NULLIF() (potential blind injection oracle)"
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
pattern: /\bTYPEOF\s*\(/i,
|
|
121
|
+
reason: "contains TYPEOF() (potential blind injection oracle)"
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
pattern: /\bIFNULL\s*\(/i,
|
|
125
|
+
reason: "contains IFNULL() (potential blind injection oracle)"
|
|
126
|
+
},
|
|
127
|
+
// Memory allocation DoS — RANDOMBLOB(N) / ZEROBLOB(N) can allocate large blocks (CWE-400)
|
|
128
|
+
{
|
|
129
|
+
pattern: /\bRANDOMBLOB\s*\(/i,
|
|
130
|
+
reason: "contains RANDOMBLOB() (potential memory allocation DoS)"
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
pattern: /\bZEROBLOB\s*\(/i,
|
|
134
|
+
reason: "contains ZEROBLOB() (potential memory allocation DoS)"
|
|
135
|
+
},
|
|
136
|
+
// Blind extraction oracle functions — can be composed for character-by-character
|
|
137
|
+
// data extraction without subqueries or CASE WHEN (CWE-89, H-1 audit finding).
|
|
138
|
+
// Example: INSTR('abc...', SUBSTR(sqlite_version(), 1, 1)) = N
|
|
139
|
+
{
|
|
140
|
+
pattern: /\bINSTR\s*\(/i,
|
|
141
|
+
reason: "contains INSTR() (potential blind extraction oracle)"
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
pattern: /\bSUBSTR\s*\(/i,
|
|
145
|
+
reason: "contains SUBSTR() (potential blind extraction oracle)"
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
pattern: /\bSUBSTRING\s*\(/i,
|
|
149
|
+
reason: "contains SUBSTRING() (potential blind extraction oracle)"
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
pattern: /\bLENGTH\s*\(/i,
|
|
153
|
+
reason: "contains LENGTH() (potential blind extraction oracle)"
|
|
154
|
+
},
|
|
155
|
+
// TRIM functions — blind extraction oracle (bypass for LIKE / SUBSTR)
|
|
156
|
+
{
|
|
157
|
+
pattern: /\b(?:L|R)?TRIM\s*\(/i,
|
|
158
|
+
reason: "contains TRIM() (potential blind extraction oracle)"
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
pattern: /\bUNICODE\s*\(/i,
|
|
162
|
+
reason: "contains UNICODE() (potential blind extraction oracle)"
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
pattern: /\bCHAR\s*\(/i,
|
|
166
|
+
reason: "contains CHAR() (potential blind extraction oracle)"
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
pattern: /\bREPLACE\s*\(/i,
|
|
170
|
+
reason: "contains REPLACE() (potential blind extraction oracle)"
|
|
171
|
+
},
|
|
172
|
+
// ABS() — can be combined with subtraction to create numeric oracles (CWE-89)
|
|
173
|
+
{
|
|
174
|
+
pattern: /\bABS\s*\(/i,
|
|
175
|
+
reason: "contains ABS() (potential blind extraction oracle)"
|
|
176
|
+
},
|
|
177
|
+
// HEX() — encodes values for character-by-character extraction (CWE-89)
|
|
178
|
+
{
|
|
179
|
+
pattern: /\bHEX\s*\(/i,
|
|
180
|
+
reason: "contains HEX() (potential blind extraction oracle)"
|
|
181
|
+
},
|
|
182
|
+
// QUOTE() — returns SQL-literal representation, can leak type/value info (CWE-89)
|
|
183
|
+
{
|
|
184
|
+
pattern: /\bQUOTE\s*\(/i,
|
|
185
|
+
reason: "contains QUOTE() (potential blind extraction oracle)"
|
|
186
|
+
},
|
|
187
|
+
// PRINTF() — format-string based extraction of internal values (CWE-89)
|
|
188
|
+
{
|
|
189
|
+
pattern: /\bPRINTF\s*\(/i,
|
|
190
|
+
reason: "contains PRINTF() (potential blind extraction oracle)"
|
|
191
|
+
},
|
|
192
|
+
// FORMAT() — SQLite 3.38.0+ alias for printf() (CWE-89)
|
|
193
|
+
{
|
|
194
|
+
pattern: /\bFORMAT\s*\(/i,
|
|
195
|
+
reason: "contains FORMAT() (potential blind extraction oracle)"
|
|
196
|
+
},
|
|
197
|
+
// CAST() — can be used to convert text to numeric oracles (CWE-89)
|
|
198
|
+
{
|
|
199
|
+
pattern: /\bCAST\s*\(/i,
|
|
200
|
+
reason: "contains CAST() (potential blind extraction oracle)"
|
|
201
|
+
}
|
|
202
|
+
];
|
|
203
|
+
var FULLWIDTH_START = 65281;
|
|
204
|
+
var FULLWIDTH_END = 65374;
|
|
205
|
+
var FULLWIDTH_ASCII_OFFSET = 65248;
|
|
206
|
+
function normalizeForPatternMatching(input) {
|
|
207
|
+
let normalized = input.normalize("NFC");
|
|
208
|
+
let hasFullwidth = false;
|
|
209
|
+
for (let i = 0; i < normalized.length; i++) {
|
|
210
|
+
const code = normalized.charCodeAt(i);
|
|
211
|
+
if (code >= FULLWIDTH_START && code <= FULLWIDTH_END) {
|
|
212
|
+
hasFullwidth = true;
|
|
213
|
+
break;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
if (hasFullwidth) {
|
|
217
|
+
const chars = [];
|
|
218
|
+
for (let i = 0; i < normalized.length; i++) {
|
|
219
|
+
const code = normalized.charCodeAt(i);
|
|
220
|
+
if (code >= FULLWIDTH_START && code <= FULLWIDTH_END) {
|
|
221
|
+
chars.push(String.fromCharCode(code - FULLWIDTH_ASCII_OFFSET));
|
|
222
|
+
} else {
|
|
223
|
+
chars.push(normalized.charAt(i));
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
normalized = chars.join("");
|
|
227
|
+
}
|
|
228
|
+
return normalized;
|
|
229
|
+
}
|
|
230
|
+
function sanitizeWhereClause(where) {
|
|
231
|
+
if (!where || typeof where !== "string") {
|
|
232
|
+
throw new UnsafeWhereClauseError("WHERE clause must be a non-empty string");
|
|
233
|
+
}
|
|
234
|
+
const MAX_WHERE_LENGTH = 10240;
|
|
235
|
+
if (where.length > MAX_WHERE_LENGTH) {
|
|
236
|
+
throw new UnsafeWhereClauseError(
|
|
237
|
+
`WHERE clause exceeds maximum length of ${String(MAX_WHERE_LENGTH)} characters`
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
const normalized = normalizeForPatternMatching(where);
|
|
241
|
+
for (const { pattern, reason } of DANGEROUS_PATTERNS) {
|
|
242
|
+
if (pattern.test(normalized)) {
|
|
243
|
+
throw new UnsafeWhereClauseError(reason);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
return where;
|
|
247
|
+
}
|
|
248
|
+
function buildWhereClause(conditions, whereClause) {
|
|
249
|
+
let finalSql = "";
|
|
250
|
+
const params = [];
|
|
251
|
+
const clauses = [];
|
|
252
|
+
if (conditions !== void 0 && conditions !== null && conditions.length > 0) {
|
|
253
|
+
const allowedOperators = /* @__PURE__ */ new Set([
|
|
254
|
+
"=",
|
|
255
|
+
"!=",
|
|
256
|
+
">",
|
|
257
|
+
">=",
|
|
258
|
+
"<",
|
|
259
|
+
"<=",
|
|
260
|
+
"LIKE",
|
|
261
|
+
"IN",
|
|
262
|
+
"IS",
|
|
263
|
+
"IS NOT",
|
|
264
|
+
"NOT LIKE"
|
|
265
|
+
]);
|
|
266
|
+
for (const cond of conditions) {
|
|
267
|
+
if (!allowedOperators.has(cond.operator.toUpperCase())) {
|
|
268
|
+
throw new Error(`Invalid operator: ${cond.operator}`);
|
|
269
|
+
}
|
|
270
|
+
const col = `"${cond.column.replace(/"/g, '""')}"`;
|
|
271
|
+
if (cond.operator.toUpperCase() === "IN" && Array.isArray(cond.value)) {
|
|
272
|
+
const placeholders = cond.value.map(() => "?").join(", ");
|
|
273
|
+
clauses.push(`${col} IN (${placeholders})`);
|
|
274
|
+
params.push(...cond.value);
|
|
275
|
+
} else {
|
|
276
|
+
clauses.push(`${col} ${cond.operator} ?`);
|
|
277
|
+
params.push(cond.value);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
finalSql = clauses.join(" AND ");
|
|
281
|
+
}
|
|
282
|
+
if (whereClause) {
|
|
283
|
+
const safeWhere = sanitizeWhereClause(whereClause);
|
|
284
|
+
if (finalSql) {
|
|
285
|
+
finalSql = `${finalSql} AND ${safeWhere}`;
|
|
286
|
+
} else {
|
|
287
|
+
finalSql = safeWhere;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
return { sql: finalSql, params };
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// src/utils/identifiers.ts
|
|
294
|
+
var IDENTIFIER_PATTERN = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
|
|
295
|
+
var MAX_IDENTIFIER_LENGTH = 255;
|
|
296
|
+
var InvalidIdentifierError = class extends Error {
|
|
297
|
+
constructor(identifier, reason) {
|
|
298
|
+
super(`Invalid identifier "${identifier}": ${reason}`);
|
|
299
|
+
this.identifier = identifier;
|
|
300
|
+
this.reason = reason;
|
|
301
|
+
this.name = "InvalidIdentifierError";
|
|
302
|
+
}
|
|
303
|
+
identifier;
|
|
304
|
+
reason;
|
|
305
|
+
};
|
|
306
|
+
function validateIdentifier(name) {
|
|
307
|
+
if (!name || typeof name !== "string") {
|
|
308
|
+
throw new InvalidIdentifierError(
|
|
309
|
+
name,
|
|
310
|
+
"Identifier must be a non-empty string"
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
if (name.length > MAX_IDENTIFIER_LENGTH) {
|
|
314
|
+
throw new InvalidIdentifierError(
|
|
315
|
+
name,
|
|
316
|
+
`Identifier exceeds maximum length of ${String(MAX_IDENTIFIER_LENGTH)} characters`
|
|
317
|
+
);
|
|
318
|
+
}
|
|
319
|
+
if (!IDENTIFIER_PATTERN.test(name)) {
|
|
320
|
+
throw new InvalidIdentifierError(
|
|
321
|
+
name,
|
|
322
|
+
"Identifier contains invalid characters. Must start with a letter or underscore and contain only letters, digits, or underscores"
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
function sanitizeIdentifier(name) {
|
|
327
|
+
validateIdentifier(name);
|
|
328
|
+
const escaped = name.replace(/"/g, '""');
|
|
329
|
+
return `"${escaped}"`;
|
|
330
|
+
}
|
|
331
|
+
function sanitizeIdentifiers(names) {
|
|
332
|
+
return names.map(sanitizeIdentifier);
|
|
333
|
+
}
|
|
334
|
+
function createColumnList(columns) {
|
|
335
|
+
return sanitizeIdentifiers(columns).join(", ");
|
|
336
|
+
}
|
|
337
|
+
function validateSameDirPath(targetPath, dbPath) {
|
|
338
|
+
if (targetPath.includes("\0")) {
|
|
339
|
+
return {
|
|
340
|
+
valid: false,
|
|
341
|
+
error: "Security: path must not contain null bytes.",
|
|
342
|
+
dbDir: dbPath === ":memory:" ? "" : dirname(resolve(dbPath))
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
if (targetPath.startsWith("file:") || targetPath.includes("?")) {
|
|
346
|
+
return {
|
|
347
|
+
valid: false,
|
|
348
|
+
error: "Security: SQLite URIs and query parameters are not allowed.",
|
|
349
|
+
dbDir: dbPath === ":memory:" ? "" : dirname(resolve(dbPath))
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
const base = basename(targetPath);
|
|
353
|
+
if (base.startsWith(".")) {
|
|
354
|
+
return {
|
|
355
|
+
valid: false,
|
|
356
|
+
error: "Security: Cannot access hidden files or dotfiles.",
|
|
357
|
+
dbDir: dbPath === ":memory:" ? "" : dirname(resolve(dbPath))
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
const validExtensions = [
|
|
361
|
+
".db",
|
|
362
|
+
".sqlite",
|
|
363
|
+
".sqlite3",
|
|
364
|
+
".sql",
|
|
365
|
+
".csv",
|
|
366
|
+
".tsv"
|
|
367
|
+
];
|
|
368
|
+
const hasValidExt = validExtensions.some(
|
|
369
|
+
(ext) => base.toLowerCase().endsWith(ext)
|
|
370
|
+
);
|
|
371
|
+
if (!hasValidExt) {
|
|
372
|
+
return {
|
|
373
|
+
valid: false,
|
|
374
|
+
error: `Security: Invalid file extension. Allowed extensions are: ${validExtensions.join(", ")}`,
|
|
375
|
+
dbDir: dbPath === ":memory:" ? "" : dirname(resolve(dbPath))
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
if (dbPath === ":memory:") {
|
|
379
|
+
return {
|
|
380
|
+
valid: false,
|
|
381
|
+
error: "Security: Filesystem operations are not permitted for :memory: databases.",
|
|
382
|
+
dbDir: ""
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
const dbDir = dirname(resolve(dbPath));
|
|
386
|
+
let resolvedTarget = resolve(targetPath);
|
|
387
|
+
try {
|
|
388
|
+
resolvedTarget = realpathSync(resolvedTarget);
|
|
389
|
+
} catch {
|
|
390
|
+
try {
|
|
391
|
+
const parentDir = realpathSync(dirname(resolvedTarget));
|
|
392
|
+
resolvedTarget = resolve(parentDir, basename(resolvedTarget));
|
|
393
|
+
} catch {
|
|
394
|
+
return {
|
|
395
|
+
valid: false,
|
|
396
|
+
error: "Security: Target parent directory must exist.",
|
|
397
|
+
dbDir
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
let resolvedDbDir;
|
|
402
|
+
try {
|
|
403
|
+
resolvedDbDir = realpathSync(dbDir);
|
|
404
|
+
} catch {
|
|
405
|
+
return {
|
|
406
|
+
valid: false,
|
|
407
|
+
error: "Security: Database directory must exist.",
|
|
408
|
+
dbDir
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
const normalizedTarget = normalize(resolvedTarget);
|
|
412
|
+
const normalizedDir = normalize(resolvedDbDir);
|
|
413
|
+
const targetDir = normalize(dirname(resolvedTarget));
|
|
414
|
+
if (relative(normalizedDir, targetDir) !== "") {
|
|
415
|
+
return {
|
|
416
|
+
valid: false,
|
|
417
|
+
error: `Security: path must be within the database directory. Path traversal is not allowed.`,
|
|
418
|
+
dbDir
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
return { valid: true, resolvedPath: normalizedTarget };
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// src/utils/validate-json-path.ts
|
|
425
|
+
var VALID_JSON_PATH_PATTERN = /^\$(\.[a-zA-Z_][a-zA-Z0-9_ -]*|\[\d+\]|\[#\]|\[\*\])*$/;
|
|
426
|
+
var MAX_JSON_PATH_LENGTH = 500;
|
|
427
|
+
function validateJsonPath(path, param = "path") {
|
|
428
|
+
if (!path.startsWith("$")) {
|
|
429
|
+
throw new ValidationError(
|
|
430
|
+
`JSON ${param} must start with $`,
|
|
431
|
+
"INVALID_JSON_PATH",
|
|
432
|
+
{
|
|
433
|
+
suggestion: "Use a valid JSON path starting with $. For example: $.key or $[0]"
|
|
434
|
+
}
|
|
435
|
+
);
|
|
436
|
+
}
|
|
437
|
+
if (path.length > MAX_JSON_PATH_LENGTH) {
|
|
438
|
+
throw new ValidationError(
|
|
439
|
+
`JSON ${param} exceeds maximum length of ${MAX_JSON_PATH_LENGTH} characters`,
|
|
440
|
+
"INVALID_JSON_PATH"
|
|
441
|
+
);
|
|
442
|
+
}
|
|
443
|
+
if (!VALID_JSON_PATH_PATTERN.test(path)) {
|
|
444
|
+
throw new ValidationError(
|
|
445
|
+
`Invalid JSON ${param} syntax: ${path}`,
|
|
446
|
+
"INVALID_JSON_PATH",
|
|
447
|
+
{
|
|
448
|
+
suggestion: "Use $.key, $[0], or $[*] patterns. Member names must start with a letter or underscore."
|
|
449
|
+
}
|
|
450
|
+
);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
var ALLOWED_AGGREGATE_FUNCTIONS = /* @__PURE__ */ new Set([
|
|
454
|
+
"count",
|
|
455
|
+
"sum",
|
|
456
|
+
"avg",
|
|
457
|
+
"min",
|
|
458
|
+
"max",
|
|
459
|
+
"group_concat",
|
|
460
|
+
"total"
|
|
461
|
+
]);
|
|
462
|
+
var AGGREGATE_FUNCTION_PATTERN = /^([A-Za-z_]+)\(\s*(\*|"[a-zA-Z_][a-zA-Z0-9_]*"|[a-zA-Z_][a-zA-Z0-9_]*)(?:\s*,\s*'[^']*')?\s*\)$/;
|
|
463
|
+
function validateAggregateFunction(fn) {
|
|
464
|
+
const match = AGGREGATE_FUNCTION_PATTERN.exec(fn.trim());
|
|
465
|
+
if (!match) {
|
|
466
|
+
throw new ValidationError(
|
|
467
|
+
`Invalid aggregate function syntax: ${fn}`,
|
|
468
|
+
"INVALID_AGGREGATE_FUNCTION",
|
|
469
|
+
{
|
|
470
|
+
suggestion: "Use a standard aggregate function like COUNT(*), SUM(column), AVG(column), MIN(column), MAX(column), GROUP_CONCAT(column), or TOTAL(column)."
|
|
471
|
+
}
|
|
472
|
+
);
|
|
473
|
+
}
|
|
474
|
+
const funcName = match[1]?.toLowerCase();
|
|
475
|
+
if (!funcName || !ALLOWED_AGGREGATE_FUNCTIONS.has(funcName)) {
|
|
476
|
+
throw new ValidationError(
|
|
477
|
+
`Disallowed aggregate function: ${match[1]}. Allowed: ${[...ALLOWED_AGGREGATE_FUNCTIONS].join(", ").toUpperCase()}`,
|
|
478
|
+
"INVALID_AGGREGATE_FUNCTION"
|
|
479
|
+
);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
// src/utils/tokens.ts
|
|
484
|
+
function estimateTokens(text, contentType = "text") {
|
|
485
|
+
const bytes = Buffer.byteLength(text, "utf8");
|
|
486
|
+
switch (contentType) {
|
|
487
|
+
case "json":
|
|
488
|
+
return Math.ceil(bytes / 3);
|
|
489
|
+
case "sql":
|
|
490
|
+
return Math.ceil(bytes / 3.5);
|
|
491
|
+
case "text":
|
|
492
|
+
default:
|
|
493
|
+
return Math.ceil(bytes / 4);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
// src/utils/icons.ts
|
|
498
|
+
var MDI_BASE = "https://cdn.jsdelivr.net/npm/@mdi/svg@7.4.47/svg";
|
|
499
|
+
var SERVER_ICONS = [
|
|
500
|
+
{
|
|
501
|
+
src: `${MDI_BASE}/server.svg`,
|
|
502
|
+
mimeType: "image/svg+xml"
|
|
503
|
+
}
|
|
504
|
+
];
|
|
505
|
+
var TOOL_GROUP_ICONS = {
|
|
506
|
+
core: [{ src: `${MDI_BASE}/database.svg`, mimeType: "image/svg+xml" }],
|
|
507
|
+
json: [{ src: `${MDI_BASE}/code-json.svg`, mimeType: "image/svg+xml" }],
|
|
508
|
+
text: [{ src: `${MDI_BASE}/format-text.svg`, mimeType: "image/svg+xml" }],
|
|
509
|
+
stats: [{ src: `${MDI_BASE}/chart-bar.svg`, mimeType: "image/svg+xml" }],
|
|
510
|
+
vector: [
|
|
511
|
+
{ src: `${MDI_BASE}/vector-polyline.svg`, mimeType: "image/svg+xml" }
|
|
512
|
+
],
|
|
513
|
+
admin: [{ src: `${MDI_BASE}/cog.svg`, mimeType: "image/svg+xml" }],
|
|
514
|
+
transactions: [
|
|
515
|
+
{ src: `${MDI_BASE}/swap-horizontal.svg`, mimeType: "image/svg+xml" }
|
|
516
|
+
],
|
|
517
|
+
geo: [{ src: `${MDI_BASE}/earth.svg`, mimeType: "image/svg+xml" }],
|
|
518
|
+
introspection: [
|
|
519
|
+
{ src: `${MDI_BASE}/graph-outline.svg`, mimeType: "image/svg+xml" }
|
|
520
|
+
],
|
|
521
|
+
migration: [
|
|
522
|
+
{ src: `${MDI_BASE}/source-branch.svg`, mimeType: "image/svg+xml" }
|
|
523
|
+
],
|
|
524
|
+
codemode: [{ src: `${MDI_BASE}/code-braces.svg`, mimeType: "image/svg+xml" }]
|
|
525
|
+
};
|
|
526
|
+
function getToolGroupIcon(group) {
|
|
527
|
+
return TOOL_GROUP_ICONS[group];
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
// src/utils/annotations.ts
|
|
531
|
+
var READ_ONLY = {
|
|
532
|
+
readOnlyHint: true,
|
|
533
|
+
destructiveHint: false,
|
|
534
|
+
openWorldHint: false,
|
|
535
|
+
sensitiveHint: false
|
|
536
|
+
};
|
|
537
|
+
var WRITE = {
|
|
538
|
+
readOnlyHint: false,
|
|
539
|
+
destructiveHint: false,
|
|
540
|
+
openWorldHint: false,
|
|
541
|
+
sensitiveHint: false
|
|
542
|
+
};
|
|
543
|
+
var DESTRUCTIVE = {
|
|
544
|
+
readOnlyHint: false,
|
|
545
|
+
destructiveHint: true,
|
|
546
|
+
openWorldHint: false,
|
|
547
|
+
sensitiveHint: false
|
|
548
|
+
};
|
|
549
|
+
var IDEMPOTENT = {
|
|
550
|
+
readOnlyHint: false,
|
|
551
|
+
destructiveHint: false,
|
|
552
|
+
idempotentHint: true,
|
|
553
|
+
openWorldHint: false,
|
|
554
|
+
sensitiveHint: false
|
|
555
|
+
};
|
|
556
|
+
var ADMIN = {
|
|
557
|
+
readOnlyHint: false,
|
|
558
|
+
destructiveHint: true,
|
|
559
|
+
openWorldHint: false,
|
|
560
|
+
sensitiveHint: true
|
|
561
|
+
// System maintenance may expose internal db structures
|
|
562
|
+
};
|
|
563
|
+
function readOnly(title) {
|
|
564
|
+
return { title, ...READ_ONLY };
|
|
565
|
+
}
|
|
566
|
+
function write(title) {
|
|
567
|
+
return { title, ...WRITE };
|
|
568
|
+
}
|
|
569
|
+
function destructive(title) {
|
|
570
|
+
return { title, ...DESTRUCTIVE };
|
|
571
|
+
}
|
|
572
|
+
function idempotent(title) {
|
|
573
|
+
return { title, ...IDEMPOTENT };
|
|
574
|
+
}
|
|
575
|
+
function admin(title) {
|
|
576
|
+
return { title, ...ADMIN };
|
|
577
|
+
}
|
|
578
|
+
var ADMIN_FS = {
|
|
579
|
+
readOnlyHint: false,
|
|
580
|
+
destructiveHint: true,
|
|
581
|
+
openWorldHint: true,
|
|
582
|
+
sensitiveHint: true
|
|
583
|
+
};
|
|
584
|
+
var WRITE_FS = {
|
|
585
|
+
readOnlyHint: false,
|
|
586
|
+
destructiveHint: false,
|
|
587
|
+
openWorldHint: true,
|
|
588
|
+
sensitiveHint: true
|
|
589
|
+
};
|
|
590
|
+
function adminFs(title) {
|
|
591
|
+
return { title, ...ADMIN_FS };
|
|
592
|
+
}
|
|
593
|
+
function writeFs(title) {
|
|
594
|
+
return { title, ...WRITE_FS };
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
// src/utils/redaction.ts
|
|
598
|
+
var SENSITIVE_KEY_PATTERN = /(?:sk-|Bearer |token\s*[:=]\s*|password\s*[:=]\s*|secret\s*[:=]\s*|apikey\s*[:=]\s*|api_key\s*[:=]\s*|AWS_SECRET_ACCESS_KEY\s*[:=]\s*|GITHUB_TOKEN\s*[:=]\s*|ghp_|gho_|ghu_|ghs_|xoxb-|xoxp-|xoxs-|AZURE_[A-Z_]*\s*[:=]\s*|DATABASE_URL\s*[:=]\s*|AKIA|sk-ant-api[a-zA-Z0-9_-]+|sk_live_[a-zA-Z0-9_]+|rk_live_[a-zA-Z0-9_]+|SG\.[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+|npm_[a-zA-Z0-9]{30,}|dpl_[a-zA-Z0-9]{30,}|hvs\.[a-zA-Z0-9_-]+)[^\s'",;)}\]]{2,}/i;
|
|
599
|
+
var SENSITIVE_VALUE_REGEX = new RegExp(SENSITIVE_KEY_PATTERN.source, "gi");
|
|
600
|
+
var SENSITIVE_KEY_REGEX = /^(password|passwd|token|secret|authorization|api_?key|credential|private_?key|access_?token|refresh_?token|database_url)$/i;
|
|
601
|
+
function redactObject(obj, depth = 0, maxDepth = 15) {
|
|
602
|
+
if (depth > maxDepth || obj === null || obj === void 0) {
|
|
603
|
+
return obj;
|
|
604
|
+
}
|
|
605
|
+
if (typeof obj === "string") {
|
|
606
|
+
return obj.replace(SENSITIVE_VALUE_REGEX, "[REDACTED]");
|
|
607
|
+
}
|
|
608
|
+
if (typeof obj !== "object") {
|
|
609
|
+
return obj;
|
|
610
|
+
}
|
|
611
|
+
if (Array.isArray(obj)) {
|
|
612
|
+
return obj.map((item) => redactObject(item, depth + 1, maxDepth));
|
|
613
|
+
}
|
|
614
|
+
const redacted = {};
|
|
615
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
616
|
+
if (SENSITIVE_KEY_REGEX.test(key)) {
|
|
617
|
+
redacted[key] = "[REDACTED]";
|
|
618
|
+
} else {
|
|
619
|
+
redacted[key] = redactObject(value, depth + 1, maxDepth);
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
return redacted;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
// src/auth/scope-map.ts
|
|
626
|
+
var toolScopeMap = /* @__PURE__ */ new Map();
|
|
627
|
+
function registerToolScope(toolName, scope) {
|
|
628
|
+
toolScopeMap.set(toolName, scope);
|
|
629
|
+
if (!toolName.startsWith("sqlite_")) {
|
|
630
|
+
toolScopeMap.set(`sqlite_${toolName}`, scope);
|
|
631
|
+
} else {
|
|
632
|
+
toolScopeMap.set(toolName.slice(7), scope);
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
function getRequiredScope(toolName) {
|
|
636
|
+
return toolScopeMap.get(toolName) ?? SCOPES.ADMIN;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
// src/utils/resource-annotations.ts
|
|
640
|
+
var HIGH_PRIORITY = {
|
|
641
|
+
audience: ["user", "assistant"],
|
|
642
|
+
priority: 0.9
|
|
643
|
+
};
|
|
644
|
+
var MEDIUM_PRIORITY = {
|
|
645
|
+
audience: ["user", "assistant"],
|
|
646
|
+
priority: 0.6
|
|
647
|
+
};
|
|
648
|
+
var LOW_PRIORITY = {
|
|
649
|
+
audience: ["user", "assistant"],
|
|
650
|
+
priority: 0.4
|
|
651
|
+
};
|
|
652
|
+
var ASSISTANT_FOCUSED = {
|
|
653
|
+
audience: ["assistant"],
|
|
654
|
+
priority: 0.5
|
|
655
|
+
};
|
|
656
|
+
var ErrorResponseFields = z.object({
|
|
657
|
+
error: z.string().optional().describe("Error message (human-readable)"),
|
|
658
|
+
code: z.string().optional().describe("Error code (e.g. VALIDATION_ERROR, QUERY_ERROR)"),
|
|
659
|
+
category: z.string().optional().describe("Error category (validation, query, connection, internal)"),
|
|
660
|
+
recoverable: z.boolean().optional().describe("Whether the error is recoverable"),
|
|
661
|
+
suggestion: z.string().optional().describe("Suggested fix for the error"),
|
|
662
|
+
details: z.record(z.string(), z.unknown()).optional().describe("Additional error context")
|
|
663
|
+
});
|
|
664
|
+
var coerceNumber = (val) => {
|
|
665
|
+
if (typeof val === "string") {
|
|
666
|
+
if (val.trim() === "") return void 0;
|
|
667
|
+
const num = Number(val);
|
|
668
|
+
return isNaN(num) ? val : num;
|
|
669
|
+
}
|
|
670
|
+
return val;
|
|
671
|
+
};
|
|
672
|
+
var BackupSchema = z.object({
|
|
673
|
+
targetPath: z.string().describe("Path for backup file")
|
|
674
|
+
});
|
|
675
|
+
var AnalyzeSchema = z.object({
|
|
676
|
+
table: z.string().optional().describe("Specific table to analyze (default: all)")
|
|
677
|
+
});
|
|
678
|
+
var IntegrityCheckSchema = z.object({
|
|
679
|
+
maxErrors: z.preprocess(
|
|
680
|
+
coerceNumber,
|
|
681
|
+
z.number().int().optional().default(100).describe("Maximum errors to report")
|
|
682
|
+
)
|
|
683
|
+
});
|
|
684
|
+
var OptimizeSchema = z.object({
|
|
685
|
+
table: z.string().optional().describe("Specific table to optimize"),
|
|
686
|
+
reindex: z.boolean().optional().default(false),
|
|
687
|
+
analyze: z.boolean().optional().default(true)
|
|
688
|
+
});
|
|
689
|
+
var RestoreSchema = z.object({
|
|
690
|
+
sourcePath: z.string().describe("Path to backup file to restore from"),
|
|
691
|
+
allowTriggers: z.boolean().optional().default(false).describe(
|
|
692
|
+
"If true, allows triggers in the backup file to be restored. This is a security risk if the backup file is untrusted."
|
|
693
|
+
)
|
|
694
|
+
});
|
|
695
|
+
var VerifyBackupSchema = z.object({
|
|
696
|
+
backupPath: z.string().describe("Path to backup file to verify")
|
|
697
|
+
});
|
|
698
|
+
var IndexStatsSchema = z.object({
|
|
699
|
+
table: z.string().optional().describe("Filter indexes by table name (default: all tables)"),
|
|
700
|
+
excludeSystemIndexes: z.boolean().optional().default(true).describe(
|
|
701
|
+
"Exclude SpatiaLite system indexes (default: true). Set to false to include all indexes."
|
|
702
|
+
)
|
|
703
|
+
});
|
|
704
|
+
var PragmaOptimizeSchema = z.object({
|
|
705
|
+
mask: z.preprocess(
|
|
706
|
+
coerceNumber,
|
|
707
|
+
z.number().int().optional().describe("Optional optimization mask (default: 0xfffe)")
|
|
708
|
+
)
|
|
709
|
+
});
|
|
710
|
+
var PragmaSettingsSchema = z.object({
|
|
711
|
+
pragma: z.string().describe("PRAGMA name (e.g., 'cache_size', 'journal_mode')"),
|
|
712
|
+
value: z.union([z.string(), z.number().int()]).optional().describe("Value to set (omit to only read)")
|
|
713
|
+
});
|
|
714
|
+
var PragmaTableInfoSchema = z.object({
|
|
715
|
+
table: z.string().describe("Table name to get column information for")
|
|
716
|
+
});
|
|
717
|
+
var PragmaCompileOptionsSchema = z.object({
|
|
718
|
+
filter: z.string().optional().describe(
|
|
719
|
+
"Optional filter pattern (case-insensitive substring match) to limit returned options"
|
|
720
|
+
)
|
|
721
|
+
});
|
|
722
|
+
var PragmaDatabaseListSchema = z.object({});
|
|
723
|
+
z.object({
|
|
724
|
+
analyze: z.boolean().optional().default(true).describe("Run ANALYZE after VACUUM")
|
|
725
|
+
});
|
|
726
|
+
var AttachDatabaseSchema = z.object({
|
|
727
|
+
filepath: z.string().describe("Path to the database file to attach"),
|
|
728
|
+
alias: z.string().regex(
|
|
729
|
+
/^[a-zA-Z_]\w*$/,
|
|
730
|
+
"Alias must start with a letter or underscore and contain only alphanumeric characters"
|
|
731
|
+
).describe("Schema alias for the attached database (e.g., 'analytics')")
|
|
732
|
+
});
|
|
733
|
+
var DetachDatabaseSchema = z.object({
|
|
734
|
+
alias: z.string().describe("Schema alias of the database to detach (cannot be 'main')")
|
|
735
|
+
});
|
|
736
|
+
var VacuumIntoCopySchema = z.object({
|
|
737
|
+
outputPath: z.string().describe(
|
|
738
|
+
"Path for the output database file. Creates a compacted copy of the database."
|
|
739
|
+
)
|
|
740
|
+
});
|
|
741
|
+
var AuditListBackupsSchema = z.object({
|
|
742
|
+
limit: z.preprocess(
|
|
743
|
+
coerceNumber,
|
|
744
|
+
z.number().int().min(1).max(100).optional().default(10).describe("Maximum number of snapshots to return (default 10, max 100)")
|
|
745
|
+
),
|
|
746
|
+
offset: z.preprocess(
|
|
747
|
+
coerceNumber,
|
|
748
|
+
z.number().int().min(0).optional().default(0).describe("Pagination offset")
|
|
749
|
+
)
|
|
750
|
+
});
|
|
751
|
+
z.object({
|
|
752
|
+
filename: z.string().describe(
|
|
753
|
+
"Snapshot filename from sqlite_audit_list_backups results (e.g., '2025-01-01T00-00-00-000Z_sqlite_drop_table_users.snapshot.json.gz')"
|
|
754
|
+
),
|
|
755
|
+
dryRun: z.boolean().optional().default(false).describe(
|
|
756
|
+
"If true, returns the DDL that would be executed without applying changes"
|
|
757
|
+
)
|
|
758
|
+
});
|
|
759
|
+
z.object({
|
|
760
|
+
filename: z.string().describe("Snapshot filename to compare against the live database schema")
|
|
761
|
+
});
|
|
762
|
+
var AuditSearchSchema = z.object({
|
|
763
|
+
tool: z.string().optional().describe("Filter by exact tool name"),
|
|
764
|
+
category: z.enum(["read", "write", "admin", "auth", "error"]).optional().describe("Filter by operation category"),
|
|
765
|
+
success: z.boolean().optional().describe("Filter by success status"),
|
|
766
|
+
requestId: z.string().optional().describe("Filter by exact request ID"),
|
|
767
|
+
fromTimestamp: z.string().optional().describe("Filter by start timestamp (ISO 8601)"),
|
|
768
|
+
toTimestamp: z.string().optional().describe("Filter by end timestamp (ISO 8601)"),
|
|
769
|
+
limit: z.preprocess(
|
|
770
|
+
coerceNumber,
|
|
771
|
+
z.number().int().min(1).max(1e3).optional().default(50).describe("Maximum number of entries to return (default 50)")
|
|
772
|
+
),
|
|
773
|
+
offset: z.preprocess(
|
|
774
|
+
coerceNumber,
|
|
775
|
+
z.number().int().min(0).optional().default(0).describe("Pagination offset")
|
|
776
|
+
)
|
|
777
|
+
});
|
|
778
|
+
var SqlDumpSchema = z.object({
|
|
779
|
+
outputPath: z.string().describe(
|
|
780
|
+
"Absolute path where the SQL text dump file will be written (e.g. '/path/to/dump.sql')"
|
|
781
|
+
)
|
|
782
|
+
});
|
|
783
|
+
var AuditListBackupsOutputSchema = z.object({
|
|
784
|
+
success: z.boolean(),
|
|
785
|
+
snapshots: z.array(z.any()).optional(),
|
|
786
|
+
count: z.number().optional(),
|
|
787
|
+
totalCount: z.number().optional(),
|
|
788
|
+
_meta: z.object({ tokenEstimate: z.number() }).optional()
|
|
789
|
+
}).extend(ErrorResponseFields.shape);
|
|
790
|
+
var AuditGetBackupOutputSchema = z.object({
|
|
791
|
+
success: z.boolean(),
|
|
792
|
+
metadata: z.any().optional(),
|
|
793
|
+
ddl: z.string().optional(),
|
|
794
|
+
data: z.string().optional()
|
|
795
|
+
}).extend(ErrorResponseFields.shape);
|
|
796
|
+
var AuditCleanupOutputSchema = z.object({
|
|
797
|
+
success: z.boolean(),
|
|
798
|
+
deletedCount: z.number().optional(),
|
|
799
|
+
message: z.string().optional()
|
|
800
|
+
}).extend(ErrorResponseFields.shape);
|
|
801
|
+
var AuditDiffBackupOutputSchema = z.object({
|
|
802
|
+
success: z.boolean(),
|
|
803
|
+
diffs: z.array(z.any()).optional(),
|
|
804
|
+
snapshotTimestamp: z.string().optional(),
|
|
805
|
+
snapshotTarget: z.string().optional()
|
|
806
|
+
}).extend(ErrorResponseFields.shape);
|
|
807
|
+
var AuditRestoreBackupOutputSchema = z.object({
|
|
808
|
+
success: z.boolean(),
|
|
809
|
+
message: z.string().optional(),
|
|
810
|
+
ddl: z.string().optional(),
|
|
811
|
+
dryRun: z.boolean().optional(),
|
|
812
|
+
changesApplied: z.number().optional()
|
|
813
|
+
}).extend(ErrorResponseFields.shape);
|
|
814
|
+
var AuditSearchOutputSchema = z.object({
|
|
815
|
+
success: z.boolean(),
|
|
816
|
+
entries: z.array(z.any()).optional(),
|
|
817
|
+
count: z.number().optional(),
|
|
818
|
+
totalCount: z.number().optional()
|
|
819
|
+
}).extend(ErrorResponseFields.shape);
|
|
820
|
+
var VacuumOutputSchema = z.object({
|
|
821
|
+
success: z.boolean(),
|
|
822
|
+
message: z.string().optional(),
|
|
823
|
+
durationMs: z.number().optional(),
|
|
824
|
+
wasmLimitation: z.boolean().optional(),
|
|
825
|
+
sizeChange: z.object({
|
|
826
|
+
before: z.number(),
|
|
827
|
+
after: z.number(),
|
|
828
|
+
saved: z.number()
|
|
829
|
+
}).optional()
|
|
830
|
+
}).extend(ErrorResponseFields.shape);
|
|
831
|
+
var BackupOutputSchema = z.object({
|
|
832
|
+
success: z.boolean(),
|
|
833
|
+
message: z.string().optional(),
|
|
834
|
+
path: z.string().optional(),
|
|
835
|
+
sizeBytes: z.number().optional(),
|
|
836
|
+
durationMs: z.number().optional(),
|
|
837
|
+
wasmLimitation: z.boolean().optional(),
|
|
838
|
+
note: z.string().optional()
|
|
839
|
+
}).extend(ErrorResponseFields.shape);
|
|
840
|
+
var SqlDumpOutputSchema = z.object({
|
|
841
|
+
success: z.boolean(),
|
|
842
|
+
message: z.string().optional(),
|
|
843
|
+
path: z.string().optional(),
|
|
844
|
+
durationMs: z.number().optional(),
|
|
845
|
+
wasmLimitation: z.boolean().optional()
|
|
846
|
+
}).extend(ErrorResponseFields.shape);
|
|
847
|
+
var AnalyzeOutputSchema = z.object({
|
|
848
|
+
success: z.boolean(),
|
|
849
|
+
message: z.string().optional(),
|
|
850
|
+
tablesAnalyzed: z.number().optional(),
|
|
851
|
+
durationMs: z.number().optional()
|
|
852
|
+
}).extend(ErrorResponseFields.shape);
|
|
853
|
+
var OptimizeOutputSchema = z.object({
|
|
854
|
+
success: z.boolean(),
|
|
855
|
+
message: z.string().optional(),
|
|
856
|
+
operations: z.array(z.string()).optional(),
|
|
857
|
+
durationMs: z.number().optional()
|
|
858
|
+
}).extend(ErrorResponseFields.shape);
|
|
859
|
+
var IntegrityCheckOutputSchema = z.object({
|
|
860
|
+
success: z.boolean(),
|
|
861
|
+
integrity: z.enum(["ok", "errors_found"]).optional(),
|
|
862
|
+
errorCount: z.number().optional(),
|
|
863
|
+
messages: z.array(z.string()).optional()
|
|
864
|
+
}).extend(ErrorResponseFields.shape);
|
|
865
|
+
var RestoreOutputSchema = z.object({
|
|
866
|
+
success: z.boolean(),
|
|
867
|
+
message: z.string().optional(),
|
|
868
|
+
sourcePath: z.string().optional(),
|
|
869
|
+
durationMs: z.number().optional(),
|
|
870
|
+
wasmLimitation: z.boolean().optional(),
|
|
871
|
+
skippedTables: z.array(z.string()).optional(),
|
|
872
|
+
note: z.string().optional()
|
|
873
|
+
}).extend(ErrorResponseFields.shape);
|
|
874
|
+
var VerifyBackupOutputSchema = z.object({
|
|
875
|
+
success: z.boolean(),
|
|
876
|
+
valid: z.boolean().optional(),
|
|
877
|
+
pageCount: z.number().optional(),
|
|
878
|
+
pageSize: z.number().optional(),
|
|
879
|
+
integrity: z.enum(["ok", "errors_found"]).optional(),
|
|
880
|
+
messages: z.array(z.string()).optional(),
|
|
881
|
+
message: z.string().optional(),
|
|
882
|
+
wasmLimitation: z.boolean().optional(),
|
|
883
|
+
backupPath: z.string().optional()
|
|
884
|
+
}).extend(ErrorResponseFields.shape);
|
|
885
|
+
var IndexColumnSchema = z.object({
|
|
886
|
+
name: z.string(),
|
|
887
|
+
seqno: z.number()
|
|
888
|
+
});
|
|
889
|
+
var IndexStatsEntrySchema = z.object({
|
|
890
|
+
name: z.string(),
|
|
891
|
+
table: z.string(),
|
|
892
|
+
unique: z.boolean(),
|
|
893
|
+
partial: z.boolean(),
|
|
894
|
+
columns: z.array(IndexColumnSchema)
|
|
895
|
+
});
|
|
896
|
+
var IndexStatsOutputSchema = z.object({
|
|
897
|
+
success: z.boolean(),
|
|
898
|
+
indexes: z.array(IndexStatsEntrySchema).optional()
|
|
899
|
+
}).extend(ErrorResponseFields.shape);
|
|
900
|
+
var PragmaCompileOptionsOutputSchema = z.object({
|
|
901
|
+
success: z.boolean(),
|
|
902
|
+
options: z.array(z.string()).optional()
|
|
903
|
+
}).extend(ErrorResponseFields.shape);
|
|
904
|
+
var DatabaseListEntrySchema = z.object({
|
|
905
|
+
seq: z.number(),
|
|
906
|
+
name: z.string(),
|
|
907
|
+
file: z.string()
|
|
908
|
+
});
|
|
909
|
+
var PragmaDatabaseListOutputSchema = z.object({
|
|
910
|
+
success: z.boolean(),
|
|
911
|
+
databases: z.array(DatabaseListEntrySchema).optional(),
|
|
912
|
+
configuredPath: z.string().optional(),
|
|
913
|
+
note: z.string().optional()
|
|
914
|
+
}).extend(ErrorResponseFields.shape);
|
|
915
|
+
var PragmaOptimizeOutputSchema = z.object({
|
|
916
|
+
success: z.boolean(),
|
|
917
|
+
message: z.string().optional(),
|
|
918
|
+
durationMs: z.number().optional()
|
|
919
|
+
}).extend(ErrorResponseFields.shape);
|
|
920
|
+
var PragmaSettingsOutputSchema = z.object({
|
|
921
|
+
success: z.boolean(),
|
|
922
|
+
pragma: z.string().optional(),
|
|
923
|
+
value: z.unknown().optional(),
|
|
924
|
+
oldValue: z.unknown().optional(),
|
|
925
|
+
newValue: z.unknown().optional()
|
|
926
|
+
}).extend(ErrorResponseFields.shape);
|
|
927
|
+
var PragmaTableInfoColumnSchema = z.object({
|
|
928
|
+
cid: z.number(),
|
|
929
|
+
name: z.string(),
|
|
930
|
+
type: z.string(),
|
|
931
|
+
notNull: z.boolean(),
|
|
932
|
+
defaultValue: z.unknown().nullable(),
|
|
933
|
+
pk: z.number()
|
|
934
|
+
});
|
|
935
|
+
var PragmaTableInfoOutputSchema = z.object({
|
|
936
|
+
success: z.boolean(),
|
|
937
|
+
table: z.string().optional(),
|
|
938
|
+
columns: z.array(PragmaTableInfoColumnSchema).optional()
|
|
939
|
+
}).extend(ErrorResponseFields.shape);
|
|
940
|
+
var AttachDatabaseOutputSchema = z.object({
|
|
941
|
+
success: z.boolean(),
|
|
942
|
+
message: z.string().optional(),
|
|
943
|
+
alias: z.string().optional(),
|
|
944
|
+
filepath: z.string().optional()
|
|
945
|
+
}).extend(ErrorResponseFields.shape);
|
|
946
|
+
var DetachDatabaseOutputSchema = z.object({
|
|
947
|
+
success: z.boolean(),
|
|
948
|
+
message: z.string().optional(),
|
|
949
|
+
alias: z.string().optional()
|
|
950
|
+
}).extend(ErrorResponseFields.shape);
|
|
951
|
+
var VacuumIntoCopyOutputSchema = z.object({
|
|
952
|
+
success: z.boolean(),
|
|
953
|
+
message: z.string().optional(),
|
|
954
|
+
outputPath: z.string().optional(),
|
|
955
|
+
sizeBytes: z.number().optional(),
|
|
956
|
+
durationMs: z.number().optional(),
|
|
957
|
+
wasmLimitation: z.boolean().optional()
|
|
958
|
+
}).extend(ErrorResponseFields.shape);
|
|
959
|
+
var ReindexSchema = z.object({
|
|
960
|
+
target: z.string().optional().describe(
|
|
961
|
+
"Index name, table name, or collation name to reindex. Omit to reindex the entire database."
|
|
962
|
+
)
|
|
963
|
+
});
|
|
964
|
+
var ReindexOutputSchema = z.object({
|
|
965
|
+
success: z.boolean(),
|
|
966
|
+
message: z.string().optional(),
|
|
967
|
+
sql: z.string().optional(),
|
|
968
|
+
durationMs: z.number().optional()
|
|
969
|
+
}).extend(ErrorResponseFields.shape);
|
|
970
|
+
var WalSchema = z.object({
|
|
971
|
+
action: z.enum(["status", "enable", "disable", "checkpoint"]).describe(
|
|
972
|
+
"WAL action: 'status' = check journal_mode, 'enable' = switch to WAL, 'disable' = switch to DELETE (default journal mode), 'checkpoint' = force WAL checkpoint"
|
|
973
|
+
),
|
|
974
|
+
checkpointMode: z.enum(["PASSIVE", "FULL", "RESTART", "TRUNCATE"]).optional().default("PASSIVE").describe(
|
|
975
|
+
"Checkpoint mode (only used with 'checkpoint' action). PASSIVE = checkpoint without blocking readers (default). FULL = wait for readers to finish. RESTART = same as FULL but restart WAL file. TRUNCATE = same as RESTART but truncate WAL file to zero bytes."
|
|
976
|
+
)
|
|
977
|
+
});
|
|
978
|
+
var WalOutputSchema = z.object({
|
|
979
|
+
success: z.boolean(),
|
|
980
|
+
message: z.string().optional(),
|
|
981
|
+
journalMode: z.string().optional(),
|
|
982
|
+
previousMode: z.string().optional(),
|
|
983
|
+
walPages: z.number().optional(),
|
|
984
|
+
checkpointedPages: z.number().optional()
|
|
985
|
+
}).extend(ErrorResponseFields.shape);
|
|
986
|
+
|
|
987
|
+
export { ASSISTANT_FOCUSED, AnalyzeOutputSchema, AnalyzeSchema, AttachDatabaseOutputSchema, AttachDatabaseSchema, AuditCleanupOutputSchema, AuditDiffBackupOutputSchema, AuditGetBackupOutputSchema, AuditListBackupsOutputSchema, AuditListBackupsSchema, AuditRestoreBackupOutputSchema, AuditSearchOutputSchema, AuditSearchSchema, BackupOutputSchema, BackupSchema, DetachDatabaseOutputSchema, DetachDatabaseSchema, ErrorResponseFields, HIGH_PRIORITY, IndexStatsOutputSchema, IndexStatsSchema, IntegrityCheckOutputSchema, IntegrityCheckSchema, LOW_PRIORITY, MEDIUM_PRIORITY, NAME, OptimizeOutputSchema, OptimizeSchema, PragmaCompileOptionsOutputSchema, PragmaCompileOptionsSchema, PragmaDatabaseListOutputSchema, PragmaDatabaseListSchema, PragmaOptimizeOutputSchema, PragmaOptimizeSchema, PragmaSettingsOutputSchema, PragmaSettingsSchema, PragmaTableInfoOutputSchema, PragmaTableInfoSchema, READ_ONLY, ReindexOutputSchema, ReindexSchema, RestoreOutputSchema, RestoreSchema, SENSITIVE_KEY_PATTERN, SERVER_ICONS, SqlDumpOutputSchema, SqlDumpSchema, VERSION, VacuumIntoCopyOutputSchema, VacuumIntoCopySchema, VacuumOutputSchema, VerifyBackupOutputSchema, VerifyBackupSchema, WalOutputSchema, WalSchema, admin, adminFs, buildWhereClause, createColumnList, destructive, estimateTokens, getRequiredScope, getToolGroupIcon, idempotent, readOnly, redactObject, registerToolScope, sanitizeIdentifier, sanitizeWhereClause, validateAggregateFunction, validateIdentifier, validateJsonPath, validateSameDirPath, write, writeFs };
|