@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.
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +145 -10
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +141 -10
package/dist/index.d.ts.map
CHANGED
|
@@ -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;
|
|
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:
|
|
51
|
+
/** Reject multi-statement input: allow one terminator only when it is the final character. */
|
|
52
52
|
const isSingleStatement = (sql) => {
|
|
53
|
-
|
|
54
|
-
|
|
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 ${
|
|
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
|
|
277
|
+
let limitedRows;
|
|
163
278
|
try {
|
|
164
|
-
|
|
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
|
|
170
|
-
let
|
|
171
|
-
|
|
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 =
|
|
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.
|
|
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.
|
|
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:
|
|
107
|
+
/** Reject multi-statement input: allow one terminator only when it is the final character. */
|
|
108
108
|
const isSingleStatement = (sql: string): boolean => {
|
|
109
|
-
|
|
110
|
-
|
|
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 ${
|
|
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
|
|
349
|
+
let limitedRows: unknown[]
|
|
238
350
|
try {
|
|
239
|
-
|
|
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
|
|
245
|
-
let
|
|
246
|
-
|
|
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 =
|
|
381
|
+
payload = limitedRows.slice(0, shown)
|
|
251
382
|
serialized = JSON.stringify(payload)
|
|
252
383
|
}
|
|
253
384
|
const truncated = shown < total
|