@yanzhang123/readonly-db-mcp 0.7.3 → 0.7.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -1,18 +1,30 @@
|
|
|
1
1
|
[](https://github.com/12zhangyan/mysql_mcp_server/actions)
|
|
2
|
-
[](https://www.npmjs.com/package/@yanzhang123/readonly-db-mcp)
|
|
3
|
+
[](https://www.npmjs.com/package/@yanzhang123/readonly-db-mcp)
|
|
4
|
+
|
|
4
5
|
# MySQL MCP Server
|
|
5
|
-
|
|
6
|
+
|
|
7
|
+
An enterprise-auditable, strictly read-only Model Context Protocol (MCP) server
|
|
8
|
+
for exploring multiple MySQL environments and databases from one process.
|
|
9
|
+
|
|
10
|
+
The supported npm distribution for this fork is
|
|
11
|
+
[`@yanzhang123/readonly-db-mcp`](https://www.npmjs.com/package/@yanzhang123/readonly-db-mcp).
|
|
12
|
+
It includes the matching Python wheel and a cross-platform launcher, so MCP
|
|
13
|
+
clients do not need a repository checkout or a separate package installation.
|
|
6
14
|
|
|
7
15
|
> **Note**: MySQL MCP Server supports both standard input/output (STDIO) and Streamable HTTP (SSE) transport modes. The SSE mode is recommended for remote/self-hosted deployments.
|
|
8
16
|
|
|
9
|
-
|
|
10
|
-
-
|
|
11
|
-
|
|
17
|
+
> [!IMPORTANT]
|
|
18
|
+
> Read-only enforcement does not trust the MySQL account grants. Even if the
|
|
19
|
+
> supplied account has `INSERT`, `UPDATE`, `DELETE`, or DDL privileges, the MCP
|
|
20
|
+
> SQL gate only accepts reviewed read statement families, runs them in a
|
|
21
|
+
> read-only transaction, and always rolls back. A database-level `SELECT`-only
|
|
22
|
+
> account is still strongly recommended as independent defense in depth.
|
|
12
23
|
|
|
13
24
|
## Features
|
|
14
25
|
- **Named connection profiles** for dev/test/staging/prod and multiple servers
|
|
15
26
|
- Select a `connection` and `database` independently on every tool call
|
|
27
|
+
- Database-to-profile routing hints without implicit cross-environment switching
|
|
16
28
|
- **Strictly read-only SQL** with fail-closed validation, a MySQL read-only transaction, and unconditional rollback
|
|
17
29
|
- Discover connections, databases, tables, schemas, and sample rows
|
|
18
30
|
- Return-size protection (`MYSQL_MAX_ROWS`, hard maximum 1000)
|
|
@@ -20,44 +32,78 @@ A Model Context Protocol (MCP) implementation that enables secure interaction wi
|
|
|
20
32
|
- **SSE/HTTP transport support** (`MCP_TRANSPORT=sse`)
|
|
21
33
|
- Per-profile SSL/TLS and SSH tunneling
|
|
22
34
|
- Passwords can stay in environment variables instead of the profiles file
|
|
35
|
+
- Compatibility `query` alias for clients migrating from older MySQL MCP servers
|
|
23
36
|
|
|
24
37
|
## Installation
|
|
25
38
|
|
|
26
39
|
### npm / npx
|
|
27
40
|
|
|
28
|
-
|
|
29
|
-
|
|
41
|
+
Requirements: Node.js 18+, npm 9+, and Python 3.11+ available on `PATH`.
|
|
42
|
+
|
|
43
|
+
Run the current release without installing it globally:
|
|
30
44
|
|
|
31
45
|
```bash
|
|
32
46
|
npx -y @yanzhang123/readonly-db-mcp
|
|
33
47
|
```
|
|
34
48
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
49
|
+
For controlled production rollouts, pin the reviewed version:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
npx -y @yanzhang123/readonly-db-mcp@x.y.z
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Replace `x.y.z` with the version approved by your organization. The unversioned
|
|
56
|
+
examples below intentionally resolve the npm `latest` tag.
|
|
57
|
+
|
|
58
|
+
On first use, the launcher creates a versioned virtual environment in the user
|
|
59
|
+
cache and installs the bundled wheel plus exact Python dependencies from a
|
|
60
|
+
version-controlled SHA-256 lock file. Downloads use the configured pip index
|
|
61
|
+
and the completed environment is cached by wheel-and-lock fingerprint. Override
|
|
62
|
+
Python with `MYSQL_MCP_PYTHON` or the cache location with
|
|
63
|
+
`MYSQL_MCP_NPM_CACHE_DIR`.
|
|
41
64
|
|
|
42
65
|
For MCP clients, use `npx` as the command and
|
|
43
66
|
`["-y", "@yanzhang123/readonly-db-mcp"]` as its arguments.
|
|
44
67
|
|
|
45
|
-
###
|
|
46
|
-
```bash
|
|
47
|
-
pip install mysql-mcp-server
|
|
48
|
-
```
|
|
68
|
+
### Minimal MCP client configuration
|
|
49
69
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
70
|
+
Create `mysql-connections.toml` from
|
|
71
|
+
[`mysql-connections.example.toml`](mysql-connections.example.toml), keep
|
|
72
|
+
passwords in environment variables, and use an absolute path:
|
|
73
|
+
|
|
74
|
+
```json
|
|
75
|
+
{
|
|
76
|
+
"mcpServers": {
|
|
77
|
+
"mysql-readonly": {
|
|
78
|
+
"command": "npx",
|
|
79
|
+
"args": ["-y", "@yanzhang123/readonly-db-mcp"],
|
|
80
|
+
"env": {
|
|
81
|
+
"MYSQL_PROFILES_FILE": "C:/absolute/path/mysql-connections.toml",
|
|
82
|
+
"MYSQL_DEV_PASSWORD": "set-in-the-client-secret-store"
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
54
87
|
```
|
|
55
88
|
|
|
56
|
-
|
|
89
|
+
On Windows clients that do not resolve npm command shims correctly, set
|
|
90
|
+
`"command": "npx.cmd"`. Do not commit the populated profile, passwords, audit
|
|
91
|
+
HMAC keys, connection strings, or client configuration containing secrets.
|
|
92
|
+
|
|
93
|
+
After startup, call `validate_connections`, then `check_connection`, before
|
|
94
|
+
running discovery queries. `check_connection` reports an irreversible account
|
|
95
|
+
fingerprint and privilege classification without returning the username or raw
|
|
96
|
+
grant statements.
|
|
97
|
+
|
|
98
|
+
### Manual Python installation
|
|
99
|
+
|
|
57
100
|
```bash
|
|
58
|
-
|
|
101
|
+
pip install mysql-mcp-server
|
|
59
102
|
```
|
|
60
103
|
|
|
104
|
+
The Python package remains available for source-oriented deployments, but the
|
|
105
|
+
scoped npm package is the documented distribution path for this fork.
|
|
106
|
+
|
|
61
107
|
## Configuration
|
|
62
108
|
|
|
63
109
|
### Recommended: named connections
|
|
@@ -239,6 +285,9 @@ All tools are declared with `readOnlyHint=true` and `destructiveHint=false`.
|
|
|
239
285
|
|
|
240
286
|
### `list_connections`
|
|
241
287
|
Lists named profiles, default database, policy limits and readiness. It never returns hosts, usernames, passwords, or SSH key paths.
|
|
288
|
+
It also returns a `database_routes` index so clients can select the correct
|
|
289
|
+
profile when one environment is split across several database-specific
|
|
290
|
+
connections.
|
|
242
291
|
|
|
243
292
|
### `validate_connections`
|
|
244
293
|
Forces a configuration reload and reports valid/invalid profiles plus missing
|
|
@@ -271,6 +320,16 @@ Executes exactly one read-only statement.
|
|
|
271
320
|
- **Pagination:** JSON output includes `truncated` and `next_offset`; pass that value back as `offset`.
|
|
272
321
|
- **Formats:** `json` preserves structured rows and metadata; `csv` uses RFC-style quoting and explicit `NULL`.
|
|
273
322
|
- **Attribution:** `audit_context` supports `actor`, `purpose`, and `ticket_id`. A profile can require any of these fields before a connection is opened.
|
|
323
|
+
- **Transient connector recovery:** client-side Connector/Python failures with
|
|
324
|
+
`errno=-1` are retried once. Persistent failures report only a safe exception
|
|
325
|
+
type and lifecycle phase; connector messages are not exposed.
|
|
326
|
+
|
|
327
|
+
### `query`
|
|
328
|
+
Compatibility alias for `execute_sql` with the same schema and all the same
|
|
329
|
+
read-only, database allowlist, masking, timeout, pagination, and audit controls.
|
|
330
|
+
Stateful legacy tools such as `use_connection` and `use_database` are
|
|
331
|
+
intentionally not restored because process-global selection is unsafe with
|
|
332
|
+
concurrent MCP clients.
|
|
274
333
|
|
|
275
334
|
### `get_schema_info`
|
|
276
335
|
Provides detailed metadata about database structures.
|
|
@@ -285,6 +344,9 @@ Fetches a representative sample of data.
|
|
|
285
344
|
- **Use Case:** Quickly understand data formats and content without fetching large result sets.
|
|
286
345
|
- **Cross-database:** Pass `database.table` to sample a table outside `MYSQL_DATABASE`; bare names use the configured database.
|
|
287
346
|
- **Identifier rules:** Names must contain only alphanumeric characters, underscores, and `$` (dots are allowed as a separator between database and table names).
|
|
347
|
+
- **Bounded execution:** Sampling applies `LIMIT limit+1 OFFSET offset` in
|
|
348
|
+
MySQL and fully consumes that small result. It does not open an unbounded
|
|
349
|
+
table scan merely to return a few rows.
|
|
288
350
|
|
|
289
351
|
## Available Prompts
|
|
290
352
|
|
|
@@ -309,14 +371,9 @@ Add this to your `claude_desktop_config.json`:
|
|
|
309
371
|
```json
|
|
310
372
|
{
|
|
311
373
|
"mcpServers": {
|
|
312
|
-
"mysql": {
|
|
313
|
-
"command": "
|
|
314
|
-
"args": [
|
|
315
|
-
"--directory",
|
|
316
|
-
"path/to/mysql_mcp_server",
|
|
317
|
-
"run",
|
|
318
|
-
"mysql_mcp_server"
|
|
319
|
-
],
|
|
374
|
+
"mysql-readonly": {
|
|
375
|
+
"command": "npx",
|
|
376
|
+
"args": ["-y", "@yanzhang123/readonly-db-mcp"],
|
|
320
377
|
"env": {
|
|
321
378
|
"MYSQL_PROFILES_FILE": "C:/absolute/path/mysql-connections.toml",
|
|
322
379
|
"MYSQL_DEV_PASSWORD": "your_dev_password",
|
|
@@ -334,14 +391,10 @@ Add this to your `mcp.json`:
|
|
|
334
391
|
```json
|
|
335
392
|
{
|
|
336
393
|
"mcpServers": {
|
|
337
|
-
"mysql": {
|
|
394
|
+
"mysql-readonly": {
|
|
338
395
|
"type": "stdio",
|
|
339
|
-
"command": "
|
|
340
|
-
"args": [
|
|
341
|
-
"--from",
|
|
342
|
-
"mysql-mcp-server",
|
|
343
|
-
"mysql_mcp_server"
|
|
344
|
-
],
|
|
396
|
+
"command": "npx",
|
|
397
|
+
"args": ["-y", "@yanzhang123/readonly-db-mcp"],
|
|
345
398
|
"env": {
|
|
346
399
|
"MYSQL_PROFILES_FILE": "C:/absolute/path/mysql-connections.toml",
|
|
347
400
|
"MYSQL_DEV_PASSWORD": "your_dev_password",
|
|
@@ -351,7 +404,8 @@ Add this to your `mcp.json`:
|
|
|
351
404
|
}
|
|
352
405
|
}
|
|
353
406
|
```
|
|
354
|
-
|
|
407
|
+
|
|
408
|
+
Use `npx.cmd` instead of `npx` if required by your Windows MCP host.
|
|
355
409
|
|
|
356
410
|
### Debugging with MCP Inspector
|
|
357
411
|
While MySQL MCP Server isn't intended to be run standalone or directly from the command line with Python, you can use the MCP Inspector to debug it.
|
|
@@ -373,11 +427,13 @@ git clone https://github.com/12zhangyan/mysql_mcp_server.git
|
|
|
373
427
|
cd mysql_mcp_server
|
|
374
428
|
# Create virtual environment
|
|
375
429
|
python -m venv venv
|
|
376
|
-
source venv/bin/activate
|
|
430
|
+
# Linux/macOS: source venv/bin/activate
|
|
431
|
+
# Windows PowerShell: .\venv\Scripts\Activate.ps1
|
|
377
432
|
# Install development dependencies
|
|
378
433
|
pip install -r requirements-dev.txt
|
|
379
434
|
# Copy the example config and edit with your credentials
|
|
380
|
-
cp .env.example .env
|
|
435
|
+
# Linux/macOS: cp .env.example .env
|
|
436
|
+
# Windows PowerShell: Copy-Item .env.example .env
|
|
381
437
|
# Edit .env with your MySQL connection details
|
|
382
438
|
# Run tests
|
|
383
439
|
pytest
|
|
@@ -388,6 +444,10 @@ pytest
|
|
|
388
444
|
- **Database enforcement:** Every exposed query runs with `autocommit=false` in a read-only transaction. Normal completion rolls back; cancellation or truncation closes the socket and forces server-side rollback.
|
|
389
445
|
- **Write-capable credentials:** Read-only behavior does not depend on account grants. Unrecognized stored functions/UDFs, side-effecting functions, sequence advancement and locking reads are rejected because they can hide effects inside `SELECT`.
|
|
390
446
|
- **Database allowlist:** `allowed_databases` is enforced with a MySQL AST parser for tools and resource URIs; system schemas are blocked by default.
|
|
447
|
+
- **Controlled metadata:** User SQL cannot query `information_schema` by
|
|
448
|
+
default. Dedicated `list_tables` and `get_schema_info` operations use narrowly
|
|
449
|
+
scoped internal metadata queries, so catalog access does not become a general
|
|
450
|
+
system-schema bypass.
|
|
391
451
|
- **Resource limits:** Calls have full-operation, socket and server statement timeouts; at most 1000 rows are returned and oversized cells are truncated.
|
|
392
452
|
- **Cancellation:** Cancelling the MCP request closes the active connector socket. The worker does not continue silently after the response is abandoned.
|
|
393
453
|
- **Enterprise audit:** Versioned UTC JSONL events include an event ID, MCP request ID, operation, caller-supplied attribution, policy decision, target database, literal-free query fingerprint, duration, result size and outcome. SQL text and result data are never logged. Optional rotation, fsync, HMAC signatures, required context and fail-closed behavior are supported.
|
|
@@ -425,11 +485,11 @@ Maintainers should follow [RELEASING.md](RELEASING.md) for synchronized Python/n
|
|
|
425
485
|
|
|
426
486
|
## Security Best Practices
|
|
427
487
|
This MCP implementation requires database access to function. For security:
|
|
428
|
-
1. **
|
|
488
|
+
1. **Prefer a dedicated MySQL user** with `SELECT` only as defense in depth; MCP enforcement remains read-only even when broader credentials are supplied
|
|
429
489
|
2. **Never use root credentials** or administrative accounts
|
|
430
|
-
3. **Restrict
|
|
431
|
-
4. **
|
|
432
|
-
5. **
|
|
490
|
+
3. **Restrict `allowed_databases`** to the schemas each profile needs
|
|
491
|
+
4. **Require audit attribution** and protect the optional HMAC key in a secret manager
|
|
492
|
+
5. **Review masking patterns, audit events, dependency updates, and account grants regularly**
|
|
433
493
|
|
|
434
494
|
See [MySQL Security Configuration Guide](https://github.com/12zhangyan/mysql_mcp_server/blob/main/SECURITY.md) for detailed instructions on:
|
|
435
495
|
- Creating a restricted MySQL user
|
|
Binary file
|
package/package.json
CHANGED
|
Binary file
|