db-mcp 1.0.1

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.
Files changed (208) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +860 -0
  3. package/dist/adapters/DatabaseAdapter.d.ts +141 -0
  4. package/dist/adapters/DatabaseAdapter.d.ts.map +1 -0
  5. package/dist/adapters/DatabaseAdapter.js +131 -0
  6. package/dist/adapters/DatabaseAdapter.js.map +1 -0
  7. package/dist/adapters/sqlite/SchemaManager.d.ts +58 -0
  8. package/dist/adapters/sqlite/SchemaManager.d.ts.map +1 -0
  9. package/dist/adapters/sqlite/SchemaManager.js +187 -0
  10. package/dist/adapters/sqlite/SchemaManager.js.map +1 -0
  11. package/dist/adapters/sqlite/SqliteAdapter.d.ts +161 -0
  12. package/dist/adapters/sqlite/SqliteAdapter.d.ts.map +1 -0
  13. package/dist/adapters/sqlite/SqliteAdapter.js +741 -0
  14. package/dist/adapters/sqlite/SqliteAdapter.js.map +1 -0
  15. package/dist/adapters/sqlite/index.d.ts +9 -0
  16. package/dist/adapters/sqlite/index.d.ts.map +1 -0
  17. package/dist/adapters/sqlite/index.js +8 -0
  18. package/dist/adapters/sqlite/index.js.map +1 -0
  19. package/dist/adapters/sqlite/json-utils.d.ts +100 -0
  20. package/dist/adapters/sqlite/json-utils.d.ts.map +1 -0
  21. package/dist/adapters/sqlite/json-utils.js +274 -0
  22. package/dist/adapters/sqlite/json-utils.js.map +1 -0
  23. package/dist/adapters/sqlite/output-schemas.d.ts +1187 -0
  24. package/dist/adapters/sqlite/output-schemas.d.ts.map +1 -0
  25. package/dist/adapters/sqlite/output-schemas.js +1337 -0
  26. package/dist/adapters/sqlite/output-schemas.js.map +1 -0
  27. package/dist/adapters/sqlite/prompts.d.ts +13 -0
  28. package/dist/adapters/sqlite/prompts.d.ts.map +1 -0
  29. package/dist/adapters/sqlite/prompts.js +605 -0
  30. package/dist/adapters/sqlite/prompts.js.map +1 -0
  31. package/dist/adapters/sqlite/resources.d.ts +13 -0
  32. package/dist/adapters/sqlite/resources.d.ts.map +1 -0
  33. package/dist/adapters/sqlite/resources.js +251 -0
  34. package/dist/adapters/sqlite/resources.js.map +1 -0
  35. package/dist/adapters/sqlite/tools/admin.d.ts +14 -0
  36. package/dist/adapters/sqlite/tools/admin.d.ts.map +1 -0
  37. package/dist/adapters/sqlite/tools/admin.js +788 -0
  38. package/dist/adapters/sqlite/tools/admin.js.map +1 -0
  39. package/dist/adapters/sqlite/tools/core.d.ts +25 -0
  40. package/dist/adapters/sqlite/tools/core.d.ts.map +1 -0
  41. package/dist/adapters/sqlite/tools/core.js +359 -0
  42. package/dist/adapters/sqlite/tools/core.js.map +1 -0
  43. package/dist/adapters/sqlite/tools/fts.d.ts +13 -0
  44. package/dist/adapters/sqlite/tools/fts.d.ts.map +1 -0
  45. package/dist/adapters/sqlite/tools/fts.js +347 -0
  46. package/dist/adapters/sqlite/tools/fts.js.map +1 -0
  47. package/dist/adapters/sqlite/tools/geo.d.ts +14 -0
  48. package/dist/adapters/sqlite/tools/geo.d.ts.map +1 -0
  49. package/dist/adapters/sqlite/tools/geo.js +252 -0
  50. package/dist/adapters/sqlite/tools/geo.js.map +1 -0
  51. package/dist/adapters/sqlite/tools/index.d.ts +30 -0
  52. package/dist/adapters/sqlite/tools/index.d.ts.map +1 -0
  53. package/dist/adapters/sqlite/tools/index.js +61 -0
  54. package/dist/adapters/sqlite/tools/index.js.map +1 -0
  55. package/dist/adapters/sqlite/tools/json-helpers.d.ts +14 -0
  56. package/dist/adapters/sqlite/tools/json-helpers.d.ts.map +1 -0
  57. package/dist/adapters/sqlite/tools/json-helpers.js +477 -0
  58. package/dist/adapters/sqlite/tools/json-helpers.js.map +1 -0
  59. package/dist/adapters/sqlite/tools/json-operations.d.ts +14 -0
  60. package/dist/adapters/sqlite/tools/json-operations.d.ts.map +1 -0
  61. package/dist/adapters/sqlite/tools/json-operations.js +839 -0
  62. package/dist/adapters/sqlite/tools/json-operations.js.map +1 -0
  63. package/dist/adapters/sqlite/tools/stats.d.ts +15 -0
  64. package/dist/adapters/sqlite/tools/stats.d.ts.map +1 -0
  65. package/dist/adapters/sqlite/tools/stats.js +1219 -0
  66. package/dist/adapters/sqlite/tools/stats.js.map +1 -0
  67. package/dist/adapters/sqlite/tools/text.d.ts +14 -0
  68. package/dist/adapters/sqlite/tools/text.d.ts.map +1 -0
  69. package/dist/adapters/sqlite/tools/text.js +1141 -0
  70. package/dist/adapters/sqlite/tools/text.js.map +1 -0
  71. package/dist/adapters/sqlite/tools/vector.d.ts +14 -0
  72. package/dist/adapters/sqlite/tools/vector.d.ts.map +1 -0
  73. package/dist/adapters/sqlite/tools/vector.js +613 -0
  74. package/dist/adapters/sqlite/tools/vector.js.map +1 -0
  75. package/dist/adapters/sqlite/tools/virtual.d.ts +13 -0
  76. package/dist/adapters/sqlite/tools/virtual.d.ts.map +1 -0
  77. package/dist/adapters/sqlite/tools/virtual.js +930 -0
  78. package/dist/adapters/sqlite/tools/virtual.js.map +1 -0
  79. package/dist/adapters/sqlite/types.d.ts +207 -0
  80. package/dist/adapters/sqlite/types.d.ts.map +1 -0
  81. package/dist/adapters/sqlite/types.js +186 -0
  82. package/dist/adapters/sqlite/types.js.map +1 -0
  83. package/dist/adapters/sqlite-native/NativeSqliteAdapter.d.ts +163 -0
  84. package/dist/adapters/sqlite-native/NativeSqliteAdapter.d.ts.map +1 -0
  85. package/dist/adapters/sqlite-native/NativeSqliteAdapter.js +748 -0
  86. package/dist/adapters/sqlite-native/NativeSqliteAdapter.js.map +1 -0
  87. package/dist/adapters/sqlite-native/index.d.ts +11 -0
  88. package/dist/adapters/sqlite-native/index.d.ts.map +1 -0
  89. package/dist/adapters/sqlite-native/index.js +11 -0
  90. package/dist/adapters/sqlite-native/index.js.map +1 -0
  91. package/dist/adapters/sqlite-native/tools/spatialite.d.ts +19 -0
  92. package/dist/adapters/sqlite-native/tools/spatialite.d.ts.map +1 -0
  93. package/dist/adapters/sqlite-native/tools/spatialite.js +628 -0
  94. package/dist/adapters/sqlite-native/tools/spatialite.js.map +1 -0
  95. package/dist/adapters/sqlite-native/tools/transactions.d.ts +12 -0
  96. package/dist/adapters/sqlite-native/tools/transactions.d.ts.map +1 -0
  97. package/dist/adapters/sqlite-native/tools/transactions.js +255 -0
  98. package/dist/adapters/sqlite-native/tools/transactions.js.map +1 -0
  99. package/dist/adapters/sqlite-native/tools/window.d.ts +12 -0
  100. package/dist/adapters/sqlite-native/tools/window.d.ts.map +1 -0
  101. package/dist/adapters/sqlite-native/tools/window.js +370 -0
  102. package/dist/adapters/sqlite-native/tools/window.js.map +1 -0
  103. package/dist/auth/AuthorizationServerDiscovery.d.ts +90 -0
  104. package/dist/auth/AuthorizationServerDiscovery.d.ts.map +1 -0
  105. package/dist/auth/AuthorizationServerDiscovery.js +204 -0
  106. package/dist/auth/AuthorizationServerDiscovery.js.map +1 -0
  107. package/dist/auth/OAuthResourceServer.d.ts +65 -0
  108. package/dist/auth/OAuthResourceServer.d.ts.map +1 -0
  109. package/dist/auth/OAuthResourceServer.js +121 -0
  110. package/dist/auth/OAuthResourceServer.js.map +1 -0
  111. package/dist/auth/TokenValidator.d.ts +60 -0
  112. package/dist/auth/TokenValidator.d.ts.map +1 -0
  113. package/dist/auth/TokenValidator.js +235 -0
  114. package/dist/auth/TokenValidator.js.map +1 -0
  115. package/dist/auth/errors.d.ts +74 -0
  116. package/dist/auth/errors.d.ts.map +1 -0
  117. package/dist/auth/errors.js +133 -0
  118. package/dist/auth/errors.js.map +1 -0
  119. package/dist/auth/index.d.ts +13 -0
  120. package/dist/auth/index.d.ts.map +1 -0
  121. package/dist/auth/index.js +15 -0
  122. package/dist/auth/index.js.map +1 -0
  123. package/dist/auth/middleware.d.ts +81 -0
  124. package/dist/auth/middleware.d.ts.map +1 -0
  125. package/dist/auth/middleware.js +291 -0
  126. package/dist/auth/middleware.js.map +1 -0
  127. package/dist/auth/scopes.d.ts +136 -0
  128. package/dist/auth/scopes.d.ts.map +1 -0
  129. package/dist/auth/scopes.js +349 -0
  130. package/dist/auth/scopes.js.map +1 -0
  131. package/dist/auth/types.d.ts +257 -0
  132. package/dist/auth/types.d.ts.map +1 -0
  133. package/dist/auth/types.js +8 -0
  134. package/dist/auth/types.js.map +1 -0
  135. package/dist/cli.d.ts +8 -0
  136. package/dist/cli.d.ts.map +1 -0
  137. package/dist/cli.js +236 -0
  138. package/dist/cli.js.map +1 -0
  139. package/dist/constants/ServerInstructions.d.ts +45 -0
  140. package/dist/constants/ServerInstructions.d.ts.map +1 -0
  141. package/dist/constants/ServerInstructions.js +356 -0
  142. package/dist/constants/ServerInstructions.js.map +1 -0
  143. package/dist/filtering/ToolConstants.d.ts +34 -0
  144. package/dist/filtering/ToolConstants.d.ts.map +1 -0
  145. package/dist/filtering/ToolConstants.js +174 -0
  146. package/dist/filtering/ToolConstants.js.map +1 -0
  147. package/dist/filtering/ToolFilter.d.ts +82 -0
  148. package/dist/filtering/ToolFilter.d.ts.map +1 -0
  149. package/dist/filtering/ToolFilter.js +296 -0
  150. package/dist/filtering/ToolFilter.js.map +1 -0
  151. package/dist/index.d.ts +13 -0
  152. package/dist/index.d.ts.map +1 -0
  153. package/dist/index.js +17 -0
  154. package/dist/index.js.map +1 -0
  155. package/dist/server/McpServer.d.ts +61 -0
  156. package/dist/server/McpServer.d.ts.map +1 -0
  157. package/dist/server/McpServer.js +270 -0
  158. package/dist/server/McpServer.js.map +1 -0
  159. package/dist/transports/http.d.ts +134 -0
  160. package/dist/transports/http.d.ts.map +1 -0
  161. package/dist/transports/http.js +516 -0
  162. package/dist/transports/http.js.map +1 -0
  163. package/dist/transports/index.d.ts +5 -0
  164. package/dist/transports/index.d.ts.map +1 -0
  165. package/dist/transports/index.js +5 -0
  166. package/dist/transports/index.js.map +1 -0
  167. package/dist/types/index.d.ts +380 -0
  168. package/dist/types/index.d.ts.map +1 -0
  169. package/dist/types/index.js +68 -0
  170. package/dist/types/index.js.map +1 -0
  171. package/dist/utils/annotations.d.ts +44 -0
  172. package/dist/utils/annotations.d.ts.map +1 -0
  173. package/dist/utils/annotations.js +77 -0
  174. package/dist/utils/annotations.js.map +1 -0
  175. package/dist/utils/errors.d.ts +155 -0
  176. package/dist/utils/errors.d.ts.map +1 -0
  177. package/dist/utils/errors.js +329 -0
  178. package/dist/utils/errors.js.map +1 -0
  179. package/dist/utils/identifiers.d.ts +121 -0
  180. package/dist/utils/identifiers.d.ts.map +1 -0
  181. package/dist/utils/identifiers.js +319 -0
  182. package/dist/utils/identifiers.js.map +1 -0
  183. package/dist/utils/index.d.ts +7 -0
  184. package/dist/utils/index.d.ts.map +1 -0
  185. package/dist/utils/index.js +7 -0
  186. package/dist/utils/index.js.map +1 -0
  187. package/dist/utils/insightsManager.d.ts +39 -0
  188. package/dist/utils/insightsManager.d.ts.map +1 -0
  189. package/dist/utils/insightsManager.js +63 -0
  190. package/dist/utils/insightsManager.js.map +1 -0
  191. package/dist/utils/logger.d.ts +189 -0
  192. package/dist/utils/logger.d.ts.map +1 -0
  193. package/dist/utils/logger.js +394 -0
  194. package/dist/utils/logger.js.map +1 -0
  195. package/dist/utils/progress-utils.d.ts +54 -0
  196. package/dist/utils/progress-utils.d.ts.map +1 -0
  197. package/dist/utils/progress-utils.js +74 -0
  198. package/dist/utils/progress-utils.js.map +1 -0
  199. package/dist/utils/resourceAnnotations.d.ts +36 -0
  200. package/dist/utils/resourceAnnotations.d.ts.map +1 -0
  201. package/dist/utils/resourceAnnotations.js +57 -0
  202. package/dist/utils/resourceAnnotations.js.map +1 -0
  203. package/dist/utils/where-clause.d.ts +41 -0
  204. package/dist/utils/where-clause.d.ts.map +1 -0
  205. package/dist/utils/where-clause.js +116 -0
  206. package/dist/utils/where-clause.js.map +1 -0
  207. package/package.json +83 -0
  208. package/server.json +53 -0
@@ -0,0 +1,748 @@
1
+ /**
2
+ * Native SQLite Adapter using better-sqlite3
3
+ *
4
+ * Provides synchronous, native SQLite access with full FTS5, window functions,
5
+ * and SpatiaLite support.
6
+ */
7
+ import Database from "better-sqlite3";
8
+ import path from "node:path";
9
+ import { fileURLToPath } from "node:url";
10
+ import { DatabaseAdapter } from "../DatabaseAdapter.js";
11
+ import { ResourceTemplate, } from "@modelcontextprotocol/sdk/server/mcp.js";
12
+ import { logger, ERROR_CODES } from "../../utils/logger.js";
13
+ // Import shared tools from sql.js adapter
14
+ import { getCoreTools } from "../sqlite/tools/core.js";
15
+ import { getJsonOperationTools } from "../sqlite/tools/json-operations.js";
16
+ import { getJsonHelperTools } from "../sqlite/tools/json-helpers.js";
17
+ import { getTextTools } from "../sqlite/tools/text.js";
18
+ import { getFtsTools } from "../sqlite/tools/fts.js";
19
+ import { getStatsTools } from "../sqlite/tools/stats.js";
20
+ import { getVirtualTools } from "../sqlite/tools/virtual.js";
21
+ import { getVectorTools } from "../sqlite/tools/vector.js";
22
+ import { getGeoTools } from "../sqlite/tools/geo.js";
23
+ import { getAdminTools } from "../sqlite/tools/admin.js";
24
+ import { getResourceDefinitions } from "../sqlite/resources.js";
25
+ import { getPromptDefinitions } from "../sqlite/prompts.js";
26
+ import { isJsonbSupportedVersion, setJsonbSupported, } from "../sqlite/json-utils.js";
27
+ // Import native-specific tools
28
+ import { getTransactionTools } from "./tools/transactions.js";
29
+ import { getWindowTools } from "./tools/window.js";
30
+ import { getSpatialiteTools, isSpatialiteLoaded } from "./tools/spatialite.js";
31
+ const log = logger.child("NATIVE_SQLITE");
32
+ /**
33
+ * Native SQLite Adapter using better-sqlite3
34
+ */
35
+ export class NativeSqliteAdapter extends DatabaseAdapter {
36
+ type = "sqlite";
37
+ name = "Native SQLite Adapter (better-sqlite3)";
38
+ version = "1.0.0";
39
+ /**
40
+ * Check if this adapter uses native (better-sqlite3) backend.
41
+ * Returns true for native adapter.
42
+ */
43
+ isNativeBackend() {
44
+ return true;
45
+ }
46
+ /**
47
+ * Get the configured database file path.
48
+ * Returns the user-configured path, not internal WASM virtual filesystem paths.
49
+ */
50
+ getConfiguredPath() {
51
+ const config = this.config;
52
+ return config?.filePath ?? config?.connectionString ?? ":memory:";
53
+ }
54
+ db = null;
55
+ /**
56
+ * Connect to a SQLite database using better-sqlite3
57
+ */
58
+ connect(config) {
59
+ if (config.type !== "sqlite") {
60
+ throw new Error(`Invalid database type: expected 'sqlite', got '${config.type}'`);
61
+ }
62
+ const sqliteConfig = config;
63
+ this.config = sqliteConfig;
64
+ try {
65
+ const filePath = sqliteConfig.filePath ?? sqliteConfig.connectionString ?? ":memory:";
66
+ // Create database connection
67
+ this.db = new Database(filePath, {
68
+ readonly: false,
69
+ fileMustExist: false,
70
+ });
71
+ log.info(`Connected to SQLite database (native): ${filePath}`, {
72
+ code: "SQLITE_CONNECT",
73
+ });
74
+ // Apply options
75
+ this.applyOptions(sqliteConfig.options);
76
+ // Enable WAL mode by default for file-based databases
77
+ if (filePath !== ":memory:" && !sqliteConfig.options?.walMode) {
78
+ try {
79
+ this.db.pragma("journal_mode = WAL");
80
+ log.info("Enabled WAL mode for better concurrency", {
81
+ code: "SQLITE_WAL",
82
+ });
83
+ }
84
+ catch {
85
+ // WAL mode may not be available
86
+ }
87
+ }
88
+ // Detect JSONB support based on SQLite version
89
+ try {
90
+ const versionResult = this.db
91
+ .prepare("SELECT sqlite_version()")
92
+ .get();
93
+ const version = versionResult?.["sqlite_version()"] ?? "0.0.0";
94
+ const jsonbSupported = isJsonbSupportedVersion(version);
95
+ setJsonbSupported(jsonbSupported);
96
+ if (jsonbSupported) {
97
+ log.info(`JSONB support enabled (SQLite ${version})`, {
98
+ code: "SQLITE_JSONB",
99
+ });
100
+ }
101
+ }
102
+ catch {
103
+ setJsonbSupported(false);
104
+ }
105
+ this.connected = true;
106
+ }
107
+ catch (error) {
108
+ const message = error instanceof Error ? error.message : String(error);
109
+ log.error(`Failed to connect to native SQLite: ${message}`, {
110
+ code: ERROR_CODES.DB.CONNECT_FAILED.full,
111
+ });
112
+ throw new Error(`Native SQLite connection failed: ${message}`);
113
+ }
114
+ return Promise.resolve();
115
+ }
116
+ /**
117
+ * Apply SQLite PRAGMA options
118
+ */
119
+ applyOptions(options) {
120
+ if (!this.db || !options)
121
+ return;
122
+ if (options.walMode) {
123
+ this.db.pragma("journal_mode = WAL");
124
+ }
125
+ if (options.foreignKeys !== undefined) {
126
+ this.db.pragma(`foreign_keys = ${options.foreignKeys ? "ON" : "OFF"}`);
127
+ }
128
+ if (options.busyTimeout !== undefined) {
129
+ this.db.pragma(`busy_timeout = ${options.busyTimeout}`);
130
+ }
131
+ if (options.cacheSize !== undefined) {
132
+ this.db.pragma(`cache_size = ${options.cacheSize}`);
133
+ }
134
+ if (options.spatialite) {
135
+ // Compute absolute path to extensions directory
136
+ const __filename = fileURLToPath(import.meta.url);
137
+ const __dirname = path.dirname(__filename);
138
+ const extensionsDir = path.resolve(__dirname, "../../../extensions");
139
+ const spatialitePaths = [
140
+ process.env["SPATIALITE_PATH"],
141
+ // Absolute paths to local extensions
142
+ path.join(extensionsDir, "mod_spatialite-5.1.0-win-amd64", "mod_spatialite"),
143
+ path.join(extensionsDir, "mod_spatialite-5.1.0-win-amd64", "mod_spatialite.dll"),
144
+ // System paths
145
+ "mod_spatialite",
146
+ "mod_spatialite.dll",
147
+ "/usr/lib/x86_64-linux-gnu/mod_spatialite.so",
148
+ "/usr/local/lib/mod_spatialite.so",
149
+ "/usr/local/lib/mod_spatialite.dylib",
150
+ ].filter((p) => Boolean(p));
151
+ // On Windows, SpatiaLite DLL has many dependencies (libgeos, libproj, etc.)
152
+ // These must be in PATH for Windows to find them when loading the extension.
153
+ // Prepend the extension directory to PATH before attempting to load.
154
+ const envSpatialitePath = process.env["SPATIALITE_PATH"];
155
+ if (envSpatialitePath && process.platform === "win32") {
156
+ const spatialiteExtDir = path.dirname(envSpatialitePath);
157
+ const currentPath = process.env["PATH"] ?? "";
158
+ if (!currentPath.includes(spatialiteExtDir)) {
159
+ process.env["PATH"] = spatialiteExtDir + ";" + currentPath;
160
+ }
161
+ }
162
+ let loaded = false;
163
+ for (const extPath of spatialitePaths) {
164
+ try {
165
+ this.db.loadExtension(extPath);
166
+ log.info(`Loaded SpatiaLite extension from ${extPath}`, {
167
+ code: "SQLITE_EXTENSION",
168
+ });
169
+ loaded = true;
170
+ break;
171
+ }
172
+ catch {
173
+ // Try next path
174
+ }
175
+ }
176
+ if (!loaded) {
177
+ log.warning("SpatiaLite extension not available. Set SPATIALITE_PATH env var.", { code: "SQLITE_EXTENSION" });
178
+ }
179
+ }
180
+ if (options.csv) {
181
+ // Compute absolute path to extensions directory
182
+ const __filename = fileURLToPath(import.meta.url);
183
+ const __dirname = path.dirname(__filename);
184
+ const extensionsDir = path.resolve(__dirname, "../../../extensions");
185
+ const csvPaths = [
186
+ process.env["CSV_EXTENSION_PATH"],
187
+ // sqlite-xsv extension with absolute paths
188
+ path.join(extensionsDir, "xsv0.dll"),
189
+ path.join(extensionsDir, "xsv0"),
190
+ // System paths
191
+ "xsv0",
192
+ "xsv0.dll",
193
+ "csv",
194
+ "csv.dll",
195
+ "csv.so",
196
+ "/usr/local/lib/csv.so",
197
+ "/usr/local/lib/csv.dylib",
198
+ ].filter((p) => Boolean(p));
199
+ let loaded = false;
200
+ for (const extPath of csvPaths) {
201
+ try {
202
+ this.db.loadExtension(extPath);
203
+ log.info(`Loaded CSV extension from ${extPath}`, {
204
+ code: "SQLITE_EXTENSION",
205
+ });
206
+ loaded = true;
207
+ break;
208
+ }
209
+ catch {
210
+ // Try next path
211
+ }
212
+ }
213
+ if (!loaded) {
214
+ log.warning("CSV extension not available. Set CSV_EXTENSION_PATH env var.", { code: "SQLITE_EXTENSION" });
215
+ }
216
+ }
217
+ }
218
+ /**
219
+ * Disconnect from the database
220
+ */
221
+ disconnect() {
222
+ if (this.db) {
223
+ this.db.close();
224
+ this.db = null;
225
+ this.connected = false;
226
+ log.info("Disconnected from native SQLite database", {
227
+ code: "SQLITE_DISCONNECT",
228
+ });
229
+ }
230
+ return Promise.resolve();
231
+ }
232
+ /**
233
+ * Get health status
234
+ */
235
+ getHealth() {
236
+ if (!this.db || !this.connected) {
237
+ return Promise.resolve({
238
+ connected: false,
239
+ latencyMs: 0,
240
+ });
241
+ }
242
+ const start = Date.now();
243
+ try {
244
+ this.db.prepare("SELECT 1").get();
245
+ return Promise.resolve({
246
+ connected: true,
247
+ latencyMs: Date.now() - start,
248
+ details: {
249
+ backend: "better-sqlite3",
250
+ fts5: this.hasFts5(),
251
+ spatialite: isSpatialiteLoaded(this),
252
+ },
253
+ });
254
+ }
255
+ catch {
256
+ return Promise.resolve({
257
+ connected: false,
258
+ latencyMs: Date.now() - start,
259
+ });
260
+ }
261
+ }
262
+ /**
263
+ * Check if FTS5 is available
264
+ */
265
+ hasFts5() {
266
+ if (!this.db)
267
+ return false;
268
+ try {
269
+ this.db.exec("CREATE VIRTUAL TABLE IF NOT EXISTS _fts5_test USING fts5(content)");
270
+ this.db.exec("DROP TABLE IF EXISTS _fts5_test");
271
+ return true;
272
+ }
273
+ catch {
274
+ return false;
275
+ }
276
+ }
277
+ /**
278
+ * Normalize parameters for SQLite binding
279
+ * Converts booleans to integers since SQLite doesn't have native boolean type
280
+ */
281
+ normalizeParams(params) {
282
+ if (!params)
283
+ return undefined;
284
+ return params.map((p) => {
285
+ if (typeof p === "boolean")
286
+ return p ? 1 : 0;
287
+ return p;
288
+ });
289
+ }
290
+ /**
291
+ * Execute a read query
292
+ */
293
+ executeReadQuery(sql, params) {
294
+ this.ensureConnected();
295
+ const start = Date.now();
296
+ try {
297
+ const db = this.ensureDb();
298
+ const stmt = db.prepare(sql);
299
+ const normalizedParams = this.normalizeParams(params);
300
+ const rows = normalizedParams
301
+ ? stmt.all(...normalizedParams)
302
+ : stmt.all();
303
+ return Promise.resolve({
304
+ rows: rows,
305
+ columns: stmt
306
+ .columns()
307
+ .map((c) => ({ name: c.name, type: c.type ?? "unknown" })),
308
+ executionTimeMs: Date.now() - start,
309
+ });
310
+ }
311
+ catch (error) {
312
+ const message = error instanceof Error ? error.message : String(error);
313
+ throw new Error(`Query failed: ${message}`);
314
+ }
315
+ }
316
+ /**
317
+ * Execute a write query
318
+ */
319
+ executeWriteQuery(sql, params) {
320
+ this.ensureConnected();
321
+ const start = Date.now();
322
+ try {
323
+ const db = this.ensureDb();
324
+ const stmt = db.prepare(sql);
325
+ const normalizedParams = this.normalizeParams(params);
326
+ const info = normalizedParams
327
+ ? stmt.run(...normalizedParams)
328
+ : stmt.run();
329
+ return Promise.resolve({
330
+ rows: [],
331
+ rowsAffected: info.changes,
332
+ executionTimeMs: Date.now() - start,
333
+ });
334
+ }
335
+ catch (error) {
336
+ const message = error instanceof Error ? error.message : String(error);
337
+ throw new Error(`Write query failed: ${message}`);
338
+ }
339
+ }
340
+ /**
341
+ * Execute any query
342
+ */
343
+ executeQuery(sql, params) {
344
+ const trimmed = sql.trim().toUpperCase();
345
+ if (trimmed.startsWith("SELECT") ||
346
+ trimmed.startsWith("PRAGMA") ||
347
+ trimmed.startsWith("EXPLAIN")) {
348
+ return this.executeReadQuery(sql, params);
349
+ }
350
+ return this.executeWriteQuery(sql, params);
351
+ }
352
+ /**
353
+ * Get schema information
354
+ */
355
+ async getSchema() {
356
+ this.ensureConnected();
357
+ const tables = await this.listTables();
358
+ return {
359
+ tables,
360
+ indexes: [],
361
+ views: [],
362
+ };
363
+ }
364
+ /**
365
+ * List all tables
366
+ */
367
+ listTables() {
368
+ this.ensureConnected();
369
+ const db = this.ensureDb();
370
+ const result = db
371
+ .prepare(`
372
+ SELECT name, type, sql
373
+ FROM sqlite_master
374
+ WHERE type IN ('table', 'view')
375
+ AND name NOT LIKE 'sqlite_%'
376
+ ORDER BY name
377
+ `)
378
+ .all();
379
+ // Build tables with column info from PRAGMA table_info()
380
+ // Filter out FTS5 virtual tables and shadow tables
381
+ const tables = result
382
+ .filter((row) => {
383
+ // Skip FTS5 virtual tables (end with "_fts") and shadow tables (contain "_fts_")
384
+ if (row.name.endsWith("_fts") || row.name.includes("_fts_")) {
385
+ return false;
386
+ }
387
+ return true;
388
+ })
389
+ .map((row) => {
390
+ const columns = db
391
+ .prepare(`PRAGMA table_info("${row.name}")`)
392
+ .all();
393
+ return {
394
+ name: row.name,
395
+ type: row.type,
396
+ columns: columns.map((c) => ({
397
+ name: c.name,
398
+ type: c.type,
399
+ nullable: c.notnull === 0,
400
+ primaryKey: c.pk > 0,
401
+ })),
402
+ };
403
+ });
404
+ return Promise.resolve(tables);
405
+ }
406
+ /**
407
+ * Describe a table
408
+ */
409
+ describeTable(tableName) {
410
+ this.ensureConnected();
411
+ const db = this.ensureDb();
412
+ const columns = db.prepare(`PRAGMA table_info("${tableName}")`).all();
413
+ // Check if table exists (PRAGMA returns empty for non-existent tables)
414
+ if (columns.length === 0) {
415
+ throw new Error(`Table '${tableName}' does not exist`);
416
+ }
417
+ return Promise.resolve({
418
+ name: tableName,
419
+ type: "table",
420
+ columns: columns.map((c) => ({
421
+ name: c.name,
422
+ type: c.type,
423
+ nullable: c.notnull === 0 ? true : false,
424
+ primaryKey: c.pk > 0 ? true : false,
425
+ })),
426
+ });
427
+ }
428
+ /**
429
+ * List schemas (SQLite only has one)
430
+ */
431
+ listSchemas() {
432
+ return Promise.resolve(["main"]);
433
+ }
434
+ /**
435
+ * Get all indexes in the database
436
+ * Required by sqlite_indexes resource
437
+ */
438
+ getAllIndexes() {
439
+ this.ensureConnected();
440
+ const db = this.ensureDb();
441
+ // Get all user-created indexes from sqlite_master
442
+ const indexes = db
443
+ .prepare(`SELECT name, tbl_name, sql
444
+ FROM sqlite_master
445
+ WHERE type = 'index' AND sql IS NOT NULL
446
+ ORDER BY tbl_name, name`)
447
+ .all();
448
+ // Build index info with column details
449
+ return indexes.map((idx) => {
450
+ // Get columns for this index
451
+ const indexInfo = db
452
+ .prepare(`PRAGMA index_info("${idx.name}")`)
453
+ .all();
454
+ return {
455
+ name: idx.name,
456
+ tableName: idx.tbl_name,
457
+ columns: indexInfo.map((col) => col.name),
458
+ unique: idx.sql?.toUpperCase().includes("UNIQUE") ?? false,
459
+ };
460
+ });
461
+ }
462
+ /**
463
+ * Get capabilities
464
+ */
465
+ getCapabilities() {
466
+ return {
467
+ json: true,
468
+ fullTextSearch: true,
469
+ vector: true,
470
+ geospatial: true,
471
+ transactions: true,
472
+ preparedStatements: true,
473
+ connectionPooling: false, // better-sqlite3 is single-connection
474
+ windowFunctions: true,
475
+ spatialite: true,
476
+ };
477
+ }
478
+ /**
479
+ * Get supported tool groups
480
+ */
481
+ getSupportedToolGroups() {
482
+ return ["core", "json", "text", "stats", "vector", "admin", "geo"];
483
+ }
484
+ /**
485
+ * Get all tool definitions
486
+ */
487
+ getToolDefinitions() {
488
+ // Type assertion needed due to interface compatibility
489
+ const self = this;
490
+ return [
491
+ ...getCoreTools(self),
492
+ ...getJsonOperationTools(self),
493
+ ...getJsonHelperTools(self),
494
+ ...getTextTools(self),
495
+ ...getFtsTools(self),
496
+ ...getStatsTools(self),
497
+ ...getVirtualTools(self),
498
+ ...getVectorTools(self),
499
+ ...getGeoTools(self),
500
+ ...getAdminTools(self),
501
+ // Native-only tools
502
+ ...getTransactionTools(this),
503
+ ...getWindowTools(this),
504
+ ...getSpatialiteTools(this),
505
+ ];
506
+ }
507
+ /**
508
+ * Get resource definitions
509
+ */
510
+ getResourceDefinitions() {
511
+ return getResourceDefinitions(this);
512
+ }
513
+ /**
514
+ * Get prompt definitions
515
+ */
516
+ getPromptDefinitions() {
517
+ return getPromptDefinitions(this);
518
+ }
519
+ /**
520
+ * Register a tool with the MCP server
521
+ * Uses modern registerTool() API for MCP 2025-11-25 compliance
522
+ */
523
+ registerTool(server, tool) {
524
+ // Build tool options for registerTool()
525
+ const toolOptions = {
526
+ description: tool.description,
527
+ };
528
+ // Pass full inputSchema (not just .shape) for proper validation
529
+ if (tool.inputSchema !== undefined) {
530
+ toolOptions["inputSchema"] = tool.inputSchema;
531
+ }
532
+ // MCP 2025-11-25: Pass outputSchema for structured responses
533
+ if (tool.outputSchema !== undefined) {
534
+ toolOptions["outputSchema"] = tool.outputSchema;
535
+ }
536
+ // MCP 2025-11-25: Pass annotations for behavioral hints
537
+ if (tool.annotations) {
538
+ toolOptions["annotations"] = tool.annotations;
539
+ }
540
+ // Track whether tool has outputSchema for response handling
541
+ const hasOutputSchema = Boolean(tool.outputSchema);
542
+ server.registerTool(tool.name, toolOptions, async (args, extra) => {
543
+ try {
544
+ // Extract progressToken from extra._meta (SDK passes RequestHandlerExtra)
545
+ const extraMeta = extra;
546
+ const progressToken = extraMeta?._meta?.progressToken;
547
+ // Create context with progress support
548
+ const context = this.createContext(undefined, server.server, progressToken);
549
+ const result = await tool.handler(args, context);
550
+ // MCP 2025-11-25: Return structuredContent if outputSchema present
551
+ if (hasOutputSchema) {
552
+ return {
553
+ content: [
554
+ {
555
+ type: "text",
556
+ text: JSON.stringify(result, null, 2),
557
+ },
558
+ ],
559
+ structuredContent: result,
560
+ };
561
+ }
562
+ // Standard text content response
563
+ return {
564
+ content: [
565
+ {
566
+ type: "text",
567
+ text: typeof result === "string"
568
+ ? result
569
+ : JSON.stringify(result, null, 2),
570
+ },
571
+ ],
572
+ };
573
+ }
574
+ catch (error) {
575
+ return {
576
+ content: [
577
+ {
578
+ type: "text",
579
+ text: `Error: ${error instanceof Error ? error.message : String(error)}`,
580
+ },
581
+ ],
582
+ isError: true,
583
+ };
584
+ }
585
+ });
586
+ }
587
+ /**
588
+ * Register a resource with the MCP server
589
+ * Handles both static resources and URI templates
590
+ */
591
+ registerResource(server, resource) {
592
+ // Check if URI contains template placeholders like {tableName}
593
+ const isTemplate = /\{[^}]+\}/.test(resource.uri);
594
+ if (isTemplate) {
595
+ // Create ResourceTemplate for parameterized URIs
596
+ // list: undefined signals no enumeration callback for this template
597
+ const template = new ResourceTemplate(resource.uri, { list: undefined });
598
+ server.registerResource(resource.name, template, {
599
+ mimeType: resource.mimeType ?? "application/json",
600
+ description: resource.description,
601
+ },
602
+ // Callback receives URL and extracted template variables
603
+ async (resourceUri, _variables) => {
604
+ // Pass full URI to handler so it can extract variables
605
+ const content = await resource.handler(resourceUri.toString(), {
606
+ timestamp: new Date(),
607
+ requestId: crypto.randomUUID(),
608
+ });
609
+ return {
610
+ contents: [
611
+ {
612
+ uri: resourceUri.toString(),
613
+ mimeType: resource.mimeType ?? "application/json",
614
+ text: typeof content === "string"
615
+ ? content
616
+ : JSON.stringify(content, null, 2),
617
+ },
618
+ ],
619
+ };
620
+ });
621
+ }
622
+ else {
623
+ // Static resource registration
624
+ server.registerResource(resource.name, resource.uri, {
625
+ mimeType: resource.mimeType ?? "application/json",
626
+ description: resource.description,
627
+ }, async (resourceUri) => {
628
+ const content = await resource.handler(resourceUri.toString(), {
629
+ timestamp: new Date(),
630
+ requestId: crypto.randomUUID(),
631
+ });
632
+ return {
633
+ contents: [
634
+ {
635
+ uri: resourceUri.toString(),
636
+ mimeType: resource.mimeType ?? "application/json",
637
+ text: typeof content === "string"
638
+ ? content
639
+ : JSON.stringify(content, null, 2),
640
+ },
641
+ ],
642
+ };
643
+ });
644
+ }
645
+ }
646
+ /**
647
+ * Register a prompt with the MCP server
648
+ */
649
+ registerPrompt(server, prompt) {
650
+ server.registerPrompt(prompt.name, { description: prompt.description }, async (args) => {
651
+ const result = await prompt.handler(args, {
652
+ timestamp: new Date(),
653
+ requestId: crypto.randomUUID(),
654
+ });
655
+ // Type-safe message construction
656
+ const messages = Array.isArray(result)
657
+ ? result
658
+ : [
659
+ {
660
+ role: "assistant",
661
+ content: {
662
+ type: "text",
663
+ text: typeof result === "string"
664
+ ? result
665
+ : JSON.stringify(result),
666
+ },
667
+ },
668
+ ];
669
+ return { messages };
670
+ });
671
+ }
672
+ /**
673
+ * Ensure database is connected
674
+ */
675
+ ensureConnected() {
676
+ if (!this.db || !this.connected) {
677
+ throw new Error("Not connected to database");
678
+ }
679
+ }
680
+ /**
681
+ * Ensure database is connected and return database instance
682
+ */
683
+ ensureDb() {
684
+ if (!this.db || !this.connected) {
685
+ throw new Error("Not connected to database");
686
+ }
687
+ return this.db;
688
+ }
689
+ /**
690
+ * Get the raw database instance (for tools)
691
+ */
692
+ getDatabase() {
693
+ return this.ensureDb();
694
+ }
695
+ /**
696
+ * Execute raw SQL and return results (for tools)
697
+ */
698
+ rawQuery(sql, params) {
699
+ return this.executeQuery(sql, params);
700
+ }
701
+ /**
702
+ * Begin a transaction
703
+ */
704
+ beginTransaction() {
705
+ const db = this.ensureDb();
706
+ db.exec("BEGIN TRANSACTION");
707
+ }
708
+ /**
709
+ * Commit a transaction
710
+ */
711
+ commitTransaction() {
712
+ const db = this.ensureDb();
713
+ db.exec("COMMIT");
714
+ }
715
+ /**
716
+ * Rollback a transaction
717
+ */
718
+ rollbackTransaction() {
719
+ const db = this.ensureDb();
720
+ db.exec("ROLLBACK");
721
+ }
722
+ /**
723
+ * Create a savepoint
724
+ */
725
+ savepoint(name) {
726
+ const db = this.ensureDb();
727
+ db.exec(`SAVEPOINT "${name}"`);
728
+ }
729
+ /**
730
+ * Release a savepoint
731
+ */
732
+ releaseSavepoint(name) {
733
+ const db = this.ensureDb();
734
+ db.exec(`RELEASE SAVEPOINT "${name}"`);
735
+ }
736
+ /**
737
+ * Rollback to a savepoint
738
+ */
739
+ rollbackToSavepoint(name) {
740
+ const db = this.ensureDb();
741
+ db.exec(`ROLLBACK TO SAVEPOINT "${name}"`);
742
+ }
743
+ }
744
+ // Factory function
745
+ export function createNativeSqliteAdapter() {
746
+ return new NativeSqliteAdapter();
747
+ }
748
+ //# sourceMappingURL=NativeSqliteAdapter.js.map