@rmwxxwmr/mcp-database-service 0.1.2

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.
Files changed (64) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +236 -0
  3. package/README.zh-CN.md +236 -0
  4. package/config/databases.example.json +48 -0
  5. package/dist/config/configSummary.d.ts +4 -0
  6. package/dist/config/configSummary.js +117 -0
  7. package/dist/config/configSummary.js.map +1 -0
  8. package/dist/config/configTypes.d.ts +81 -0
  9. package/dist/config/configTypes.js +2 -0
  10. package/dist/config/configTypes.js.map +1 -0
  11. package/dist/config/configValidation.d.ts +6 -0
  12. package/dist/config/configValidation.js +142 -0
  13. package/dist/config/configValidation.js.map +1 -0
  14. package/dist/config/loadConfig.d.ts +8 -0
  15. package/dist/config/loadConfig.js +85 -0
  16. package/dist/config/loadConfig.js.map +1 -0
  17. package/dist/core/errors.d.ts +15 -0
  18. package/dist/core/errors.js +28 -0
  19. package/dist/core/errors.js.map +1 -0
  20. package/dist/core/logger.d.ts +7 -0
  21. package/dist/core/logger.js +68 -0
  22. package/dist/core/logger.js.map +1 -0
  23. package/dist/core/resultTypes.d.ts +49 -0
  24. package/dist/core/resultTypes.js +2 -0
  25. package/dist/core/resultTypes.js.map +1 -0
  26. package/dist/db/clientFactory.d.ts +9 -0
  27. package/dist/db/clientFactory.js +27 -0
  28. package/dist/db/clientFactory.js.map +1 -0
  29. package/dist/db/readonlyGuard.d.ts +14 -0
  30. package/dist/db/readonlyGuard.js +253 -0
  31. package/dist/db/readonlyGuard.js.map +1 -0
  32. package/dist/db/redis/redisClient.d.ts +16 -0
  33. package/dist/db/redis/redisClient.js +106 -0
  34. package/dist/db/redis/redisClient.js.map +1 -0
  35. package/dist/db/sql/baseSqlAdapter.d.ts +52 -0
  36. package/dist/db/sql/baseSqlAdapter.js +310 -0
  37. package/dist/db/sql/baseSqlAdapter.js.map +1 -0
  38. package/dist/db/sql/mysqlClient.d.ts +33 -0
  39. package/dist/db/sql/mysqlClient.js +150 -0
  40. package/dist/db/sql/mysqlClient.js.map +1 -0
  41. package/dist/db/sql/openGaussClient.d.ts +9 -0
  42. package/dist/db/sql/openGaussClient.js +11 -0
  43. package/dist/db/sql/openGaussClient.js.map +1 -0
  44. package/dist/db/sql/oracleClient.d.ts +33 -0
  45. package/dist/db/sql/oracleClient.js +203 -0
  46. package/dist/db/sql/oracleClient.js.map +1 -0
  47. package/dist/db/sql/postgresClient.d.ts +33 -0
  48. package/dist/db/sql/postgresClient.js +160 -0
  49. package/dist/db/sql/postgresClient.js.map +1 -0
  50. package/dist/db/types.d.ts +24 -0
  51. package/dist/db/types.js +2 -0
  52. package/dist/db/types.js.map +1 -0
  53. package/dist/index.d.ts +2 -0
  54. package/dist/index.js +21 -0
  55. package/dist/server/createServer.d.ts +46 -0
  56. package/dist/server/createServer.js +441 -0
  57. package/dist/server/createServer.js.map +1 -0
  58. package/dist/server/toolRegistry.d.ts +36 -0
  59. package/dist/server/toolRegistry.js +927 -0
  60. package/dist/server/toolRegistry.js.map +1 -0
  61. package/dist/utils/normalize.d.ts +6 -0
  62. package/dist/utils/normalize.js +29 -0
  63. package/dist/utils/normalize.js.map +1 -0
  64. package/package.json +62 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 rmwxxwmr
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,236 @@
1
+ English | [简体中文](./README.zh-CN.md)
2
+
3
+ # MCP Database Service
4
+
5
+ A multi-database MCP server for Model Context Protocol (MCP), written in TypeScript.
6
+
7
+ It supports MySQL, PostgreSQL, Oracle, openGauss, and Redis, with lazy short-lived connections, read-oriented database tools, SQL plan analysis, config reload, and guarded write execution.
8
+
9
+ This project is intended for AI agents and MCP clients that need safe database discovery, querying, performance analysis, and controlled write operations.
10
+
11
+ ## Quick Start
12
+
13
+ Install from npm:
14
+
15
+ ```powershell
16
+ npm install -g @rmwxxwmr/mcp-database-service
17
+ mcp-database-service --config ./config/databases.example.json
18
+ ```
19
+
20
+ Run from source:
21
+
22
+ ```bash
23
+ npm install
24
+ npm run build
25
+ node dist/index.js --config ./config/databases.example.json
26
+ ```
27
+
28
+ ## Support Matrix
29
+
30
+ | Database | Query Tools | Metadata Tools | `explain_query` | `analyze_query` | Write Support |
31
+ | --- | --- | --- | --- | --- | --- |
32
+ | MySQL | Yes | Yes | Yes | Yes | Yes |
33
+ | PostgreSQL | Yes | Yes | Yes | Yes | Yes |
34
+ | openGauss | Yes | Yes | Yes | Yes | Yes |
35
+ | Oracle | Yes | Yes | Yes | No | Yes |
36
+ | Redis | Yes | Limited to Redis tools | No | No | No |
37
+
38
+ Notes:
39
+ - show_create_table currently supports MySQL and Oracle. PostgreSQL and openGauss currently return NOT_SUPPORTED.
40
+ - Operational tools such as `show_variables`, `find_long_running_queries`, `find_blocking_sessions`, and `show_locks` depend on the visibility and privileges of the configured database account.
41
+
42
+ ## Supported Databases
43
+ - MySQL
44
+ - Oracle
45
+ - PostgreSQL
46
+ - openGauss (via PostgreSQL protocol compatibility)
47
+ - Redis
48
+
49
+ ## Features
50
+ - Multiple named database targets in a single config file
51
+ - Optional file logging with configurable output directory
52
+ - Manual config reload without restarting the MCP server
53
+ - Automatic config reload when the JSON file changes on disk
54
+ - Strict read-only enforcement for query tools
55
+ - Optional write execution with explicit MCP confirmation for writable targets
56
+ - Lazy connections with guaranteed cleanup after each request
57
+ - Metadata discovery tools for SQL databases
58
+ - Dedicated read tools for Redis
59
+
60
+ ## Configuration
61
+ Provide the config path by one of these methods:
62
+
63
+ 1. `node dist/index.js --config ./config/databases.json`
64
+ 2. Set `MCP_DATABASE_CONFIG=/absolute/path/to/databases.json`
65
+
66
+ The configuration file must be a JSON object with a required top-level `databases` array. Optional top-level sections such as `logging` and `query` may also be provided. Example:
67
+
68
+ ```json
69
+ {
70
+ "logging": {
71
+ "enabled": true,
72
+ "directory": "./logs"
73
+ },
74
+ "query": {
75
+ "timeoutMs": 5000
76
+ },
77
+ "databases": [
78
+ {
79
+ "key": "main-mysql",
80
+ "type": "mysql",
81
+ "readonly": true,
82
+ "connection": {
83
+ "host": "127.0.0.1",
84
+ "port": 3306,
85
+ "databaseName": "app_db",
86
+ "user": "root",
87
+ "password": "secret",
88
+ "connectTimeoutMs": 5000
89
+ }
90
+ }
91
+ ]
92
+ }
93
+ ```
94
+
95
+ `logging.enabled` defaults to `false`. When enabled, logs are written to the system temporary directory by default. You can override that with `logging.directory`, and relative paths are resolved relative to the config file location. In the example above, logs are written under `./logs`.
96
+
97
+ `query.timeoutMs` is optional. When set, the server applies a query timeout to database operations. In the example above, queries time out after `5000` milliseconds.
98
+
99
+ Oracle supports both Thin and Thick mode. Thick mode uses the same `oracledb` package, but requires Oracle Instant Client on the host machine. Example:
100
+
101
+ ```json
102
+ {
103
+ "key": "oracle-thick-example",
104
+ "type": "oracle",
105
+ "readonly": true,
106
+ "connection": {
107
+ "host": "127.0.0.1",
108
+ "port": 1521,
109
+ "serviceName": "XEPDB1",
110
+ "user": "system",
111
+ "password": "secret",
112
+ "clientMode": "thick",
113
+ "clientLibDir": "C:\\oracle\\instantclient_19_25"
114
+ }
115
+ }
116
+ ```
117
+
118
+ ## Available MCP Tools
119
+ - `show_loaded_config`: show the current in-memory config path, load time, and all configured database targets
120
+ - `reload_config`: reload the JSON config file currently in use and atomically replace the in-memory configuration on success
121
+ - `list_databases`: list all configured target keys and logical database names without opening database connections
122
+ - `ping_database`: test connectivity for one configured target
123
+ - `list_schemas`: list schemas for one SQL target
124
+ - `list_tables`: list tables/views under one SQL schema or the default schema
125
+ - `list_views`: list views under one SQL schema or the default schema
126
+ - `describe_table`: inspect columns before writing joins, reports, or optimization SQL
127
+ - `show_create_table`: inspect exact database-side DDL when the current database supports it
128
+ - `search_tables`: search tables or views by partial name
129
+ - `search_columns`: search columns by partial name across a schema
130
+ - `list_indexes`: inspect table indexes for performance analysis
131
+ - `get_table_statistics`: inspect approximate row counts, storage metrics, and database-specific table statistics
132
+ - `show_variables`: inspect database runtime configuration variables
133
+ - `find_long_running_queries`: inspect currently running sessions above a duration threshold
134
+ - `find_blocking_sessions`: inspect current blocking relationships between sessions
135
+ - `show_locks`: inspect current lock rows exposed by the database
136
+ - `execute_query`: run one read-only SQL query; pass the original query SQL, not write SQL
137
+ - `explain_query`: get the static execution plan for one read-only SQL query; pass the original query SQL, not `EXPLAIN ...`
138
+ - `analyze_query`: get runtime analysis for one read-only SQL query; pass the original query SQL, not `EXPLAIN ANALYZE ...`
139
+ - `execute_statement`: run one non-query SQL statement on a writable target after explicit manual confirmation
140
+ - `redis_get`: read one Redis string key
141
+ - `redis_hgetall`: read one Redis hash key
142
+ - `redis_scan`: cursor-scan Redis keys safely with an optional pattern
143
+
144
+ ## Development
145
+
146
+ ```bash
147
+ npm install
148
+ npm run build
149
+ node dist/index.js --config ./config/databases.example.json
150
+ ```
151
+
152
+ ## Global Installation
153
+
154
+ This project exposes a CLI command named `mcp-database-service` through the package `bin` field.
155
+
156
+ Recommended options:
157
+
158
+ 1. Install from npm:
159
+
160
+ ```powershell
161
+ npm install -g @rmwxxwmr/mcp-database-service
162
+ ```
163
+
164
+ 2. Or install from the local source tree with the helper script:
165
+
166
+ ```powershell
167
+ pwsh -File .\scripts\install-global.ps1
168
+ ```
169
+
170
+ Or on Linux/macOS:
171
+
172
+ ```bash
173
+ sh ./scripts/install-global.sh
174
+ ```
175
+
176
+ The helper scripts install dependencies, build the project, create a tarball with `npm pack`, install that tarball globally with `npm install -g <tarball>`, and then delete the temporary tarball. They do not use `npm link`.
177
+
178
+ 3. Or install the packed tarball manually:
179
+
180
+ ```powershell
181
+ npm pack
182
+ npm install -g .\mcp-database-service-0.1.0.tgz
183
+ ```
184
+
185
+ The package only publishes runtime files through the `files` field, so packaged installation includes `dist` and the runtime README/config example, not the whole source tree.
186
+
187
+ After installation, the command can be used like this:
188
+
189
+ ```powershell
190
+ mcp-database-service --config .\config\databases.example.json
191
+ ```
192
+
193
+ Example MCP server configuration:
194
+
195
+ ```json
196
+ {
197
+ "mcpServers": {
198
+ "database": {
199
+ "command": "mcp-database-service",
200
+ "args": [
201
+ "--config",
202
+ "C:\\path\\to\\databases.json"
203
+ ]
204
+ }
205
+ }
206
+ }
207
+ ```
208
+
209
+ ## Config Reload
210
+
211
+ - The server loads the JSON config file at startup and keeps a validated in-memory snapshot.
212
+ - The server also watches the same JSON file and automatically reloads it after on-disk changes are detected.
213
+ - Automatic reload is debounced to avoid reloading half-written files too aggressively.
214
+ - You can still use `reload_config` to force a manual reload without restarting the process.
215
+ - Reload is atomic: if the new file is invalid, the old in-memory configuration remains active.
216
+ - `show_loaded_config` can be used to inspect the current config path, load time, and configured database targets.
217
+ - `show_loaded_config` also includes the current logging status, resolved log directory, and configured query timeout.
218
+ - `show_loaded_config` also includes a sanitized connection summary for each target, such as host, port, databaseName or serviceName, user name, and Oracle client mode, but it never exposes passwords.
219
+
220
+ ## Oracle Notes
221
+ - Thin mode is the default when `clientMode` is omitted.
222
+ - Thick mode requires `clientMode: "thick"` and a valid `clientLibDir`.
223
+ - All Oracle targets in one process must use the same client mode. Thick mode targets must also share the same `clientLibDir`.
224
+ - `analyze_query` is currently not supported for Oracle and will return `NOT_SUPPORTED`.
225
+
226
+ ## Write Statements
227
+ - `execute_query` remains read-only and blocks non-query SQL.
228
+ - `execute_statement` is intended for writable SQL targets only.
229
+ - `execute_statement` requires `readonly: false` on the target database config.
230
+ - Before executing a non-query SQL statement, the server asks the MCP client for explicit user confirmation through MCP elicitation when the client supports it.
231
+ - If the MCP client does not support elicitation, `execute_statement` automatically falls back to a two-step confirmation flow: the first call returns confirmation details and a `confirmationId`, and the second call must resend the same SQL with `confirmationId` and `confirmExecution: true` after the user confirms.
232
+ - `execute_statement` confirmation includes SQL type, target object, SQL preview, parameter preview, and risk hints for dangerous statements.
233
+
234
+
235
+
236
+
@@ -0,0 +1,236 @@
1
+ [English](./README.md) | 简体中文
2
+
3
+ # MCP Database Service
4
+
5
+ 一个基于 TypeScript 实现的多数据库 MCP 服务,面向 Model Context Protocol (MCP)。
6
+
7
+ 它支持 MySQL、PostgreSQL、Oracle、openGauss 和 Redis,提供懒连接、读为主的数据库工具、SQL 执行计划分析、配置热刷新,以及带保护机制的写操作执行。
8
+
9
+ 这个项目适合需要安全地做数据库发现、查询、性能分析和受控写操作的 AI agent 与 MCP client。
10
+
11
+ ## 快速开始
12
+
13
+ 从 npm 安装:
14
+
15
+ ```powershell
16
+ npm install -g @rmwxxwmr/mcp-database-service
17
+ mcp-database-service --config ./config/databases.example.json
18
+ ```
19
+
20
+ 从源码运行:
21
+
22
+ ```bash
23
+ npm install
24
+ npm run build
25
+ node dist/index.js --config ./config/databases.example.json
26
+ ```
27
+
28
+ ## 支持矩阵
29
+
30
+ | 数据库 | 查询工具 | 元数据工具 | `explain_query` | `analyze_query` | 写操作支持 |
31
+ | --- | --- | --- | --- | --- | --- |
32
+ | MySQL | 是 | 是 | 是 | 是 | 是 |
33
+ | PostgreSQL | 是 | 是 | 是 | 是 | 是 |
34
+ | openGauss | 是 | 是 | 是 | 是 | 是 |
35
+ | Oracle | 是 | 是 | 是 | 否 | 是 |
36
+ | Redis | 是 | 仅 Redis 专用工具 | 否 | 否 | 否 |
37
+
38
+ 补充说明:
39
+ - show_create_table 当前支持 MySQL 和 Oracle;PostgreSQL 与 openGauss 目前会返回 NOT_SUPPORTED。
40
+ - `show_variables`、`find_long_running_queries`、`find_blocking_sessions`、`show_locks` 这类运行态排障工具依赖数据库账号可见性和权限,结果可能为空或受限。
41
+
42
+ ## 支持的数据库
43
+ - MySQL
44
+ - Oracle
45
+ - PostgreSQL
46
+ - openGauss(通过 PostgreSQL 协议兼容)
47
+ - Redis
48
+
49
+ ## 特性
50
+ - 单个配置文件中支持多个数据库目标
51
+ - 支持可选的文件日志,可自定义输出目录
52
+ - 无需重启服务即可手动刷新配置
53
+ - JSON 配置文件变更后自动热刷新
54
+ - 对查询工具进行严格只读限制
55
+ - 可写目标支持显式确认后的写操作
56
+ - 每次请求使用懒连接,并在完成后保证关闭
57
+ - 为 SQL 数据库提供元数据发现工具
58
+ - 为 Redis 提供专用只读工具
59
+
60
+ ## 配置
61
+ 可以通过以下任一方式传入配置文件路径:
62
+
63
+ 1. `node dist/index.js --config ./config/databases.json`
64
+ 2. 设置 `MCP_DATABASE_CONFIG=/absolute/path/to/databases.json`
65
+
66
+ 配置文件必须是一个 JSON 对象,其中顶层 `databases` 数组是必填项;`logging`、`query` 等顶层配置项是可选的。示例:
67
+
68
+ ```json
69
+ {
70
+ "logging": {
71
+ "enabled": true,
72
+ "directory": "./logs"
73
+ },
74
+ "query": {
75
+ "timeoutMs": 5000
76
+ },
77
+ "databases": [
78
+ {
79
+ "key": "main-mysql",
80
+ "type": "mysql",
81
+ "readonly": true,
82
+ "connection": {
83
+ "host": "127.0.0.1",
84
+ "port": 3306,
85
+ "databaseName": "app_db",
86
+ "user": "root",
87
+ "password": "secret",
88
+ "connectTimeoutMs": 5000
89
+ }
90
+ }
91
+ ]
92
+ }
93
+ ```
94
+
95
+ `logging.enabled` 默认是 `false`。开启后,日志默认写入系统临时目录;你也可以通过 `logging.directory` 自定义目录,若填相对路径,则相对于配置文件所在目录解析。上面的示例会把日志写到 `./logs`。
96
+
97
+ `query.timeoutMs` 是可选项。配置后,服务会为数据库操作应用查询超时。上面的示例会在 `5000` 毫秒后超时。
98
+
99
+ Oracle 同时支持 Thin 和 Thick 模式。Thick 模式仍然使用同一个 `oracledb` 包,但要求宿主机安装 Oracle Instant Client。示例:
100
+
101
+ ```json
102
+ {
103
+ "key": "oracle-thick-example",
104
+ "type": "oracle",
105
+ "readonly": true,
106
+ "connection": {
107
+ "host": "127.0.0.1",
108
+ "port": 1521,
109
+ "serviceName": "XEPDB1",
110
+ "user": "system",
111
+ "password": "secret",
112
+ "clientMode": "thick",
113
+ "clientLibDir": "C:\\oracle\\instantclient_19_25"
114
+ }
115
+ }
116
+ ```
117
+
118
+ ## 可用 MCP Tools
119
+ - `show_loaded_config`:查看当前内存中的配置路径、加载时间和所有已配置数据库目标
120
+ - `reload_config`:重新读取当前 JSON 配置文件,并在成功时原子替换内存配置
121
+ - `list_databases`:列出所有已配置目标的 key 和逻辑数据库名,不会打开数据库连接
122
+ - `ping_database`:测试某个已配置目标的连通性
123
+ - `list_schemas`:列出某个 SQL 目标下的 schema
124
+ - `list_tables`:列出某个 SQL schema 或默认 schema 下的表 / 视图
125
+ - `list_views`:列出某个 SQL schema 或默认 schema 下的视图
126
+ - `describe_table`:查看列信息,适合写 join、报表或优化 SQL 前使用
127
+ - `show_create_table`:在当前数据库支持时查看数据库侧的 DDL 定义
128
+ - `search_tables`:按部分名称搜索表或视图
129
+ - `search_columns`:按部分名称搜索 schema 下的列
130
+ - `list_indexes`:查看表索引,适合做性能分析
131
+ - `get_table_statistics`:查看近似行数、存储信息和数据库特定统计信息
132
+ - `show_variables`:查看数据库运行时参数
133
+ - `find_long_running_queries`:查看超过阈值的当前长时间运行会话
134
+ - `find_blocking_sessions`:查看当前阻塞关系
135
+ - `show_locks`:查看数据库当前可见的锁信息
136
+ - `execute_query`:执行只读 SQL 查询;传原始查询 SQL,不要传写 SQL
137
+ - `explain_query`:查看只读 SQL 的静态执行计划;传原始查询 SQL,不要传 `EXPLAIN ...`
138
+ - `analyze_query`:查看只读 SQL 的运行时分析;传原始查询 SQL,不要传 `EXPLAIN ANALYZE ...`
139
+ - `execute_statement`:在可写目标上执行非查询 SQL,但必须先经过显式确认
140
+ - `redis_get`:读取一个 Redis 字符串 key
141
+ - `redis_hgetall`:读取一个 Redis hash key
142
+ - `redis_scan`:按游标安全扫描 Redis key,可选 pattern
143
+
144
+ ## 开发
145
+
146
+ ```bash
147
+ npm install
148
+ npm run build
149
+ node dist/index.js --config ./config/databases.example.json
150
+ ```
151
+
152
+ ## 全局安装
153
+
154
+ 本项目通过 `bin` 字段暴露了一个 CLI 命令:`mcp-database-service`。
155
+
156
+ 推荐方式:
157
+
158
+ 1. 直接从 npm 安装:
159
+
160
+ ```powershell
161
+ npm install -g @rmwxxwmr/mcp-database-service
162
+ ```
163
+
164
+ 2. 或从本地源码树通过辅助脚本安装:
165
+
166
+ ```powershell
167
+ pwsh -File .\scripts\install-global.ps1
168
+ ```
169
+
170
+ Linux / macOS 可使用:
171
+
172
+ ```bash
173
+ sh ./scripts/install-global.sh
174
+ ```
175
+
176
+ 这些脚本会安装依赖、构建项目、通过 `npm pack` 生成 tarball、再用 `npm install -g <tarball>` 全局安装,最后删除临时 tarball。它们不会使用 `npm link`。
177
+
178
+ 3. 或手动安装打包产物:
179
+
180
+ ```powershell
181
+ npm pack
182
+ npm install -g .\mcp-database-service-0.1.0.tgz
183
+ ```
184
+
185
+ 由于 `files` 字段只发布运行时文件,所以打包安装时会包含 `dist`、运行时 README 和配置示例,而不是整个源码目录。
186
+
187
+ 安装后可以这样启动:
188
+
189
+ ```powershell
190
+ mcp-database-service --config .\config\databases.example.json
191
+ ```
192
+
193
+ MCP 服务配置示例:
194
+
195
+ ```json
196
+ {
197
+ "mcpServers": {
198
+ "database": {
199
+ "command": "mcp-database-service",
200
+ "args": [
201
+ "--config",
202
+ "C:\\path\\to\\databases.json"
203
+ ]
204
+ }
205
+ }
206
+ }
207
+ ```
208
+
209
+ ## 配置刷新
210
+
211
+ - 服务启动时会加载 JSON 配置文件,并保留一份校验通过的内存快照
212
+ - 服务也会监听同一个 JSON 文件,在磁盘变更后自动热刷新
213
+ - 自动刷新有防抖,避免在文件半写入状态下频繁重载
214
+ - 你仍然可以使用 `reload_config` 手动刷新,而无需重启进程
215
+ - 刷新是原子的:如果新文件无效,旧的内存配置会继续保持生效
216
+ - 可以用 `show_loaded_config` 查看当前配置路径、加载时间和已配置数据库目标
217
+ - `show_loaded_config` 也会返回当前日志开关状态、解析后的日志目录以及配置的查询超时
218
+ - `show_loaded_config` 还会返回脱敏后的连接摘要,例如 host、port、databaseName 或 serviceName、用户名以及 Oracle client mode,但不会暴露密码
219
+
220
+ ## Oracle 说明
221
+ - 未配置 `clientMode` 时,默认使用 Thin 模式
222
+ - Thick 模式要求 `clientMode: "thick"`,并提供有效的 `clientLibDir`
223
+ - 同一进程中的所有 Oracle 目标必须使用相同的 client mode;如果使用 Thick,还必须共用同一个 `clientLibDir`
224
+ - Oracle 目前不支持 `analyze_query`,会返回 `NOT_SUPPORTED`
225
+
226
+ ## 写操作说明
227
+ - `execute_query` 始终是只读的,会拦截非查询 SQL
228
+ - `execute_statement` 仅用于可写 SQL 目标
229
+ - `execute_statement` 要求目标配置为 `readonly: false`
230
+ - 如果 MCP client 支持交互确认,服务会在执行非查询 SQL 前通过 MCP elicitation 请求用户确认
231
+ - 如果 MCP client 不支持 elicitation,`execute_statement` 会自动退回到二段式确认流程:第一次调用返回确认详情和 `confirmationId`,用户确认后,第二次必须带上 `confirmationId` 和 `confirmExecution: true`,并重复同一条 SQL 才会真正执行
232
+ - `execute_statement` 的确认信息会包含 SQL 类型、目标对象、SQL 预览、参数预览,以及高风险语句的风险提示
233
+
234
+
235
+
236
+
@@ -0,0 +1,48 @@
1
+ {
2
+ "logging": {
3
+ "enabled": true,
4
+ "directory": "./logs"
5
+ },
6
+ "query": {
7
+ "timeoutMs": 5000
8
+ },
9
+ "databases": [
10
+ {
11
+ "key": "main-mysql",
12
+ "type": "mysql",
13
+ "readonly": true,
14
+ "connection": {
15
+ "host": "127.0.0.1",
16
+ "port": 3306,
17
+ "databaseName": "app_db",
18
+ "user": "root",
19
+ "password": "secret",
20
+ "connectTimeoutMs": 5000
21
+ }
22
+ },
23
+ {
24
+ "key": "cache-redis",
25
+ "type": "redis",
26
+ "readonly": true,
27
+ "connection": {
28
+ "url": "redis://127.0.0.1:6379/0",
29
+ "connectTimeoutMs": 5000
30
+ }
31
+ },
32
+ {
33
+ "key": "oracle-thick-example",
34
+ "type": "oracle",
35
+ "readonly": true,
36
+ "connection": {
37
+ "host": "127.0.0.1",
38
+ "port": 1521,
39
+ "serviceName": "XEPDB1",
40
+ "user": "system",
41
+ "password": "secret",
42
+ "connectTimeoutMs": 5000,
43
+ "clientMode": "thick",
44
+ "clientLibDir": "D:\\Work\\Navicat\\instantclient_19_25"
45
+ }
46
+ }
47
+ ]
48
+ }
@@ -0,0 +1,4 @@
1
+ import type { DatabaseConfig, LoadedConfig } from "./configTypes.js";
2
+ export declare function summarizeLoadedConfig(config: LoadedConfig): Record<string, unknown>;
3
+ export declare function summarizeDatabaseConfig(database: DatabaseConfig): Record<string, unknown>;
4
+ export declare function summarizeDatabaseListItem(database: DatabaseConfig): Record<string, unknown>;
@@ -0,0 +1,117 @@
1
+ import { URL } from "node:url";
2
+ export function summarizeLoadedConfig(config) {
3
+ return {
4
+ configPath: config.configPath,
5
+ loadedAt: config.loadedAt,
6
+ databaseCount: config.databases.length,
7
+ logging: {
8
+ enabled: config.logging.enabled,
9
+ directory: config.logging.directory
10
+ },
11
+ query: {
12
+ timeoutMs: config.query.timeoutMs
13
+ },
14
+ items: config.databases.map((database) => summarizeDatabaseConfig(database))
15
+ };
16
+ }
17
+ export function summarizeDatabaseConfig(database) {
18
+ return {
19
+ key: database.key,
20
+ databaseName: summarizeLogicalDatabaseName(database),
21
+ type: database.type,
22
+ readonly: database.readonly,
23
+ connection: summarizeConnection(database)
24
+ };
25
+ }
26
+ export function summarizeDatabaseListItem(database) {
27
+ return {
28
+ key: database.key,
29
+ databaseName: summarizeLogicalDatabaseName(database),
30
+ type: database.type,
31
+ readonly: database.readonly
32
+ };
33
+ }
34
+ function summarizeConnection(database) {
35
+ switch (database.type) {
36
+ case "mysql":
37
+ return summarizeMysqlConnection(database);
38
+ case "postgresql":
39
+ case "opengauss":
40
+ return summarizePostgresConnection(database);
41
+ case "oracle":
42
+ return summarizeOracleConnection(database);
43
+ case "redis":
44
+ return summarizeRedisConnection(database);
45
+ }
46
+ }
47
+ function summarizeMysqlConnection(database) {
48
+ return {
49
+ host: database.connection.host,
50
+ port: database.connection.port ?? 3306,
51
+ databaseName: database.connection.databaseName,
52
+ user: database.connection.user,
53
+ connectTimeoutMs: database.connection.connectTimeoutMs ?? null,
54
+ sslEnabled: database.connection.ssl === true || typeof database.connection.ssl === "object"
55
+ };
56
+ }
57
+ function summarizePostgresConnection(database) {
58
+ return {
59
+ host: database.connection.host,
60
+ port: database.connection.port ?? 5432,
61
+ databaseName: database.connection.databaseName,
62
+ user: database.connection.user,
63
+ connectTimeoutMs: database.connection.connectTimeoutMs ?? null,
64
+ sslEnabled: database.connection.ssl === true || typeof database.connection.ssl === "object"
65
+ };
66
+ }
67
+ function summarizeOracleConnection(database) {
68
+ return {
69
+ host: database.connection.host,
70
+ port: database.connection.port ?? 1521,
71
+ serviceName: database.connection.serviceName ?? null,
72
+ sid: database.connection.sid ?? null,
73
+ user: database.connection.user,
74
+ connectTimeoutMs: database.connection.connectTimeoutMs ?? null,
75
+ clientMode: database.connection.clientMode ?? (database.connection.clientLibDir ? "thick" : "thin"),
76
+ clientLibDir: database.connection.clientLibDir ?? null
77
+ };
78
+ }
79
+ function summarizeRedisConnection(database) {
80
+ return {
81
+ url: database.connection.url ? sanitizeRedisUrl(database.connection.url) : null,
82
+ host: database.connection.host ?? null,
83
+ port: database.connection.port ?? null,
84
+ databaseName: database.connection.databaseName ?? null,
85
+ username: database.connection.username ?? null,
86
+ connectTimeoutMs: database.connection.connectTimeoutMs ?? null
87
+ };
88
+ }
89
+ function summarizeLogicalDatabaseName(database) {
90
+ switch (database.type) {
91
+ case "mysql":
92
+ return database.connection.databaseName;
93
+ case "postgresql":
94
+ case "opengauss":
95
+ return database.connection.databaseName;
96
+ case "oracle":
97
+ return database.connection.serviceName ?? database.connection.sid ?? null;
98
+ case "redis":
99
+ return database.connection.databaseName ?? null;
100
+ }
101
+ }
102
+ function sanitizeRedisUrl(rawUrl) {
103
+ try {
104
+ const parsed = new URL(rawUrl);
105
+ if (parsed.password) {
106
+ parsed.password = "***";
107
+ }
108
+ if (parsed.username) {
109
+ parsed.username = parsed.username;
110
+ }
111
+ return parsed.toString();
112
+ }
113
+ catch {
114
+ return rawUrl.replace(/\/\/([^:@/]+):([^@/]+)@/, "//$1:***@");
115
+ }
116
+ }
117
+ //# sourceMappingURL=configSummary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configSummary.js","sourceRoot":"","sources":["../../src/config/configSummary.ts"],"names":[],"mappings":"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"}