@vrs-soft/wecom-aibot-mcp 2.4.3 → 2.4.5
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 +68 -37
- package/dist/config-wizard.js +41 -27
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -313,9 +313,16 @@ async function main() {
|
|
|
313
313
|
// 确定安装模式
|
|
314
314
|
const installMode = args.includes('--http-only') ? 'http-only' :
|
|
315
315
|
args.includes('--channel-only') ? 'channel-only' : 'full';
|
|
316
|
-
//
|
|
317
|
-
//
|
|
318
|
-
|
|
316
|
+
// 以下命令跳过顶部 ensureGlobalConfigs,避免覆盖配置
|
|
317
|
+
// --setup: 向导完成后自己调用
|
|
318
|
+
// --channel: 作为 Channel MCP 代理运行,不应改写全局配置
|
|
319
|
+
// --reinstall / --http-only: 有自己的处理逻辑
|
|
320
|
+
// --version / -v: 只查版本,不写配置
|
|
321
|
+
const skipEnsure = args.includes('--reinstall') || args.includes('--http-only') ||
|
|
322
|
+
args.includes('--setup') || args.includes('--channel') ||
|
|
323
|
+
args.includes('--version') || args.includes('-v') ||
|
|
324
|
+
args.includes('--start') || args.includes('--debug');
|
|
325
|
+
if (!skipEnsure) {
|
|
319
326
|
// 强制覆盖所有全局配置(不依赖智能体)
|
|
320
327
|
ensureGlobalConfigs(installMode);
|
|
321
328
|
}
|
|
@@ -516,29 +523,45 @@ async function main() {
|
|
|
516
523
|
setAuthToken(token);
|
|
517
524
|
// HTTPS 证书配置
|
|
518
525
|
const defaultCertPath = path.join(os.homedir(), '.wecom-aibot-mcp', 'cert.pem');
|
|
519
|
-
const defaultKeyPath = path.join(os.homedir(), '.wecom-aibot-mcp', 'key.pem');
|
|
520
526
|
console.log('\n HTTPS 证书配置(留空跳过,保持 HTTP 模式)');
|
|
521
|
-
console.log('
|
|
522
|
-
console.log(`
|
|
523
|
-
console.log(
|
|
524
|
-
console.log('
|
|
525
|
-
|
|
526
|
-
|
|
527
|
+
console.log(' 请输入完整路径含文件名(.pem / .crt / .key 均可),例如:');
|
|
528
|
+
console.log(` ${defaultCertPath}`);
|
|
529
|
+
console.log(' /etc/letsencrypt/live/example.com/fullchain.pem');
|
|
530
|
+
console.log(' /etc/gitlab/ssl/gitlab.example.com.crt\n');
|
|
531
|
+
const checkFile = (p, label) => {
|
|
532
|
+
if (!fs.existsSync(p)) {
|
|
533
|
+
console.log(`[setup] ⚠️ ${label}文件不存在: ${p}`);
|
|
534
|
+
return false;
|
|
535
|
+
}
|
|
536
|
+
if (fs.statSync(p).isDirectory()) {
|
|
537
|
+
console.log(`[setup] ⚠️ ${label}路径是目录而非文件: ${p}`);
|
|
538
|
+
return false;
|
|
539
|
+
}
|
|
540
|
+
return true;
|
|
541
|
+
};
|
|
527
542
|
const rl2 = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
528
|
-
const certInput = await new Promise(resolve => rl2.question(`SSL
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
543
|
+
const certInput = await new Promise(resolve => rl2.question(`SSL 证书文件完整路径(留空跳过): `, a => { rl2.close(); resolve(a.trim()); }));
|
|
544
|
+
if (certInput) {
|
|
545
|
+
if (!checkFile(certInput, '证书')) {
|
|
546
|
+
console.log('[setup] 跳过 HTTPS 配置');
|
|
547
|
+
}
|
|
548
|
+
else {
|
|
549
|
+
const rl3 = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
550
|
+
const keyInput = await new Promise(resolve => rl3.question(`SSL 私钥文件完整路径: `, a => { rl3.close(); resolve(a.trim()); }));
|
|
551
|
+
if (keyInput && checkFile(keyInput, '私钥')) {
|
|
552
|
+
setHttpsConfig(certInput, keyInput);
|
|
553
|
+
console.log(`[setup] HTTPS 已配置`);
|
|
554
|
+
console.log(` 证书: ${certInput}`);
|
|
555
|
+
console.log(` 私钥: ${keyInput}`);
|
|
556
|
+
}
|
|
557
|
+
else if (!keyInput) {
|
|
558
|
+
console.log('[setup] 私钥路径不能为空,跳过 HTTPS 配置');
|
|
559
|
+
}
|
|
560
|
+
}
|
|
539
561
|
}
|
|
540
562
|
else {
|
|
541
|
-
console.log(`[setup]
|
|
563
|
+
console.log(`[setup] 跳过 HTTPS,使用 HTTP 模式`);
|
|
564
|
+
console.log(`[setup] 如需启用 HTTPS,配置证书后重新运行 --setup --server`);
|
|
542
565
|
}
|
|
543
566
|
console.log('\n[setup] Server 配置完成!');
|
|
544
567
|
console.log(' 启动: npx @vrs-soft/wecom-aibot-mcp --http-only --start');
|
|
@@ -548,23 +571,31 @@ async function main() {
|
|
|
548
571
|
else if (wantChannel) {
|
|
549
572
|
// Channel 客户端
|
|
550
573
|
console.log('\n[setup] Channel Client 安装模式\n');
|
|
551
|
-
|
|
574
|
+
// 交互式安装必须每次都提示,不能直接用已有的环境变量(可能是旧值)
|
|
575
|
+
const readline = await import('readline');
|
|
576
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
577
|
+
const existingUrl = process.env.MCP_URL || '';
|
|
578
|
+
const urlPrompt = existingUrl
|
|
579
|
+
? `远程服务器地址(当前: ${existingUrl},直接回车保持不变): `
|
|
580
|
+
: `远程服务器地址(如 https://your-server:18963): `;
|
|
581
|
+
const urlInput = await new Promise(resolve => rl.question(urlPrompt, a => { rl.close(); resolve(a.trim()); }));
|
|
582
|
+
const mcpUrl = urlInput || existingUrl;
|
|
552
583
|
if (!mcpUrl) {
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
mcpUrl = await new Promise(resolve => rl.question('远程服务器地址(如 https://your-server:18963): ', a => { rl.close(); resolve(a.trim()); }));
|
|
556
|
-
if (!mcpUrl) {
|
|
557
|
-
console.log('[setup] ❌ 地址不能为空');
|
|
558
|
-
process.exit(1);
|
|
559
|
-
}
|
|
560
|
-
process.env.MCP_URL = mcpUrl;
|
|
584
|
+
console.log('[setup] ❌ 地址不能为空');
|
|
585
|
+
process.exit(1);
|
|
561
586
|
}
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
const
|
|
565
|
-
const
|
|
566
|
-
|
|
567
|
-
|
|
587
|
+
process.env.MCP_URL = mcpUrl;
|
|
588
|
+
{
|
|
589
|
+
const existingToken = getAuthToken();
|
|
590
|
+
const tokenPrompt = existingToken
|
|
591
|
+
? `Auth Token(当前: ${existingToken.slice(0, 8)}...${existingToken.slice(-4)},直接回车保持不变): `
|
|
592
|
+
: 'Auth Token(留空跳过): ';
|
|
593
|
+
const readline2 = await import('readline');
|
|
594
|
+
const rl2 = readline2.createInterface({ input: process.stdin, output: process.stdout });
|
|
595
|
+
const tokenInput = await new Promise(resolve => rl2.question(tokenPrompt, a => { rl2.close(); resolve(a.trim()); }));
|
|
596
|
+
const finalToken = tokenInput || existingToken || '';
|
|
597
|
+
if (finalToken)
|
|
598
|
+
setAuthToken(finalToken);
|
|
568
599
|
}
|
|
569
600
|
ensureGlobalConfigs('channel-only');
|
|
570
601
|
console.log('[setup] Channel MCP 配置完成!请重启 Claude Code 以加载配置');
|
package/dist/config-wizard.js
CHANGED
|
@@ -1032,9 +1032,10 @@ export function ensureGlobalConfigs(mode = 'full', remoteOptions) {
|
|
|
1032
1032
|
}
|
|
1033
1033
|
if (!claudeConfig.mcpServers)
|
|
1034
1034
|
claudeConfig.mcpServers = {};
|
|
1035
|
+
const mcpEndpointUrl = remoteOptions.url.replace(/\/+$/, '') + '/mcp';
|
|
1035
1036
|
claudeConfig.mcpServers['wecom-aibot'] = {
|
|
1036
1037
|
type: 'http',
|
|
1037
|
-
url:
|
|
1038
|
+
url: mcpEndpointUrl,
|
|
1038
1039
|
headers: { Authorization: `Bearer ${remoteOptions.token}` },
|
|
1039
1040
|
};
|
|
1040
1041
|
fs.writeFileSync(CLAUDE_CONFIG_FILE, JSON.stringify(claudeConfig, null, 2));
|
|
@@ -1044,8 +1045,8 @@ export function ensureGlobalConfigs(mode = 'full', remoteOptions) {
|
|
|
1044
1045
|
}
|
|
1045
1046
|
// remote-channel 模式:写入远程 HTTP MCP(带 token)+ Channel MCP
|
|
1046
1047
|
if (mode === 'remote-channel') {
|
|
1047
|
-
if (!remoteOptions?.url
|
|
1048
|
-
console.log('[config] ❌ 远程模式需要提供 URL
|
|
1048
|
+
if (!remoteOptions?.url) {
|
|
1049
|
+
console.log('[config] ❌ 远程模式需要提供 URL');
|
|
1049
1050
|
return { upgraded: false, previousVersion };
|
|
1050
1051
|
}
|
|
1051
1052
|
let claudeConfig = {};
|
|
@@ -1054,21 +1055,20 @@ export function ensureGlobalConfigs(mode = 'full', remoteOptions) {
|
|
|
1054
1055
|
}
|
|
1055
1056
|
if (!claudeConfig.mcpServers)
|
|
1056
1057
|
claudeConfig.mcpServers = {};
|
|
1057
|
-
// HTTP MCP 配置(带 token
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
headers
|
|
1062
|
-
|
|
1058
|
+
// HTTP MCP 配置(带 token,可选)
|
|
1059
|
+
const mcpEndpointUrl = remoteOptions.url.replace(/\/+$/, '') + '/mcp';
|
|
1060
|
+
const httpMcpConfig = { type: 'http', url: mcpEndpointUrl };
|
|
1061
|
+
if (remoteOptions.token)
|
|
1062
|
+
httpMcpConfig.headers = { Authorization: `Bearer ${remoteOptions.token}` };
|
|
1063
|
+
claudeConfig.mcpServers['wecom-aibot'] = httpMcpConfig;
|
|
1063
1064
|
// Channel MCP 配置(带 MCP_URL + MCP_AUTH_TOKEN)
|
|
1064
|
-
const
|
|
1065
|
+
const channelEnvRemote = { MCP_URL: remoteOptions.url.replace(/\/+$/, '') };
|
|
1066
|
+
if (remoteOptions.token)
|
|
1067
|
+
channelEnvRemote.MCP_AUTH_TOKEN = remoteOptions.token;
|
|
1065
1068
|
claudeConfig.mcpServers['wecom-aibot-channel'] = {
|
|
1066
|
-
command: '
|
|
1067
|
-
args: [
|
|
1068
|
-
env:
|
|
1069
|
-
MCP_URL: remoteOptions.url,
|
|
1070
|
-
MCP_AUTH_TOKEN: remoteOptions.token,
|
|
1071
|
-
},
|
|
1069
|
+
command: 'npx',
|
|
1070
|
+
args: ['-y', '@vrs-soft/wecom-aibot-mcp', '--channel'],
|
|
1071
|
+
env: channelEnvRemote,
|
|
1072
1072
|
};
|
|
1073
1073
|
fs.writeFileSync(CLAUDE_CONFIG_FILE, JSON.stringify(claudeConfig, null, 2));
|
|
1074
1074
|
console.log('[config] remote-channel 模式:已写入 HTTP MCP + Channel MCP 配置(带 Token)');
|
|
@@ -1086,6 +1086,11 @@ export function ensureGlobalConfigs(mode = 'full', remoteOptions) {
|
|
|
1086
1086
|
}
|
|
1087
1087
|
if (!claudeConfig.mcpServers)
|
|
1088
1088
|
claudeConfig.mcpServers = {};
|
|
1089
|
+
// 从 node_modules 运行(npm/npx 安装)时用 npx,本地开发时用绝对路径
|
|
1090
|
+
const isPackageInstall = __dirname.includes('node_modules');
|
|
1091
|
+
const channelCmd = isPackageInstall
|
|
1092
|
+
? { command: 'npx', args: ['-y', '@vrs-soft/wecom-aibot-mcp', '--channel'] }
|
|
1093
|
+
: { command: 'node', args: [path.join(__dirname, 'bin.js'), '--channel'] };
|
|
1089
1094
|
if (mode === 'channel-only') {
|
|
1090
1095
|
// Channel-only 模式:必须通过 MCP_URL 指定远程地址
|
|
1091
1096
|
const mcpUrl = process.env.MCP_URL;
|
|
@@ -1094,19 +1099,17 @@ export function ensureGlobalConfigs(mode = 'full', remoteOptions) {
|
|
|
1094
1099
|
console.log('[config] 请设置环境变量: MCP_URL=http://远程IP:18963');
|
|
1095
1100
|
return { upgraded: false, previousVersion };
|
|
1096
1101
|
}
|
|
1097
|
-
|
|
1098
|
-
const binPath = path.join(__dirname, 'bin.js');
|
|
1099
|
-
const channelEnv = { MCP_URL: mcpUrl };
|
|
1102
|
+
const channelEnv = { MCP_URL: mcpUrl.replace(/\/+$/, '') };
|
|
1100
1103
|
const authToken = getAuthToken();
|
|
1101
1104
|
if (authToken) {
|
|
1102
1105
|
channelEnv.MCP_AUTH_TOKEN = authToken;
|
|
1103
1106
|
}
|
|
1104
1107
|
claudeConfig.mcpServers['wecom-aibot-channel'] = {
|
|
1105
|
-
command:
|
|
1106
|
-
args:
|
|
1108
|
+
command: channelCmd.command,
|
|
1109
|
+
args: channelCmd.args,
|
|
1107
1110
|
env: channelEnv,
|
|
1108
1111
|
};
|
|
1109
|
-
console.log(`[config] Channel-only 模式:Channel MCP
|
|
1112
|
+
console.log(`[config] Channel-only 模式:Channel MCP 已配置`);
|
|
1110
1113
|
}
|
|
1111
1114
|
else {
|
|
1112
1115
|
// full 模式:同时写入 HTTP MCP 和 Channel MCP 配置
|
|
@@ -1114,12 +1117,23 @@ export function ensureGlobalConfigs(mode = 'full', remoteOptions) {
|
|
|
1114
1117
|
type: 'http',
|
|
1115
1118
|
url: 'http://127.0.0.1:18963/mcp',
|
|
1116
1119
|
};
|
|
1117
|
-
// Channel MCP
|
|
1118
|
-
const
|
|
1120
|
+
// Channel MCP 配置:保留已有的自定义 MCP_URL(如 channel-only 安装时写入的远程地址)
|
|
1121
|
+
const existingChannel = claudeConfig.mcpServers['wecom-aibot-channel'];
|
|
1122
|
+
const existingMcpUrl = existingChannel?.env?.MCP_URL;
|
|
1123
|
+
const isRemote = existingMcpUrl && !existingMcpUrl.startsWith('http://127.0.0.1');
|
|
1124
|
+
const channelMcpUrl = isRemote ? existingMcpUrl : 'http://127.0.0.1:18963';
|
|
1125
|
+
const channelEnvFull = { MCP_URL: channelMcpUrl };
|
|
1126
|
+
// 保留已有的 MCP_AUTH_TOKEN(远程安装时写入),或从 server.json 读取
|
|
1127
|
+
const existingToken = existingChannel?.env?.MCP_AUTH_TOKEN;
|
|
1128
|
+
if (isRemote) {
|
|
1129
|
+
const token = existingToken || getAuthToken();
|
|
1130
|
+
if (token)
|
|
1131
|
+
channelEnvFull.MCP_AUTH_TOKEN = token;
|
|
1132
|
+
}
|
|
1119
1133
|
claudeConfig.mcpServers['wecom-aibot-channel'] = {
|
|
1120
|
-
command:
|
|
1121
|
-
args:
|
|
1122
|
-
env:
|
|
1134
|
+
command: channelCmd.command,
|
|
1135
|
+
args: channelCmd.args,
|
|
1136
|
+
env: channelEnvFull,
|
|
1123
1137
|
};
|
|
1124
1138
|
console.log(`[config] full 模式:Channel MCP 使用本地路径`);
|
|
1125
1139
|
}
|