@nifrajs/mcp-db 2.2.0 → 2.3.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 CHANGED
@@ -22,7 +22,7 @@ because it cannot provide the same engine-level read-only guarantee.
22
22
 
23
23
  ## For AI agents
24
24
 
25
- Start with [`LLM.md`](./LLM.md) — this package's contract card (the exports you call + its footguns),
25
+ Start with [`LLM.md`](./LLM.md) - this package's contract card (the exports you call + its footguns),
26
26
  one cheap read instead of the whole corpus. For the wider framework: the repo's
27
27
  [`AGENTS.md`](../../AGENTS.md) is the copy-paste quick reference, and
28
28
  [`llms-full.txt`](../../llms-full.txt) is the full machine-readable corpus. Run `nifra check` as the
package/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  /**
2
- * `@nifrajs/mcp-db` — serve a SQLite database as an MCP server, fail-closed.
2
+ * `@nifrajs/mcp-db` - serve a SQLite database as an MCP server, fail-closed.
3
3
  *
4
4
  * Out of the box only SCHEMA tools are exposed (`list_tables`, `describe_table`), and only for
5
5
  * tables on the explicit `tables` allowlist. Query execution is OPT-IN and requires BOTH the
6
- * allowlist and an `authorize` hook — a database is PII by default, and an MCP client is an LLM;
6
+ * allowlist and an `authorize` hook - a database is PII by default, and an MCP client is an LLM;
7
7
  * this package refuses to be mounted open rather than defaulting open.
8
8
  *
9
9
  * Read-only is enforced in layers, not promised: `PRAGMA query_only = ON` on the connection
@@ -12,7 +12,7 @@
12
12
  * capped by rows and bytes (an LLM does not need 100k rows; a transport does not want them) with
13
13
  * an explicit `truncated` marker.
14
14
  *
15
- * Bun/Node SQLite only (anything `bun:sqlite`-shaped, bound structurally — no driver dependency).
15
+ * Bun/Node SQLite only (anything `bun:sqlite`-shaped, bound structurally - no driver dependency).
16
16
  * There is deliberately NO D1 mode: D1 has no `query_only`, so read-only cannot be guaranteed.
17
17
  *
18
18
  * import { Database } from "bun:sqlite"
@@ -32,7 +32,7 @@ export interface SqliteDatabaseLike {
32
32
  /** Execute a statement for its side effect (used only for `PRAGMA query_only`). */
33
33
  run(sql: string): unknown;
34
34
  }
35
- /** Context forwarded to `authorize` — the inbound HTTP Request carrying the `run_query` call. */
35
+ /** Context forwarded to `authorize` - the inbound HTTP Request carrying the `run_query` call. */
36
36
  export interface McpDbAuthorizeContext {
37
37
  readonly toolName: "run_query";
38
38
  readonly request: Request;
@@ -41,8 +41,8 @@ export interface RunQueryOptions {
41
41
  /**
42
42
  * REQUIRED. Authorize each `run_query` call at the transport boundary (inspect the inbound
43
43
  * Request's auth). Return false to reject with a JSON-RPC error. There is no unauthenticated
44
- * mode — schema tools are the anonymous surface. Note: `run_query` is therefore HTTP-only;
45
- * direct `handle()` dispatch rejects it (no Request to authorize — fails closed).
44
+ * mode - schema tools are the anonymous surface. Note: `run_query` is therefore HTTP-only;
45
+ * direct `handle()` dispatch rejects it (no Request to authorize - fails closed).
46
46
  */
47
47
  readonly authorize: (context: McpDbAuthorizeContext) => boolean | Promise<boolean>;
48
48
  /** Max rows returned per query (default 100). */
@@ -64,9 +64,9 @@ export interface ServeDatabaseAsMcpOptions {
64
64
  readonly version?: string;
65
65
  /**
66
66
  * Set `PRAGMA query_only = ON` on the connection at construction (default true). Disable ONLY
67
- * when the same connection must also serve writes elsewhere in the app — with it disabled,
67
+ * when the same connection must also serve writes elsewhere in the app - with it disabled,
68
68
  * `run_query` still gates on SELECT/WITH + plan verification, but the engine-level guarantee is
69
- * yours to provide (e.g. open a second, read-only connection for the MCP mount — preferred).
69
+ * yours to provide (e.g. open a second, read-only connection for the MCP mount - preferred).
70
70
  */
71
71
  readonly enforceQueryOnly?: boolean;
72
72
  }
@@ -75,7 +75,7 @@ export declare class McpDbConfigError extends Error {
75
75
  }
76
76
  /**
77
77
  * Serve `db` as a mountable MCP server (`mcp.fetch` at `POST /mcp`). See module docs for the
78
- * security model. Throws {@link McpDbConfigError} on any unsafe configuration — always at
78
+ * security model. Throws {@link McpDbConfigError} on any unsafe configuration - always at
79
79
  * construction (boot), never at request time.
80
80
  */
81
81
  export declare function serveDatabaseAsMcp(db: SqliteDatabaseLike, options: ServeDatabaseAsMcpOptions): McpServer;
@@ -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;AAwBD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,EAAE,EAAE,kBAAkB,EACtB,OAAO,EAAE,yBAAyB,GACjC,SAAS,CAgMX"}
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"}
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  /**
2
- * `@nifrajs/mcp-db` — serve a SQLite database as an MCP server, fail-closed.
2
+ * `@nifrajs/mcp-db` - serve a SQLite database as an MCP server, fail-closed.
3
3
  *
4
4
  * Out of the box only SCHEMA tools are exposed (`list_tables`, `describe_table`), and only for
5
5
  * tables on the explicit `tables` allowlist. Query execution is OPT-IN and requires BOTH the
6
- * allowlist and an `authorize` hook — a database is PII by default, and an MCP client is an LLM;
6
+ * allowlist and an `authorize` hook - a database is PII by default, and an MCP client is an LLM;
7
7
  * this package refuses to be mounted open rather than defaulting open.
8
8
  *
9
9
  * Read-only is enforced in layers, not promised: `PRAGMA query_only = ON` on the connection
@@ -12,7 +12,7 @@
12
12
  * capped by rows and bytes (an LLM does not need 100k rows; a transport does not want them) with
13
13
  * an explicit `truncated` marker.
14
14
  *
15
- * Bun/Node SQLite only (anything `bun:sqlite`-shaped, bound structurally — no driver dependency).
15
+ * Bun/Node SQLite only (anything `bun:sqlite`-shaped, bound structurally - no driver dependency).
16
16
  * There is deliberately NO D1 mode: D1 has no `query_only`, so read-only cannot be guaranteed.
17
17
  *
18
18
  * import { Database } from "bun:sqlite"
@@ -29,8 +29,19 @@ export class McpDbConfigError extends Error {
29
29
  this.name = "McpDbConfigError";
30
30
  }
31
31
  }
32
- /** A safe SQL identifier — quoting is not enough for PRAGMA args, so reject instead. */
32
+ /** A safe SQL identifier - quoting is not enough for PRAGMA args, so reject instead. */
33
33
  const SAFE_IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;
34
+ /** Build SQL containing identifiers only after validating every substitution at this boundary. */
35
+ function sqlIdentifiers(strings, ...identifiers) {
36
+ let sql = strings[0] ?? "";
37
+ for (const [index, identifier] of identifiers.entries()) {
38
+ if (!SAFE_IDENTIFIER.test(identifier)) {
39
+ throw new McpDbConfigError(`unsafe SQL identifier ${JSON.stringify(identifier)}`);
40
+ }
41
+ sql += identifier + (strings[index + 1] ?? "");
42
+ }
43
+ return sql;
44
+ }
34
45
  const stripSqlNoise = (sql) => sql
35
46
  // Strings first so comment markers inside literals don't count.
36
47
  .replace(/'(?:[^']|'')*'/g, "''")
@@ -48,12 +59,12 @@ const isReadStatement = (sql) => {
48
59
  };
49
60
  /**
50
61
  * Serve `db` as a mountable MCP server (`mcp.fetch` at `POST /mcp`). See module docs for the
51
- * security model. Throws {@link McpDbConfigError} on any unsafe configuration — always at
62
+ * security model. Throws {@link McpDbConfigError} on any unsafe configuration - always at
52
63
  * construction (boot), never at request time.
53
64
  */
54
65
  export function serveDatabaseAsMcp(db, options) {
55
66
  if (options.tables.length === 0) {
56
- throw new McpDbConfigError("an explicit non-empty `tables` allowlist is required — this package never defaults to exposing a whole database");
67
+ throw new McpDbConfigError("an explicit non-empty `tables` allowlist is required - this package never defaults to exposing a whole database");
57
68
  }
58
69
  for (const table of options.tables) {
59
70
  if (!SAFE_IDENTIFIER.test(table)) {
@@ -66,7 +77,7 @@ export function serveDatabaseAsMcp(db, options) {
66
77
  db.run("PRAGMA query_only = ON");
67
78
  }
68
79
  catch (error) {
69
- throw new McpDbConfigError(`could not set PRAGMA query_only on the connection (${String(error)}) — pass a bun:sqlite-shaped database or set enforceQueryOnly: false with a read-only connection`);
80
+ throw new McpDbConfigError(`could not set PRAGMA query_only on the connection (${String(error)}) - pass a bun:sqlite-shaped database or set enforceQueryOnly: false with a read-only connection`);
70
81
  }
71
82
  }
72
83
  const maxRows = options.runQuery?.maxRows ?? 100;
@@ -76,7 +87,9 @@ export function serveDatabaseAsMcp(db, options) {
76
87
  description: "List the tables this server exposes, with row counts.",
77
88
  handler: () => {
78
89
  const rows = options.tables.map((table) => {
79
- const [count] = db.prepare(`SELECT count(*) AS n FROM "${table}"`).all();
90
+ const [count] = db
91
+ .prepare(sqlIdentifiers `SELECT count(*) AS n FROM "${table}"`)
92
+ .all();
80
93
  return { table, rows: count?.n ?? 0 };
81
94
  });
82
95
  return { text: JSON.stringify(rows), structuredContent: { tables: rows } };
@@ -97,7 +110,7 @@ export function serveDatabaseAsMcp(db, options) {
97
110
  }
98
111
  // Identifier is allowlist-verified (and the allowlist is identifier-checked at boot),
99
112
  // so interpolation here cannot inject.
100
- const columns = db.prepare(`PRAGMA table_info("${table}")`).all();
113
+ const columns = db.prepare(sqlIdentifiers `PRAGMA table_info("${table}")`).all();
101
114
  return { text: JSON.stringify(columns), structuredContent: { table, columns } };
102
115
  },
103
116
  });
@@ -180,7 +193,7 @@ export function serveDatabaseAsMcp(db, options) {
180
193
  if (options.runQuery === undefined)
181
194
  return server;
182
195
  // `run_query` is authorized at the TRANSPORT boundary, where the inbound Request's credentials
183
- // are visible — the handler itself performs no auth, so every path to it must pass this gate:
196
+ // are visible - the handler itself performs no auth, so every path to it must pass this gate:
184
197
  // the wrapped fetch authorizes, and direct handle() dispatch fails closed (no Request → no auth).
185
198
  const { authorize } = options.runQuery;
186
199
  const rpcId = (id) => typeof id === "string" || typeof id === "number" ? id : null;
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,7 +1,7 @@
1
1
  {
2
2
  "name": "@nifrajs/mcp-db",
3
- "version": "2.2.0",
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.",
3
+ "version": "2.3.0",
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",
7
7
  "typescript",
@@ -35,7 +35,7 @@
35
35
  "access": "public"
36
36
  },
37
37
  "dependencies": {
38
- "@nifrajs/mcp": "2.2.0"
38
+ "@nifrajs/mcp": "2.3.0"
39
39
  },
40
40
  "repository": {
41
41
  "type": "git",
package/src/index.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  /**
2
- * `@nifrajs/mcp-db` — serve a SQLite database as an MCP server, fail-closed.
2
+ * `@nifrajs/mcp-db` - serve a SQLite database as an MCP server, fail-closed.
3
3
  *
4
4
  * Out of the box only SCHEMA tools are exposed (`list_tables`, `describe_table`), and only for
5
5
  * tables on the explicit `tables` allowlist. Query execution is OPT-IN and requires BOTH the
6
- * allowlist and an `authorize` hook — a database is PII by default, and an MCP client is an LLM;
6
+ * allowlist and an `authorize` hook - a database is PII by default, and an MCP client is an LLM;
7
7
  * this package refuses to be mounted open rather than defaulting open.
8
8
  *
9
9
  * Read-only is enforced in layers, not promised: `PRAGMA query_only = ON` on the connection
@@ -12,7 +12,7 @@
12
12
  * capped by rows and bytes (an LLM does not need 100k rows; a transport does not want them) with
13
13
  * an explicit `truncated` marker.
14
14
  *
15
- * Bun/Node SQLite only (anything `bun:sqlite`-shaped, bound structurally — no driver dependency).
15
+ * Bun/Node SQLite only (anything `bun:sqlite`-shaped, bound structurally - no driver dependency).
16
16
  * There is deliberately NO D1 mode: D1 has no `query_only`, so read-only cannot be guaranteed.
17
17
  *
18
18
  * import { Database } from "bun:sqlite"
@@ -33,7 +33,7 @@ export interface SqliteDatabaseLike {
33
33
  run(sql: string): unknown
34
34
  }
35
35
 
36
- /** Context forwarded to `authorize` — the inbound HTTP Request carrying the `run_query` call. */
36
+ /** Context forwarded to `authorize` - the inbound HTTP Request carrying the `run_query` call. */
37
37
  export interface McpDbAuthorizeContext {
38
38
  readonly toolName: "run_query"
39
39
  readonly request: Request
@@ -43,8 +43,8 @@ export interface RunQueryOptions {
43
43
  /**
44
44
  * REQUIRED. Authorize each `run_query` call at the transport boundary (inspect the inbound
45
45
  * Request's auth). Return false to reject with a JSON-RPC error. There is no unauthenticated
46
- * mode — schema tools are the anonymous surface. Note: `run_query` is therefore HTTP-only;
47
- * direct `handle()` dispatch rejects it (no Request to authorize — fails closed).
46
+ * mode - schema tools are the anonymous surface. Note: `run_query` is therefore HTTP-only;
47
+ * direct `handle()` dispatch rejects it (no Request to authorize - fails closed).
48
48
  */
49
49
  readonly authorize: (context: McpDbAuthorizeContext) => boolean | Promise<boolean>
50
50
  /** Max rows returned per query (default 100). */
@@ -67,9 +67,9 @@ export interface ServeDatabaseAsMcpOptions {
67
67
  readonly version?: string
68
68
  /**
69
69
  * Set `PRAGMA query_only = ON` on the connection at construction (default true). Disable ONLY
70
- * when the same connection must also serve writes elsewhere in the app — with it disabled,
70
+ * when the same connection must also serve writes elsewhere in the app - with it disabled,
71
71
  * `run_query` still gates on SELECT/WITH + plan verification, but the engine-level guarantee is
72
- * yours to provide (e.g. open a second, read-only connection for the MCP mount — preferred).
72
+ * yours to provide (e.g. open a second, read-only connection for the MCP mount - preferred).
73
73
  */
74
74
  readonly enforceQueryOnly?: boolean
75
75
  }
@@ -81,9 +81,21 @@ export class McpDbConfigError extends Error {
81
81
  }
82
82
  }
83
83
 
84
- /** A safe SQL identifier — quoting is not enough for PRAGMA args, so reject instead. */
84
+ /** A safe SQL identifier - quoting is not enough for PRAGMA args, so reject instead. */
85
85
  const SAFE_IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/
86
86
 
87
+ /** Build SQL containing identifiers only after validating every substitution at this boundary. */
88
+ function sqlIdentifiers(strings: TemplateStringsArray, ...identifiers: readonly string[]): string {
89
+ let sql = strings[0] ?? ""
90
+ for (const [index, identifier] of identifiers.entries()) {
91
+ if (!SAFE_IDENTIFIER.test(identifier)) {
92
+ throw new McpDbConfigError(`unsafe SQL identifier ${JSON.stringify(identifier)}`)
93
+ }
94
+ sql += identifier + (strings[index + 1] ?? "")
95
+ }
96
+ return sql
97
+ }
98
+
87
99
  const stripSqlNoise = (sql: string): string =>
88
100
  sql
89
101
  // Strings first so comment markers inside literals don't count.
@@ -105,7 +117,7 @@ const isReadStatement = (sql: string): boolean => {
105
117
 
106
118
  /**
107
119
  * Serve `db` as a mountable MCP server (`mcp.fetch` at `POST /mcp`). See module docs for the
108
- * security model. Throws {@link McpDbConfigError} on any unsafe configuration — always at
120
+ * security model. Throws {@link McpDbConfigError} on any unsafe configuration - always at
109
121
  * construction (boot), never at request time.
110
122
  */
111
123
  export function serveDatabaseAsMcp(
@@ -114,7 +126,7 @@ export function serveDatabaseAsMcp(
114
126
  ): McpServer {
115
127
  if (options.tables.length === 0) {
116
128
  throw new McpDbConfigError(
117
- "an explicit non-empty `tables` allowlist is required — this package never defaults to exposing a whole database",
129
+ "an explicit non-empty `tables` allowlist is required - this package never defaults to exposing a whole database",
118
130
  )
119
131
  }
120
132
  for (const table of options.tables) {
@@ -131,7 +143,7 @@ export function serveDatabaseAsMcp(
131
143
  db.run("PRAGMA query_only = ON")
132
144
  } catch (error) {
133
145
  throw new McpDbConfigError(
134
- `could not set PRAGMA query_only on the connection (${String(error)}) — pass a bun:sqlite-shaped database or set enforceQueryOnly: false with a read-only connection`,
146
+ `could not set PRAGMA query_only on the connection (${String(error)}) - pass a bun:sqlite-shaped database or set enforceQueryOnly: false with a read-only connection`,
135
147
  )
136
148
  }
137
149
  }
@@ -144,7 +156,9 @@ export function serveDatabaseAsMcp(
144
156
  description: "List the tables this server exposes, with row counts.",
145
157
  handler: () => {
146
158
  const rows = options.tables.map((table) => {
147
- const [count] = db.prepare(`SELECT count(*) AS n FROM "${table}"`).all() as Array<{
159
+ const [count] = db
160
+ .prepare(sqlIdentifiers`SELECT count(*) AS n FROM "${table}"`)
161
+ .all() as Array<{
148
162
  n: number
149
163
  }>
150
164
  return { table, rows: count?.n ?? 0 }
@@ -168,7 +182,7 @@ export function serveDatabaseAsMcp(
168
182
  }
169
183
  // Identifier is allowlist-verified (and the allowlist is identifier-checked at boot),
170
184
  // so interpolation here cannot inject.
171
- const columns = db.prepare(`PRAGMA table_info("${table}")`).all()
185
+ const columns = db.prepare(sqlIdentifiers`PRAGMA table_info("${table}")`).all()
172
186
  return { text: JSON.stringify(columns), structuredContent: { table, columns } }
173
187
  },
174
188
  })
@@ -256,7 +270,7 @@ export function serveDatabaseAsMcp(
256
270
  if (options.runQuery === undefined) return server
257
271
 
258
272
  // `run_query` is authorized at the TRANSPORT boundary, where the inbound Request's credentials
259
- // are visible — the handler itself performs no auth, so every path to it must pass this gate:
273
+ // are visible - the handler itself performs no auth, so every path to it must pass this gate:
260
274
  // the wrapped fetch authorizes, and direct handle() dispatch fails closed (no Request → no auth).
261
275
  const { authorize } = options.runQuery
262
276