vmoo-mcp-database-server 1.3.8 → 1.3.10
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 +20 -0
- package/package.json +1 -1
- package/shared/database-utils.js +1 -1
- package/shared/privacy-utils.js +30 -32
- package/shared/security-utils.js +3 -2
- package/vmoo-database-deliver/server.js +11 -0
- package/vmoo-database-deliver-prod/server.js +11 -0
- package/vmoo-database-dev/server.js +11 -0
- package/vmoo-database-prod/server.js +11 -0
package/README.md
CHANGED
|
@@ -188,6 +188,26 @@ node mcp-vmoo-database-server.js 2> debug.log
|
|
|
188
188
|
- 验证Augment配置文件路径正确
|
|
189
189
|
- 确保Node.js版本 >= 18.0.0
|
|
190
190
|
|
|
191
|
+
## 🚀 自动发布
|
|
192
|
+
|
|
193
|
+
本项目已配置 GitHub Actions CI/CD,推送到 `main` 分支时会自动发布新版本到 npm。
|
|
194
|
+
|
|
195
|
+
### 发版流程
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
# 1. 修改 package.json 中的 version
|
|
199
|
+
# 2. 提交并推送
|
|
200
|
+
git add .
|
|
201
|
+
git commit -m "bump: 版本 x.x.x - 变更说明"
|
|
202
|
+
git push origin main
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
- ✅ 自动检测版本号变化,仅在版本号更新时触发发布
|
|
206
|
+
- ✅ 仅核心文件变更时触发(`shared/`、`vmoo-database-*/`、`bin/`、`index.js`、`package.json`)
|
|
207
|
+
- ⏭️ 版本号未变化时自动跳过
|
|
208
|
+
|
|
209
|
+
> 首次配置请参考 [NPM 自动发布配置指南](docs/npm-publish-setup.md)
|
|
210
|
+
|
|
191
211
|
## 许可证
|
|
192
212
|
|
|
193
213
|
MIT License
|
package/package.json
CHANGED
package/shared/database-utils.js
CHANGED
package/shared/privacy-utils.js
CHANGED
|
@@ -139,42 +139,42 @@ function anonymizeBankCard(bankCard) {
|
|
|
139
139
|
|
|
140
140
|
/**
|
|
141
141
|
* 对查询结果进行数据匿名化处理
|
|
142
|
+
* 使用精确字段名匹配,避免误伤业务数据(如 location_name, goods_name 等)
|
|
142
143
|
* @param {Array} rows 查询结果
|
|
143
144
|
* @returns {Array} 匿名化后的结果
|
|
144
145
|
*/
|
|
145
146
|
function anonymizeQueryResults(rows) {
|
|
146
147
|
if (!Array.isArray(rows)) return rows;
|
|
147
148
|
|
|
148
|
-
//
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
149
|
+
// 精确匹配的字段名 -> 匿名化函数映射
|
|
150
|
+
// 只列举数据库中真正包含用户隐私的字段名
|
|
151
|
+
const exactFieldMappings = {
|
|
152
|
+
// === 手机号字段 ===
|
|
153
|
+
'mobile': anonymizePhone, // fanwe_user.mobile, fanwe_dc_consignee.mobile, fanwe_dc_order.mobile, ps_user.mobile
|
|
154
|
+
'phone': anonymizePhone, // ps_sender.phone, ps_receiver.phone
|
|
155
|
+
'pre_mobile': anonymizePhone, // fanwe_dc_order.pre_mobile
|
|
156
|
+
'lottery_mobile': anonymizePhone, // fanwe_user.lottery_mobile
|
|
155
157
|
|
|
156
|
-
// 身份证字段
|
|
157
|
-
id_card: anonymizeIdCard,
|
|
158
|
-
identity_card: anonymizeIdCard,
|
|
159
|
-
id_number: anonymizeIdCard,
|
|
158
|
+
// === 身份证字段 ===
|
|
159
|
+
'id_card': anonymizeIdCard, // ps_user.id_card
|
|
160
160
|
|
|
161
|
-
// 邮箱字段
|
|
162
|
-
email: anonymizeEmail,
|
|
163
|
-
mail: anonymizeEmail,
|
|
161
|
+
// === 邮箱字段 ===
|
|
162
|
+
'email': anonymizeEmail, // fanwe_user.email
|
|
164
163
|
|
|
165
|
-
//
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
consignee: anonymizeName,
|
|
164
|
+
// === 真实姓名字段(仅限真正的人名,不包括业务名称) ===
|
|
165
|
+
'true_name': anonymizeName, // ps_user.true_name, ps_order.true_name
|
|
166
|
+
'trun_old_true_name': anonymizeName,// ps_order.trun_old_true_name (转单前骑手名)
|
|
167
|
+
'consignee': anonymizeName, // fanwe_dc_consignee.consignee, fanwe_dc_order.consignee (收货人姓名)
|
|
170
168
|
|
|
171
|
-
//
|
|
172
|
-
address: anonymizeAddress,
|
|
173
|
-
|
|
169
|
+
// === 用户地址字段(仅限收货/配送地址,不包括店铺地址等业务地址) ===
|
|
170
|
+
'address': anonymizeAddress, // fanwe_dc_consignee.address, ps_sender.address, ps_receiver.address
|
|
171
|
+
'api_address': anonymizeAddress, // fanwe_dc_consignee.api_address, fanwe_dc_order.api_address
|
|
172
|
+
'address_detail': anonymizeAddress, // ps_sender.address_detail, ps_receiver.address_detail
|
|
173
|
+
'geo_address': anonymizeAddress, // fanwe_user.geo_address
|
|
174
174
|
|
|
175
|
-
// 银行卡字段
|
|
176
|
-
bank_card: anonymizeBankCard,
|
|
177
|
-
card_number: anonymizeBankCard
|
|
175
|
+
// === 银行卡字段 ===
|
|
176
|
+
'bank_card': anonymizeBankCard,
|
|
177
|
+
'card_number': anonymizeBankCard
|
|
178
178
|
};
|
|
179
179
|
|
|
180
180
|
return rows.map(row => {
|
|
@@ -183,13 +183,11 @@ function anonymizeQueryResults(rows) {
|
|
|
183
183
|
Object.keys(anonymizedRow).forEach(key => {
|
|
184
184
|
const lowerKey = key.toLowerCase();
|
|
185
185
|
|
|
186
|
-
//
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
}
|
|
192
|
-
});
|
|
186
|
+
// 使用精确匹配,而非 includes 模糊匹配
|
|
187
|
+
if (exactFieldMappings[lowerKey]) {
|
|
188
|
+
const anonymizeFunc = exactFieldMappings[lowerKey];
|
|
189
|
+
anonymizedRow[key] = anonymizeFunc(anonymizedRow[key]);
|
|
190
|
+
}
|
|
193
191
|
});
|
|
194
192
|
|
|
195
193
|
return anonymizedRow;
|
package/shared/security-utils.js
CHANGED
|
@@ -17,8 +17,9 @@ class QueryRateLimiter {
|
|
|
17
17
|
this.maxQueriesPerMinute = 10;
|
|
18
18
|
this.cleanupInterval = 60000; // 1分钟清理一次
|
|
19
19
|
|
|
20
|
-
//
|
|
21
|
-
setInterval(() => this.cleanup(), this.cleanupInterval);
|
|
20
|
+
// 定期清理过期记录(使用 unref 防止 timer 阻止进程退出)
|
|
21
|
+
const cleanupTimer = setInterval(() => this.cleanup(), this.cleanupInterval);
|
|
22
|
+
cleanupTimer.unref();
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
/**
|
|
@@ -283,6 +283,17 @@ async function main() {
|
|
|
283
283
|
console.error(`VMOO配送测试站MCP服务器已启动 - ${config.server.name} v${config.server.version}`);
|
|
284
284
|
console.error(`安全级别: ${config.security.level} - ${config.security.description}`);
|
|
285
285
|
console.error(`️ 表前缀: ${prefixConfig ? (prefixConfig.enabled ? prefixConfig.prefix : '无前缀') : 'fanwe_(默认)'}`);
|
|
286
|
+
|
|
287
|
+
// Graceful shutdown:当 MCP 通信管道关闭时,主动退出进程
|
|
288
|
+
const gracefulShutdown = async () => {
|
|
289
|
+
console.error('MCP服务器正在关闭...');
|
|
290
|
+
try { await pool.end(); } catch (e) { /* ignore */ }
|
|
291
|
+
process.exit(0);
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
process.stdin.on('end', gracefulShutdown);
|
|
295
|
+
process.on('SIGTERM', gracefulShutdown);
|
|
296
|
+
process.on('SIGINT', gracefulShutdown);
|
|
286
297
|
}
|
|
287
298
|
|
|
288
299
|
main().catch(console.error);
|
|
@@ -299,6 +299,17 @@ async function main() {
|
|
|
299
299
|
console.error(`安全级别: ${config.security.level} - ${config.security.description}`);
|
|
300
300
|
console.error(`️ 防护功能: 频率限制防爬虫数据匿名化`);
|
|
301
301
|
console.error(`️ 表前缀: ${prefixConfig ? (prefixConfig.enabled ? prefixConfig.prefix : '无前缀') : 'fanwe_(默认)'}`);
|
|
302
|
+
|
|
303
|
+
// Graceful shutdown:当 MCP 通信管道关闭时,主动退出进程
|
|
304
|
+
const gracefulShutdown = async () => {
|
|
305
|
+
console.error('MCP服务器正在关闭...');
|
|
306
|
+
try { await pool.end(); } catch (e) { /* ignore */ }
|
|
307
|
+
process.exit(0);
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
process.stdin.on('end', gracefulShutdown);
|
|
311
|
+
process.on('SIGTERM', gracefulShutdown);
|
|
312
|
+
process.on('SIGINT', gracefulShutdown);
|
|
302
313
|
}
|
|
303
314
|
|
|
304
315
|
main().catch(console.error);
|
|
@@ -276,6 +276,17 @@ async function main() {
|
|
|
276
276
|
await server.connect(transport);
|
|
277
277
|
console.error(`VMOO开发环境MCP服务器已启动 - ${config.server.name} v${config.server.version}`);
|
|
278
278
|
console.error(`安全级别: ${config.security.level} - ${config.security.description}`);
|
|
279
|
+
|
|
280
|
+
// Graceful shutdown:当 MCP 通信管道关闭时,主动退出进程
|
|
281
|
+
const gracefulShutdown = async () => {
|
|
282
|
+
console.error('MCP服务器正在关闭...');
|
|
283
|
+
try { await pool.end(); } catch (e) { /* ignore */ }
|
|
284
|
+
process.exit(0);
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
process.stdin.on('end', gracefulShutdown);
|
|
288
|
+
process.on('SIGTERM', gracefulShutdown);
|
|
289
|
+
process.on('SIGINT', gracefulShutdown);
|
|
279
290
|
}
|
|
280
291
|
|
|
281
292
|
main().catch(console.error);
|
|
@@ -295,6 +295,17 @@ async function main() {
|
|
|
295
295
|
console.error(`VMOO生产环境MCP服务器已启动 - ${config.server.name} v${config.server.version}`);
|
|
296
296
|
console.error(`安全级别: ${config.security.level} - ${config.security.description}`);
|
|
297
297
|
console.error(`️ 防护功能: 频率限制防爬虫数据匿名化`);
|
|
298
|
+
|
|
299
|
+
// Graceful shutdown:当 MCP 通信管道关闭时,主动退出进程
|
|
300
|
+
const gracefulShutdown = async () => {
|
|
301
|
+
console.error('MCP服务器正在关闭...');
|
|
302
|
+
try { await pool.end(); } catch (e) { /* ignore */ }
|
|
303
|
+
process.exit(0);
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
process.stdin.on('end', gracefulShutdown);
|
|
307
|
+
process.on('SIGTERM', gracefulShutdown);
|
|
308
|
+
process.on('SIGINT', gracefulShutdown);
|
|
298
309
|
}
|
|
299
310
|
|
|
300
311
|
main().catch(console.error);
|