mcp-sqlite-server 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +103 -0
- package/dist/index.js +327 -0
- package/dist/index.js.map +1 -0
- package/package.json +72 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ofer Shapira
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# mcp-server-sqlite
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/mcp-sqlite-server)
|
|
4
|
+
[](https://www.npmjs.com/package/mcp-sqlite-server)
|
|
5
|
+
[](https://github.com/ofershap/mcp-server-sqlite/actions/workflows/ci.yml)
|
|
6
|
+
[](https://www.typescriptlang.org/)
|
|
7
|
+
[](https://opensource.org/licenses/MIT)
|
|
8
|
+
|
|
9
|
+
Query SQLite databases, inspect schemas, and explain queries from your AI assistant. Read-only by default for safety.
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npx mcp-sqlite-server
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
> Works with Claude Desktop, Cursor, VS Code Copilot, and any MCP client. Reads local `.db` files, no auth needed.
|
|
16
|
+
|
|
17
|
+

|
|
18
|
+
|
|
19
|
+
<sub>Demo built with <a href="https://github.com/ofershap/remotion-readme-kit">remotion-readme-kit</a></sub>
|
|
20
|
+
|
|
21
|
+
## Why
|
|
22
|
+
|
|
23
|
+
SQLite is everywhere. It's the default database for mobile apps, Electron apps, local-first tools, and increasingly for server-side projects too (Turso, Cloudflare D1, Bun's built-in SQLite). The official MCP reference includes a basic SQLite server, but it's Python-only. If you're working in a TypeScript/Node.js environment and want to ask your assistant "what tables are in this database?" or "run this query and show me the results," this server handles that. It opens the database read-only by default so you can explore safely, and you can opt into write mode when you need it.
|
|
24
|
+
|
|
25
|
+
## Tools
|
|
26
|
+
|
|
27
|
+
| Tool | What it does |
|
|
28
|
+
| ---------------- | ------------------------------------------------------------------------ |
|
|
29
|
+
| `query` | Execute SQL (SELECT, PRAGMA, EXPLAIN, WITH). Returns results as a table. |
|
|
30
|
+
| `schema` | Get full schema: all tables with columns, types, and row counts. |
|
|
31
|
+
| `table_info` | Detailed info for a single table: columns, constraints, row count. |
|
|
32
|
+
| `explain` | Run EXPLAIN QUERY PLAN to optimize queries. |
|
|
33
|
+
| `list_databases` | List .db, .sqlite, .sqlite3 files in a directory. |
|
|
34
|
+
|
|
35
|
+
## Quick Start
|
|
36
|
+
|
|
37
|
+
### Cursor
|
|
38
|
+
|
|
39
|
+
Add to `.cursor/mcp.json`:
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"mcpServers": {
|
|
44
|
+
"sqlite": {
|
|
45
|
+
"command": "npx",
|
|
46
|
+
"args": ["mcp-sqlite-server"]
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Claude Desktop
|
|
53
|
+
|
|
54
|
+
Add to `claude_desktop_config.json` (macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`):
|
|
55
|
+
|
|
56
|
+
```json
|
|
57
|
+
{
|
|
58
|
+
"mcpServers": {
|
|
59
|
+
"sqlite": {
|
|
60
|
+
"command": "npx",
|
|
61
|
+
"args": ["mcp-sqlite-server"]
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### VS Code
|
|
68
|
+
|
|
69
|
+
Configure the MCP server in your VS Code settings to run `npx mcp-sqlite-server`.
|
|
70
|
+
|
|
71
|
+
## Example prompts
|
|
72
|
+
|
|
73
|
+
- "Show me the schema of my database at ./data.db"
|
|
74
|
+
- "Query the users table: SELECT * FROM users LIMIT 10"
|
|
75
|
+
- "Explain the query plan for this complex join"
|
|
76
|
+
- "What tables are in this database?"
|
|
77
|
+
- "Find all .db files in the current directory"
|
|
78
|
+
|
|
79
|
+
## Safety
|
|
80
|
+
|
|
81
|
+
Read-only by default. The `query` tool accepts only SELECT, PRAGMA, EXPLAIN, and WITH in readonly mode. Set `readonly=false` in the tool args to enable INSERT, UPDATE, DELETE, etc.
|
|
82
|
+
|
|
83
|
+
## Development
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
npm install
|
|
87
|
+
npm run typecheck
|
|
88
|
+
npm run build
|
|
89
|
+
npm test
|
|
90
|
+
npm run format
|
|
91
|
+
npm run lint
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Author
|
|
95
|
+
|
|
96
|
+
**Ofer Shapira**
|
|
97
|
+
|
|
98
|
+
[](https://linkedin.com/in/ofershap)
|
|
99
|
+
[](https://github.com/ofershap)
|
|
100
|
+
|
|
101
|
+
## License
|
|
102
|
+
|
|
103
|
+
MIT © 2026 Ofer Shapira
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/index.ts
|
|
4
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
5
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
6
|
+
import path2 from "path";
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
|
|
9
|
+
// src/sqlite.ts
|
|
10
|
+
import Database from "better-sqlite3";
|
|
11
|
+
import fs from "fs";
|
|
12
|
+
import path from "path";
|
|
13
|
+
function openDb(dbPath) {
|
|
14
|
+
if (!fs.existsSync(dbPath)) {
|
|
15
|
+
throw new Error(`Database file not found: ${dbPath}`);
|
|
16
|
+
}
|
|
17
|
+
return new Database(dbPath, { readonly: true });
|
|
18
|
+
}
|
|
19
|
+
function openDbWritable(dbPath) {
|
|
20
|
+
return new Database(dbPath);
|
|
21
|
+
}
|
|
22
|
+
function query(dbPath, sql, readonly = true) {
|
|
23
|
+
const db = readonly ? openDb(dbPath) : openDbWritable(dbPath);
|
|
24
|
+
try {
|
|
25
|
+
const trimmed = sql.trim();
|
|
26
|
+
const isSelect = /^(SELECT|PRAGMA|EXPLAIN|WITH)\b/i.test(trimmed);
|
|
27
|
+
if (readonly && !isSelect) {
|
|
28
|
+
throw new Error(
|
|
29
|
+
"Write operations are not allowed in read-only mode. Set readonly=false to enable writes."
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
if (isSelect) {
|
|
33
|
+
const stmt = db.prepare(trimmed);
|
|
34
|
+
const rows = stmt.all();
|
|
35
|
+
const firstRow = rows[0];
|
|
36
|
+
const columns = firstRow ? Object.keys(firstRow) : [];
|
|
37
|
+
return { columns, rows, rowCount: rows.length };
|
|
38
|
+
} else {
|
|
39
|
+
db.exec(trimmed);
|
|
40
|
+
return { columns: [], rows: [], rowCount: 0 };
|
|
41
|
+
}
|
|
42
|
+
} finally {
|
|
43
|
+
db.close();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function schema(dbPath) {
|
|
47
|
+
const db = openDb(dbPath);
|
|
48
|
+
try {
|
|
49
|
+
const tables = db.prepare(
|
|
50
|
+
"SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' ORDER BY name"
|
|
51
|
+
).all();
|
|
52
|
+
const tableInfos = tables.map((t) => {
|
|
53
|
+
const columns = db.prepare(`PRAGMA table_info("${t.name}")`).all();
|
|
54
|
+
const countResult = db.prepare(`SELECT COUNT(*) as count FROM "${t.name}"`).get();
|
|
55
|
+
return {
|
|
56
|
+
name: t.name,
|
|
57
|
+
columns: columns.map((c) => ({
|
|
58
|
+
name: c.name,
|
|
59
|
+
type: c.type,
|
|
60
|
+
notnull: c.notnull === 1,
|
|
61
|
+
pk: c.pk === 1,
|
|
62
|
+
defaultValue: c.dflt_value
|
|
63
|
+
})),
|
|
64
|
+
rowCount: countResult.count
|
|
65
|
+
};
|
|
66
|
+
});
|
|
67
|
+
return { tables: tableInfos, totalTables: tableInfos.length };
|
|
68
|
+
} finally {
|
|
69
|
+
db.close();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function tableInfo(dbPath, tableName) {
|
|
73
|
+
const db = openDb(dbPath);
|
|
74
|
+
try {
|
|
75
|
+
const columns = db.prepare(`PRAGMA table_info("${tableName}")`).all();
|
|
76
|
+
if (columns.length === 0) {
|
|
77
|
+
throw new Error(`Table "${tableName}" not found`);
|
|
78
|
+
}
|
|
79
|
+
const countResult = db.prepare(`SELECT COUNT(*) as count FROM "${tableName}"`).get();
|
|
80
|
+
return {
|
|
81
|
+
name: tableName,
|
|
82
|
+
columns: columns.map((c) => ({
|
|
83
|
+
name: c.name,
|
|
84
|
+
type: c.type,
|
|
85
|
+
notnull: c.notnull === 1,
|
|
86
|
+
pk: c.pk === 1,
|
|
87
|
+
defaultValue: c.dflt_value
|
|
88
|
+
})),
|
|
89
|
+
rowCount: countResult.count
|
|
90
|
+
};
|
|
91
|
+
} finally {
|
|
92
|
+
db.close();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function explain(dbPath, sql) {
|
|
96
|
+
const db = openDb(dbPath);
|
|
97
|
+
try {
|
|
98
|
+
const rows = db.prepare(`EXPLAIN QUERY PLAN ${sql}`).all();
|
|
99
|
+
return rows.map((r) => `${r.id} | ${r.parent} | ${r.detail}`).join("\n");
|
|
100
|
+
} finally {
|
|
101
|
+
db.close();
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function listDatabases(directory) {
|
|
105
|
+
const entries = fs.readdirSync(directory, { withFileTypes: true });
|
|
106
|
+
return entries.filter((e) => e.isFile() && /\.(db|sqlite|sqlite3)$/i.test(e.name)).map((e) => path.join(directory, e.name)).sort();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// src/index.ts
|
|
110
|
+
function formatQueryResult(columns, rows) {
|
|
111
|
+
if (columns.length === 0 && rows.length === 0) {
|
|
112
|
+
return "(No columns returned)";
|
|
113
|
+
}
|
|
114
|
+
if (columns.length === 0) {
|
|
115
|
+
return `(${rows.length} row(s) affected)`;
|
|
116
|
+
}
|
|
117
|
+
const widths = columns.map(
|
|
118
|
+
(col) => Math.max(col.length, ...rows.map((r) => String(r[col] ?? "").length))
|
|
119
|
+
);
|
|
120
|
+
const sep = widths.map((w) => "-".repeat(w)).join("-+-");
|
|
121
|
+
const header = columns.map((c, i) => c.padEnd(widths[i] ?? 0)).join(" | ");
|
|
122
|
+
const lines = [header, sep];
|
|
123
|
+
for (const row of rows) {
|
|
124
|
+
const line = columns.map((c, i) => String(row[c] ?? "").padEnd(widths[i] ?? 0)).join(" | ");
|
|
125
|
+
lines.push(line);
|
|
126
|
+
}
|
|
127
|
+
return lines.join("\n");
|
|
128
|
+
}
|
|
129
|
+
function formatSchema(schemaInfo) {
|
|
130
|
+
const lines = [`Schema: ${schemaInfo.totalTables} table(s)`, ""];
|
|
131
|
+
for (const t of schemaInfo.tables) {
|
|
132
|
+
const colSpecs = t.columns.map((c) => {
|
|
133
|
+
let spec = `${c.name} (${c.type})`;
|
|
134
|
+
if (c.pk) spec += " PK";
|
|
135
|
+
if (c.notnull) spec += " NOT NULL";
|
|
136
|
+
if (c.defaultValue != null) spec += ` DEFAULT ${c.defaultValue}`;
|
|
137
|
+
return spec;
|
|
138
|
+
});
|
|
139
|
+
lines.push(`### ${t.name} (${t.rowCount} rows)`);
|
|
140
|
+
lines.push(colSpecs.map((s) => ` - ${s}`).join("\n"));
|
|
141
|
+
lines.push("");
|
|
142
|
+
}
|
|
143
|
+
return lines.join("\n").trimEnd();
|
|
144
|
+
}
|
|
145
|
+
var server = new McpServer({
|
|
146
|
+
name: "mcp-server-sqlite",
|
|
147
|
+
version: "1.0.0"
|
|
148
|
+
});
|
|
149
|
+
server.tool(
|
|
150
|
+
"query",
|
|
151
|
+
"Execute a SQL query against a SQLite database. Returns results as a formatted table. Read-only by default.",
|
|
152
|
+
{
|
|
153
|
+
db: z.string().describe("Path to the .db or .sqlite file"),
|
|
154
|
+
sql: z.string().describe("SQL query to execute"),
|
|
155
|
+
readonly: z.boolean().default(true).describe("If true, only SELECT/PRAGMA/EXPLAIN allowed")
|
|
156
|
+
},
|
|
157
|
+
async ({ db, sql, readonly }) => {
|
|
158
|
+
try {
|
|
159
|
+
const resolved = path2.resolve(db);
|
|
160
|
+
const result = query(resolved, sql, readonly);
|
|
161
|
+
const text = formatQueryResult(result.columns, result.rows);
|
|
162
|
+
return {
|
|
163
|
+
content: [
|
|
164
|
+
{
|
|
165
|
+
type: "text",
|
|
166
|
+
text: `Rows: ${result.rowCount}
|
|
167
|
+
|
|
168
|
+
${text}`
|
|
169
|
+
}
|
|
170
|
+
]
|
|
171
|
+
};
|
|
172
|
+
} catch (err) {
|
|
173
|
+
return {
|
|
174
|
+
content: [
|
|
175
|
+
{
|
|
176
|
+
type: "text",
|
|
177
|
+
text: `Error: ${err instanceof Error ? err.message : String(err)}`
|
|
178
|
+
}
|
|
179
|
+
],
|
|
180
|
+
isError: true
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
);
|
|
185
|
+
server.tool(
|
|
186
|
+
"schema",
|
|
187
|
+
"Get the schema of a SQLite database: all tables with columns and row counts.",
|
|
188
|
+
{
|
|
189
|
+
db: z.string().describe("Path to the .db or .sqlite file")
|
|
190
|
+
},
|
|
191
|
+
async ({ db }) => {
|
|
192
|
+
try {
|
|
193
|
+
const resolved = path2.resolve(db);
|
|
194
|
+
const schemaInfo = schema(resolved);
|
|
195
|
+
const text = formatSchema(schemaInfo);
|
|
196
|
+
return { content: [{ type: "text", text }] };
|
|
197
|
+
} catch (err) {
|
|
198
|
+
return {
|
|
199
|
+
content: [
|
|
200
|
+
{
|
|
201
|
+
type: "text",
|
|
202
|
+
text: `Error: ${err instanceof Error ? err.message : String(err)}`
|
|
203
|
+
}
|
|
204
|
+
],
|
|
205
|
+
isError: true
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
);
|
|
210
|
+
server.tool(
|
|
211
|
+
"table_info",
|
|
212
|
+
"Get detailed info about a single table: columns, types, constraints, and row count.",
|
|
213
|
+
{
|
|
214
|
+
db: z.string().describe("Path to the .db or .sqlite file"),
|
|
215
|
+
table: z.string().describe("Table name")
|
|
216
|
+
},
|
|
217
|
+
async ({ db, table }) => {
|
|
218
|
+
try {
|
|
219
|
+
const resolved = path2.resolve(db);
|
|
220
|
+
const info = tableInfo(resolved, table);
|
|
221
|
+
const colSpecs = info.columns.map((c) => {
|
|
222
|
+
let spec = `${c.name} (${c.type})`;
|
|
223
|
+
if (c.pk) spec += " PK";
|
|
224
|
+
if (c.notnull) spec += " NOT NULL";
|
|
225
|
+
if (c.defaultValue != null) spec += ` DEFAULT ${c.defaultValue}`;
|
|
226
|
+
return spec;
|
|
227
|
+
});
|
|
228
|
+
const text = [
|
|
229
|
+
`### ${info.name} (${info.rowCount} rows)`,
|
|
230
|
+
"",
|
|
231
|
+
...colSpecs.map((s) => `- ${s}`)
|
|
232
|
+
].join("\n");
|
|
233
|
+
return { content: [{ type: "text", text }] };
|
|
234
|
+
} catch (err) {
|
|
235
|
+
return {
|
|
236
|
+
content: [
|
|
237
|
+
{
|
|
238
|
+
type: "text",
|
|
239
|
+
text: `Error: ${err instanceof Error ? err.message : String(err)}`
|
|
240
|
+
}
|
|
241
|
+
],
|
|
242
|
+
isError: true
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
);
|
|
247
|
+
server.tool(
|
|
248
|
+
"explain",
|
|
249
|
+
"Explain the query plan for a SQL query (EXPLAIN QUERY PLAN). Helps optimize queries.",
|
|
250
|
+
{
|
|
251
|
+
db: z.string().describe("Path to the .db or .sqlite file"),
|
|
252
|
+
sql: z.string().describe("SQL query to explain")
|
|
253
|
+
},
|
|
254
|
+
async ({ db, sql }) => {
|
|
255
|
+
try {
|
|
256
|
+
const resolved = path2.resolve(db);
|
|
257
|
+
const plan = explain(resolved, sql);
|
|
258
|
+
return {
|
|
259
|
+
content: [{ type: "text", text: `Query plan:
|
|
260
|
+
${plan}` }]
|
|
261
|
+
};
|
|
262
|
+
} catch (err) {
|
|
263
|
+
return {
|
|
264
|
+
content: [
|
|
265
|
+
{
|
|
266
|
+
type: "text",
|
|
267
|
+
text: `Error: ${err instanceof Error ? err.message : String(err)}`
|
|
268
|
+
}
|
|
269
|
+
],
|
|
270
|
+
isError: true
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
);
|
|
275
|
+
server.tool(
|
|
276
|
+
"list_databases",
|
|
277
|
+
"List all SQLite database files (.db, .sqlite, .sqlite3) in a directory.",
|
|
278
|
+
{
|
|
279
|
+
directory: z.string().default(".").describe("Directory path to scan (default: current directory)")
|
|
280
|
+
},
|
|
281
|
+
async ({ directory }) => {
|
|
282
|
+
try {
|
|
283
|
+
const resolved = path2.resolve(directory);
|
|
284
|
+
const dbs = listDatabases(resolved);
|
|
285
|
+
if (dbs.length === 0) {
|
|
286
|
+
return {
|
|
287
|
+
content: [
|
|
288
|
+
{
|
|
289
|
+
type: "text",
|
|
290
|
+
text: `No .db, .sqlite, or .sqlite3 files found in ${resolved}`
|
|
291
|
+
}
|
|
292
|
+
]
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
const text = dbs.map((p) => `- ${p}`).join("\n");
|
|
296
|
+
return {
|
|
297
|
+
content: [
|
|
298
|
+
{
|
|
299
|
+
type: "text",
|
|
300
|
+
text: `Found ${dbs.length} database(s):
|
|
301
|
+
|
|
302
|
+
${text}`
|
|
303
|
+
}
|
|
304
|
+
]
|
|
305
|
+
};
|
|
306
|
+
} catch (err) {
|
|
307
|
+
return {
|
|
308
|
+
content: [
|
|
309
|
+
{
|
|
310
|
+
type: "text",
|
|
311
|
+
text: `Error: ${err instanceof Error ? err.message : String(err)}`
|
|
312
|
+
}
|
|
313
|
+
],
|
|
314
|
+
isError: true
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
);
|
|
319
|
+
async function main() {
|
|
320
|
+
const transport = new StdioServerTransport();
|
|
321
|
+
await server.connect(transport);
|
|
322
|
+
}
|
|
323
|
+
main().catch((err) => {
|
|
324
|
+
console.error("Fatal error:", err);
|
|
325
|
+
process.exit(1);
|
|
326
|
+
});
|
|
327
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/sqlite.ts"],"sourcesContent":["import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\nimport type { TableInfo } from \"./sqlite.js\";\nimport { query, schema, tableInfo, explain, listDatabases } from \"./sqlite.js\";\n\nfunction formatQueryResult(\n columns: string[],\n rows: Record<string, unknown>[],\n): string {\n if (columns.length === 0 && rows.length === 0) {\n return \"(No columns returned)\";\n }\n if (columns.length === 0) {\n return `(${rows.length} row(s) affected)`;\n }\n const widths = columns.map((col) =>\n Math.max(col.length, ...rows.map((r) => String(r[col] ?? \"\").length)),\n );\n const sep = widths.map((w) => \"-\".repeat(w)).join(\"-+-\");\n const header = columns.map((c, i) => c.padEnd(widths[i] ?? 0)).join(\" | \");\n const lines = [header, sep];\n for (const row of rows) {\n const line = columns\n .map((c, i) => String(row[c] ?? \"\").padEnd(widths[i] ?? 0))\n .join(\" | \");\n lines.push(line);\n }\n return lines.join(\"\\n\");\n}\n\nfunction formatSchema(schemaInfo: {\n tables: {\n name: string;\n columns: {\n name: string;\n type: string;\n notnull: boolean;\n pk: boolean;\n defaultValue: string | null;\n }[];\n rowCount: number;\n }[];\n totalTables: number;\n}): string {\n const lines: string[] = [`Schema: ${schemaInfo.totalTables} table(s)`, \"\"];\n for (const t of schemaInfo.tables) {\n const colSpecs = t.columns.map((c) => {\n let spec = `${c.name} (${c.type})`;\n if (c.pk) spec += \" PK\";\n if (c.notnull) spec += \" NOT NULL\";\n if (c.defaultValue != null) spec += ` DEFAULT ${c.defaultValue}`;\n return spec;\n });\n lines.push(`### ${t.name} (${t.rowCount} rows)`);\n lines.push(colSpecs.map((s) => ` - ${s}`).join(\"\\n\"));\n lines.push(\"\");\n }\n return lines.join(\"\\n\").trimEnd();\n}\n\nconst server = new McpServer({\n name: \"mcp-server-sqlite\",\n version: \"1.0.0\",\n});\n\nserver.tool(\n \"query\",\n \"Execute a SQL query against a SQLite database. Returns results as a formatted table. Read-only by default.\",\n {\n db: z.string().describe(\"Path to the .db or .sqlite file\"),\n sql: z.string().describe(\"SQL query to execute\"),\n readonly: z\n .boolean()\n .default(true)\n .describe(\"If true, only SELECT/PRAGMA/EXPLAIN allowed\"),\n },\n async ({ db, sql, readonly }) => {\n try {\n const resolved = path.resolve(db);\n const result = query(resolved, sql, readonly);\n const text = formatQueryResult(result.columns, result.rows);\n return {\n content: [\n {\n type: \"text\",\n text: `Rows: ${result.rowCount}\\n\\n${text}`,\n },\n ],\n };\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: `Error: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n isError: true,\n };\n }\n },\n);\n\nserver.tool(\n \"schema\",\n \"Get the schema of a SQLite database: all tables with columns and row counts.\",\n {\n db: z.string().describe(\"Path to the .db or .sqlite file\"),\n },\n async ({ db }) => {\n try {\n const resolved = path.resolve(db);\n const schemaInfo = schema(resolved);\n const text = formatSchema(schemaInfo);\n return { content: [{ type: \"text\", text }] };\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: `Error: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n isError: true,\n };\n }\n },\n);\n\nserver.tool(\n \"table_info\",\n \"Get detailed info about a single table: columns, types, constraints, and row count.\",\n {\n db: z.string().describe(\"Path to the .db or .sqlite file\"),\n table: z.string().describe(\"Table name\"),\n },\n async ({ db, table }) => {\n try {\n const resolved = path.resolve(db);\n const info = tableInfo(resolved, table);\n const colSpecs = info.columns.map((c: TableInfo[\"columns\"][number]) => {\n let spec = `${c.name} (${c.type})`;\n if (c.pk) spec += \" PK\";\n if (c.notnull) spec += \" NOT NULL\";\n if (c.defaultValue != null) spec += ` DEFAULT ${c.defaultValue}`;\n return spec;\n });\n const text = [\n `### ${info.name} (${info.rowCount} rows)`,\n \"\",\n ...colSpecs.map((s: string) => `- ${s}`),\n ].join(\"\\n\");\n return { content: [{ type: \"text\", text }] };\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: `Error: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n isError: true,\n };\n }\n },\n);\n\nserver.tool(\n \"explain\",\n \"Explain the query plan for a SQL query (EXPLAIN QUERY PLAN). Helps optimize queries.\",\n {\n db: z.string().describe(\"Path to the .db or .sqlite file\"),\n sql: z.string().describe(\"SQL query to explain\"),\n },\n async ({ db, sql }) => {\n try {\n const resolved = path.resolve(db);\n const plan = explain(resolved, sql);\n return {\n content: [{ type: \"text\", text: `Query plan:\\n${plan}` }],\n };\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: `Error: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n isError: true,\n };\n }\n },\n);\n\nserver.tool(\n \"list_databases\",\n \"List all SQLite database files (.db, .sqlite, .sqlite3) in a directory.\",\n {\n directory: z\n .string()\n .default(\".\")\n .describe(\"Directory path to scan (default: current directory)\"),\n },\n async ({ directory }) => {\n try {\n const resolved = path.resolve(directory);\n const dbs = listDatabases(resolved);\n if (dbs.length === 0) {\n return {\n content: [\n {\n type: \"text\",\n text: `No .db, .sqlite, or .sqlite3 files found in ${resolved}`,\n },\n ],\n };\n }\n const text = dbs.map((p: string) => `- ${p}`).join(\"\\n\");\n return {\n content: [\n {\n type: \"text\",\n text: `Found ${dbs.length} database(s):\\n\\n${text}`,\n },\n ],\n };\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: `Error: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n isError: true,\n };\n }\n },\n);\n\nasync function main() {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n\nmain().catch((err) => {\n console.error(\"Fatal error:\", err);\n process.exit(1);\n});\n","import Database from \"better-sqlite3\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nexport interface QueryResult {\n columns: string[];\n rows: Record<string, unknown>[];\n rowCount: number;\n}\n\nexport interface TableInfo {\n name: string;\n columns: {\n name: string;\n type: string;\n notnull: boolean;\n pk: boolean;\n defaultValue: string | null;\n }[];\n rowCount: number;\n}\n\nexport interface SchemaInfo {\n tables: TableInfo[];\n totalTables: number;\n}\n\nfunction openDb(dbPath: string): Database.Database {\n if (!fs.existsSync(dbPath)) {\n throw new Error(`Database file not found: ${dbPath}`);\n }\n return new Database(dbPath, { readonly: true });\n}\n\nfunction openDbWritable(dbPath: string): Database.Database {\n return new Database(dbPath);\n}\n\nexport function query(\n dbPath: string,\n sql: string,\n readonly = true,\n): QueryResult {\n const db = readonly ? openDb(dbPath) : openDbWritable(dbPath);\n try {\n const trimmed = sql.trim();\n const isSelect = /^(SELECT|PRAGMA|EXPLAIN|WITH)\\b/i.test(trimmed);\n\n if (readonly && !isSelect) {\n throw new Error(\n \"Write operations are not allowed in read-only mode. Set readonly=false to enable writes.\",\n );\n }\n\n if (isSelect) {\n const stmt = db.prepare(trimmed);\n const rows = stmt.all() as Record<string, unknown>[];\n const firstRow = rows[0];\n const columns = firstRow ? Object.keys(firstRow) : [];\n return { columns, rows, rowCount: rows.length };\n } else {\n db.exec(trimmed);\n return { columns: [], rows: [], rowCount: 0 };\n }\n } finally {\n db.close();\n }\n}\n\nexport function schema(dbPath: string): SchemaInfo {\n const db = openDb(dbPath);\n try {\n const tables = db\n .prepare(\n \"SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' ORDER BY name\",\n )\n .all() as { name: string }[];\n\n const tableInfos: TableInfo[] = tables.map((t) => {\n const columns = db.prepare(`PRAGMA table_info(\"${t.name}\")`).all() as {\n name: string;\n type: string;\n notnull: number;\n pk: number;\n dflt_value: string | null;\n }[];\n\n const countResult = db\n .prepare(`SELECT COUNT(*) as count FROM \"${t.name}\"`)\n .get() as { count: number };\n\n return {\n name: t.name,\n columns: columns.map((c) => ({\n name: c.name,\n type: c.type,\n notnull: c.notnull === 1,\n pk: c.pk === 1,\n defaultValue: c.dflt_value,\n })),\n rowCount: countResult.count,\n };\n });\n\n return { tables: tableInfos, totalTables: tableInfos.length };\n } finally {\n db.close();\n }\n}\n\nexport function tableInfo(dbPath: string, tableName: string): TableInfo {\n const db = openDb(dbPath);\n try {\n const columns = db.prepare(`PRAGMA table_info(\"${tableName}\")`).all() as {\n name: string;\n type: string;\n notnull: number;\n pk: number;\n dflt_value: string | null;\n }[];\n if (columns.length === 0) {\n throw new Error(`Table \"${tableName}\" not found`);\n }\n\n const countResult = db\n .prepare(`SELECT COUNT(*) as count FROM \"${tableName}\"`)\n .get() as { count: number };\n\n return {\n name: tableName,\n columns: columns.map((c) => ({\n name: c.name,\n type: c.type,\n notnull: c.notnull === 1,\n pk: c.pk === 1,\n defaultValue: c.dflt_value,\n })),\n rowCount: countResult.count,\n };\n } finally {\n db.close();\n }\n}\n\nexport function explain(dbPath: string, sql: string): string {\n const db = openDb(dbPath);\n try {\n const rows = db.prepare(`EXPLAIN QUERY PLAN ${sql}`).all() as Record<\n string,\n unknown\n >[];\n return rows.map((r) => `${r.id} | ${r.parent} | ${r.detail}`).join(\"\\n\");\n } finally {\n db.close();\n }\n}\n\nexport function listDatabases(directory: string): string[] {\n const entries = fs.readdirSync(directory, { withFileTypes: true });\n return entries\n .filter((e) => e.isFile() && /\\.(db|sqlite|sqlite3)$/i.test(e.name))\n .map((e) => path.join(directory, e.name))\n .sort();\n}\n"],"mappings":"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","names":["path","path"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mcp-sqlite-server",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "MCP server for SQLite — query databases, inspect schemas, explain queries, and export data from your IDE",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"mcp-sqlite-server": "./dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "tsup",
|
|
14
|
+
"typecheck": "tsc --noEmit",
|
|
15
|
+
"test": "vitest run",
|
|
16
|
+
"test:watch": "vitest",
|
|
17
|
+
"test:coverage": "vitest run --coverage",
|
|
18
|
+
"lint": "eslint . && prettier --check .",
|
|
19
|
+
"format": "prettier --write .",
|
|
20
|
+
"prepare": "husky"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"mcp",
|
|
24
|
+
"mcp-server",
|
|
25
|
+
"model-context-protocol",
|
|
26
|
+
"sqlite",
|
|
27
|
+
"database",
|
|
28
|
+
"sql",
|
|
29
|
+
"query",
|
|
30
|
+
"schema",
|
|
31
|
+
"turso",
|
|
32
|
+
"d1",
|
|
33
|
+
"ai",
|
|
34
|
+
"llm",
|
|
35
|
+
"claude",
|
|
36
|
+
"cursor"
|
|
37
|
+
],
|
|
38
|
+
"author": "Ofer Shapira",
|
|
39
|
+
"license": "MIT",
|
|
40
|
+
"repository": {
|
|
41
|
+
"type": "git",
|
|
42
|
+
"url": "https://github.com/ofershap/mcp-server-sqlite.git"
|
|
43
|
+
},
|
|
44
|
+
"bugs": {
|
|
45
|
+
"url": "https://github.com/ofershap/mcp-server-sqlite/issues"
|
|
46
|
+
},
|
|
47
|
+
"homepage": "https://github.com/ofershap/mcp-server-sqlite#readme",
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
50
|
+
"better-sqlite3": "^11.0.0",
|
|
51
|
+
"zod": "^3.25.0"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@eslint/js": "^9.0.0",
|
|
55
|
+
"@types/better-sqlite3": "^7.6.0",
|
|
56
|
+
"@types/node": "^22.0.0",
|
|
57
|
+
"@vitest/coverage-v8": "^3.2.0",
|
|
58
|
+
"eslint": "^9.0.0",
|
|
59
|
+
"eslint-config-prettier": "^10.0.0",
|
|
60
|
+
"husky": "^9.0.0",
|
|
61
|
+
"lint-staged": "^15.0.0",
|
|
62
|
+
"prettier": "^3.0.0",
|
|
63
|
+
"tsup": "^8.0.0",
|
|
64
|
+
"typescript": "^5.7.0",
|
|
65
|
+
"typescript-eslint": "^8.0.0",
|
|
66
|
+
"vitest": "^3.2.0"
|
|
67
|
+
},
|
|
68
|
+
"lint-staged": {
|
|
69
|
+
"*.{ts,tsx,js}": "eslint --fix",
|
|
70
|
+
"*.{json,md,yml,yaml}": "prettier --write"
|
|
71
|
+
}
|
|
72
|
+
}
|