@pilat/mcp-datalink 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.
- package/README.md +442 -0
- package/databases.example.json +18 -0
- package/dist/__integration__/global-setup.d.ts +8 -0
- package/dist/__integration__/global-setup.d.ts.map +1 -0
- package/dist/__integration__/global-setup.js +34 -0
- package/dist/__integration__/global-setup.js.map +1 -0
- package/dist/__integration__/global-teardown.d.ts +8 -0
- package/dist/__integration__/global-teardown.d.ts.map +1 -0
- package/dist/__integration__/global-teardown.js +17 -0
- package/dist/__integration__/global-teardown.js.map +1 -0
- package/dist/__integration__/helpers.d.ts +58 -0
- package/dist/__integration__/helpers.d.ts.map +1 -0
- package/dist/__integration__/helpers.js +568 -0
- package/dist/__integration__/helpers.js.map +1 -0
- package/dist/__integration__/setup.d.ts +79 -0
- package/dist/__integration__/setup.d.ts.map +1 -0
- package/dist/__integration__/setup.js +230 -0
- package/dist/__integration__/setup.js.map +1 -0
- package/dist/adapters/factory.d.ts +40 -0
- package/dist/adapters/factory.d.ts.map +1 -0
- package/dist/adapters/factory.js +114 -0
- package/dist/adapters/factory.js.map +1 -0
- package/dist/adapters/index.d.ts +31 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +34 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/mysql/adapter.d.ts +61 -0
- package/dist/adapters/mysql/adapter.d.ts.map +1 -0
- package/dist/adapters/mysql/adapter.js +567 -0
- package/dist/adapters/mysql/adapter.js.map +1 -0
- package/dist/adapters/postgresql/adapter.d.ts +52 -0
- package/dist/adapters/postgresql/adapter.d.ts.map +1 -0
- package/dist/adapters/postgresql/adapter.js +429 -0
- package/dist/adapters/postgresql/adapter.js.map +1 -0
- package/dist/adapters/sqlite/adapter.d.ts +56 -0
- package/dist/adapters/sqlite/adapter.d.ts.map +1 -0
- package/dist/adapters/sqlite/adapter.js +582 -0
- package/dist/adapters/sqlite/adapter.js.map +1 -0
- package/dist/adapters/types.d.ts +155 -0
- package/dist/adapters/types.d.ts.map +1 -0
- package/dist/adapters/types.js +7 -0
- package/dist/adapters/types.js.map +1 -0
- package/dist/config/loader.d.ts +11 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +127 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +38 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +21 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +191 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/describe-table.d.ts +11 -0
- package/dist/tools/describe-table.d.ts.map +1 -0
- package/dist/tools/describe-table.js +23 -0
- package/dist/tools/describe-table.js.map +1 -0
- package/dist/tools/execute.d.ts +22 -0
- package/dist/tools/execute.d.ts.map +1 -0
- package/dist/tools/execute.js +48 -0
- package/dist/tools/execute.js.map +1 -0
- package/dist/tools/explain.d.ts +25 -0
- package/dist/tools/explain.d.ts.map +1 -0
- package/dist/tools/explain.js +81 -0
- package/dist/tools/explain.js.map +1 -0
- package/dist/tools/list-databases.d.ts +18 -0
- package/dist/tools/list-databases.d.ts.map +1 -0
- package/dist/tools/list-databases.js +17 -0
- package/dist/tools/list-databases.js.map +1 -0
- package/dist/tools/list-tables.d.ts +22 -0
- package/dist/tools/list-tables.d.ts.map +1 -0
- package/dist/tools/list-tables.js +43 -0
- package/dist/tools/list-tables.js.map +1 -0
- package/dist/tools/query.d.ts +25 -0
- package/dist/tools/query.d.ts.map +1 -0
- package/dist/tools/query.js +109 -0
- package/dist/tools/query.js.map +1 -0
- package/dist/types.d.ts +93 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/errors.d.ts +22 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +41 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/formatter.d.ts +13 -0
- package/dist/utils/formatter.d.ts.map +1 -0
- package/dist/utils/formatter.js +56 -0
- package/dist/utils/formatter.js.map +1 -0
- package/dist/utils/truncate.d.ts +37 -0
- package/dist/utils/truncate.d.ts.map +1 -0
- package/dist/utils/truncate.js +91 -0
- package/dist/utils/truncate.js.map +1 -0
- package/package.json +65 -0
package/README.md
ADDED
|
@@ -0,0 +1,442 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/pilat/mcp-datalink/master/.github/logo.png" alt="MCP Datalink" width="120" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<h1 align="center">MCP Datalink</h1>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<strong>Secure database access for AI assistants via Model Context Protocol</strong>
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
<a href="https://www.npmjs.com/package/@pilat/mcp-datalink"><img src="https://img.shields.io/npm/v/@pilat/mcp-datalink.svg?style=flat-square&color=blue" alt="npm version" /></a>
|
|
13
|
+
<a href="https://www.npmjs.com/package/@pilat/mcp-datalink"><img src="https://img.shields.io/npm/dm/@pilat/mcp-datalink.svg?style=flat-square&color=green" alt="npm downloads" /></a>
|
|
14
|
+
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square" alt="License: MIT" /></a>
|
|
15
|
+
<a href="https://github.com/pilat/mcp-datalink"><img src="https://img.shields.io/github/stars/pilat/mcp-datalink?style=flat-square&color=orange" alt="GitHub stars" /></a>
|
|
16
|
+
<img src="https://img.shields.io/badge/Node.js-20+-339933?style=flat-square&logo=node.js&logoColor=white" alt="Node.js 20+" />
|
|
17
|
+
</p>
|
|
18
|
+
|
|
19
|
+
<p align="center">
|
|
20
|
+
<a href="#quick-start">Quick Start</a> |
|
|
21
|
+
<a href="#supported-databases">Databases</a> |
|
|
22
|
+
<a href="#mcp-client-configuration">Clients</a> |
|
|
23
|
+
<a href="#available-tools">Tools</a> |
|
|
24
|
+
<a href="#security">Security</a> |
|
|
25
|
+
<a href="#configuration">Configuration</a>
|
|
26
|
+
</p>
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
MCP Datalink is an [MCP (Model Context Protocol)](https://modelcontextprotocol.io) server that gives AI assistants secure, read/write access to your databases. Connect your favorite AI tools to PostgreSQL, MySQL, or SQLite with enterprise-grade security controls.
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
AI Assistant <--> MCP Datalink <--> Your Databases
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Why MCP Datalink?
|
|
37
|
+
|
|
38
|
+
- **Universal Compatibility** - Works with any MCP-compatible client: Claude Desktop, Claude Code, Cursor, Cline, and more
|
|
39
|
+
- **Multi-Database Support** - Connect PostgreSQL, MySQL, and SQLite simultaneously
|
|
40
|
+
- **Security-First Design** - Prepared statements, query validation, readonly modes, and DDL blocking
|
|
41
|
+
- **Context-Aware Output** - Smart truncation prevents context overflow in AI conversations
|
|
42
|
+
- **Zero-Install Option** - Run directly with `npx` - no global installation required
|
|
43
|
+
- **Production Ready** - Battle-tested with comprehensive test coverage
|
|
44
|
+
|
|
45
|
+
## Supported Databases
|
|
46
|
+
|
|
47
|
+
| Database | Status | Driver |
|
|
48
|
+
|----------|--------|--------|
|
|
49
|
+
| <img src="https://img.shields.io/badge/PostgreSQL-4169E1?style=flat-square&logo=postgresql&logoColor=white" alt="PostgreSQL" /> | Stable | node-postgres |
|
|
50
|
+
| <img src="https://img.shields.io/badge/MySQL-4479A1?style=flat-square&logo=mysql&logoColor=white" alt="MySQL" /> | Stable | mysql2 |
|
|
51
|
+
| <img src="https://img.shields.io/badge/SQLite-003B57?style=flat-square&logo=sqlite&logoColor=white" alt="SQLite" /> | Stable | better-sqlite3 |
|
|
52
|
+
|
|
53
|
+
## Quick Start
|
|
54
|
+
|
|
55
|
+
### 1. Create a configuration file
|
|
56
|
+
|
|
57
|
+
Create `databases.json` in your project directory:
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
{
|
|
61
|
+
"databases": {
|
|
62
|
+
"mydb": {
|
|
63
|
+
"url": "postgresql://user:password@localhost:5432/myapp"
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### 2. Add to your MCP client
|
|
70
|
+
|
|
71
|
+
Add to your client's MCP configuration (see [client-specific examples](#mcp-client-configuration) below):
|
|
72
|
+
|
|
73
|
+
```json
|
|
74
|
+
{
|
|
75
|
+
"mcpServers": {
|
|
76
|
+
"datalink": {
|
|
77
|
+
"command": "npx",
|
|
78
|
+
"args": ["-y", "@pilat/mcp-datalink", "--config", "./databases.json"]
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### 3. Start using it!
|
|
85
|
+
|
|
86
|
+
Your AI assistant now has access to 6 powerful database tools:
|
|
87
|
+
|
|
88
|
+
- `list_databases` - View all configured connections
|
|
89
|
+
- `list_tables` - Browse tables with row estimates
|
|
90
|
+
- `describe_table` - Inspect schemas, indexes, and foreign keys
|
|
91
|
+
- `query` - Execute SELECT queries safely
|
|
92
|
+
- `execute` - Run INSERT/UPDATE/DELETE with write protection
|
|
93
|
+
- `explain` - Analyze query execution plans
|
|
94
|
+
|
|
95
|
+
## MCP Client Configuration
|
|
96
|
+
|
|
97
|
+
MCP Datalink works with any MCP-compatible client. Here are setup instructions for popular tools:
|
|
98
|
+
|
|
99
|
+
<details>
|
|
100
|
+
<summary><strong>Claude Desktop</strong></summary>
|
|
101
|
+
|
|
102
|
+
Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
|
|
103
|
+
|
|
104
|
+
```json
|
|
105
|
+
{
|
|
106
|
+
"mcpServers": {
|
|
107
|
+
"datalink": {
|
|
108
|
+
"command": "npx",
|
|
109
|
+
"args": ["-y", "@pilat/mcp-datalink", "--config", "/path/to/databases.json"]
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
</details>
|
|
116
|
+
|
|
117
|
+
<details>
|
|
118
|
+
<summary><strong>Claude Code (CLI)</strong></summary>
|
|
119
|
+
|
|
120
|
+
Add to `~/.claude/settings.json`:
|
|
121
|
+
|
|
122
|
+
```json
|
|
123
|
+
{
|
|
124
|
+
"mcpServers": {
|
|
125
|
+
"datalink": {
|
|
126
|
+
"command": "npx",
|
|
127
|
+
"args": ["-y", "@pilat/mcp-datalink", "--config", "./databases.json"]
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Or use the CLI command:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
claude mcp add datalink -- npx -y @pilat/mcp-datalink --config ./databases.json
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
</details>
|
|
140
|
+
|
|
141
|
+
<details>
|
|
142
|
+
<summary><strong>Cursor</strong></summary>
|
|
143
|
+
|
|
144
|
+
Add to your Cursor MCP settings (Settings > MCP):
|
|
145
|
+
|
|
146
|
+
```json
|
|
147
|
+
{
|
|
148
|
+
"mcpServers": {
|
|
149
|
+
"datalink": {
|
|
150
|
+
"command": "npx",
|
|
151
|
+
"args": ["-y", "@pilat/mcp-datalink", "--config", "./databases.json"]
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
</details>
|
|
158
|
+
|
|
159
|
+
<details>
|
|
160
|
+
<summary><strong>Cline (VS Code Extension)</strong></summary>
|
|
161
|
+
|
|
162
|
+
Add to your Cline MCP configuration in VS Code settings:
|
|
163
|
+
|
|
164
|
+
```json
|
|
165
|
+
{
|
|
166
|
+
"cline.mcpServers": {
|
|
167
|
+
"datalink": {
|
|
168
|
+
"command": "npx",
|
|
169
|
+
"args": ["-y", "@pilat/mcp-datalink", "--config", "./databases.json"]
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
</details>
|
|
176
|
+
|
|
177
|
+
<details>
|
|
178
|
+
<summary><strong>Custom MCP Clients</strong></summary>
|
|
179
|
+
|
|
180
|
+
For any MCP-compatible client, use the standard server configuration:
|
|
181
|
+
|
|
182
|
+
```json
|
|
183
|
+
{
|
|
184
|
+
"command": "npx",
|
|
185
|
+
"args": ["-y", "@pilat/mcp-datalink", "--config", "/absolute/path/to/databases.json"]
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Or with global installation:
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
npm install -g @pilat/mcp-datalink
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
```json
|
|
196
|
+
{
|
|
197
|
+
"command": "mcp-datalink",
|
|
198
|
+
"args": ["--config", "/absolute/path/to/databases.json"]
|
|
199
|
+
}
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
</details>
|
|
203
|
+
|
|
204
|
+
## Available Tools
|
|
205
|
+
|
|
206
|
+
| Tool | Description | Example Use Case |
|
|
207
|
+
|------|-------------|------------------|
|
|
208
|
+
| `list_databases` | List all configured database connections | "What databases do I have access to?" |
|
|
209
|
+
| `list_tables` | List tables with row estimates and types | "Show me all tables in the main database" |
|
|
210
|
+
| `describe_table` | Get detailed schema information | "What columns does the users table have?" |
|
|
211
|
+
| `query` | Execute SELECT queries (returns Markdown) | "Find all users created this month" |
|
|
212
|
+
| `execute` | Execute INSERT/UPDATE/DELETE | "Update the user's email address" |
|
|
213
|
+
| `explain` | Show query execution plans | "Why is this query slow?" |
|
|
214
|
+
|
|
215
|
+
### Example Interaction
|
|
216
|
+
|
|
217
|
+
```
|
|
218
|
+
You: "What tables are in my database?"
|
|
219
|
+
AI: Let me check...
|
|
220
|
+
[Uses list_tables tool]
|
|
221
|
+
|
|
222
|
+
Found 5 tables:
|
|
223
|
+
- users (15,234 rows)
|
|
224
|
+
- orders (48,291 rows)
|
|
225
|
+
- products (1,205 rows)
|
|
226
|
+
- categories (24 rows)
|
|
227
|
+
- order_items (142,891 rows)
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## Configuration
|
|
231
|
+
|
|
232
|
+
### Configuration File
|
|
233
|
+
|
|
234
|
+
Create a `databases.json` file with your database connections:
|
|
235
|
+
|
|
236
|
+
```json
|
|
237
|
+
{
|
|
238
|
+
"databases": {
|
|
239
|
+
"production": {
|
|
240
|
+
"url": "postgresql://user:pass@prod.example.com:5432/app",
|
|
241
|
+
"readonly": true
|
|
242
|
+
},
|
|
243
|
+
"development": {
|
|
244
|
+
"url": "postgresql://dev:dev@localhost:5432/app_dev",
|
|
245
|
+
"readonly": false
|
|
246
|
+
},
|
|
247
|
+
"analytics": {
|
|
248
|
+
"url": "mysql://analyst:pass@analytics.example.com:3306/warehouse",
|
|
249
|
+
"readonly": true
|
|
250
|
+
},
|
|
251
|
+
"local": {
|
|
252
|
+
"url": "sqlite:///path/to/database.db"
|
|
253
|
+
}
|
|
254
|
+
},
|
|
255
|
+
"defaults": {
|
|
256
|
+
"timeout": 30000,
|
|
257
|
+
"maxRows": 100,
|
|
258
|
+
"maxCellLength": 500,
|
|
259
|
+
"maxTotalSize": 65536
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### Connection Options
|
|
265
|
+
|
|
266
|
+
| Option | Type | Default | Description |
|
|
267
|
+
|--------|------|---------|-------------|
|
|
268
|
+
| `url` | string | required | Database connection string |
|
|
269
|
+
| `readonly` | boolean | `false` | Block INSERT/UPDATE/DELETE operations |
|
|
270
|
+
| `maxRows` | number | `100` | Maximum rows returned per query |
|
|
271
|
+
|
|
272
|
+
### URL Formats
|
|
273
|
+
|
|
274
|
+
```bash
|
|
275
|
+
# PostgreSQL
|
|
276
|
+
postgresql://user:password@host:5432/database
|
|
277
|
+
|
|
278
|
+
# MySQL
|
|
279
|
+
mysql://user:password@host:3306/database
|
|
280
|
+
|
|
281
|
+
# SQLite
|
|
282
|
+
sqlite:///absolute/path/to/database.db
|
|
283
|
+
sqlite://./relative/path/to/database.db
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### Environment Variables
|
|
287
|
+
|
|
288
|
+
Alternative to config file - set connections via environment variables:
|
|
289
|
+
|
|
290
|
+
```bash
|
|
291
|
+
DB_MCP_PRODUCTION_URL=postgresql://user:pass@prod.example.com:5432/app
|
|
292
|
+
DB_MCP_DEVELOPMENT_URL=postgresql://dev:dev@localhost:5432/app_dev
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
Pattern: `DB_MCP_{NAME}_URL` creates a connection named `{name}` (lowercase).
|
|
296
|
+
|
|
297
|
+
### Config Resolution Order
|
|
298
|
+
|
|
299
|
+
1. CLI argument: `--config ./path/to/config.json`
|
|
300
|
+
2. Environment variable: `DB_MCP_CONFIG=/path/to/config.json`
|
|
301
|
+
3. Current directory: `./databases.json`
|
|
302
|
+
4. Home directory: `~/.config/db-mcp/databases.json`
|
|
303
|
+
|
|
304
|
+
## Security
|
|
305
|
+
|
|
306
|
+
MCP Datalink is designed with security as a core principle:
|
|
307
|
+
|
|
308
|
+
| Feature | Description |
|
|
309
|
+
|---------|-------------|
|
|
310
|
+
| **Prepared Statements** | All queries use parameterized queries to prevent SQL injection |
|
|
311
|
+
| **Query Validation** | SQL parser validates and restricts query types |
|
|
312
|
+
| **Single Statement Only** | Multi-statement queries are rejected |
|
|
313
|
+
| **DDL Blocking** | CREATE, DROP, ALTER, TRUNCATE are forbidden |
|
|
314
|
+
| **Readonly Mode** | Per-connection write protection |
|
|
315
|
+
| **Connection Isolation** | Fresh connection per request, no connection reuse |
|
|
316
|
+
| **Output Limits** | Prevents context overflow with configurable size limits |
|
|
317
|
+
|
|
318
|
+
### Output Limits
|
|
319
|
+
|
|
320
|
+
To prevent overwhelming AI context windows, all outputs are automatically limited:
|
|
321
|
+
|
|
322
|
+
| Parameter | Default | Maximum |
|
|
323
|
+
|-----------|---------|---------|
|
|
324
|
+
| `maxRows` | 100 | 500 |
|
|
325
|
+
| `maxCellLength` | 500 chars | 1,000 chars |
|
|
326
|
+
| `maxTotalSize` | 64 KB | 256 KB |
|
|
327
|
+
| `maxColumns` | 50 | 100 |
|
|
328
|
+
|
|
329
|
+
When limits are exceeded, responses include `truncated: true` with pagination hints.
|
|
330
|
+
|
|
331
|
+
## Installation Options
|
|
332
|
+
|
|
333
|
+
### Zero-Install (Recommended)
|
|
334
|
+
|
|
335
|
+
Run directly with `npx` - the package is downloaded automatically:
|
|
336
|
+
|
|
337
|
+
```bash
|
|
338
|
+
npx @pilat/mcp-datalink --config ./databases.json
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
### Global Installation
|
|
342
|
+
|
|
343
|
+
```bash
|
|
344
|
+
npm install -g @pilat/mcp-datalink
|
|
345
|
+
mcp-datalink --config ./databases.json
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
### Local Installation
|
|
349
|
+
|
|
350
|
+
```bash
|
|
351
|
+
npm install @pilat/mcp-datalink
|
|
352
|
+
npx mcp-datalink --config ./databases.json
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
## Development
|
|
356
|
+
|
|
357
|
+
```bash
|
|
358
|
+
# Clone the repository
|
|
359
|
+
git clone https://github.com/pilat/mcp-datalink.git
|
|
360
|
+
cd mcp-datalink
|
|
361
|
+
|
|
362
|
+
# Install dependencies
|
|
363
|
+
npm install
|
|
364
|
+
|
|
365
|
+
# Build
|
|
366
|
+
npm run build
|
|
367
|
+
|
|
368
|
+
# Run tests
|
|
369
|
+
npm run test:unit # Unit tests (fast, no external deps)
|
|
370
|
+
npm run test:integration # Integration tests (uses testcontainers)
|
|
371
|
+
npm test # All tests
|
|
372
|
+
|
|
373
|
+
# Development mode
|
|
374
|
+
npm run dev # Watch mode with auto-rebuild
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
### Testing with MCP Inspector
|
|
378
|
+
|
|
379
|
+
```bash
|
|
380
|
+
npx @modelcontextprotocol/inspector node dist/index.js -- --config ./databases.json
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
## Contributing
|
|
384
|
+
|
|
385
|
+
Contributions are welcome! Please read our contributing guidelines:
|
|
386
|
+
|
|
387
|
+
1. Fork the repository
|
|
388
|
+
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
|
|
389
|
+
3. Commit your changes (`git commit -m 'feat: add amazing feature'`)
|
|
390
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
391
|
+
5. Open a Pull Request
|
|
392
|
+
|
|
393
|
+
### Commit Convention
|
|
394
|
+
|
|
395
|
+
We use [Conventional Commits](https://www.conventionalcommits.org/):
|
|
396
|
+
|
|
397
|
+
```
|
|
398
|
+
feat(tools): add new database tool
|
|
399
|
+
fix(security): enforce query validation
|
|
400
|
+
docs: update README
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
## Roadmap
|
|
404
|
+
|
|
405
|
+
### Databases
|
|
406
|
+
- [x] PostgreSQL support
|
|
407
|
+
- [x] MySQL support
|
|
408
|
+
- [x] SQLite support
|
|
409
|
+
- [ ] MongoDB support
|
|
410
|
+
- [ ] Redis support
|
|
411
|
+
|
|
412
|
+
### Security Hardening
|
|
413
|
+
- [ ] MySQL AST parser (replace regex-based parsing)
|
|
414
|
+
- [ ] SQLite AST parser
|
|
415
|
+
- [ ] Production error sanitization mode
|
|
416
|
+
- [ ] Timeout upper bound validation
|
|
417
|
+
- [ ] SQLite path allowlist
|
|
418
|
+
|
|
419
|
+
### Features
|
|
420
|
+
- [ ] Connection pooling
|
|
421
|
+
- [ ] Query history / audit log
|
|
422
|
+
- [ ] Transaction support
|
|
423
|
+
- [ ] Schema diff between databases
|
|
424
|
+
- [ ] SSH tunnel support
|
|
425
|
+
- [ ] Read replicas routing
|
|
426
|
+
|
|
427
|
+
## Links
|
|
428
|
+
|
|
429
|
+
- [GitHub Repository](https://github.com/pilat/mcp-datalink)
|
|
430
|
+
- [npm Package](https://www.npmjs.com/package/@pilat/mcp-datalink)
|
|
431
|
+
- [Issue Tracker](https://github.com/pilat/mcp-datalink/issues)
|
|
432
|
+
- [MCP Documentation](https://modelcontextprotocol.io)
|
|
433
|
+
|
|
434
|
+
## License
|
|
435
|
+
|
|
436
|
+
MIT License - see [LICENSE](LICENSE) for details.
|
|
437
|
+
|
|
438
|
+
---
|
|
439
|
+
|
|
440
|
+
<p align="center">
|
|
441
|
+
<sub>Built with care by <a href="https://github.com/pilat">@pilat</a></sub>
|
|
442
|
+
</p>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"databases": {
|
|
3
|
+
"main": {
|
|
4
|
+
"url": "postgresql://user:password@localhost:5432/myapp",
|
|
5
|
+
"readonly": false
|
|
6
|
+
},
|
|
7
|
+
"analytics": {
|
|
8
|
+
"url": "postgresql://readonly:password@analytics.example.com:5432/warehouse",
|
|
9
|
+
"readonly": true
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"defaults": {
|
|
13
|
+
"timeout": 30000,
|
|
14
|
+
"maxRows": 100,
|
|
15
|
+
"maxCellLength": 500,
|
|
16
|
+
"maxTotalSize": 65536
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vitest global setup for integration tests
|
|
3
|
+
*
|
|
4
|
+
* Starts PostgreSQL and MySQL containers and initializes the test databases.
|
|
5
|
+
* Also creates and initializes the SQLite test database (no Docker needed).
|
|
6
|
+
*/
|
|
7
|
+
export default function globalSetup(): Promise<void>;
|
|
8
|
+
//# sourceMappingURL=global-setup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"global-setup.d.ts","sourceRoot":"","sources":["../../src/__integration__/global-setup.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAYH,wBAA8B,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAiCzD"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vitest global setup for integration tests
|
|
3
|
+
*
|
|
4
|
+
* Starts PostgreSQL and MySQL containers and initializes the test databases.
|
|
5
|
+
* Also creates and initializes the SQLite test database (no Docker needed).
|
|
6
|
+
*/
|
|
7
|
+
import { startContainers, createSqliteTestDb } from './setup.js';
|
|
8
|
+
import { initializeSchema, seedTestData, initializeMySqlSchema, seedMySqlTestData, initializeSqliteSchema, seedSqliteTestData, } from './helpers.js';
|
|
9
|
+
export default async function globalSetup() {
|
|
10
|
+
console.log('\n=== Integration Test Setup ===\n');
|
|
11
|
+
// Start both PostgreSQL and MySQL containers
|
|
12
|
+
await startContainers();
|
|
13
|
+
// Initialize PostgreSQL schema
|
|
14
|
+
console.log('Initializing PostgreSQL schema...');
|
|
15
|
+
await initializeSchema();
|
|
16
|
+
// Seed PostgreSQL test data
|
|
17
|
+
console.log('Seeding PostgreSQL test data...');
|
|
18
|
+
await seedTestData();
|
|
19
|
+
// Initialize MySQL schema
|
|
20
|
+
console.log('Initializing MySQL schema...');
|
|
21
|
+
await initializeMySqlSchema();
|
|
22
|
+
// Seed MySQL test data
|
|
23
|
+
console.log('Seeding MySQL test data...');
|
|
24
|
+
await seedMySqlTestData();
|
|
25
|
+
// Create and initialize SQLite database (no Docker needed)
|
|
26
|
+
console.log('Creating SQLite test database...');
|
|
27
|
+
createSqliteTestDb();
|
|
28
|
+
console.log('Initializing SQLite schema...');
|
|
29
|
+
await initializeSqliteSchema();
|
|
30
|
+
console.log('Seeding SQLite test data...');
|
|
31
|
+
await seedSqliteTestData();
|
|
32
|
+
console.log('\n=== Setup Complete ===\n');
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=global-setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"global-setup.js","sourceRoot":"","sources":["../../src/__integration__/global-setup.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACjE,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,qBAAqB,EACrB,iBAAiB,EACjB,sBAAsB,EACtB,kBAAkB,GACnB,MAAM,cAAc,CAAC;AAEtB,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,WAAW;IACvC,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;IAElD,6CAA6C;IAC7C,MAAM,eAAe,EAAE,CAAC;IAExB,+BAA+B;IAC/B,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;IACjD,MAAM,gBAAgB,EAAE,CAAC;IAEzB,4BAA4B;IAC5B,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;IAC/C,MAAM,YAAY,EAAE,CAAC;IAErB,0BAA0B;IAC1B,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;IAC5C,MAAM,qBAAqB,EAAE,CAAC;IAE9B,uBAAuB;IACvB,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;IAC1C,MAAM,iBAAiB,EAAE,CAAC;IAE1B,2DAA2D;IAC3D,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;IAChD,kBAAkB,EAAE,CAAC;IAErB,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;IAC7C,MAAM,sBAAsB,EAAE,CAAC;IAE/B,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;IAC3C,MAAM,kBAAkB,EAAE,CAAC;IAE3B,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;AAC5C,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vitest global teardown for integration tests
|
|
3
|
+
*
|
|
4
|
+
* Stops and removes the PostgreSQL and MySQL containers.
|
|
5
|
+
* Deletes the SQLite test database file.
|
|
6
|
+
*/
|
|
7
|
+
export default function globalTeardown(): Promise<void>;
|
|
8
|
+
//# sourceMappingURL=global-teardown.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"global-teardown.d.ts","sourceRoot":"","sources":["../../src/__integration__/global-teardown.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,wBAA8B,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAW5D"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vitest global teardown for integration tests
|
|
3
|
+
*
|
|
4
|
+
* Stops and removes the PostgreSQL and MySQL containers.
|
|
5
|
+
* Deletes the SQLite test database file.
|
|
6
|
+
*/
|
|
7
|
+
import { stopContainers, deleteSqliteTestDb } from './setup.js';
|
|
8
|
+
export default async function globalTeardown() {
|
|
9
|
+
console.log('\n=== Integration Test Teardown ===\n');
|
|
10
|
+
// Stop all test containers (PostgreSQL + MySQL)
|
|
11
|
+
await stopContainers();
|
|
12
|
+
// Delete SQLite test database file
|
|
13
|
+
console.log('Deleting SQLite test database...');
|
|
14
|
+
deleteSqliteTestDb();
|
|
15
|
+
console.log('\n=== Teardown Complete ===\n');
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=global-teardown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"global-teardown.js","sourceRoot":"","sources":["../../src/__integration__/global-teardown.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEhE,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,cAAc;IAC1C,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC;IAErD,gDAAgD;IAChD,MAAM,cAAc,EAAE,CAAC;IAEvB,mCAAmC;IACnC,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;IAChD,kBAAkB,EAAE,CAAC;IAErB,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;AAC/C,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration test helpers
|
|
3
|
+
*
|
|
4
|
+
* Provides test configuration factory and database utilities.
|
|
5
|
+
*/
|
|
6
|
+
import type { Config } from '../types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Create a test configuration with optional overrides
|
|
9
|
+
*/
|
|
10
|
+
export declare function createTestConfig(overrides?: Partial<Config>): Config;
|
|
11
|
+
/**
|
|
12
|
+
* Initialize the test database schema
|
|
13
|
+
*/
|
|
14
|
+
export declare function initializeSchema(): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Seed the test database with sample data
|
|
17
|
+
* Uses TRUNCATE CASCADE for fast, atomic cleanup then re-insert
|
|
18
|
+
*/
|
|
19
|
+
export declare function seedTestData(): Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* Clean up test data between tests
|
|
22
|
+
*/
|
|
23
|
+
export declare function cleanupTestData(): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Create a SQLite test configuration with optional overrides
|
|
26
|
+
*/
|
|
27
|
+
export declare function createSqliteTestConfig(overrides?: Partial<Config>): Config;
|
|
28
|
+
/**
|
|
29
|
+
* Initialize the SQLite test database schema
|
|
30
|
+
*/
|
|
31
|
+
export declare function initializeSqliteSchema(): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* Seed the SQLite test database with sample data
|
|
34
|
+
* Uses full cleanup + re-insert to ensure consistent state
|
|
35
|
+
*/
|
|
36
|
+
export declare function seedSqliteTestData(): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* Clean up SQLite test data between tests
|
|
39
|
+
*/
|
|
40
|
+
export declare function cleanupSqliteTestData(): Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* Create a MySQL test configuration with optional overrides
|
|
43
|
+
*/
|
|
44
|
+
export declare function createMySqlTestConfig(overrides?: Partial<Config>): Config;
|
|
45
|
+
/**
|
|
46
|
+
* Initialize the MySQL test database schema
|
|
47
|
+
*/
|
|
48
|
+
export declare function initializeMySqlSchema(): Promise<void>;
|
|
49
|
+
/**
|
|
50
|
+
* Seed the MySQL test database with sample data
|
|
51
|
+
* Uses TRUNCATE for fast cleanup then re-insert
|
|
52
|
+
*/
|
|
53
|
+
export declare function seedMySqlTestData(): Promise<void>;
|
|
54
|
+
/**
|
|
55
|
+
* Clean up MySQL test data between tests
|
|
56
|
+
*/
|
|
57
|
+
export declare function cleanupMySqlTestData(): Promise<void>;
|
|
58
|
+
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/__integration__/helpers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAK1C;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAyCpE;AAED;;GAEG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAgGtD;AAED;;;GAGG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CA2ClD;AAED;;GAEG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAKrD;AAMD;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAwC1E;AAED;;GAEG;AACH,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC,CAwF5D;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAgDxD;AAED;;GAEG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC,CAK3D;AAMD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAyCzE;AAED;;GAEG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC,CAgG3D;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CA0CvD;AAED;;GAEG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAS1D"}
|