dingtalk-ask-mcp-server 0.1.5 → 0.1.6

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 CHANGED
@@ -66,11 +66,13 @@ dingtalk-ask install --client-id <AppKey> --client-secret <AppSecret> \
66
66
 
67
67
  | 宿主 | 改动的文件 | 写入内容 |
68
68
  |---|---|---|
69
- | **Claude Code** | `<当前目录>/.mcp.json` | `mcpServers.dingtalk-ask`(服务 + 凭证 env) |
70
- | | `<当前目录>/.claude/settings.json`(`--global` 则 `~/.claude/settings.json`) | `PermissionRequest` 钩子 + `env.MCP_TOOL_TIMEOUT` |
69
+ | **Claude Code**(项目级) | `<当前目录>/.mcp.json` | `mcpServers.dingtalk-ask`(服务 + 凭证 env) |
70
+ | | `<当前目录>/.claude/settings.json` | `PermissionRequest` 钩子 + `env.MCP_TOOL_TIMEOUT` |
71
+ | **Claude Code**(`--global`·所有项目) | `~/.claude.json`(先备份 `.bak`) | `mcpServers.dingtalk-ask` |
72
+ | | `~/.claude/settings.json` | 钩子 + `MCP_TOOL_TIMEOUT` |
71
73
  | **Codex** | `~/.codex/config.toml` | `[mcp_servers.dingtalk-ask]`(含 `tool_timeout_sec=1500` + 凭证,先备份 `.bak`) |
72
74
 
73
- 默认 **CC 必装,检测到 `~/.codex` 时 Codex 一并装**。装完**重启 Claude Code / 重开 Codex 会话**生效。
75
+ 默认 **CC 必装,检测到 `~/.codex` 时 Codex 一并装**。CC 默认写**项目级**(只对当前项目生效);加 **`--global`** 写**用户级**,免每个项目各装一次(合并保留你其它 MCP server)。装完**重启 Claude Code / 重开 Codex 会话**生效。
74
76
 
75
77
  ### 方式 B:手动接入(想自己控制时)
76
78
 
@@ -55,17 +55,22 @@ function writeJson(path, obj) {
55
55
  mkdirSync(dirname(path), { recursive: true });
56
56
  writeFileSync(path, `${JSON.stringify(obj, null, 2)}\n`, 'utf8');
57
57
  }
58
- /** 装 Claude Code:.mcp.json(MCP server)+ .claude/settings.json(钩子 + MCP_TOOL_TIMEOUT)。 */
58
+ /** 装 Claude Code:MCP server(项目 .mcp.json --global 用户级 ~/.claude.json)+ 钩子 + MCP_TOOL_TIMEOUT */
59
59
  function installClaudeCode(config, argv, nodePath, indexPath) {
60
60
  const cwd = process.cwd();
61
- // 1. .mcp.json
62
- const mcpPath = join(cwd, '.mcp.json');
61
+ const global = argv.includes('--global');
62
+ // 1. MCP server:--global 写 ~/.claude.json(用户级,所有项目可见),否则项目 .mcp.json
63
+ const mcpPath = global ? join(homedir(), '.claude.json') : join(cwd, '.mcp.json');
63
64
  const entry = buildMcpEntry(config, nodePath, indexPath);
64
- const { settings: mcpMerged, existed } = mergeMcpServers(readJson(mcpPath), MCP_SERVER_NAME, entry);
65
+ const before = readJson(mcpPath); // 解析失败会抛错中止,绝不覆盖(保护 ~/.claude.json)。
66
+ const { settings: mcpMerged, existed } = mergeMcpServers(before, MCP_SERVER_NAME, entry);
67
+ if (global && existsSync(mcpPath)) {
68
+ copyFileSync(mcpPath, `${mcpPath}.bak`);
69
+ }
65
70
  writeJson(mcpPath, mcpMerged);
66
- console.log(`✅ [CC] ${existed ? '更新' : '写入'} MCP server 到 ${mcpPath}`);
67
- // 2. .claude/settings.json:钩子 + MCP_TOOL_TIMEOUT(略大于 ask 超时)
68
- const settingsPath = resolveSettingsPath(argv.includes('--global') ? ['--global'] : [], cwd, homedir());
71
+ console.log(`✅ [CC] ${existed ? '更新' : '写入'} MCP server 到 ${mcpPath}${global ? '(用户级·所有项目可见,已备份 .bak)' : ''}`);
72
+ // 2. .claude/settings.json:钩子 + MCP_TOOL_TIMEOUT(略大于 ask 超时)。
73
+ const settingsPath = resolveSettingsPath(global ? ['--global'] : [], cwd, homedir());
69
74
  const command = `node "${permissionHookPath()}"`;
70
75
  const hookMerged = mergeHook(readJson(settingsPath), command);
71
76
  const tmMerged = ensureMcpToolTimeout(hookMerged.settings, config.timeoutMs + 60_000);
@@ -161,6 +166,8 @@ async function runInfo() {
161
166
  console.log('\n【配置 · Claude Code】');
162
167
  const mcp = inspectMcpJson(tolerantJson(join(cwd, '.mcp.json')));
163
168
  console.log(` .mcp.json (${cwd}):${mcp.configured ? `✅ 已配(command=${mcp.command ?? '?'}, userId=${mask(mcp.userId)})` : '❌ 未配'}`);
169
+ const userMcp = inspectMcpJson(tolerantJson(join(homedir(), '.claude.json')));
170
+ console.log(` 用户级 ~/.claude.json:${userMcp.configured ? `✅ 已配(所有项目可见,userId=${mask(userMcp.userId)})` : '❌ 未配'}`);
164
171
  const projSettings = inspectSettingsHook(tolerantJson(join(cwd, '.claude', 'settings.json')));
165
172
  // MCP_TOOL_TIMEOUT 可能在 settings.json 或 settings.local.json,两处都看。
166
173
  const localTimeout = inspectSettingsHook(tolerantJson(join(cwd, '.claude', 'settings.local.json'))).mcpToolTimeout;
@@ -288,16 +295,20 @@ function runUninstall(rest) {
288
295
  const doCc = host === undefined || host === 'cc' || host === 'both';
289
296
  const doCodex = host === 'codex' || host === 'both' || (host === undefined && existsSync(join(homedir(), '.codex')));
290
297
  if (doCc) {
291
- const mcpPath = join(cwd, '.mcp.json');
298
+ const global = rest.includes('--global');
299
+ const mcpPath = global ? join(homedir(), '.claude.json') : join(cwd, '.mcp.json');
292
300
  const mcp = removeMcpServer(tolerantJson(mcpPath), MCP_SERVER_NAME);
293
301
  if (mcp.removed) {
302
+ if (global && existsSync(mcpPath)) {
303
+ copyFileSync(mcpPath, `${mcpPath}.bak`);
304
+ }
294
305
  writeJson(mcpPath, mcp.settings);
295
- console.log(`· [CC] 从 ${mcpPath} 移除 MCP server`);
306
+ console.log(`· [CC] 从 ${mcpPath} 移除 MCP server${global ? '(已备份 .bak)' : ''}`);
296
307
  }
297
308
  else {
298
309
  console.log(`· [CC] ${mcpPath} 无 dingtalk-ask,跳过`);
299
310
  }
300
- const settingsPath = resolveSettingsPath(rest.includes('--global') ? ['--global'] : [], cwd, homedir());
311
+ const settingsPath = resolveSettingsPath(global ? ['--global'] : [], cwd, homedir());
301
312
  const hookRes = removeHook(tolerantJson(settingsPath));
302
313
  if (hookRes.removed) {
303
314
  writeJson(settingsPath, hookRes.settings);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dingtalk-ask-mcp-server",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "Human-in-the-loop MCP server:把 code agent(Claude Code / Codex)的决策与命令审批推送到钉钉,阻塞等你在手机回复。离开电脑也能远程拍板。",
5
5
  "keywords": [
6
6
  "mcp",