@yanzhang123/readonly-db-mcp 0.7.3 → 0.7.4
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,75 @@ 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@0.7.3
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
On first use, the launcher creates a versioned virtual environment in the user
|
|
56
|
+
cache and installs the bundled wheel plus exact Python dependencies from a
|
|
57
|
+
version-controlled SHA-256 lock file. Downloads use the configured pip index
|
|
58
|
+
and the completed environment is cached by wheel-and-lock fingerprint. Override
|
|
59
|
+
Python with `MYSQL_MCP_PYTHON` or the cache location with
|
|
60
|
+
`MYSQL_MCP_NPM_CACHE_DIR`.
|
|
41
61
|
|
|
42
62
|
For MCP clients, use `npx` as the command and
|
|
43
63
|
`["-y", "@yanzhang123/readonly-db-mcp"]` as its arguments.
|
|
44
64
|
|
|
45
|
-
###
|
|
46
|
-
```bash
|
|
47
|
-
pip install mysql-mcp-server
|
|
48
|
-
```
|
|
65
|
+
### Minimal MCP client configuration
|
|
49
66
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
67
|
+
Create `mysql-connections.toml` from
|
|
68
|
+
[`mysql-connections.example.toml`](mysql-connections.example.toml), keep
|
|
69
|
+
passwords in environment variables, and use an absolute path:
|
|
70
|
+
|
|
71
|
+
```json
|
|
72
|
+
{
|
|
73
|
+
"mcpServers": {
|
|
74
|
+
"mysql-readonly": {
|
|
75
|
+
"command": "npx",
|
|
76
|
+
"args": ["-y", "@yanzhang123/readonly-db-mcp@0.7.3"],
|
|
77
|
+
"env": {
|
|
78
|
+
"MYSQL_PROFILES_FILE": "C:/absolute/path/mysql-connections.toml",
|
|
79
|
+
"MYSQL_DEV_PASSWORD": "set-in-the-client-secret-store"
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
54
84
|
```
|
|
55
85
|
|
|
56
|
-
|
|
86
|
+
On Windows clients that do not resolve npm command shims correctly, set
|
|
87
|
+
`"command": "npx.cmd"`. Do not commit the populated profile, passwords, audit
|
|
88
|
+
HMAC keys, connection strings, or client configuration containing secrets.
|
|
89
|
+
|
|
90
|
+
After startup, call `validate_connections`, then `check_connection`, before
|
|
91
|
+
running discovery queries. `check_connection` reports an irreversible account
|
|
92
|
+
fingerprint and privilege classification without returning the username or raw
|
|
93
|
+
grant statements.
|
|
94
|
+
|
|
95
|
+
### Manual Python installation
|
|
96
|
+
|
|
57
97
|
```bash
|
|
58
|
-
|
|
98
|
+
pip install mysql-mcp-server
|
|
59
99
|
```
|
|
60
100
|
|
|
101
|
+
The Python package remains available for source-oriented deployments, but the
|
|
102
|
+
scoped npm package is the documented distribution path for this fork.
|
|
103
|
+
|
|
61
104
|
## Configuration
|
|
62
105
|
|
|
63
106
|
### Recommended: named connections
|
|
@@ -239,6 +282,9 @@ All tools are declared with `readOnlyHint=true` and `destructiveHint=false`.
|
|
|
239
282
|
|
|
240
283
|
### `list_connections`
|
|
241
284
|
Lists named profiles, default database, policy limits and readiness. It never returns hosts, usernames, passwords, or SSH key paths.
|
|
285
|
+
It also returns a `database_routes` index so clients can select the correct
|
|
286
|
+
profile when one environment is split across several database-specific
|
|
287
|
+
connections.
|
|
242
288
|
|
|
243
289
|
### `validate_connections`
|
|
244
290
|
Forces a configuration reload and reports valid/invalid profiles plus missing
|
|
@@ -271,6 +317,16 @@ Executes exactly one read-only statement.
|
|
|
271
317
|
- **Pagination:** JSON output includes `truncated` and `next_offset`; pass that value back as `offset`.
|
|
272
318
|
- **Formats:** `json` preserves structured rows and metadata; `csv` uses RFC-style quoting and explicit `NULL`.
|
|
273
319
|
- **Attribution:** `audit_context` supports `actor`, `purpose`, and `ticket_id`. A profile can require any of these fields before a connection is opened.
|
|
320
|
+
- **Transient connector recovery:** client-side Connector/Python failures with
|
|
321
|
+
`errno=-1` are retried once. Persistent failures report only a safe exception
|
|
322
|
+
type and lifecycle phase; connector messages are not exposed.
|
|
323
|
+
|
|
324
|
+
### `query`
|
|
325
|
+
Compatibility alias for `execute_sql` with the same schema and all the same
|
|
326
|
+
read-only, database allowlist, masking, timeout, pagination, and audit controls.
|
|
327
|
+
Stateful legacy tools such as `use_connection` and `use_database` are
|
|
328
|
+
intentionally not restored because process-global selection is unsafe with
|
|
329
|
+
concurrent MCP clients.
|
|
274
330
|
|
|
275
331
|
### `get_schema_info`
|
|
276
332
|
Provides detailed metadata about database structures.
|
|
@@ -285,6 +341,9 @@ Fetches a representative sample of data.
|
|
|
285
341
|
- **Use Case:** Quickly understand data formats and content without fetching large result sets.
|
|
286
342
|
- **Cross-database:** Pass `database.table` to sample a table outside `MYSQL_DATABASE`; bare names use the configured database.
|
|
287
343
|
- **Identifier rules:** Names must contain only alphanumeric characters, underscores, and `$` (dots are allowed as a separator between database and table names).
|
|
344
|
+
- **Bounded execution:** Sampling applies `LIMIT limit+1 OFFSET offset` in
|
|
345
|
+
MySQL and fully consumes that small result. It does not open an unbounded
|
|
346
|
+
table scan merely to return a few rows.
|
|
288
347
|
|
|
289
348
|
## Available Prompts
|
|
290
349
|
|
|
@@ -309,14 +368,9 @@ Add this to your `claude_desktop_config.json`:
|
|
|
309
368
|
```json
|
|
310
369
|
{
|
|
311
370
|
"mcpServers": {
|
|
312
|
-
"mysql": {
|
|
313
|
-
"command": "
|
|
314
|
-
"args": [
|
|
315
|
-
"--directory",
|
|
316
|
-
"path/to/mysql_mcp_server",
|
|
317
|
-
"run",
|
|
318
|
-
"mysql_mcp_server"
|
|
319
|
-
],
|
|
371
|
+
"mysql-readonly": {
|
|
372
|
+
"command": "npx",
|
|
373
|
+
"args": ["-y", "@yanzhang123/readonly-db-mcp@0.7.3"],
|
|
320
374
|
"env": {
|
|
321
375
|
"MYSQL_PROFILES_FILE": "C:/absolute/path/mysql-connections.toml",
|
|
322
376
|
"MYSQL_DEV_PASSWORD": "your_dev_password",
|
|
@@ -334,14 +388,10 @@ Add this to your `mcp.json`:
|
|
|
334
388
|
```json
|
|
335
389
|
{
|
|
336
390
|
"mcpServers": {
|
|
337
|
-
"mysql": {
|
|
391
|
+
"mysql-readonly": {
|
|
338
392
|
"type": "stdio",
|
|
339
|
-
"command": "
|
|
340
|
-
"args": [
|
|
341
|
-
"--from",
|
|
342
|
-
"mysql-mcp-server",
|
|
343
|
-
"mysql_mcp_server"
|
|
344
|
-
],
|
|
393
|
+
"command": "npx",
|
|
394
|
+
"args": ["-y", "@yanzhang123/readonly-db-mcp@0.7.3"],
|
|
345
395
|
"env": {
|
|
346
396
|
"MYSQL_PROFILES_FILE": "C:/absolute/path/mysql-connections.toml",
|
|
347
397
|
"MYSQL_DEV_PASSWORD": "your_dev_password",
|
|
@@ -351,7 +401,8 @@ Add this to your `mcp.json`:
|
|
|
351
401
|
}
|
|
352
402
|
}
|
|
353
403
|
```
|
|
354
|
-
|
|
404
|
+
|
|
405
|
+
Use `npx.cmd` instead of `npx` if required by your Windows MCP host.
|
|
355
406
|
|
|
356
407
|
### Debugging with MCP Inspector
|
|
357
408
|
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 +424,13 @@ git clone https://github.com/12zhangyan/mysql_mcp_server.git
|
|
|
373
424
|
cd mysql_mcp_server
|
|
374
425
|
# Create virtual environment
|
|
375
426
|
python -m venv venv
|
|
376
|
-
source venv/bin/activate
|
|
427
|
+
# Linux/macOS: source venv/bin/activate
|
|
428
|
+
# Windows PowerShell: .\venv\Scripts\Activate.ps1
|
|
377
429
|
# Install development dependencies
|
|
378
430
|
pip install -r requirements-dev.txt
|
|
379
431
|
# Copy the example config and edit with your credentials
|
|
380
|
-
cp .env.example .env
|
|
432
|
+
# Linux/macOS: cp .env.example .env
|
|
433
|
+
# Windows PowerShell: Copy-Item .env.example .env
|
|
381
434
|
# Edit .env with your MySQL connection details
|
|
382
435
|
# Run tests
|
|
383
436
|
pytest
|
|
@@ -388,6 +441,10 @@ pytest
|
|
|
388
441
|
- **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
442
|
- **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
443
|
- **Database allowlist:** `allowed_databases` is enforced with a MySQL AST parser for tools and resource URIs; system schemas are blocked by default.
|
|
444
|
+
- **Controlled metadata:** User SQL cannot query `information_schema` by
|
|
445
|
+
default. Dedicated `list_tables` and `get_schema_info` operations use narrowly
|
|
446
|
+
scoped internal metadata queries, so catalog access does not become a general
|
|
447
|
+
system-schema bypass.
|
|
391
448
|
- **Resource limits:** Calls have full-operation, socket and server statement timeouts; at most 1000 rows are returned and oversized cells are truncated.
|
|
392
449
|
- **Cancellation:** Cancelling the MCP request closes the active connector socket. The worker does not continue silently after the response is abandoned.
|
|
393
450
|
- **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 +482,11 @@ Maintainers should follow [RELEASING.md](RELEASING.md) for synchronized Python/n
|
|
|
425
482
|
|
|
426
483
|
## Security Best Practices
|
|
427
484
|
This MCP implementation requires database access to function. For security:
|
|
428
|
-
1. **
|
|
485
|
+
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
486
|
2. **Never use root credentials** or administrative accounts
|
|
430
|
-
3. **Restrict
|
|
431
|
-
4. **
|
|
432
|
-
5. **
|
|
487
|
+
3. **Restrict `allowed_databases`** to the schemas each profile needs
|
|
488
|
+
4. **Require audit attribution** and protect the optional HMAC key in a secret manager
|
|
489
|
+
5. **Review masking patterns, audit events, dependency updates, and account grants regularly**
|
|
433
490
|
|
|
434
491
|
See [MySQL Security Configuration Guide](https://github.com/12zhangyan/mysql_mcp_server/blob/main/SECURITY.md) for detailed instructions on:
|
|
435
492
|
- Creating a restricted MySQL user
|
|
Binary file
|
package/package.json
CHANGED
|
Binary file
|