@vrs-soft/wecom-aibot-mcp 2.4.23 → 2.4.24

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.
@@ -12,9 +12,50 @@
12
12
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
13
13
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
14
14
  import { z } from 'zod';
15
+ import { execSync } from 'child_process';
15
16
  import { VERSION, installSkill } from './config-wizard.js';
16
17
  import { addPermissionHook, registerActiveProject, unregisterActiveProject, updateWechatModeConfig } from './project-config.js';
17
18
  import { logger } from './logger.js';
19
+ /**
20
+ * 沿进程树向上查找 Claude Code TUI 的 PID。
21
+ *
22
+ * 背景:本地 dev (`command: "node"`) 时 channel-server 是 Claude TUI 的直接子进程,
23
+ * process.ppid = Claude TUI ✓
24
+ * 但 npx 部署 (`command: "npx"`) 时多了一层 npx:
25
+ * Claude TUI → npx → node bin.js (channel-server)
26
+ * process.ppid = npx ❌
27
+ * permission-hook.sh 从 hook 自身向上查 active-projects.json 时只能命中 Claude TUI
28
+ * 这条祖先链。如果注册的是 npx 的 PID,hook 永远找不到 → 静默 exit 0 → 跳过审批。
29
+ *
30
+ * 此函数从 startPid 起向上遍历,找到第一个命令名为 "claude" 的进程,返回其 PID。
31
+ * 找不到时回退到 startPid(保持旧行为,至少 dev 场景不退化)。
32
+ */
33
+ function findClaudePid(startPid) {
34
+ let pid = startPid;
35
+ for (let i = 0; i < 8; i++) {
36
+ if (!pid || pid <= 1)
37
+ break;
38
+ try {
39
+ const comm = execSync(`ps -p ${pid} -o comm=`, { stdio: ['ignore', 'pipe', 'ignore'] })
40
+ .toString()
41
+ .trim();
42
+ // ps comm= 返回执行文件 basename。Claude Code TUI 安装名就是 "claude"
43
+ if (comm === 'claude' || comm.endsWith('/claude'))
44
+ return pid;
45
+ const ppidStr = execSync(`ps -p ${pid} -o ppid=`, { stdio: ['ignore', 'pipe', 'ignore'] })
46
+ .toString()
47
+ .trim();
48
+ const ppid = parseInt(ppidStr, 10);
49
+ if (!ppid || ppid === pid)
50
+ break;
51
+ pid = ppid;
52
+ }
53
+ catch {
54
+ break;
55
+ }
56
+ }
57
+ return startPid;
58
+ }
18
59
  const MCP_URL = process.env.MCP_URL || 'http://127.0.0.1:18963';
19
60
  const MCP_AUTH_TOKEN = process.env.MCP_AUTH_TOKEN;
20
61
  // 构建带 auth 的 fetch headers
@@ -437,9 +478,16 @@ function registerChannelTools(server) {
437
478
  const localProjectDir = project_dir || process.cwd();
438
479
  const hookResult = addPermissionHook(localProjectDir);
439
480
  logger.info('本地 PermissionRequest hook 已写入', { path: hookResult.path, success: hookResult.success });
440
- // 注册本地 PID projectDir(供本地 permission-hook.sh 通过进程树匹配项目)
441
- registerActiveProject(process.ppid ?? process.pid, localProjectDir);
442
- logger.info('本地 active-projects 已注册', { pid: process.ppid ?? process.pid, projectDir: localProjectDir });
481
+ // 注册 Claude TUI PID(不能用 process.ppid,npx 部署时 ppid 是 npx 不是 Claude)
482
+ const startPid = process.ppid ?? process.pid;
483
+ const claudePid = findClaudePid(startPid);
484
+ registerActiveProject(claudePid, localProjectDir);
485
+ logger.info('本地 active-projects 已注册', {
486
+ pid: claudePid,
487
+ rawPpid: startPid,
488
+ resolvedClaudePid: claudePid !== startPid,
489
+ projectDir: localProjectDir,
490
+ });
443
491
  // 写入本地 wecom-aibot.json(远程 HTTP MCP 写在远端 fs,agent 本地需要自己落地)
444
492
  updateWechatModeConfig(localProjectDir, {
445
493
  wechatMode: true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vrs-soft/wecom-aibot-mcp",
3
- "version": "2.4.23",
3
+ "version": "2.4.24",
4
4
  "description": "企业微信智能机器人 MCP 服务 - Claude Code 审批通道",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",