mcp-dbutils 0.9.0__py3-none-any.whl → 0.10.0__py3-none-any.whl
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.
- mcp_dbutils/postgres/config.py +80 -19
- mcp_dbutils-0.10.0.dist-info/METADATA +227 -0
- {mcp_dbutils-0.9.0.dist-info → mcp_dbutils-0.10.0.dist-info}/RECORD +6 -6
- mcp_dbutils-0.9.0.dist-info/METADATA +0 -392
- {mcp_dbutils-0.9.0.dist-info → mcp_dbutils-0.10.0.dist-info}/WHEEL +0 -0
- {mcp_dbutils-0.9.0.dist-info → mcp_dbutils-0.10.0.dist-info}/entry_points.txt +0 -0
- {mcp_dbutils-0.9.0.dist-info → mcp_dbutils-0.10.0.dist-info}/licenses/LICENSE +0 -0
mcp_dbutils/postgres/config.py
CHANGED
@@ -1,28 +1,35 @@
|
|
1
1
|
"""PostgreSQL configuration module"""
|
2
2
|
from dataclasses import dataclass
|
3
3
|
from typing import Optional, Dict, Any, Literal
|
4
|
-
from urllib.parse import urlparse
|
4
|
+
from urllib.parse import urlparse, parse_qs
|
5
5
|
from ..config import ConnectionConfig
|
6
6
|
|
7
|
-
|
8
|
-
|
7
|
+
@dataclass
|
8
|
+
class SSLConfig:
|
9
|
+
"""SSL configuration for PostgreSQL connection"""
|
10
|
+
mode: Literal['disable', 'require', 'verify-ca', 'verify-full'] = 'disable'
|
11
|
+
cert: Optional[str] = None
|
12
|
+
key: Optional[str] = None
|
13
|
+
root: Optional[str] = None
|
14
|
+
|
15
|
+
def parse_url(url: str) -> Dict[str, Any]:
|
16
|
+
"""Parse PostgreSQL URL into connection parameters
|
9
17
|
|
10
18
|
Args:
|
11
|
-
|
19
|
+
url: URL (e.g. postgresql://host:port/dbname?sslmode=verify-full)
|
12
20
|
|
13
21
|
Returns:
|
14
|
-
Dictionary of connection parameters
|
22
|
+
Dictionary of connection parameters including SSL settings
|
15
23
|
"""
|
16
|
-
if not
|
17
|
-
raise ValueError("Invalid PostgreSQL
|
24
|
+
if not url.startswith('postgresql://'):
|
25
|
+
raise ValueError("Invalid PostgreSQL URL format")
|
18
26
|
|
19
|
-
# Remove jdbc: prefix and ensure no credentials in URL
|
20
|
-
url = jdbc_url[5:]
|
21
27
|
if '@' in url:
|
22
|
-
raise ValueError("
|
28
|
+
raise ValueError("URL should not contain credentials. Please provide username and password separately.")
|
23
29
|
|
24
|
-
# Parse URL
|
30
|
+
# Parse URL and query parameters
|
25
31
|
parsed = urlparse(url)
|
32
|
+
query_params = parse_qs(parsed.query)
|
26
33
|
|
27
34
|
params = {
|
28
35
|
'host': parsed.hostname or 'localhost',
|
@@ -32,6 +39,24 @@ def parse_jdbc_url(jdbc_url: str) -> Dict[str, str]:
|
|
32
39
|
|
33
40
|
if not params['dbname']:
|
34
41
|
raise ValueError("PostgreSQL database name must be specified in URL")
|
42
|
+
|
43
|
+
# Parse SSL parameters if present
|
44
|
+
ssl_params = {}
|
45
|
+
if 'sslmode' in query_params:
|
46
|
+
mode = query_params['sslmode'][0]
|
47
|
+
if mode not in ['disable', 'require', 'verify-ca', 'verify-full']:
|
48
|
+
raise ValueError(f"Invalid sslmode: {mode}")
|
49
|
+
ssl_params['mode'] = mode
|
50
|
+
|
51
|
+
if 'sslcert' in query_params:
|
52
|
+
ssl_params['cert'] = query_params['sslcert'][0]
|
53
|
+
if 'sslkey' in query_params:
|
54
|
+
ssl_params['key'] = query_params['sslkey'][0]
|
55
|
+
if 'sslrootcert' in query_params:
|
56
|
+
ssl_params['root'] = query_params['sslrootcert'][0]
|
57
|
+
|
58
|
+
if ssl_params:
|
59
|
+
params['ssl'] = SSLConfig(**ssl_params)
|
35
60
|
|
36
61
|
return params
|
37
62
|
|
@@ -44,6 +69,8 @@ class PostgreSQLConfig(ConnectionConfig):
|
|
44
69
|
port: str = '5432'
|
45
70
|
local_host: Optional[str] = None
|
46
71
|
type: Literal['postgres'] = 'postgres'
|
72
|
+
url: Optional[str] = None
|
73
|
+
ssl: Optional[SSLConfig] = None
|
47
74
|
|
48
75
|
@classmethod
|
49
76
|
def from_yaml(cls, yaml_path: str, db_name: str, local_host: Optional[str] = None) -> 'PostgreSQLConfig':
|
@@ -74,9 +101,9 @@ class PostgreSQLConfig(ConnectionConfig):
|
|
74
101
|
raise ValueError("Password must be specified in connection configuration")
|
75
102
|
|
76
103
|
# Get connection parameters
|
77
|
-
if '
|
78
|
-
# Parse
|
79
|
-
params =
|
104
|
+
if 'url' in db_config:
|
105
|
+
# Parse URL for connection parameters
|
106
|
+
params = parse_url(db_config['url'])
|
80
107
|
config = cls(
|
81
108
|
dbname=params['dbname'],
|
82
109
|
user=db_config['user'],
|
@@ -84,6 +111,8 @@ class PostgreSQLConfig(ConnectionConfig):
|
|
84
111
|
host=params['host'],
|
85
112
|
port=params['port'],
|
86
113
|
local_host=local_host,
|
114
|
+
url=db_config['url'],
|
115
|
+
ssl=params.get('ssl')
|
87
116
|
)
|
88
117
|
else:
|
89
118
|
if not db_config.get('dbname'):
|
@@ -92,6 +121,24 @@ class PostgreSQLConfig(ConnectionConfig):
|
|
92
121
|
raise ValueError("Host must be specified in connection configuration")
|
93
122
|
if not db_config.get('port'):
|
94
123
|
raise ValueError("Port must be specified in connection configuration")
|
124
|
+
|
125
|
+
# Parse SSL configuration if present
|
126
|
+
ssl_config = None
|
127
|
+
if 'ssl' in db_config:
|
128
|
+
ssl_params = db_config['ssl']
|
129
|
+
if not isinstance(ssl_params, dict):
|
130
|
+
raise ValueError("SSL configuration must be a dictionary")
|
131
|
+
|
132
|
+
if ssl_params.get('mode') not in [None, 'disable', 'require', 'verify-ca', 'verify-full']:
|
133
|
+
raise ValueError(f"Invalid sslmode: {ssl_params.get('mode')}")
|
134
|
+
|
135
|
+
ssl_config = SSLConfig(
|
136
|
+
mode=ssl_params.get('mode', 'disable'),
|
137
|
+
cert=ssl_params.get('cert'),
|
138
|
+
key=ssl_params.get('key'),
|
139
|
+
root=ssl_params.get('root')
|
140
|
+
)
|
141
|
+
|
95
142
|
config = cls(
|
96
143
|
dbname=db_config['dbname'],
|
97
144
|
user=db_config['user'],
|
@@ -99,17 +146,18 @@ class PostgreSQLConfig(ConnectionConfig):
|
|
99
146
|
host=db_config['host'],
|
100
147
|
port=str(db_config['port']),
|
101
148
|
local_host=local_host,
|
149
|
+
ssl=ssl_config
|
102
150
|
)
|
103
151
|
config.debug = cls.get_debug_mode()
|
104
152
|
return config
|
105
153
|
|
106
154
|
@classmethod
|
107
|
-
def
|
108
|
-
|
109
|
-
"""Create configuration from
|
155
|
+
def from_url(cls, url: str, user: str, password: str,
|
156
|
+
local_host: Optional[str] = None) -> 'PostgreSQLConfig':
|
157
|
+
"""Create configuration from URL and credentials
|
110
158
|
|
111
159
|
Args:
|
112
|
-
|
160
|
+
url: URL (postgresql://host:port/dbname)
|
113
161
|
user: Username for connection
|
114
162
|
password: Password for connection
|
115
163
|
local_host: Optional local host address
|
@@ -117,7 +165,7 @@ class PostgreSQLConfig(ConnectionConfig):
|
|
117
165
|
Raises:
|
118
166
|
ValueError: If URL format is invalid or required parameters are missing
|
119
167
|
"""
|
120
|
-
params =
|
168
|
+
params = parse_url(url)
|
121
169
|
|
122
170
|
config = cls(
|
123
171
|
dbname=params['dbname'],
|
@@ -126,6 +174,8 @@ class PostgreSQLConfig(ConnectionConfig):
|
|
126
174
|
host=params['host'],
|
127
175
|
port=params['port'],
|
128
176
|
local_host=local_host,
|
177
|
+
url=url,
|
178
|
+
ssl=params.get('ssl')
|
129
179
|
)
|
130
180
|
config.debug = cls.get_debug_mode()
|
131
181
|
return config
|
@@ -139,6 +189,17 @@ class PostgreSQLConfig(ConnectionConfig):
|
|
139
189
|
'host': self.local_host or self.host,
|
140
190
|
'port': self.port
|
141
191
|
}
|
192
|
+
|
193
|
+
# Add SSL parameters if configured
|
194
|
+
if self.ssl:
|
195
|
+
params['sslmode'] = self.ssl.mode
|
196
|
+
if self.ssl.cert:
|
197
|
+
params['sslcert'] = self.ssl.cert
|
198
|
+
if self.ssl.key:
|
199
|
+
params['sslkey'] = self.ssl.key
|
200
|
+
if self.ssl.root:
|
201
|
+
params['sslrootcert'] = self.ssl.root
|
202
|
+
|
142
203
|
return {k: v for k, v in params.items() if v}
|
143
204
|
|
144
205
|
def get_masked_connection_info(self) -> Dict[str, Any]:
|
@@ -0,0 +1,227 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: mcp-dbutils
|
3
|
+
Version: 0.10.0
|
4
|
+
Summary: MCP Database Utilities Service
|
5
|
+
Author: Dong Hao
|
6
|
+
License-Expression: MIT
|
7
|
+
License-File: LICENSE
|
8
|
+
Requires-Python: >=3.10
|
9
|
+
Requires-Dist: mcp>=1.2.1
|
10
|
+
Requires-Dist: psycopg2-binary>=2.9.10
|
11
|
+
Requires-Dist: python-dotenv>=1.0.1
|
12
|
+
Requires-Dist: pyyaml>=6.0.2
|
13
|
+
Provides-Extra: test
|
14
|
+
Requires-Dist: aiosqlite>=0.19.0; extra == 'test'
|
15
|
+
Requires-Dist: docker>=7.0.0; extra == 'test'
|
16
|
+
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'test'
|
17
|
+
Requires-Dist: pytest-cov>=4.1.0; extra == 'test'
|
18
|
+
Requires-Dist: pytest-docker>=2.0.0; extra == 'test'
|
19
|
+
Requires-Dist: pytest>=7.0.0; extra == 'test'
|
20
|
+
Requires-Dist: testcontainers>=3.7.0; extra == 'test'
|
21
|
+
Description-Content-Type: text/markdown
|
22
|
+
|
23
|
+
# MCP Database Utilities
|
24
|
+
|
25
|
+

|
26
|
+

|
27
|
+
[](https://github.com/donghao1393/mcp-dbutils/actions)
|
28
|
+

|
29
|
+

|
30
|
+
[](https://smithery.ai/server/@donghao1393/mcp-dbutils)
|
31
|
+
|
32
|
+
[中文文档](README_CN.md)
|
33
|
+
|
34
|
+
## Overview
|
35
|
+
MCP Database Utilities is a unified database access service that supports multiple database types (PostgreSQL and SQLite). Through its abstraction layer design, it provides a simple and unified database operation interface for MCP servers.
|
36
|
+
|
37
|
+
## Features
|
38
|
+
- Unified database access interface
|
39
|
+
- Support for multiple database configurations
|
40
|
+
- Secure read-only query execution
|
41
|
+
- Table structure and schema information retrieval
|
42
|
+
- Database tables listing via MCP tools
|
43
|
+
- Intelligent connection management and resource cleanup
|
44
|
+
- Debug mode support
|
45
|
+
- SSL/TLS connection support for PostgreSQL
|
46
|
+
|
47
|
+
## Installation and Configuration
|
48
|
+
|
49
|
+
### Installation Methods
|
50
|
+
#### Installing via Smithery
|
51
|
+
|
52
|
+
To install Database Utilities for Claude Desktop automatically via [Smithery](https://smithery.ai/server/@donghao1393/mcp-dbutils):
|
53
|
+
|
54
|
+
```bash
|
55
|
+
npx -y @smithery/cli install @donghao1393/mcp-dbutils --client claude
|
56
|
+
```
|
57
|
+
|
58
|
+
#### Using uvx (Recommended)
|
59
|
+
No installation required, run directly using `uvx`:
|
60
|
+
```bash
|
61
|
+
uvx mcp-dbutils --config /path/to/config.yaml
|
62
|
+
```
|
63
|
+
|
64
|
+
Add to Claude configuration:
|
65
|
+
```json
|
66
|
+
"mcpServers": {
|
67
|
+
"mcp-dbutils": {
|
68
|
+
"command": "uvx",
|
69
|
+
"args": [
|
70
|
+
"mcp-dbutils",
|
71
|
+
"--config",
|
72
|
+
"/path/to/config.yaml"
|
73
|
+
],
|
74
|
+
"env": {
|
75
|
+
"MCP_DEBUG": "1" // Optional: Enable debug mode
|
76
|
+
}
|
77
|
+
}
|
78
|
+
}
|
79
|
+
```
|
80
|
+
|
81
|
+
#### Using pip
|
82
|
+
```bash
|
83
|
+
pip install mcp-dbutils
|
84
|
+
```
|
85
|
+
|
86
|
+
Add to Claude configuration:
|
87
|
+
```json
|
88
|
+
"mcpServers": {
|
89
|
+
"mcp-dbutils": {
|
90
|
+
"command": "python",
|
91
|
+
"args": [
|
92
|
+
"-m",
|
93
|
+
"mcp_dbutils",
|
94
|
+
"--config",
|
95
|
+
"/path/to/config.yaml"
|
96
|
+
],
|
97
|
+
"env": {
|
98
|
+
"MCP_DEBUG": "1" // Optional: Enable debug mode
|
99
|
+
}
|
100
|
+
}
|
101
|
+
}
|
102
|
+
```
|
103
|
+
|
104
|
+
#### Using Docker
|
105
|
+
```bash
|
106
|
+
docker run -i --rm \
|
107
|
+
-v /path/to/config.yaml:/app/config.yaml \
|
108
|
+
-v /path/to/sqlite.db:/app/sqlite.db \ # Optional: for SQLite database
|
109
|
+
-e MCP_DEBUG=1 \ # Optional: Enable debug mode
|
110
|
+
mcp/dbutils --config /app/config.yaml
|
111
|
+
```
|
112
|
+
|
113
|
+
Add to Claude configuration:
|
114
|
+
```json
|
115
|
+
"mcpServers": {
|
116
|
+
"mcp-dbutils": {
|
117
|
+
"command": "docker",
|
118
|
+
"args": [
|
119
|
+
"run",
|
120
|
+
"-i",
|
121
|
+
"--rm",
|
122
|
+
"-v",
|
123
|
+
"/path/to/config.yaml:/app/config.yaml",
|
124
|
+
"-v",
|
125
|
+
"/path/to/sqlite.db:/app/sqlite.db", // Optional: for SQLite database
|
126
|
+
"mcp/dbutils",
|
127
|
+
"--config",
|
128
|
+
"/app/config.yaml"
|
129
|
+
],
|
130
|
+
"env": {
|
131
|
+
"MCP_DEBUG": "1" // Optional: Enable debug mode
|
132
|
+
}
|
133
|
+
}
|
134
|
+
}
|
135
|
+
```
|
136
|
+
|
137
|
+
> **Note for Docker database connections:**
|
138
|
+
> - For SQLite: Mount your database file using `-v /path/to/sqlite.db:/app/sqlite.db`
|
139
|
+
> - For PostgreSQL running on host:
|
140
|
+
> - On Mac/Windows: Use `host.docker.internal` as host in config
|
141
|
+
> - On Linux: Use `172.17.0.1` (docker0 IP) or run with `--network="host"`
|
142
|
+
|
143
|
+
### Requirements
|
144
|
+
- Python 3.10+
|
145
|
+
- PostgreSQL (optional)
|
146
|
+
- SQLite3 (optional)
|
147
|
+
|
148
|
+
### Configuration File
|
149
|
+
The project requires a YAML configuration file, specified via the `--config` parameter. Configuration examples:
|
150
|
+
|
151
|
+
```yaml
|
152
|
+
connections:
|
153
|
+
# SQLite configuration examples
|
154
|
+
dev-db:
|
155
|
+
type: sqlite
|
156
|
+
path: /path/to/dev.db
|
157
|
+
# Password is optional
|
158
|
+
password:
|
159
|
+
|
160
|
+
# PostgreSQL standard configuration
|
161
|
+
test-db:
|
162
|
+
type: postgres
|
163
|
+
host: postgres.example.com
|
164
|
+
port: 5432
|
165
|
+
dbname: test_db
|
166
|
+
user: test_user
|
167
|
+
password: test_pass
|
168
|
+
|
169
|
+
# PostgreSQL URL configuration with SSL
|
170
|
+
prod-db:
|
171
|
+
type: postgres
|
172
|
+
url: postgresql://postgres.example.com:5432/prod-db?sslmode=verify-full
|
173
|
+
user: prod_user
|
174
|
+
password: prod_pass
|
175
|
+
|
176
|
+
# PostgreSQL full SSL configuration example
|
177
|
+
secure-db:
|
178
|
+
type: postgres
|
179
|
+
host: secure-db.example.com
|
180
|
+
port: 5432
|
181
|
+
dbname: secure_db
|
182
|
+
user: secure_user
|
183
|
+
password: secure_pass
|
184
|
+
ssl:
|
185
|
+
mode: verify-full # disable/require/verify-ca/verify-full
|
186
|
+
cert: /path/to/client-cert.pem
|
187
|
+
key: /path/to/client-key.pem
|
188
|
+
root: /path/to/root.crt
|
189
|
+
```
|
190
|
+
|
191
|
+
PostgreSQL SSL Configuration Options:
|
192
|
+
1. Using URL parameters:
|
193
|
+
```
|
194
|
+
postgresql://host:port/dbname?sslmode=verify-full&sslcert=/path/to/cert.pem
|
195
|
+
```
|
196
|
+
2. Using dedicated SSL configuration section:
|
197
|
+
```yaml
|
198
|
+
ssl:
|
199
|
+
mode: verify-full # SSL verification mode
|
200
|
+
cert: /path/to/cert.pem # Client certificate
|
201
|
+
key: /path/to/key.pem # Client private key
|
202
|
+
root: /path/to/root.crt # CA certificate
|
203
|
+
```
|
204
|
+
|
205
|
+
SSL Modes:
|
206
|
+
- disable: No SSL
|
207
|
+
- require: Use SSL but no certificate verification
|
208
|
+
- verify-ca: Verify server certificate is signed by trusted CA
|
209
|
+
- verify-full: Verify server certificate and hostname match
|
210
|
+
|
211
|
+
SQLite Configuration Options:
|
212
|
+
1. Basic configuration with path:
|
213
|
+
```yaml
|
214
|
+
type: sqlite
|
215
|
+
path: /path/to/db.sqlite
|
216
|
+
password: optional_password # Optional encryption
|
217
|
+
```
|
218
|
+
2. Using URI parameters:
|
219
|
+
```yaml
|
220
|
+
type: sqlite
|
221
|
+
path: /path/to/db.sqlite?mode=ro&cache=shared
|
222
|
+
```
|
223
|
+
|
224
|
+
### Debug Mode
|
225
|
+
Set environment variable `MCP_DEBUG=1` to enable debug mode for detailed logging output.
|
226
|
+
|
227
|
+
[Rest of the README content remains unchanged...]
|
@@ -4,15 +4,15 @@ mcp_dbutils/config.py,sha256=uFI4Haw4en5gxHfCM9zugUqNCQFikdlHJZU_NTht7gQ,1905
|
|
4
4
|
mcp_dbutils/log.py,sha256=fibVIwsb1HVU5zriGrDZTMEirKjgIuxuN_B_YTdAJ7I,996
|
5
5
|
mcp_dbutils/stats.py,sha256=WYD9NAKHH2bFKmUSTOg18-SuIXergpznPq8AtIjtxdI,7101
|
6
6
|
mcp_dbutils/postgres/__init__.py,sha256=XanCXw-kVE6ayqFqjuLJ9swWPcCVlcKZXB2Et2Wjl9w,154
|
7
|
-
mcp_dbutils/postgres/config.py,sha256=
|
7
|
+
mcp_dbutils/postgres/config.py,sha256=FG0YUV4TtP1IGZT87ov_PK-ouOEjAOHdSaK42klk5OE,7750
|
8
8
|
mcp_dbutils/postgres/handler.py,sha256=O45K0MOosNQ68SJ8piXXH3aZ74RVQ981hudk6faj28Y,24397
|
9
9
|
mcp_dbutils/postgres/server.py,sha256=FROogvjr3xlKAZcAvJMNHGgyHqT_LaMK9-vYbA0Dbm0,8716
|
10
10
|
mcp_dbutils/sqlite/__init__.py,sha256=lTUOkSfSWNw_BohJ_KNxYKMCANdtpGa3JK_ZyJsg_Ls,134
|
11
11
|
mcp_dbutils/sqlite/config.py,sha256=2ekTp89rcCu4qQN1O3sZjIcOwjhzWi4tisD20T2WAik,4533
|
12
12
|
mcp_dbutils/sqlite/handler.py,sha256=VxBVbwpNSQHyiudQXYFYpcdoScvbK2IGzYMbkcpvFcI,17731
|
13
13
|
mcp_dbutils/sqlite/server.py,sha256=49ug43nyXZApclMXo0t5dKCN4wjDyDUZ-vmf746ac8M,7709
|
14
|
-
mcp_dbutils-0.
|
15
|
-
mcp_dbutils-0.
|
16
|
-
mcp_dbutils-0.
|
17
|
-
mcp_dbutils-0.
|
18
|
-
mcp_dbutils-0.
|
14
|
+
mcp_dbutils-0.10.0.dist-info/METADATA,sha256=TC_KrWktHUIG6vznvxhIsz-pJG_WWxgH8s1HQJO7NgQ,6262
|
15
|
+
mcp_dbutils-0.10.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
16
|
+
mcp_dbutils-0.10.0.dist-info/entry_points.txt,sha256=XTjt0QmYRgKOJQT6skR9bp1EMUfIrgpHeZJPZ3CJffs,49
|
17
|
+
mcp_dbutils-0.10.0.dist-info/licenses/LICENSE,sha256=1A_CwpWVlbjrKdVEYO77vYfnXlW7oxcilZ8FpA_BzCI,1065
|
18
|
+
mcp_dbutils-0.10.0.dist-info/RECORD,,
|
@@ -1,392 +0,0 @@
|
|
1
|
-
Metadata-Version: 2.4
|
2
|
-
Name: mcp-dbutils
|
3
|
-
Version: 0.9.0
|
4
|
-
Summary: MCP Database Utilities Service
|
5
|
-
Author: Dong Hao
|
6
|
-
License-Expression: MIT
|
7
|
-
License-File: LICENSE
|
8
|
-
Requires-Python: >=3.10
|
9
|
-
Requires-Dist: mcp>=1.2.1
|
10
|
-
Requires-Dist: psycopg2-binary>=2.9.10
|
11
|
-
Requires-Dist: python-dotenv>=1.0.1
|
12
|
-
Requires-Dist: pyyaml>=6.0.2
|
13
|
-
Provides-Extra: test
|
14
|
-
Requires-Dist: aiosqlite>=0.19.0; extra == 'test'
|
15
|
-
Requires-Dist: docker>=7.0.0; extra == 'test'
|
16
|
-
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'test'
|
17
|
-
Requires-Dist: pytest-cov>=4.1.0; extra == 'test'
|
18
|
-
Requires-Dist: pytest-docker>=2.0.0; extra == 'test'
|
19
|
-
Requires-Dist: pytest>=7.0.0; extra == 'test'
|
20
|
-
Requires-Dist: testcontainers>=3.7.0; extra == 'test'
|
21
|
-
Description-Content-Type: text/markdown
|
22
|
-
|
23
|
-
# MCP Database Utilities
|
24
|
-
|
25
|
-

|
26
|
-

|
27
|
-
[](https://github.com/donghao1393/mcp-dbutils/actions)
|
28
|
-

|
29
|
-

|
30
|
-
[](https://smithery.ai/server/@donghao1393/mcp-dbutils)
|
31
|
-
|
32
|
-
[中文文档](README_CN.md)
|
33
|
-
|
34
|
-
## Overview
|
35
|
-
MCP Database Utilities is a unified database access service that supports multiple database types (PostgreSQL and SQLite). Through its abstraction layer design, it provides a simple and unified database operation interface for MCP servers.
|
36
|
-
|
37
|
-
## Features
|
38
|
-
- Unified database access interface
|
39
|
-
- Support for multiple database configurations
|
40
|
-
- Secure read-only query execution
|
41
|
-
- Table structure and schema information retrieval
|
42
|
-
- Database tables listing via MCP tools
|
43
|
-
- Intelligent connection management and resource cleanup
|
44
|
-
- Debug mode support
|
45
|
-
|
46
|
-
## Installation and Configuration
|
47
|
-
|
48
|
-
### Installation Methods
|
49
|
-
#### Installing via Smithery
|
50
|
-
|
51
|
-
To install Database Utilities for Claude Desktop automatically via [Smithery](https://smithery.ai/server/@donghao1393/mcp-dbutils):
|
52
|
-
|
53
|
-
```bash
|
54
|
-
npx -y @smithery/cli install @donghao1393/mcp-dbutils --client claude
|
55
|
-
```
|
56
|
-
|
57
|
-
#### Using uvx (Recommended)
|
58
|
-
No installation required, run directly using `uvx`:
|
59
|
-
```bash
|
60
|
-
uvx mcp-dbutils --config /path/to/config.yaml
|
61
|
-
```
|
62
|
-
|
63
|
-
Add to Claude configuration:
|
64
|
-
```json
|
65
|
-
"mcpServers": {
|
66
|
-
"mcp-dbutils": {
|
67
|
-
"command": "uvx",
|
68
|
-
"args": [
|
69
|
-
"mcp-dbutils",
|
70
|
-
"--config",
|
71
|
-
"/path/to/config.yaml"
|
72
|
-
],
|
73
|
-
"env": {
|
74
|
-
"MCP_DEBUG": "1" // Optional: Enable debug mode
|
75
|
-
}
|
76
|
-
}
|
77
|
-
}
|
78
|
-
```
|
79
|
-
|
80
|
-
#### Using pip
|
81
|
-
```bash
|
82
|
-
pip install mcp-dbutils
|
83
|
-
```
|
84
|
-
|
85
|
-
Add to Claude configuration:
|
86
|
-
```json
|
87
|
-
"mcpServers": {
|
88
|
-
"mcp-dbutils": {
|
89
|
-
"command": "python",
|
90
|
-
"args": [
|
91
|
-
"-m",
|
92
|
-
"mcp_dbutils",
|
93
|
-
"--config",
|
94
|
-
"/path/to/config.yaml"
|
95
|
-
],
|
96
|
-
"env": {
|
97
|
-
"MCP_DEBUG": "1" // Optional: Enable debug mode
|
98
|
-
}
|
99
|
-
}
|
100
|
-
}
|
101
|
-
```
|
102
|
-
|
103
|
-
#### Using Docker
|
104
|
-
```bash
|
105
|
-
docker run -i --rm \
|
106
|
-
-v /path/to/config.yaml:/app/config.yaml \
|
107
|
-
-v /path/to/sqlite.db:/app/sqlite.db \ # Optional: for SQLite database
|
108
|
-
-e MCP_DEBUG=1 \ # Optional: Enable debug mode
|
109
|
-
mcp/dbutils --config /app/config.yaml
|
110
|
-
```
|
111
|
-
|
112
|
-
Add to Claude configuration:
|
113
|
-
```json
|
114
|
-
"mcpServers": {
|
115
|
-
"mcp-dbutils": {
|
116
|
-
"command": "docker",
|
117
|
-
"args": [
|
118
|
-
"run",
|
119
|
-
"-i",
|
120
|
-
"--rm",
|
121
|
-
"-v",
|
122
|
-
"/path/to/config.yaml:/app/config.yaml",
|
123
|
-
"-v",
|
124
|
-
"/path/to/sqlite.db:/app/sqlite.db", // Optional: for SQLite database
|
125
|
-
"mcp/dbutils",
|
126
|
-
"--config",
|
127
|
-
"/app/config.yaml"
|
128
|
-
],
|
129
|
-
"env": {
|
130
|
-
"MCP_DEBUG": "1" // Optional: Enable debug mode
|
131
|
-
}
|
132
|
-
}
|
133
|
-
}
|
134
|
-
```
|
135
|
-
|
136
|
-
> **Note for Docker database connections:**
|
137
|
-
> - For SQLite: Mount your database file using `-v /path/to/sqlite.db:/app/sqlite.db`
|
138
|
-
> - For PostgreSQL running on host:
|
139
|
-
> - On Mac/Windows: Use `host.docker.internal` as host in config
|
140
|
-
> - On Linux: Use `172.17.0.1` (docker0 IP) or run with `--network="host"`
|
141
|
-
|
142
|
-
### Requirements
|
143
|
-
- Python 3.10+
|
144
|
-
- PostgreSQL (optional)
|
145
|
-
- SQLite3 (optional)
|
146
|
-
|
147
|
-
### Configuration File
|
148
|
-
The project requires a YAML configuration file, specified via the `--config` parameter. Configuration example:
|
149
|
-
|
150
|
-
```yaml
|
151
|
-
connections:
|
152
|
-
# Standard PostgreSQL configuration example
|
153
|
-
my_postgres:
|
154
|
-
type: postgres
|
155
|
-
dbname: test_db
|
156
|
-
user: postgres
|
157
|
-
password: secret
|
158
|
-
host: host.docker.internal # For Mac/Windows
|
159
|
-
# host: 172.17.0.1 # For Linux (docker0 IP)
|
160
|
-
port: 5432
|
161
|
-
|
162
|
-
# PostgreSQL with JDBC URL example
|
163
|
-
my_postgres_jdbc:
|
164
|
-
type: postgres
|
165
|
-
jdbc_url: jdbc:postgresql://host.docker.internal:5432/test_db
|
166
|
-
user: postgres # Credentials must be provided separately
|
167
|
-
password: secret # Not included in JDBC URL for security
|
168
|
-
|
169
|
-
# SQLite standard configuration
|
170
|
-
my_sqlite:
|
171
|
-
type: sqlite
|
172
|
-
path: /app/sqlite.db # Database file path
|
173
|
-
password: optional_password # optional
|
174
|
-
|
175
|
-
# SQLite with JDBC URL configuration
|
176
|
-
my_sqlite_jdbc:
|
177
|
-
type: sqlite
|
178
|
-
jdbc_url: jdbc:sqlite:/app/data.db?mode=ro&cache=shared # Supports query parameters
|
179
|
-
password: optional_password # Provided separately for security
|
180
|
-
```
|
181
|
-
|
182
|
-
The configuration supports JDBC URL format for both PostgreSQL and SQLite:
|
183
|
-
|
184
|
-
PostgreSQL:
|
185
|
-
1. Standard configuration with individual parameters
|
186
|
-
2. JDBC URL configuration with separate credentials
|
187
|
-
|
188
|
-
SQLite:
|
189
|
-
1. Standard configuration with path parameter
|
190
|
-
2. JDBC URL configuration with query parameters support:
|
191
|
-
- mode=ro: Read-only mode
|
192
|
-
- cache=shared: Shared cache mode
|
193
|
-
- Other SQLite URI parameters
|
194
|
-
|
195
|
-
### Debug Mode
|
196
|
-
Set environment variable `MCP_DEBUG=1` to enable debug mode for detailed logging output.
|
197
|
-
|
198
|
-
## Architecture Design
|
199
|
-
|
200
|
-
### Core Concept: Abstraction Layer
|
201
|
-
|
202
|
-
```mermaid
|
203
|
-
graph TD
|
204
|
-
Client[Client] --> DatabaseServer[Database Server]
|
205
|
-
subgraph MCP Server
|
206
|
-
DatabaseServer
|
207
|
-
DatabaseHandler[Database Handler]
|
208
|
-
PostgresHandler[PostgreSQL Handler]
|
209
|
-
SQLiteHandler[SQLite Handler]
|
210
|
-
DatabaseServer --> DatabaseHandler
|
211
|
-
DatabaseHandler --> PostgresHandler
|
212
|
-
DatabaseHandler --> SQLiteHandler
|
213
|
-
end
|
214
|
-
PostgresHandler --> PostgreSQL[(PostgreSQL)]
|
215
|
-
SQLiteHandler --> SQLite[(SQLite)]
|
216
|
-
```
|
217
|
-
|
218
|
-
The abstraction layer design is the core architectural concept in MCP Database Utilities. Just like a universal remote control that works with different devices, users only need to know the basic operations without understanding the underlying complexities.
|
219
|
-
|
220
|
-
#### 1. Simplified User Interaction
|
221
|
-
- Users only need to know the database configuration name (e.g., "my_postgres")
|
222
|
-
- No need to deal with connection parameters and implementation details
|
223
|
-
- MCP server automatically handles database connections and queries
|
224
|
-
|
225
|
-
#### 2. Unified Interface Design
|
226
|
-
- DatabaseHandler abstract class defines unified operation interfaces
|
227
|
-
- All specific database implementations (PostgreSQL/SQLite) follow the same interface
|
228
|
-
- Users interact with different databases in the same way
|
229
|
-
|
230
|
-
#### 3. Configuration and Implementation Separation
|
231
|
-
- Complex database configuration parameters are encapsulated in configuration files
|
232
|
-
- Runtime access through simple database names
|
233
|
-
- Easy management and modification of database configurations without affecting business code
|
234
|
-
|
235
|
-
### System Components
|
236
|
-
1. DatabaseServer
|
237
|
-
- Core component of the MCP server
|
238
|
-
- Handles resource and tool requests
|
239
|
-
- Manages database connection lifecycle
|
240
|
-
|
241
|
-
2. DatabaseHandler
|
242
|
-
- Abstract base class defining unified interface
|
243
|
-
- Includes get_tables(), get_schema(), execute_query(), etc.
|
244
|
-
- Implemented by PostgreSQL and SQLite handlers
|
245
|
-
|
246
|
-
3. Configuration System
|
247
|
-
- YAML-based configuration file
|
248
|
-
- Support for multiple database configurations
|
249
|
-
- Type-safe configuration validation
|
250
|
-
|
251
|
-
4. Error Handling and Logging
|
252
|
-
- Unified error handling mechanism
|
253
|
-
- Detailed logging output
|
254
|
-
- Sensitive information masking
|
255
|
-
|
256
|
-
## Usage Examples
|
257
|
-
|
258
|
-
### Basic Query
|
259
|
-
```python
|
260
|
-
# Access through connection name
|
261
|
-
async with server.get_handler("my_postgres") as handler:
|
262
|
-
# Execute SQL query
|
263
|
-
result = await handler.execute_query("SELECT * FROM users")
|
264
|
-
```
|
265
|
-
|
266
|
-
### View Table Structure
|
267
|
-
```python
|
268
|
-
# Get all tables
|
269
|
-
tables = await handler.get_tables()
|
270
|
-
|
271
|
-
# Get specific table schema
|
272
|
-
schema = await handler.get_schema("users")
|
273
|
-
```
|
274
|
-
|
275
|
-
### Error Handling
|
276
|
-
```python
|
277
|
-
try:
|
278
|
-
async with server.get_handler("my_connection") as handler:
|
279
|
-
result = await handler.execute_query("SELECT * FROM users")
|
280
|
-
except ValueError as e:
|
281
|
-
print(f"Configuration error: {e}")
|
282
|
-
except Exception as e:
|
283
|
-
print(f"Query error: {e}")
|
284
|
-
```
|
285
|
-
|
286
|
-
## Security Notes
|
287
|
-
- Supports SELECT queries only to protect database security
|
288
|
-
- Automatically masks sensitive information (like passwords) in logs
|
289
|
-
- Executes queries in read-only transactions
|
290
|
-
|
291
|
-
## API Documentation
|
292
|
-
|
293
|
-
### DatabaseServer
|
294
|
-
Core server class providing:
|
295
|
-
- Resource list retrieval
|
296
|
-
- Tool call handling (list_tables, query)
|
297
|
-
- Database handler management
|
298
|
-
|
299
|
-
### MCP Tools
|
300
|
-
|
301
|
-
#### dbutils-list-tables
|
302
|
-
Lists all tables in the specified database.
|
303
|
-
- Parameters:
|
304
|
-
* connection: Database connection name
|
305
|
-
- Returns: Text content with a list of table names
|
306
|
-
|
307
|
-
#### dbutils-run-query
|
308
|
-
Executes a SQL query on the specified database.
|
309
|
-
- Parameters:
|
310
|
-
* connection: Database connection name
|
311
|
-
* sql: SQL query to execute (SELECT only)
|
312
|
-
- Returns: Query results in a formatted text
|
313
|
-
|
314
|
-
#### dbutils-get-stats
|
315
|
-
Get table statistics information.
|
316
|
-
- Parameters:
|
317
|
-
* connection: Database connection name
|
318
|
-
* table: Table name
|
319
|
-
- Returns: Statistics including row count, size, column stats
|
320
|
-
|
321
|
-
#### dbutils-list-constraints
|
322
|
-
List table constraints (primary key, foreign keys, etc).
|
323
|
-
- Parameters:
|
324
|
-
* connection: Database connection name
|
325
|
-
* table: Table name
|
326
|
-
- Returns: Detailed constraint information
|
327
|
-
|
328
|
-
#### dbutils-explain-query
|
329
|
-
Get query execution plan with cost estimates.
|
330
|
-
- Parameters:
|
331
|
-
* connection: Database connection name
|
332
|
-
* sql: SQL query to explain
|
333
|
-
- Returns: Formatted execution plan
|
334
|
-
|
335
|
-
#### dbutils-get-performance
|
336
|
-
Get database performance statistics.
|
337
|
-
- Parameters:
|
338
|
-
* connection: Database connection name
|
339
|
-
- Returns: Detailed performance statistics including query times, query types, error rates, and resource usage
|
340
|
-
|
341
|
-
#### dbutils-analyze-query
|
342
|
-
Analyze a SQL query for performance and provide optimization suggestions.
|
343
|
-
- Parameters:
|
344
|
-
* connection: Database connection name
|
345
|
-
* sql: SQL query to analyze
|
346
|
-
- Returns: Query analysis with execution plan, timing information, and optimization suggestions
|
347
|
-
|
348
|
-
### DatabaseHandler
|
349
|
-
Abstract base class defining interfaces:
|
350
|
-
- get_tables(): Get table resource list
|
351
|
-
- get_schema(): Get table structure
|
352
|
-
- execute_query(): Execute SQL query
|
353
|
-
- cleanup(): Resource cleanup
|
354
|
-
|
355
|
-
### PostgreSQL Implementation
|
356
|
-
Provides PostgreSQL-specific features:
|
357
|
-
- Remote connection support
|
358
|
-
- Table description information
|
359
|
-
- Constraint queries
|
360
|
-
|
361
|
-
### SQLite Implementation
|
362
|
-
Provides SQLite-specific features:
|
363
|
-
- File path handling
|
364
|
-
- URI scheme support
|
365
|
-
- Password protection support (optional)
|
366
|
-
|
367
|
-
## Contributing
|
368
|
-
Contributions are welcome! Here's how you can help:
|
369
|
-
|
370
|
-
1. 🐛 Report bugs: Open an issue describing the bug and how to reproduce it
|
371
|
-
2. 💡 Suggest features: Open an issue to propose new features
|
372
|
-
3. 🛠️ Submit PRs: Fork the repo and create a pull request with your changes
|
373
|
-
|
374
|
-
### Development Setup
|
375
|
-
1. Clone the repository
|
376
|
-
2. Create a virtual environment using `uv venv`
|
377
|
-
3. Install dependencies with `uv sync --all-extras`
|
378
|
-
4. Run tests with `pytest`
|
379
|
-
|
380
|
-
For detailed guidelines, see [CONTRIBUTING.md](.github/CONTRIBUTING.md)
|
381
|
-
|
382
|
-
## Acknowledgments
|
383
|
-
- [MCP Servers](https://github.com/modelcontextprotocol/servers) for inspiration and demonstration
|
384
|
-
- AI Editors:
|
385
|
-
* [Claude Desktop](https://claude.ai/download)
|
386
|
-
* [5ire](https://5ire.app/)
|
387
|
-
* [Cline](https://cline.bot)
|
388
|
-
- [Model Context Protocol](https://modelcontextprotocol.io/) for comprehensive interfaces
|
389
|
-
|
390
|
-
## Star History
|
391
|
-
|
392
|
-
[](https://star-history.com/#donghao1393/mcp-dbutils&Date)
|
File without changes
|
File without changes
|
File without changes
|