Skip to content

feat(mcp): 支持 pnpm 作为包管理器并适配裸 Node 安装环境 - #6381

Open
domye wants to merge 10 commits into
t8y2:mainfrom
domye:feat/pnpm-support
Open

feat(mcp): 支持 pnpm 作为包管理器并适配裸 Node 安装环境#6381
domye wants to merge 10 commits into
t8y2:mainfrom
domye:feat/pnpm-support

Conversation

@domye

@domye domye commented Aug 16, 2026

Copy link
Copy Markdown
Contributor
  • 修复 find_npm_cli 仅查找 node 同目录 npm-cli.js 的问题:裸 Node(pnpm 管理 / 版本管理器安装,node 旁无 npm)时,回退到 PATH 上解析 npm 并取其真实 npm-cli.js
  • 新增 pnpm_shim_target 解析 pnpm 启动器 shim 内嵌的真实脚本路径(pnpm 的 .CMD shim 不带 cmd-shim-target 标记,与 npm 不同)
  • 包探测新增 pnpm 全局 bin 目录:locate_command("pnpm") 所在目录,识别 pnpm 安装的 @dbx-app/mcp-server 全局包
  • 安装命令跟随包管理器:检测到 pnpm 时显示 pnpm add -g @dbx-app/mcp-server,未装包时 install_or_update 也走 pnpm add 而非 npm install
  • 新增 Rust 单测 pnpm_shim_resolves_inline_script_path

变更说明

DBX 的 MCP 服务器状态检测此前依赖 node 与 npm 相邻安装、包位于 npm 全局根目录。当用户使用 pnpm 管理(常见于裸 Node + pnpm 全局包、版本管理器)时:

  • node 是裸安装(无 npm-cli.js),旧 find_npm_cli 直接失败 → 整个探测返回空 → MCP 配置页 Node.js/npm 版本、当前版本全部不显示;
  • dbx-mcp-server 由 pnpm add -g 装入 pnpm 全局 bin(非 npm 全局根),旧逻辑检测不到 → 显示"未检测到全局安装";
  • 安装命令写死 npm,与 pnpm 用户的实际操作不符。

本 PR 三处根因修复:

  1. find_npm_cli 增加 PATH 兜底,解析 where npm / which npm 所在目录下的 node_modules/npm/bin/npm-cli.js;
  2. pnpm_shim_target 解析 pnpm shim 内联脚本路径,配合 mcp_package_from_script 还原包根与版
    本;
  3. probe 增加 pnpm 全局 bin 目录候选,且 pnpm 在 PATH 时安装/更新/卸载命令跟随 pnpm(pnpm add / pnpm update / pnpm remove)。

变更类型

  • Bug 修复
  • 新功能
  • 性能优化
  • 代码重构
  • 文档更新
  • CI / 构建

涉及前端

  • 本 PR 不涉及前端改动(仅 Rust 后端 src-tauri/src/commands/mcp.rs)

验证

  • pnpm shim 解析路径实测:对真实环境 D:\Environment\pnpm\bin\dbx-mcp-server.CMD 解析出的 node_modules@dbx-app\mcp-server\bin\dbx-mcp-server.js 存在,包版本 0.4.62
  • 新增单测 pnpm_shim_resolves_inline_script_path

domye added 2 commits August 16, 2026 14:44
- 新增 `pnpm_shim_target` 函数解析 pnpm 启动器内联脚本路径
- 在定位 MCP 包时增加 pnpm bin 目录作为备选路径
- 在查找 npm cli 时回退至 PATH 环境变量以支持无 npm 伴生的 Node 安装
- 添加针对 pnpm shim 解析的单元测试
- 新增 pnpm 安装命令常量
- 在未检测到 npm 包时优先使用 pnpm
- 实现 install_command 方法以支持 pnpm
- 更新 update_command 逻辑以处理 pnpm 安装场景
- 修正状态检查中的 install_command 引用
@github-actions github-actions Bot added area/desktop Desktop application or Tauri shell enhancement New feature or request labels Aug 16, 2026
- 增加 locate_command("dbx-mcp-server") 逻辑以检测 PATH 中的 shim
- 将 path_shim_package 合并到 preferred_mcp_package 的参数中
- 支持 Yarn、Bun 及手动配置目录的包管理器检测
@domye

domye commented Aug 16, 2026

Copy link
Copy Markdown
Contributor Author

直接 locate_command("dbx-mcp-server") 找 PATH 上的 shim,解析其包——这样任何把 shim 放 PATH 的安装(yarn/bun/手动)都能显示当前版本

@t8y2 t8y2 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这版还有两个兼容性缺口需要处理:

  1. NodeRuntime::probe 仍然通过 find_npm_cli(...)? 强制要求 npm CLI,随后立即执行 npm root -g。如果环境确实只有 Node + pnpm、PATH 中没有 npm,探测会在 pnpm 包发现逻辑运行前直接返回失败,因此目前还没有完整支持标题所述的裸 Node 安装环境。请补充完全没有 npm 的回归场景,并让 npm 元数据在 pnpm-only 路径中不再成为前置条件。

  2. PATH shim 的注释和描述宣称支持 Yarn、Bun 与手动安装,但 mcp_package_from_command_dir 在附近找不到 pnpm 时会把这些安装统一标记为 Npm。这样界面中的更新和卸载操作会对非 npm 安装执行 npm 命令。需要准确识别包管理器,或者将无法确认来源的包设为只读探测并禁用对应管理操作,避免误操作其他包管理器的全局安装。

domye added 4 commits August 16, 2026 18:02
- 新增 managed_automatically 字段到 McpServerStatus 接口
- 新增 Unknown 包管理器类型,用于处理无法确认来源的安装(如 Yarn、Bun 或手动复制)
- 将 npm_cli_path 和 npm_root 改为 Option 类型,支持 pnpm-only 或裸 Node 环境
- 安装/卸载按钮在检测到非自动管理模式时禁用,并显示手动管理提示
- 更新错误信息文案,区分 npm 不可用与未知管理器的情况
- 补充单元测试验证未知包管理器的只读行为及 pnpm 识别逻辑
- 在 `McpServerStatus` 中新增 `runtime_available` 字段,指示是否存在兼容的 Node.js 运行时(npm、pnpm 或裸环境)
- 独立检测 `npm_available` 字段,以便在仅有 pnpm 或无 npm CLI 的环境中正确反映状态
- 更新前端 UI 及逻辑,将安装按钮的禁用条件从 `npm_available` 修改为 `runtime_available`
- 使用 `translateBackendError` 统一处理后端错误信息
- 新增针对未知包管理器和 npm CLI 缺失的国际化错误提示
- 添加 `pnpm_global_dir` 函数查询 pnpm 实际管理的全局目录
- 新增 `pnpm_package_manageable` 检查,确保只在 pnpm 可管理的目录下自动操作
- 将 pnpm home 目录优先加入 PATH,避免 pnpm 因全局 bin 目录不在 PATH 而拒绝运行
- 防止对旧版 `pnpm-global` 布局的包执行错误的更新/删除操作
- 在检测位置时增加对 pnpm home 目录的探测,以兼容全局 shims
- 安装/更新逻辑统一使用 `pnpm add -g`,以修复旧版布局下的更新问题
- 优化包管理器识别逻辑,通过路径特征区分 pnpm 与其他管理器
- 优化错误信息,根据不同包管理器显示具体的全局安装路径
- 移除不可靠的 `pnpm_package_manageable` 检查,改用路径字符串匹配
- 更新单元测试以覆盖 pnpm store-links 和 legacy 布局
@github-actions github-actions Bot added the ui-change Changes user-visible interface, text, or visual assets label Aug 16, 2026
- 将 `#[test]` 属性移动到函数定义上方
- 移除重复的 `#[test]` 声明
- 确保 `pnpm_shim_resolves_inline_script_path` 测试正确注册
@domye

domye commented Aug 16, 2026

Copy link
Copy Markdown
Contributor Author

1. 区分"运行时可用"与"npm CLI 可用"

  • 新增 McpServerStatus.runtime_available(解析到兼容 Node 运行时 = npm/pnpm/裸 node 任一);npm_available 语义改为
    "npm CLI 实际存在",pnpm-only 环境不再误报。
  • 前端安装/更新/卸载按钮改用 runtime_available 门控(pnpm 装/卸可用);"npm" 状态卡显示真实的 npm 存在性。

2. pnpm 更新/安装改用 pnpm add -g(根因修复)

  • pnpm update -g 只操作当前 pnpm 的 global-dir;在遗留/不匹配布局(如旧 pnpm-global 目录)下会"静默装回原版"。改为
    pnpm add -g:总是把最新版装进 pnpm 真实 global-dir 并修复布局,更新与首次安装统一走它。

3. 探测 pnpm 全局 bin 目录(修复"装完找不到包")

  • pnpm 把全局 shim 写到 global-bin-dir(常是 pnpm home 本身,而非存放 pnpm.CMD 的 bin 子目录)。probe 新增
    pnpm_home_package,两个位置都查,pnpm add -g 后能定位到包。

4. pnpm shim 识别(pnpm_located_shim)

  • pnpm 的 store-links / pnpm-global 布局目录里没有 pnpm.CMD 紧邻,旧逻辑会误判 Unknown。现在 shim 路径含
    pnpm-store/pnpm-global 标记时,回退用 PATH 上的 pnpm 归类为 Pnpm;Yarn/Bun/手动 shim 仍判 Unknown(只读,避免误跑
    npm/pnpm 命令)。

5. run_package_manager_command PATH 修复

  • 把 pnpm 全局 bin 目录(home)前置进 PATH,消除 pnpm 的 "global bin directory is not in PATH" 拒绝。

6. 安装后校验信息修复

  • pnpm 装完后校验不再拿 npm 的 global root 报错;按实际包管理器(npm root / pnpm global / 未知)给出准确落点信息。

7. 后端错误本地化

  • 安装/卸载错误改走 translateBackendError,新增 mcpUnknownPackageManager、mcpNpmCliUnavailable 映射(en/zh)。

@domye

domye commented Aug 16, 2026

Copy link
Copy Markdown
Contributor Author
PixPin_2026-08-16_19-24-59 已通过本机测试

domye added 2 commits August 16, 2026 19:35
- 调整 `npm_root` 和 `npm_cli_path` 的断言以匹配 `Option` 类型
- 确保测试用例正确处理可能为空的返回值
- 根据平台动态生成 shim 文件名和内容,分别处理 Windows 和 Unix 环境
- 调整 pnpm 命令日志断言,从 `update` 改为 `add` 以匹配实际行为
- 统一路径分隔符处理,确保跨平台测试兼容性

@t8y2 t8y2 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个 head 仍有几项需要修改:

  1. 当前根据 pnpm 可执行文件的位置推断并覆盖 PNPM_HOME。例如 /usr/local/bin/pnpm 会得到 PNPM_HOME=/usr/local,可能导致普通用户无写权限,或者把全局包装到与用户现有 pnpm 配置不同的目录。这里应读取 pnpm 的真实全局目录或保留用户环境,而不是从启动器路径推断。

  2. 目前仍将“shim 同目录或父目录存在 pnpm”视为该 shim 属于 pnpm。Yarn、Bun 或手工 shim 与 pnpm 共用 /usr/local/bin 等 PATH 目录时,更新和卸载仍可能错误调用 pnpm。需要从 shim 的真实目标或安装布局确认所有权;无法确认来源时应只读展示并禁用管理操作。

  3. 设置页显示的升级命令仍是 pnpm update -g,实际按钮执行的是 pnpm add -g,用户看到的命令与真实行为不一致。

  4. 现有测试仍没有真正覆盖“Node + pnpm,PATH 完全没有 npm”时通过 NodeRuntime::probe 的完整路径;当前 exact-head Rust 测试仍有 1 项失败,frontend typecheck 和 i18n Autofill 也未通过。

请先统一 pnpm 全局目录和 shim 所有权语义,补充真实无 npm 的 probe 回归测试,并修复 exact-head CI 后再请求复审。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/desktop Desktop application or Tauri shell enhancement New feature or request ui-change Changes user-visible interface, text, or visual assets

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants