@vrs-soft/wecom-aibot-mcp 2.4.1 → 2.4.3

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 } 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, updateMcpAuthHeaders, runRemoteInstallWizard, VERSION, } from './config-wizard.js';
16
+ import { runConfigWizard, loadConfig, saveConfig, deleteRobotConfigInteractive, uninstall, addMcpConfig, detectUserIdFromMessage, ensureHookInstalled, listAllRobots, ensureGlobalConfigs, 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';
@@ -251,8 +251,10 @@ async function startMcpServerForeground(isDebug = false) {
251
251
  logger.log(' ║ Claude Code 审批通道 ║');
252
252
  logger.log(' ╚════════════════════════════════════════════════════════╝');
253
253
  logger.log('');
254
- logger.log(`[mcp] 启动 MCP HTTP Server (端口: ${HTTP_PORT})...`);
255
- await startHttpServer(server);
254
+ const httpsConfig = getHttpsConfig() ?? undefined;
255
+ const protocol = httpsConfig ? 'HTTPS' : 'HTTP';
256
+ logger.log(`[mcp] 启动 MCP ${protocol} Server (端口: ${HTTP_PORT})...`);
257
+ await startHttpServer(server, HTTP_PORT, httpsConfig);
256
258
  startKeepaliveMonitor();
257
259
  logger.log(`[mcp] MCP Server 已就绪`);
258
260
  logger.log(`[mcp] HTTP endpoint: http://127.0.0.1:${HTTP_PORT}/mcp`);
@@ -504,18 +506,44 @@ async function main() {
504
506
  console.log('[setup] 安装完成!请重启 Claude Code 以加载配置');
505
507
  }
506
508
  else if (wantServer) {
507
- // 服务器端
508
- console.log('\n[setup] Server 安装模式\n');
509
- const savedConfig = loadConfig();
510
- if (!savedConfig?.botId)
511
- await runConfigWizard();
509
+ // 服务器端:分两步——先完成 Server 安装,再配置机器人
510
+ console.log('\n[setup] ─── 步骤 1/2:Server 安装 ───\n');
511
+ console.log(' Server 负责运行 HTTP MCP 服务,Bot 配置在下一步单独完成\n');
512
512
  const readline = await import('readline');
513
513
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
514
- const token = await new Promise(resolve => rl.question('Auth Token(Client 端需填写相同 Token,留空跳过): ', a => { rl.close(); resolve(a.trim()); }));
514
+ const token = await new Promise(resolve => rl.question('Auth Token(Client 端连接时需填写相同 Token,留空跳过): ', a => { rl.close(); resolve(a.trim()); }));
515
515
  if (token)
516
516
  setAuthToken(token);
517
+ // HTTPS 证书配置
518
+ const defaultCertPath = path.join(os.homedir(), '.wecom-aibot-mcp', 'cert.pem');
519
+ const defaultKeyPath = path.join(os.homedir(), '.wecom-aibot-mcp', 'key.pem');
520
+ console.log('\n HTTPS 证书配置(留空跳过,保持 HTTP 模式)');
521
+ console.log(' 默认证书位置(将证书文件放到此路径即可):');
522
+ console.log(` 证书: ${defaultCertPath}`);
523
+ console.log(` 私钥: ${defaultKeyPath}`);
524
+ console.log(' 如使用 Let\'s Encrypt,路径通常为:');
525
+ console.log(' /etc/letsencrypt/live/<域名>/fullchain.pem');
526
+ console.log(' /etc/letsencrypt/live/<域名>/privkey.pem\n');
527
+ const rl2 = readline.createInterface({ input: process.stdin, output: process.stdout });
528
+ const certInput = await new Promise(resolve => rl2.question(`SSL 证书路径(直接回车使用默认): `, a => { rl2.close(); resolve(a.trim()); }));
529
+ const certPath = certInput || defaultCertPath;
530
+ if (fs.existsSync(certPath)) {
531
+ const rl3 = readline.createInterface({ input: process.stdin, output: process.stdout });
532
+ const keyInput = await new Promise(resolve => rl3.question(`SSL 私钥路径(直接回车使用默认): `, a => { rl3.close(); resolve(a.trim()); }));
533
+ const keyPath = keyInput || defaultKeyPath;
534
+ setHttpsConfig(certPath, keyPath);
535
+ console.log(`[setup] HTTPS 已配置: ${certPath}`);
536
+ }
537
+ else if (certInput) {
538
+ console.log(`[setup] ⚠️ 证书文件不存在: ${certPath},跳过 HTTPS 配置`);
539
+ }
540
+ else {
541
+ console.log(`[setup] 将证书放到默认位置后重新运行 --setup --server 即可启用 HTTPS`);
542
+ }
517
543
  console.log('\n[setup] Server 配置完成!');
518
544
  console.log(' 启动: npx @vrs-soft/wecom-aibot-mcp --http-only --start');
545
+ console.log('\n[setup] ─── 步骤 2/2:配置企业微信机器人 ───\n');
546
+ await addMcpConfig();
519
547
  }
520
548
  else if (wantChannel) {
521
549
  // Channel 客户端
@@ -10,6 +10,11 @@ export declare const VERSION: string;
10
10
  export declare function loadConfig(): WecomConfig | null;
11
11
  export declare function getAuthToken(): string | undefined;
12
12
  export declare function setAuthToken(token: string | undefined): boolean;
13
+ export declare function getHttpsConfig(): {
14
+ certPath: string;
15
+ keyPath: string;
16
+ } | null;
17
+ export declare function setHttpsConfig(certPath: string, keyPath: string): boolean;
13
18
  export declare function updateMcpAuthHeaders(token?: string): void;
14
19
  export declare function listAllMcpInstances(): Array<{
15
20
  name: string;
@@ -104,6 +104,38 @@ export function setAuthToken(token) {
104
104
  fs.writeFileSync(SERVER_CONFIG_FILE, JSON.stringify(config, null, 2));
105
105
  return true;
106
106
  }
107
+ // 获取 HTTPS 证书配置(从 server.json 读取)
108
+ export function getHttpsConfig() {
109
+ if (!fs.existsSync(SERVER_CONFIG_FILE))
110
+ return null;
111
+ try {
112
+ const config = JSON.parse(fs.readFileSync(SERVER_CONFIG_FILE, 'utf-8'));
113
+ if (config.certPath && config.keyPath) {
114
+ return { certPath: config.certPath, keyPath: config.keyPath };
115
+ }
116
+ return null;
117
+ }
118
+ catch {
119
+ return null;
120
+ }
121
+ }
122
+ // 设置 HTTPS 证书配置(写入 server.json)
123
+ export function setHttpsConfig(certPath, keyPath) {
124
+ ensureConfigDir();
125
+ let config = {};
126
+ if (fs.existsSync(SERVER_CONFIG_FILE)) {
127
+ try {
128
+ config = JSON.parse(fs.readFileSync(SERVER_CONFIG_FILE, 'utf-8'));
129
+ }
130
+ catch {
131
+ // ignore
132
+ }
133
+ }
134
+ config.certPath = certPath;
135
+ config.keyPath = keyPath;
136
+ fs.writeFileSync(SERVER_CONFIG_FILE, JSON.stringify(config, null, 2));
137
+ return true;
138
+ }
107
139
  // 更新 ~/.claude.json 中 wecom-aibot MCP 配置的 auth headers
108
140
  export function updateMcpAuthHeaders(token) {
109
141
  if (!fs.existsSync(CLAUDE_CONFIG_FILE))
@@ -62,7 +62,10 @@ export declare function getCCRegistryEntry(ccId: string): CCRegistryEntry | null
62
62
  export declare function getCCCount(): number;
63
63
  export declare function getCCCountByRobot(robotName: string): number;
64
64
  export declare function getOnlineCcIds(): string[];
65
- export declare function startHttpServer(_server: McpServer, port?: number): Promise<void>;
65
+ export declare function startHttpServer(_server: McpServer, port?: number, httpsConfig?: {
66
+ certPath: string;
67
+ keyPath: string;
68
+ }): Promise<void>;
66
69
  export declare function stopHttpServer(): void;
67
70
  export declare function cleanupPortFile(): void;
68
71
  export {};
@@ -13,6 +13,7 @@
13
13
  * - Session → robotName → WebSocket Connection
14
14
  */
15
15
  import * as http from 'http';
16
+ import * as https from 'https';
16
17
  import * as path from 'path';
17
18
  import * as os from 'os';
18
19
  import * as fs from 'fs';
@@ -461,12 +462,12 @@ ${onlineList.map(id => `• 【${id}】`).join('\n')}
461
462
  示例:引用【${onlineList[0]}】的消息后回复`;
462
463
  await client.sendText(reply);
463
464
  }
464
- export async function startHttpServer(_server, port = HTTP_PORT) {
465
+ export async function startHttpServer(_server, port = HTTP_PORT, httpsConfig) {
465
466
  startTime = Date.now();
466
467
  // 初始化 MCP Server
467
468
  initMcpServer();
468
469
  return new Promise((resolve, reject) => {
469
- httpServer = http.createServer(async (req, res) => {
470
+ const requestHandler = async (req, res) => {
470
471
  res.setHeader('Access-Control-Allow-Origin', '*');
471
472
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS');
472
473
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, Mcp-Session-Id');
@@ -758,7 +759,16 @@ export async function startHttpServer(_server, port = HTTP_PORT) {
758
759
  }
759
760
  res.writeHead(404, { 'Content-Type': 'application/json' });
760
761
  res.end(JSON.stringify({ error: 'Not Found' }));
761
- });
762
+ };
763
+ // 根据是否有 HTTPS 配置创建对应的 server
764
+ if (httpsConfig) {
765
+ const cert = fs.readFileSync(httpsConfig.certPath, 'utf-8');
766
+ const key = fs.readFileSync(httpsConfig.keyPath, 'utf-8');
767
+ httpServer = https.createServer({ cert, key }, requestHandler);
768
+ }
769
+ else {
770
+ httpServer = http.createServer(requestHandler);
771
+ }
762
772
  httpServer.on('error', (err) => {
763
773
  if (err.code === 'EADDRINUSE') {
764
774
  reject(new Error(`端口 ${port} 已被占用`));
@@ -767,9 +777,12 @@ export async function startHttpServer(_server, port = HTTP_PORT) {
767
777
  reject(err);
768
778
  }
769
779
  });
770
- httpServer.listen(port, '127.0.0.1', async () => {
771
- logger.log(`[http] MCP Server 已启动: http://127.0.0.1:${port}`);
772
- logger.log(`[http] MCP endpoint: http://127.0.0.1:${port}/mcp (stateless mode)`);
780
+ // HTTPS 模式绑定所有网卡(供远程客户端访问),HTTP 模式只绑本地
781
+ const host = httpsConfig ? '0.0.0.0' : '127.0.0.1';
782
+ const protocol = httpsConfig ? 'https' : 'http';
783
+ httpServer.listen(port, host, async () => {
784
+ logger.log(`[http] MCP Server 已启动: ${protocol}://${host}:${port}`);
785
+ logger.log(`[http] MCP endpoint: ${protocol}://${host}:${port}/mcp (stateless mode)`);
773
786
  // 自动连接所有配置的机器人
774
787
  await connectAllRobots();
775
788
  resolve();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vrs-soft/wecom-aibot-mcp",
3
- "version": "2.4.1",
3
+ "version": "2.4.3",
4
4
  "description": "企业微信智能机器人 MCP 服务 - Claude Code 审批通道",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",