@vrs-soft/wecom-aibot-mcp 2.4.25 → 2.4.26

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/dist/bin.js CHANGED
@@ -13,7 +13,7 @@ import { spawn, execSync } from 'child_process';
13
13
  import * as fs from 'fs';
14
14
  import * as path from 'path';
15
15
  import * as os from 'os';
16
- import { runConfigWizard, loadConfig, saveConfig, deleteRobotConfigInteractive, uninstall, addMcpConfig, detectUserIdFromMessage, ensureHookInstalled, listAllRobots, ensureGlobalConfigs, getAuthToken, setAuthToken, getHttpsConfig, setHttpsConfig, updateMcpAuthHeaders, runRemoteInstallWizard, VERSION, } from './config-wizard.js';
16
+ import { runConfigWizard, loadConfig, saveConfig, deleteRobotConfigInteractive, uninstall, addMcpConfig, detectUserIdFromMessage, ensureHookInstalled, listAllRobots, ensureGlobalConfigs, getInstalledMode, getAuthToken, setAuthToken, getHttpsConfig, setHttpsConfig, updateMcpAuthHeaders, runRemoteInstallWizard, VERSION, } from './config-wizard.js';
17
17
  import { initClient } from './client.js';
18
18
  import { registerTools } from './tools/index.js';
19
19
  import { startHttpServer, stopHttpServer, HTTP_PORT } from './http-server.js';
@@ -373,9 +373,14 @@ function startMcpServerBackground() {
373
373
  }
374
374
  async function main() {
375
375
  const args = process.argv.slice(2);
376
- // 确定安装模式
377
- const installMode = args.includes('--http-only') ? 'http-only' :
378
- args.includes('--channel-only') ? 'channel-only' : 'full';
376
+ // 确定安装模式:优先 CLI flag,其次复用 version.json 里上次的 mode(保持 remote / channel-only 等模式不被 --upgrade 打回 full)
377
+ const explicitMode = args.includes('--http-only') ? 'http-only' :
378
+ args.includes('--channel-only') ? 'channel-only' : undefined;
379
+ const prior = getInstalledMode();
380
+ const installMode = explicitMode || prior.mode || 'full';
381
+ const remoteOptions = (installMode === 'remote' || installMode === 'remote-channel') && prior.remote?.url
382
+ ? { url: prior.remote.url, token: prior.remote.token || '' }
383
+ : undefined;
379
384
  // 以下命令跳过顶部 ensureGlobalConfigs,避免覆盖配置
380
385
  // --setup: 向导完成后自己调用
381
386
  // --channel: 作为 Channel MCP 代理运行,不应改写全局配置
@@ -390,7 +395,17 @@ async function main() {
390
395
  args.includes('--clean-cache') || args.includes('--set-token') || args.includes('--config');
391
396
  if (!skipEnsure) {
392
397
  // 强制覆盖所有全局配置(不依赖智能体)
393
- ensureGlobalConfigs(installMode);
398
+ if (installMode === 'remote' || installMode === 'remote-channel') {
399
+ if (remoteOptions) {
400
+ ensureGlobalConfigs(installMode, remoteOptions);
401
+ }
402
+ else {
403
+ console.log(`[mcp] 检测到上次安装模式 ${installMode},但缺少远程参数;跳过配置写入。如需变更请使用 --setup`);
404
+ }
405
+ }
406
+ else {
407
+ ensureGlobalConfigs(installMode);
408
+ }
394
409
  }
395
410
  // 解析命令行参数
396
411
  if (args.includes('--help') || args.includes('-h')) {
@@ -40,7 +40,15 @@ export declare function getDocMcpUrl(robotName?: string): {
40
40
  error?: string;
41
41
  };
42
42
  export declare function ensureHookInstalled(): void;
43
- export declare function ensureGlobalConfigs(mode?: 'full' | 'http-only' | 'channel-only' | 'remote' | 'remote-channel', remoteOptions?: {
43
+ export type InstallMode = 'full' | 'http-only' | 'channel-only' | 'remote' | 'remote-channel';
44
+ export declare function getInstalledMode(): {
45
+ mode?: InstallMode;
46
+ remote?: {
47
+ url: string;
48
+ token?: string;
49
+ };
50
+ };
51
+ export declare function ensureGlobalConfigs(mode?: InstallMode, remoteOptions?: {
44
52
  url: string;
45
53
  token: string;
46
54
  }): {
@@ -177,10 +177,19 @@ export function deleteConfig() {
177
177
  if (fs.existsSync(CLAUDE_CONFIG_FILE)) {
178
178
  const content = fs.readFileSync(CLAUDE_CONFIG_FILE, 'utf-8');
179
179
  const claudeConfig = JSON.parse(content);
180
+ let changed = false;
180
181
  if (claudeConfig.mcpServers?.['wecom-aibot']) {
181
182
  delete claudeConfig.mcpServers['wecom-aibot'];
182
- fs.writeFileSync(CLAUDE_CONFIG_FILE, JSON.stringify(claudeConfig, null, 2));
183
183
  console.log('[config] 已从 ~/.claude.json 删除 wecom-aibot 配置');
184
+ changed = true;
185
+ }
186
+ if (claudeConfig.mcpServers?.['wecom-aibot-channel']) {
187
+ delete claudeConfig.mcpServers['wecom-aibot-channel'];
188
+ console.log('[config] 已从 ~/.claude.json 删除 wecom-aibot-channel 配置');
189
+ changed = true;
190
+ }
191
+ if (changed) {
192
+ fs.writeFileSync(CLAUDE_CONFIG_FILE, JSON.stringify(claudeConfig, null, 2));
184
193
  }
185
194
  }
186
195
  }
@@ -194,14 +203,27 @@ export function deleteHook() {
194
203
  if (fs.existsSync(CLAUDE_SETTINGS_FILE)) {
195
204
  const content = fs.readFileSync(CLAUDE_SETTINGS_FILE, 'utf-8');
196
205
  const settings = JSON.parse(content);
206
+ let changed = false;
197
207
  if (settings.hooks && settings.hooks['PermissionRequest']) {
198
208
  // 只删除 wecom-aibot 相关的 hook
199
209
  settings.hooks['PermissionRequest'] = settings.hooks['PermissionRequest'].filter((hook) => !hook.hooks?.some?.((h) => h.command?.includes?.('wecom-aibot-mcp')));
200
210
  if (settings.hooks['PermissionRequest'].length === 0) {
201
211
  delete settings.hooks['PermissionRequest'];
202
212
  }
203
- fs.writeFileSync(CLAUDE_SETTINGS_FILE, JSON.stringify(settings, null, 2));
204
213
  console.log('[config] 已删除 PermissionRequest hook');
214
+ changed = true;
215
+ }
216
+ // 移除 wecom-aibot 相关的 MCP 权限
217
+ if (Array.isArray(settings.permissions?.allow)) {
218
+ const before = settings.permissions.allow.length;
219
+ settings.permissions.allow = settings.permissions.allow.filter((p) => !/^mcp__wecom-aibot(-channel)?__/.test(p));
220
+ if (settings.permissions.allow.length !== before) {
221
+ console.log(`[config] 已移除 ${before - settings.permissions.allow.length} 条 wecom-aibot MCP 权限`);
222
+ changed = true;
223
+ }
224
+ }
225
+ if (changed) {
226
+ fs.writeFileSync(CLAUDE_SETTINGS_FILE, JSON.stringify(settings, null, 2));
205
227
  }
206
228
  // 删除 hook 脚本文件
207
229
  if (fs.existsSync(HOOK_SCRIPT_PATH)) {
@@ -1064,6 +1086,30 @@ export function ensureHookInstalled() {
1064
1086
  writeMcpPermissions();
1065
1087
  writeStopHookScript();
1066
1088
  }
1089
+ // 读取上次安装的模式 + 远程参数(来自 version.json)
1090
+ export function getInstalledMode() {
1091
+ if (!fs.existsSync(VERSION_FILE))
1092
+ return {};
1093
+ try {
1094
+ const data = JSON.parse(fs.readFileSync(VERSION_FILE, 'utf-8'));
1095
+ const result = {};
1096
+ if (data.mode)
1097
+ result.mode = data.mode;
1098
+ if (data.remote?.url)
1099
+ result.remote = { url: data.remote.url, token: data.remote.token };
1100
+ return result;
1101
+ }
1102
+ catch {
1103
+ return {};
1104
+ }
1105
+ }
1106
+ // 写 version.json(统一入口,记录 mode + 远程参数,用于后续 --upgrade 复用)
1107
+ function writeVersionFile(mode, remoteOptions) {
1108
+ const payload = { version: VERSION, installedAt: Date.now(), mode };
1109
+ if (remoteOptions?.url)
1110
+ payload.remote = { url: remoteOptions.url, ...(remoteOptions.token ? { token: remoteOptions.token } : {}) };
1111
+ fs.writeFileSync(VERSION_FILE, JSON.stringify(payload, null, 2));
1112
+ }
1067
1113
  // 确保所有全局配置已写入(强制覆盖,不依赖智能体)
1068
1114
  export function ensureGlobalConfigs(mode = 'full', remoteOptions) {
1069
1115
  ensureConfigDir();
@@ -1085,7 +1131,7 @@ export function ensureGlobalConfigs(mode = 'full', remoteOptions) {
1085
1131
  // 只写权限配置和 Hook(可选,用于本地调试)
1086
1132
  writeMcpPermissions();
1087
1133
  console.log('[config] 已写入权限配置到 ~/.claude/settings.local.json');
1088
- fs.writeFileSync(VERSION_FILE, JSON.stringify({ version: VERSION, installedAt: Date.now() }, null, 2));
1134
+ writeVersionFile(mode);
1089
1135
  return { upgraded, previousVersion };
1090
1136
  }
1091
1137
  // remote 模式:仅写入远程 HTTP MCP 配置(带 token headers),不装 Channel/Hook
@@ -1108,7 +1154,7 @@ export function ensureGlobalConfigs(mode = 'full', remoteOptions) {
1108
1154
  };
1109
1155
  fs.writeFileSync(CLAUDE_CONFIG_FILE, JSON.stringify(claudeConfig, null, 2));
1110
1156
  console.log('[config] remote 模式:已写入远程 HTTP MCP 配置(带 Token)');
1111
- fs.writeFileSync(VERSION_FILE, JSON.stringify({ version: VERSION, installedAt: Date.now() }, null, 2));
1157
+ writeVersionFile(mode, remoteOptions);
1112
1158
  return { upgraded, previousVersion };
1113
1159
  }
1114
1160
  // remote-channel 模式:远程部署的 Channel 客户端——只写 Channel MCP,不写 HTTP MCP
@@ -1143,7 +1189,7 @@ export function ensureGlobalConfigs(mode = 'full', remoteOptions) {
1143
1189
  // Channel 模式需要权限配置
1144
1190
  writeMcpPermissions();
1145
1191
  console.log('[config] 已写入权限配置到 ~/.claude/settings.local.json');
1146
- fs.writeFileSync(VERSION_FILE, JSON.stringify({ version: VERSION, installedAt: Date.now() }, null, 2));
1192
+ writeVersionFile(mode, remoteOptions);
1147
1193
  return { upgraded, previousVersion };
1148
1194
  }
1149
1195
  // 1. 强制写入 MCP 配置到 ~/.claude.json
@@ -1211,7 +1257,7 @@ export function ensureGlobalConfigs(mode = 'full', remoteOptions) {
1211
1257
  writeMcpPermissions();
1212
1258
  console.log('[config] 已写入权限配置到 ~/.claude/settings.local.json');
1213
1259
  // 3. 写入版本号
1214
- fs.writeFileSync(VERSION_FILE, JSON.stringify({ version: VERSION, installedAt: Date.now() }, null, 2));
1260
+ writeVersionFile(mode);
1215
1261
  console.log(`[config] 已记录版本号: ${VERSION}`);
1216
1262
  return { upgraded, previousVersion };
1217
1263
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vrs-soft/wecom-aibot-mcp",
3
- "version": "2.4.25",
3
+ "version": "2.4.26",
4
4
  "description": "企业微信智能机器人 MCP 服务 - Claude Code 审批通道",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",