universal-db-mcp 0.1.0
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/CONTRIBUTING.md +93 -0
- package/DEPLOYMENT.md +411 -0
- package/EXAMPLES.md +362 -0
- package/LICENSE +21 -0
- package/README.md +167 -0
- package/dist/adapters/mysql.d.ts +41 -0
- package/dist/adapters/mysql.d.ts.map +1 -0
- package/dist/adapters/mysql.js +173 -0
- package/dist/adapters/mysql.js.map +1 -0
- package/dist/adapters/postgres.d.ts +41 -0
- package/dist/adapters/postgres.d.ts.map +1 -0
- package/dist/adapters/postgres.js +210 -0
- package/dist/adapters/postgres.js.map +1 -0
- package/dist/adapters/redis.d.ts +53 -0
- package/dist/adapters/redis.d.ts.map +1 -0
- package/dist/adapters/redis.js +227 -0
- package/dist/adapters/redis.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +100 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +32 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +194 -0
- package/dist/server.js.map +1 -0
- package/dist/types/adapter.d.ts +114 -0
- package/dist/types/adapter.d.ts.map +1 -0
- package/dist/types/adapter.js +6 -0
- package/dist/types/adapter.js.map +1 -0
- package/dist/utils/safety.d.ts +24 -0
- package/dist/utils/safety.d.ts.map +1 -0
- package/dist/utils/safety.js +56 -0
- package/dist/utils/safety.js.map +1 -0
- package/package.json +65 -0
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# 贡献指南
|
|
2
|
+
|
|
3
|
+
感谢你对 MCP 数据库万能连接器的关注!我们欢迎所有形式的贡献。
|
|
4
|
+
|
|
5
|
+
## 🤝 如何贡献
|
|
6
|
+
|
|
7
|
+
### 报告 Bug
|
|
8
|
+
|
|
9
|
+
如果你发现了 Bug,请在 [GitHub Issues](https://github.com/yourusername/universal-db-mcp/issues) 中提交,并包含:
|
|
10
|
+
|
|
11
|
+
- 详细的问题描述
|
|
12
|
+
- 复现步骤
|
|
13
|
+
- 预期行为 vs 实际行为
|
|
14
|
+
- 环境信息(操作系统、Node.js 版本、数据库版本)
|
|
15
|
+
|
|
16
|
+
### 提交功能建议
|
|
17
|
+
|
|
18
|
+
我们欢迎新功能建议!请先在 Issues 中讨论,确保该功能符合项目方向。
|
|
19
|
+
|
|
20
|
+
### 提交代码
|
|
21
|
+
|
|
22
|
+
1. **Fork 本仓库**
|
|
23
|
+
2. **创建特性分支**: `git checkout -b feature/amazing-feature`
|
|
24
|
+
3. **编写代码**: 遵循下面的代码规范
|
|
25
|
+
4. **提交更改**: `git commit -m '添加某某功能'`
|
|
26
|
+
5. **推送分支**: `git push origin feature/amazing-feature`
|
|
27
|
+
6. **创建 Pull Request**
|
|
28
|
+
|
|
29
|
+
## 📝 代码规范
|
|
30
|
+
|
|
31
|
+
- 使用 TypeScript 严格模式
|
|
32
|
+
- 关键架构决策需要添加中文注释
|
|
33
|
+
- 用户可见的消息必须使用简体中文
|
|
34
|
+
- 遵循现有的代码风格
|
|
35
|
+
|
|
36
|
+
## 🔌 添加新数据库支持
|
|
37
|
+
|
|
38
|
+
如果你想添加新的数据库支持(如 MongoDB、SQLite),请按以下步骤:
|
|
39
|
+
|
|
40
|
+
1. 在 `src/adapters/` 下创建新文件(如 `mongodb.ts`)
|
|
41
|
+
2. 实现 `DbAdapter` 接口
|
|
42
|
+
3. 在 `src/index.ts` 中添加对应的 case 分支
|
|
43
|
+
4. 更新 `README.md` 的支持列表
|
|
44
|
+
5. 添加相应的 npm 依赖
|
|
45
|
+
|
|
46
|
+
### 示例结构
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
// src/adapters/mongodb.ts
|
|
50
|
+
import type { DbAdapter, QueryResult, SchemaInfo } from '../types/adapter.js';
|
|
51
|
+
|
|
52
|
+
export class MongoDBAdapter implements DbAdapter {
|
|
53
|
+
async connect(): Promise<void> {
|
|
54
|
+
// 实现连接逻辑
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async disconnect(): Promise<void> {
|
|
58
|
+
// 实现断开连接逻辑
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async executeQuery(query: string, params?: unknown[]): Promise<QueryResult> {
|
|
62
|
+
// 实现查询逻辑
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async getSchema(): Promise<SchemaInfo> {
|
|
66
|
+
// 实现获取结构逻辑
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
isWriteOperation(query: string): boolean {
|
|
70
|
+
// 实现写操作检测
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## ✅ 提交前检查清单
|
|
76
|
+
|
|
77
|
+
- [ ] 代码通过 TypeScript 编译 (`npm run build`)
|
|
78
|
+
- [ ] 关键逻辑添加了中文注释
|
|
79
|
+
- [ ] 用户可见消息使用简体中文
|
|
80
|
+
- [ ] 更新了相关文档
|
|
81
|
+
- [ ] 测试了基本功能
|
|
82
|
+
|
|
83
|
+
## 📄 许可证
|
|
84
|
+
|
|
85
|
+
提交代码即表示你同意将代码以 MIT 许可证开源。
|
|
86
|
+
|
|
87
|
+
## 💬 联系方式
|
|
88
|
+
|
|
89
|
+
如有疑问,欢迎在 Issues 中讨论或联系维护者。
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
再次感谢你的贡献!🎉
|
package/DEPLOYMENT.md
ADDED
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
# 部署指南
|
|
2
|
+
|
|
3
|
+
本文档介绍如何将 MCP 数据库万能连接器部署到不同环境。
|
|
4
|
+
|
|
5
|
+
## 📦 发布到 NPM
|
|
6
|
+
|
|
7
|
+
### 准备工作
|
|
8
|
+
|
|
9
|
+
1. **注册 NPM 账号**
|
|
10
|
+
```bash
|
|
11
|
+
npm adduser
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
2. **更新 package.json**
|
|
15
|
+
|
|
16
|
+
确保以下字段正确:
|
|
17
|
+
```json
|
|
18
|
+
{
|
|
19
|
+
"name": "universal-db-mcp",
|
|
20
|
+
"version": "0.1.0",
|
|
21
|
+
"description": "MCP 数据库万能连接器 - 让 Claude Desktop 直接连接你的数据库",
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "https://github.com/yourusername/universal-db-mcp.git"
|
|
25
|
+
},
|
|
26
|
+
"keywords": [
|
|
27
|
+
"mcp",
|
|
28
|
+
"model-context-protocol",
|
|
29
|
+
"claude",
|
|
30
|
+
"database",
|
|
31
|
+
"mysql",
|
|
32
|
+
"postgresql",
|
|
33
|
+
"redis"
|
|
34
|
+
]
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
3. **构建项目**
|
|
39
|
+
```bash
|
|
40
|
+
npm run build
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
4. **测试本地安装**
|
|
44
|
+
```bash
|
|
45
|
+
npm pack
|
|
46
|
+
npm install -g ./universal-db-mcp-0.1.0.tgz
|
|
47
|
+
universal-db-mcp --help
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### 发布
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# 发布到 NPM
|
|
54
|
+
npm publish
|
|
55
|
+
|
|
56
|
+
# 如果是第一次发布,可能需要验证邮箱
|
|
57
|
+
# 如果包名已被占用,需要修改 package.json 中的 name
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### 版本管理
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
# 补丁版本(bug 修复)
|
|
64
|
+
npm version patch # 0.1.0 -> 0.1.1
|
|
65
|
+
|
|
66
|
+
# 次要版本(新功能)
|
|
67
|
+
npm version minor # 0.1.0 -> 0.2.0
|
|
68
|
+
|
|
69
|
+
# 主要版本(破坏性更改)
|
|
70
|
+
npm version major # 0.1.0 -> 1.0.0
|
|
71
|
+
|
|
72
|
+
# 发布新版本
|
|
73
|
+
npm publish
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## 🐳 Docker 部署
|
|
79
|
+
|
|
80
|
+
### 创建 Dockerfile
|
|
81
|
+
|
|
82
|
+
```dockerfile
|
|
83
|
+
FROM node:20-alpine
|
|
84
|
+
|
|
85
|
+
WORKDIR /app
|
|
86
|
+
|
|
87
|
+
# 复制 package 文件
|
|
88
|
+
COPY package*.json ./
|
|
89
|
+
|
|
90
|
+
# 安装依赖
|
|
91
|
+
RUN npm ci --only=production
|
|
92
|
+
|
|
93
|
+
# 复制源代码
|
|
94
|
+
COPY . .
|
|
95
|
+
|
|
96
|
+
# 构建
|
|
97
|
+
RUN npm run build
|
|
98
|
+
|
|
99
|
+
# 设置入口点
|
|
100
|
+
ENTRYPOINT ["node", "dist/index.js"]
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### 构建镜像
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
docker build -t universal-db-mcp:latest .
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### 运行容器
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
# MySQL 示例
|
|
113
|
+
docker run -it \
|
|
114
|
+
universal-db-mcp:latest \
|
|
115
|
+
--type mysql \
|
|
116
|
+
--host host.docker.internal \
|
|
117
|
+
--port 3306 \
|
|
118
|
+
--user root \
|
|
119
|
+
--password password \
|
|
120
|
+
--database mydb
|
|
121
|
+
|
|
122
|
+
# 使用环境变量
|
|
123
|
+
docker run -it \
|
|
124
|
+
-e DB_TYPE=mysql \
|
|
125
|
+
-e DB_HOST=host.docker.internal \
|
|
126
|
+
-e DB_PORT=3306 \
|
|
127
|
+
-e DB_USER=root \
|
|
128
|
+
-e DB_PASSWORD=password \
|
|
129
|
+
-e DB_NAME=mydb \
|
|
130
|
+
universal-db-mcp:latest
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## 🔧 本地开发部署
|
|
136
|
+
|
|
137
|
+
### 从源码安装
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
# 克隆仓库
|
|
141
|
+
git clone https://github.com/yourusername/universal-db-mcp.git
|
|
142
|
+
cd universal-db-mcp
|
|
143
|
+
|
|
144
|
+
# 安装依赖
|
|
145
|
+
npm install
|
|
146
|
+
|
|
147
|
+
# 构建
|
|
148
|
+
npm run build
|
|
149
|
+
|
|
150
|
+
# 全局链接(用于开发)
|
|
151
|
+
npm link
|
|
152
|
+
|
|
153
|
+
# 现在可以直接使用
|
|
154
|
+
universal-db-mcp --help
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### 开发模式
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
# 监听文件变化,自动重新编译
|
|
161
|
+
npm run dev
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### 在 Claude Desktop 中使用本地版本
|
|
165
|
+
|
|
166
|
+
编辑 Claude Desktop 配置文件,使用本地路径:
|
|
167
|
+
|
|
168
|
+
```json
|
|
169
|
+
{
|
|
170
|
+
"mcpServers": {
|
|
171
|
+
"local-db": {
|
|
172
|
+
"command": "node",
|
|
173
|
+
"args": [
|
|
174
|
+
"/path/to/universal-db-mcp/dist/index.js",
|
|
175
|
+
"--type", "mysql",
|
|
176
|
+
"--host", "localhost",
|
|
177
|
+
"--port", "3306",
|
|
178
|
+
"--user", "root",
|
|
179
|
+
"--password", "password",
|
|
180
|
+
"--database", "test"
|
|
181
|
+
]
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## 🌐 企业内网部署
|
|
190
|
+
|
|
191
|
+
### 场景:通过跳板机访问数据库
|
|
192
|
+
|
|
193
|
+
1. **在跳板机上安装**
|
|
194
|
+
```bash
|
|
195
|
+
ssh jumphost
|
|
196
|
+
npm install -g universal-db-mcp
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
2. **配置 SSH 隧道**
|
|
200
|
+
```bash
|
|
201
|
+
# 本地机器执行
|
|
202
|
+
ssh -L 3306:db-server:3306 user@jumphost -N
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
3. **Claude Desktop 配置**
|
|
206
|
+
```json
|
|
207
|
+
{
|
|
208
|
+
"mcpServers": {
|
|
209
|
+
"prod-db": {
|
|
210
|
+
"command": "npx",
|
|
211
|
+
"args": [
|
|
212
|
+
"universal-db-mcp",
|
|
213
|
+
"--type", "mysql",
|
|
214
|
+
"--host", "localhost",
|
|
215
|
+
"--port", "3306",
|
|
216
|
+
"--user", "readonly",
|
|
217
|
+
"--password", "secure_password",
|
|
218
|
+
"--database", "production"
|
|
219
|
+
]
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### 场景:使用 VPN 连接
|
|
226
|
+
|
|
227
|
+
1. **连接企业 VPN**
|
|
228
|
+
|
|
229
|
+
2. **直接配置内网地址**
|
|
230
|
+
```json
|
|
231
|
+
{
|
|
232
|
+
"mcpServers": {
|
|
233
|
+
"internal-db": {
|
|
234
|
+
"command": "npx",
|
|
235
|
+
"args": [
|
|
236
|
+
"universal-db-mcp",
|
|
237
|
+
"--type", "postgres",
|
|
238
|
+
"--host", "10.0.1.100",
|
|
239
|
+
"--port", "5432",
|
|
240
|
+
"--user", "analyst",
|
|
241
|
+
"--password", "password",
|
|
242
|
+
"--database", "analytics"
|
|
243
|
+
]
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
## 🔐 安全最佳实践
|
|
252
|
+
|
|
253
|
+
### 1. 使用专用数据库账号
|
|
254
|
+
|
|
255
|
+
**MySQL**:
|
|
256
|
+
```sql
|
|
257
|
+
-- 创建只读用户
|
|
258
|
+
CREATE USER 'mcp_readonly'@'%' IDENTIFIED BY 'secure_password';
|
|
259
|
+
GRANT SELECT ON mydb.* TO 'mcp_readonly'@'%';
|
|
260
|
+
FLUSH PRIVILEGES;
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
**PostgreSQL**:
|
|
264
|
+
```sql
|
|
265
|
+
-- 创建只读用户
|
|
266
|
+
CREATE USER mcp_readonly WITH PASSWORD 'secure_password';
|
|
267
|
+
GRANT CONNECT ON DATABASE mydb TO mcp_readonly;
|
|
268
|
+
GRANT USAGE ON SCHEMA public TO mcp_readonly;
|
|
269
|
+
GRANT SELECT ON ALL TABLES IN SCHEMA public TO mcp_readonly;
|
|
270
|
+
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO mcp_readonly;
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### 2. 使用环境变量存储密码
|
|
274
|
+
|
|
275
|
+
创建 `.env` 文件(不要提交到 Git):
|
|
276
|
+
```bash
|
|
277
|
+
DB_PASSWORD=your_secure_password
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
修改 Claude Desktop 配置使用环境变量:
|
|
281
|
+
```json
|
|
282
|
+
{
|
|
283
|
+
"mcpServers": {
|
|
284
|
+
"secure-db": {
|
|
285
|
+
"command": "bash",
|
|
286
|
+
"args": [
|
|
287
|
+
"-c",
|
|
288
|
+
"source ~/.env && npx universal-db-mcp --type mysql --host localhost --port 3306 --user root --password $DB_PASSWORD --database mydb"
|
|
289
|
+
]
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
### 3. 网络隔离
|
|
296
|
+
|
|
297
|
+
- 使用防火墙限制数据库访问
|
|
298
|
+
- 仅允许特定 IP 连接
|
|
299
|
+
- 使用 SSL/TLS 加密连接
|
|
300
|
+
|
|
301
|
+
### 4. 审计日志
|
|
302
|
+
|
|
303
|
+
定期检查 Claude Desktop 的日志:
|
|
304
|
+
|
|
305
|
+
**macOS**: `~/Library/Logs/Claude/`
|
|
306
|
+
**Windows**: `%APPDATA%\Claude\logs\`
|
|
307
|
+
|
|
308
|
+
---
|
|
309
|
+
|
|
310
|
+
## 📊 监控和日志
|
|
311
|
+
|
|
312
|
+
### 启用详细日志
|
|
313
|
+
|
|
314
|
+
MCP 服务器的日志输出到 stderr,可以通过 Claude Desktop 查看。
|
|
315
|
+
|
|
316
|
+
### 自定义日志记录
|
|
317
|
+
|
|
318
|
+
如果需要更详细的日志,可以修改源码添加日志记录:
|
|
319
|
+
|
|
320
|
+
```typescript
|
|
321
|
+
// src/server.ts
|
|
322
|
+
console.error(`[${new Date().toISOString()}] 执行查询: ${query}`);
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
---
|
|
326
|
+
|
|
327
|
+
## 🚀 性能优化
|
|
328
|
+
|
|
329
|
+
### 1. 连接池(未来改进)
|
|
330
|
+
|
|
331
|
+
当前版本使用单一连接,未来可以添加连接池支持:
|
|
332
|
+
|
|
333
|
+
```typescript
|
|
334
|
+
// 使用 mysql2 连接池
|
|
335
|
+
const pool = mysql.createPool({
|
|
336
|
+
host: config.host,
|
|
337
|
+
port: config.port,
|
|
338
|
+
user: config.user,
|
|
339
|
+
password: config.password,
|
|
340
|
+
database: config.database,
|
|
341
|
+
connectionLimit: 10,
|
|
342
|
+
});
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
### 2. 查询缓存
|
|
346
|
+
|
|
347
|
+
对于频繁查询的 schema 信息,可以添加缓存:
|
|
348
|
+
|
|
349
|
+
```typescript
|
|
350
|
+
private schemaCache: SchemaInfo | null = null;
|
|
351
|
+
private schemaCacheTime: number = 0;
|
|
352
|
+
private CACHE_TTL = 60000; // 1 分钟
|
|
353
|
+
|
|
354
|
+
async getSchema(): Promise<SchemaInfo> {
|
|
355
|
+
const now = Date.now();
|
|
356
|
+
if (this.schemaCache && now - this.schemaCacheTime < this.CACHE_TTL) {
|
|
357
|
+
return this.schemaCache;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
this.schemaCache = await this.fetchSchema();
|
|
361
|
+
this.schemaCacheTime = now;
|
|
362
|
+
return this.schemaCache;
|
|
363
|
+
}
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
---
|
|
367
|
+
|
|
368
|
+
## 🐛 故障排查
|
|
369
|
+
|
|
370
|
+
### 问题:Claude Desktop 无法连接
|
|
371
|
+
|
|
372
|
+
**检查步骤**:
|
|
373
|
+
1. 验证配置文件格式正确(JSON 语法)
|
|
374
|
+
2. 重启 Claude Desktop
|
|
375
|
+
3. 查看 Claude Desktop 日志
|
|
376
|
+
4. 手动测试命令:
|
|
377
|
+
```bash
|
|
378
|
+
npx universal-db-mcp --type mysql --host localhost --port 3306 --user root --password password --database test
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
### 问题:数据库连接超时
|
|
382
|
+
|
|
383
|
+
**解决方案**:
|
|
384
|
+
1. 检查数据库服务是否运行
|
|
385
|
+
2. 验证网络连接
|
|
386
|
+
3. 检查防火墙规则
|
|
387
|
+
4. 增加连接超时时间(需要修改源码)
|
|
388
|
+
|
|
389
|
+
### 问题:权限错误
|
|
390
|
+
|
|
391
|
+
**解决方案**:
|
|
392
|
+
1. 确认数据库用户权限
|
|
393
|
+
2. 检查数据库访问控制列表
|
|
394
|
+
3. 验证用户名和密码
|
|
395
|
+
|
|
396
|
+
---
|
|
397
|
+
|
|
398
|
+
## 📚 更多资源
|
|
399
|
+
|
|
400
|
+
- [使用示例](./EXAMPLES.md)
|
|
401
|
+
- [贡献指南](./CONTRIBUTING.md)
|
|
402
|
+
- [GitHub Issues](https://github.com/yourusername/universal-db-mcp/issues)
|
|
403
|
+
- [Model Context Protocol 文档](https://modelcontextprotocol.io/)
|
|
404
|
+
|
|
405
|
+
---
|
|
406
|
+
|
|
407
|
+
## 🎉 部署成功!
|
|
408
|
+
|
|
409
|
+
完成部署后,你就可以在 Claude Desktop 中使用自然语言查询数据库了!
|
|
410
|
+
|
|
411
|
+
如有问题,欢迎提交 Issue 或参与讨论。
|