@nifrajs/mcp-db 2.8.1 → 2.8.2

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAwD,KAAK,SAAS,EAAE,MAAM,cAAc,CAAA;AAEnG,4EAA4E;AAC5E,MAAM,WAAW,kBAAkB;IACjC,kEAAkE;IAClE,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG;QAAE,GAAG,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,CAAA;KAAE,CAAA;IAC9D,mFAAmF;IACnF,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAC1B;AAED,iGAAiG;AACjG,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAA;IAC9B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAC1B;AAED,MAAM,WAAW,eAAe;IAC9B;;;;;OAKG;IACH,QAAQ,CAAC,SAAS,EAAE,CAAC,OAAO,EAAE,qBAAqB,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAClF,iDAAiD;IACjD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB,4DAA4D;IAC5D,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CACjC;AAED,MAAM,WAAW,yBAAyB;IACxC;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;IAClC,gEAAgE;IAChE,QAAQ,CAAC,QAAQ,CAAC,EAAE,eAAe,CAAA;IACnC,wEAAwE;IACxE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB;;;;;OAKG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAA;CACpC;AAED,qBAAa,gBAAiB,SAAQ,KAAK;gBAC7B,OAAO,EAAE,MAAM;CAI5B;AAoCD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,EAAE,EAAE,kBAAkB,EACtB,OAAO,EAAE,yBAAyB,GACjC,SAAS,CAkMX"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAwD,KAAK,SAAS,EAAE,MAAM,cAAc,CAAA;AAEnG,4EAA4E;AAC5E,MAAM,WAAW,kBAAkB;IACjC,kEAAkE;IAClE,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG;QAAE,GAAG,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,CAAA;KAAE,CAAA;IAC9D,mFAAmF;IACnF,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAC1B;AAED,iGAAiG;AACjG,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAA;IAC9B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAC1B;AAED,MAAM,WAAW,eAAe;IAC9B;;;;;OAKG;IACH,QAAQ,CAAC,SAAS,EAAE,CAAC,OAAO,EAAE,qBAAqB,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAClF,iDAAiD;IACjD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB,4DAA4D;IAC5D,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CACjC;AAED,MAAM,WAAW,yBAAyB;IACxC;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;IAClC,gEAAgE;IAChE,QAAQ,CAAC,QAAQ,CAAC,EAAE,eAAe,CAAA;IACnC,wEAAwE;IACxE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB;;;;;OAKG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAA;CACpC;AAED,qBAAa,gBAAiB,SAAQ,KAAK;gBAC7B,OAAO,EAAE,MAAM;CAI5B;AAwID;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,EAAE,EAAE,kBAAkB,EACtB,OAAO,EAAE,yBAAyB,GACjC,SAAS,CAiOX"}
package/dist/index.js CHANGED
@@ -48,15 +48,120 @@ const stripSqlNoise = (sql) => sql
48
48
  .replace(/"(?:[^"]|"")*"/g, '""')
49
49
  .replace(/--[^\n]*/g, " ")
50
50
  .replace(/\/\*[\s\S]*?\*\//g, " ");
51
- /** Reject multi-statement input: any `;` outside literals/comments except one trailing. */
51
+ /** Reject multi-statement input: allow one terminator only when it is the final character. */
52
52
  const isSingleStatement = (sql) => {
53
- const noise = stripSqlNoise(sql).trim().replace(/;$/, "");
54
- return !noise.includes(";");
53
+ let quote = null;
54
+ let lineComment = false;
55
+ let blockComment = false;
56
+ for (let i = 0; i < sql.length; i++) {
57
+ const char = sql[i];
58
+ const next = sql[i + 1];
59
+ if (lineComment) {
60
+ if (char === "\n")
61
+ lineComment = false;
62
+ continue;
63
+ }
64
+ if (blockComment) {
65
+ if (char === "*" && next === "/") {
66
+ blockComment = false;
67
+ i++;
68
+ }
69
+ continue;
70
+ }
71
+ if (quote !== null) {
72
+ if (char === quote) {
73
+ if (next === quote)
74
+ i++;
75
+ else
76
+ quote = null;
77
+ }
78
+ continue;
79
+ }
80
+ if (char === "'" || char === '"') {
81
+ quote = char;
82
+ continue;
83
+ }
84
+ if (char === "-" && next === "-") {
85
+ lineComment = true;
86
+ i++;
87
+ continue;
88
+ }
89
+ if (char === "/" && next === "*") {
90
+ blockComment = true;
91
+ i++;
92
+ continue;
93
+ }
94
+ if (char === ";") {
95
+ return sql.slice(i + 1).trim() === "";
96
+ }
97
+ }
98
+ return true;
55
99
  };
56
100
  const isReadStatement = (sql) => {
57
101
  const head = stripSqlNoise(sql).trim().toLowerCase();
58
102
  return head.startsWith("select") || head.startsWith("with");
59
103
  };
104
+ /** Remove one trailing statement terminator (and anything after it) while preserving literals and
105
+ * identifiers. Wrapping the query in a bounded subquery must not let a trailing comment consume the
106
+ * wrapper's closing parenthesis. */
107
+ function executableSql(sql) {
108
+ let quote = null;
109
+ let lineComment = false;
110
+ let lineCommentStart = -1;
111
+ let blockComment = false;
112
+ for (let i = 0; i < sql.length; i++) {
113
+ const char = sql[i];
114
+ const next = sql[i + 1];
115
+ if (lineComment) {
116
+ if (char === "\n") {
117
+ lineComment = false;
118
+ lineCommentStart = -1;
119
+ }
120
+ continue;
121
+ }
122
+ if (blockComment) {
123
+ if (char === "*" && next === "/") {
124
+ blockComment = false;
125
+ i++;
126
+ }
127
+ continue;
128
+ }
129
+ if (quote !== null) {
130
+ if (char === quote) {
131
+ if (next === quote)
132
+ i++;
133
+ else
134
+ quote = null;
135
+ }
136
+ continue;
137
+ }
138
+ if (char === "'" || char === '"') {
139
+ quote = char;
140
+ continue;
141
+ }
142
+ if (char === "-" && next === "-") {
143
+ lineComment = true;
144
+ lineCommentStart = i;
145
+ i++;
146
+ continue;
147
+ }
148
+ if (char === "/" && next === "*") {
149
+ blockComment = true;
150
+ i++;
151
+ continue;
152
+ }
153
+ if (char === ";")
154
+ return sql.slice(0, i).trim();
155
+ }
156
+ if (lineComment && lineCommentStart >= 0)
157
+ return sql.slice(0, lineCommentStart).trim();
158
+ return sql.trim();
159
+ }
160
+ function assertResultLimit(value, name) {
161
+ if (!Number.isSafeInteger(value) || value <= 0 || value >= Number.MAX_SAFE_INTEGER) {
162
+ throw new McpDbConfigError(`${name} must be a finite positive safe integer`);
163
+ }
164
+ }
60
165
  /**
61
166
  * Serve `db` as a mountable MCP server (`mcp.fetch` at `POST /mcp`). See module docs for the
62
167
  * security model. Throws {@link McpDbConfigError} on any unsafe configuration - always at
@@ -82,6 +187,8 @@ export function serveDatabaseAsMcp(db, options) {
82
187
  }
83
188
  const maxRows = options.runQuery?.maxRows ?? 100;
84
189
  const maxResultBytes = options.runQuery?.maxResultBytes ?? 100 * 1024;
190
+ assertResultLimit(maxRows, "maxRows");
191
+ assertResultLimit(maxResultBytes, "maxResultBytes");
85
192
  const listTables = defineMcpTool({
86
193
  name: "list_tables",
87
194
  description: "List the tables this server exposes, with row counts.",
@@ -139,15 +246,23 @@ export function serveDatabaseAsMcp(db, options) {
139
246
  }
140
247
  // Verify via the query plan that only allowlisted tables are touched. SQLite names every
141
248
  // scanned/searched relation in EXPLAIN QUERY PLAN detail rows.
249
+ const query = executableSql(sql);
142
250
  let planRows;
143
251
  try {
144
- planRows = db.prepare(`EXPLAIN QUERY PLAN ${sql}`).all();
252
+ planRows = db.prepare(`EXPLAIN QUERY PLAN ${query}`).all();
145
253
  }
146
254
  catch (error) {
147
255
  return { isError: true, text: `query failed to plan: ${String(error)}` };
148
256
  }
149
257
  for (const row of planRows) {
150
258
  const detail = typeof row.detail === "string" ? row.detail : "";
259
+ // SQLite also emits non-table nodes such as `SCAN CONSTANT ROW` for a
260
+ // constant-only SELECT. Only treat a scan/search target as a relation
261
+ // when it is not one of those planner pseudo-nodes.
262
+ if (/^SCAN\s+CONSTANT\s+ROW$/i.test(detail.trim()) ||
263
+ /^SCAN\s+SUBQUERY\s+\d+$/i.test(detail.trim())) {
264
+ continue;
265
+ }
151
266
  const match = /(?:SCAN|SEARCH)\s+(?:TABLE\s+)?([A-Za-z_][A-Za-z0-9_]*)/i.exec(detail);
152
267
  if (match !== null) {
153
268
  const relation = match[1]?.toLowerCase() ?? "";
@@ -159,20 +274,40 @@ export function serveDatabaseAsMcp(db, options) {
159
274
  }
160
275
  }
161
276
  }
162
- let rows;
277
+ let limitedRows;
163
278
  try {
164
- rows = db.prepare(sql).all();
279
+ // Fetch at most one row beyond the advertised cap. This keeps the database driver's
280
+ // materialization bounded even when the caller submits `SELECT * FROM a_huge_table`.
281
+ limitedRows = db
282
+ .prepare(`SELECT * FROM (${query}) AS "__nifra_result" LIMIT ${maxRows + 1}`)
283
+ .all();
165
284
  }
166
285
  catch (error) {
167
286
  return { isError: true, text: `query failed: ${String(error)}` };
168
287
  }
169
- const total = rows.length;
170
- let shown = Math.min(total, maxRows);
171
- let payload = rows.slice(0, shown);
288
+ const wasLimited = limitedRows.length > maxRows;
289
+ let total = limitedRows.length;
290
+ if (wasLimited) {
291
+ try {
292
+ const countRows = db
293
+ .prepare(`SELECT count(*) AS "__nifra_total" FROM (${query}) AS "__nifra_count"`)
294
+ .all();
295
+ const count = countRows[0]?.__nifra_total;
296
+ if (typeof count !== "number" || !Number.isSafeInteger(count) || count < maxRows) {
297
+ return { isError: true, text: "query failed: invalid row count" };
298
+ }
299
+ total = count;
300
+ }
301
+ catch (error) {
302
+ return { isError: true, text: `query failed to count results: ${String(error)}` };
303
+ }
304
+ }
305
+ let shown = Math.min(limitedRows.length, maxRows);
306
+ let payload = limitedRows.slice(0, shown);
172
307
  let serialized = JSON.stringify(payload);
173
308
  while (serialized.length > maxResultBytes && shown > 0) {
174
309
  shown = Math.max(0, Math.floor(shown / 2));
175
- payload = rows.slice(0, shown);
310
+ payload = limitedRows.slice(0, shown);
176
311
  serialized = JSON.stringify(payload);
177
312
  }
178
313
  const truncated = shown < total;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nifrajs/mcp-db",
3
- "version": "2.8.1",
3
+ "version": "2.8.2",
4
4
  "description": "Serve a SQLite database as a fail-closed MCP server - allowlisted schema tools by default, opt-in read-only queries with plan verification.",
5
5
  "keywords": [
6
6
  "bun",
@@ -35,7 +35,7 @@
35
35
  "access": "public"
36
36
  },
37
37
  "dependencies": {
38
- "@nifrajs/mcp": "2.8.1"
38
+ "@nifrajs/mcp": "2.8.2"
39
39
  },
40
40
  "repository": {
41
41
  "type": "git",
package/src/index.ts CHANGED
@@ -104,10 +104,51 @@ const stripSqlNoise = (sql: string): string =>
104
104
  .replace(/--[^\n]*/g, " ")
105
105
  .replace(/\/\*[\s\S]*?\*\//g, " ")
106
106
 
107
- /** Reject multi-statement input: any `;` outside literals/comments except one trailing. */
107
+ /** Reject multi-statement input: allow one terminator only when it is the final character. */
108
108
  const isSingleStatement = (sql: string): boolean => {
109
- const noise = stripSqlNoise(sql).trim().replace(/;$/, "")
110
- return !noise.includes(";")
109
+ let quote: "'" | '"' | null = null
110
+ let lineComment = false
111
+ let blockComment = false
112
+ for (let i = 0; i < sql.length; i++) {
113
+ const char = sql[i]
114
+ const next = sql[i + 1]
115
+ if (lineComment) {
116
+ if (char === "\n") lineComment = false
117
+ continue
118
+ }
119
+ if (blockComment) {
120
+ if (char === "*" && next === "/") {
121
+ blockComment = false
122
+ i++
123
+ }
124
+ continue
125
+ }
126
+ if (quote !== null) {
127
+ if (char === quote) {
128
+ if (next === quote) i++
129
+ else quote = null
130
+ }
131
+ continue
132
+ }
133
+ if (char === "'" || char === '"') {
134
+ quote = char
135
+ continue
136
+ }
137
+ if (char === "-" && next === "-") {
138
+ lineComment = true
139
+ i++
140
+ continue
141
+ }
142
+ if (char === "/" && next === "*") {
143
+ blockComment = true
144
+ i++
145
+ continue
146
+ }
147
+ if (char === ";") {
148
+ return sql.slice(i + 1).trim() === ""
149
+ }
150
+ }
151
+ return true
111
152
  }
112
153
 
113
154
  const isReadStatement = (sql: string): boolean => {
@@ -115,6 +156,65 @@ const isReadStatement = (sql: string): boolean => {
115
156
  return head.startsWith("select") || head.startsWith("with")
116
157
  }
117
158
 
159
+ /** Remove one trailing statement terminator (and anything after it) while preserving literals and
160
+ * identifiers. Wrapping the query in a bounded subquery must not let a trailing comment consume the
161
+ * wrapper's closing parenthesis. */
162
+ function executableSql(sql: string): string {
163
+ let quote: "'" | '"' | null = null
164
+ let lineComment = false
165
+ let lineCommentStart = -1
166
+ let blockComment = false
167
+ for (let i = 0; i < sql.length; i++) {
168
+ const char = sql[i]
169
+ const next = sql[i + 1]
170
+ if (lineComment) {
171
+ if (char === "\n") {
172
+ lineComment = false
173
+ lineCommentStart = -1
174
+ }
175
+ continue
176
+ }
177
+ if (blockComment) {
178
+ if (char === "*" && next === "/") {
179
+ blockComment = false
180
+ i++
181
+ }
182
+ continue
183
+ }
184
+ if (quote !== null) {
185
+ if (char === quote) {
186
+ if (next === quote) i++
187
+ else quote = null
188
+ }
189
+ continue
190
+ }
191
+ if (char === "'" || char === '"') {
192
+ quote = char
193
+ continue
194
+ }
195
+ if (char === "-" && next === "-") {
196
+ lineComment = true
197
+ lineCommentStart = i
198
+ i++
199
+ continue
200
+ }
201
+ if (char === "/" && next === "*") {
202
+ blockComment = true
203
+ i++
204
+ continue
205
+ }
206
+ if (char === ";") return sql.slice(0, i).trim()
207
+ }
208
+ if (lineComment && lineCommentStart >= 0) return sql.slice(0, lineCommentStart).trim()
209
+ return sql.trim()
210
+ }
211
+
212
+ function assertResultLimit(value: number, name: string): void {
213
+ if (!Number.isSafeInteger(value) || value <= 0 || value >= Number.MAX_SAFE_INTEGER) {
214
+ throw new McpDbConfigError(`${name} must be a finite positive safe integer`)
215
+ }
216
+ }
217
+
118
218
  /**
119
219
  * Serve `db` as a mountable MCP server (`mcp.fetch` at `POST /mcp`). See module docs for the
120
220
  * security model. Throws {@link McpDbConfigError} on any unsafe configuration - always at
@@ -150,6 +250,8 @@ export function serveDatabaseAsMcp(
150
250
 
151
251
  const maxRows = options.runQuery?.maxRows ?? 100
152
252
  const maxResultBytes = options.runQuery?.maxResultBytes ?? 100 * 1024
253
+ assertResultLimit(maxRows, "maxRows")
254
+ assertResultLimit(maxResultBytes, "maxResultBytes")
153
255
 
154
256
  const listTables = defineMcpTool({
155
257
  name: "list_tables",
@@ -214,14 +316,24 @@ export function serveDatabaseAsMcp(
214
316
 
215
317
  // Verify via the query plan that only allowlisted tables are touched. SQLite names every
216
318
  // scanned/searched relation in EXPLAIN QUERY PLAN detail rows.
319
+ const query = executableSql(sql)
217
320
  let planRows: Array<{ detail?: unknown }>
218
321
  try {
219
- planRows = db.prepare(`EXPLAIN QUERY PLAN ${sql}`).all() as Array<{ detail?: unknown }>
322
+ planRows = db.prepare(`EXPLAIN QUERY PLAN ${query}`).all() as Array<{ detail?: unknown }>
220
323
  } catch (error) {
221
324
  return { isError: true, text: `query failed to plan: ${String(error)}` }
222
325
  }
223
326
  for (const row of planRows) {
224
327
  const detail = typeof row.detail === "string" ? row.detail : ""
328
+ // SQLite also emits non-table nodes such as `SCAN CONSTANT ROW` for a
329
+ // constant-only SELECT. Only treat a scan/search target as a relation
330
+ // when it is not one of those planner pseudo-nodes.
331
+ if (
332
+ /^SCAN\s+CONSTANT\s+ROW$/i.test(detail.trim()) ||
333
+ /^SCAN\s+SUBQUERY\s+\d+$/i.test(detail.trim())
334
+ ) {
335
+ continue
336
+ }
225
337
  const match = /(?:SCAN|SEARCH)\s+(?:TABLE\s+)?([A-Za-z_][A-Za-z0-9_]*)/i.exec(detail)
226
338
  if (match !== null) {
227
339
  const relation = match[1]?.toLowerCase() ?? ""
@@ -234,20 +346,39 @@ export function serveDatabaseAsMcp(
234
346
  }
235
347
  }
236
348
 
237
- let rows: unknown[]
349
+ let limitedRows: unknown[]
238
350
  try {
239
- rows = db.prepare(sql).all()
351
+ // Fetch at most one row beyond the advertised cap. This keeps the database driver's
352
+ // materialization bounded even when the caller submits `SELECT * FROM a_huge_table`.
353
+ limitedRows = db
354
+ .prepare(`SELECT * FROM (${query}) AS "__nifra_result" LIMIT ${maxRows + 1}`)
355
+ .all()
240
356
  } catch (error) {
241
357
  return { isError: true, text: `query failed: ${String(error)}` }
242
358
  }
243
359
 
244
- const total = rows.length
245
- let shown = Math.min(total, maxRows)
246
- let payload = rows.slice(0, shown)
360
+ const wasLimited = limitedRows.length > maxRows
361
+ let total = limitedRows.length
362
+ if (wasLimited) {
363
+ try {
364
+ const countRows = db
365
+ .prepare(`SELECT count(*) AS "__nifra_total" FROM (${query}) AS "__nifra_count"`)
366
+ .all() as Array<{ __nifra_total?: unknown }>
367
+ const count = countRows[0]?.__nifra_total
368
+ if (typeof count !== "number" || !Number.isSafeInteger(count) || count < maxRows) {
369
+ return { isError: true, text: "query failed: invalid row count" }
370
+ }
371
+ total = count
372
+ } catch (error) {
373
+ return { isError: true, text: `query failed to count results: ${String(error)}` }
374
+ }
375
+ }
376
+ let shown = Math.min(limitedRows.length, maxRows)
377
+ let payload = limitedRows.slice(0, shown)
247
378
  let serialized = JSON.stringify(payload)
248
379
  while (serialized.length > maxResultBytes && shown > 0) {
249
380
  shown = Math.max(0, Math.floor(shown / 2))
250
- payload = rows.slice(0, shown)
381
+ payload = limitedRows.slice(0, shown)
251
382
  serialized = JSON.stringify(payload)
252
383
  }
253
384
  const truncated = shown < total