feat: prefer remote MCP OAuth installation

This commit is contained in:
2026-08-18 18:24:47 +00:00
parent 55e43e3451
commit 0d5e192e95
20 changed files with 449 additions and 392 deletions
+11 -15
View File
@@ -3,24 +3,20 @@
## 数据路径
```text
用户 ─ Messenger ─ Agent ─ stdio 轻量桥 ─ HTTPS/OAuth ─ 统一审批网关
├─ 钉钉 OA
└─ 薪福通
用户 ─ Messenger ─ Agent ─ 远程 Streamable HTTP MCP/OAuth ─ 统一审批网关
├─ 钉钉 OA
└─ 薪福通
```
本地桥只完成 MCP stdio 与远程 Streamable HTTP 的转换,保存用户自己的短期 access/refresh token,不包含企业密钥、不读取审批上游,也不监听端口。
支持远程 MCP 和标准 OAuth 的宿主直接连接网关,不安装客户端运行时。只有宿主缺少远程传输或 OAuth 能力时,才使用本地 Bridge 把 stdio 转换为远程 Streamable HTTP;Bridge 只保存用户自己的短期 access/refresh token,不包含企业密钥、不读取审批上游,也不监听端口。
## 客户端安装边界
终端不再使用全局 npm prefix。无第三方依赖的首次安装器通过自有 HTTPS 到达用户机器,随后使用固定 Ed25519 公钥验证 schema v3 清单签名,并校验每个 artifact 的 SHA-256。客户端运行依赖被内置在签名 artifact 中,终端使用 npm 离线模式展开,不在安装时引入清单以外的代码。首次安装以 HTTPS 和安装说明中固定的安装器/公钥哈希建立信任;本地固定公钥保护后续更新链路。发布私钥不进入 Git、网关进程或公开目录。
默认安装仅在宿主中登记远程 HTTPS MCP URL。OAuth 客户端注册、PKCE、Token 保存和刷新均由宿主的标准 MCP 实现负责,终端不需要 Node/npm、Bridge 或项目安装器。网关的 MCP `instructions` 与工具描述提供业务工作流,终端修改本地提示不能绕过服务器的身份和写前校验。
运行时位于稳定的用户数据目录,启动器与 Node/NVM 具体版本解耦。Windows、Linux、macOS 的平台引导会复用兼容系统 Node;系统没有 Node 时,从固定精确版本的国内镜像下载并用 Node 官方 SHA-256 校验 x64/ARM64 制品,再放入插件自己的用户目录。项目发布物把国内 Gitea Release 作为首选静态源,并在签名清单中固定自建 HTTPS 备用源,首次安装与更新可在网络失败时自动回退;下载源不构成信任根,签名或哈希不符时立即终止。安装和更新优先调用系统 `curl`,因此直接复用宿主已验证的代理配置;Node `fetch` 只在没有 `curl` 时兜底。安装不修改 PATH,也不需要管理员权限。启动器固定使用安装时选定的 Node,更新和卸载沿用同一运行时;离线 npm 子进程不会继承 Node 专用代理开关。
兼容发行物只为不支持远程 MCP/OAuth 的宿主保留。它不使用全局 npm prefix:首次安装器以固定 Ed25519 公钥验证 schema v3 清单和 artifact SHA-256,并把内置依赖展开到稳定的用户目录。Windows/Linux/macOS 引导可复用系统 Node 或安装经官方哈希校验的固定私有 Node,不改 PATH、不要求管理员权限。发布物优先使用国内 Gitea 和 Node 固定版本源,自建 HTTPS/官方源作为受同一签名或哈希保护的备用。
安装器只有一条通用路径,输出稳定 `bridgePath`、通用 `skillPath`、标准 `mcpConfig`、`nodeRuntime` 和机器可读 `postInstall`,不识别 Agent 品牌,也不写任何 Agent 的私有配置。stdout 只承载最终 JSON,stderr 输出可安全展示的阶段进度;默认写入使用同步文件描述符,减少宿主结束进程时诊断文本尚未刷新。离线 npm 展开有 180 秒硬超时和明确错误,三个独立发布物并行下载。跨进程目录锁阻止两个 Agent 同时安装;锁记录 PID,外部终止后下一次安装可回收死亡锁及 `.staging-*` 残留。
`postInstall` 通过已安装的 Bridge 和正式网关主动检查登录;它只返回认证状态、短期授权链接与下一步工具提示,不返回 Token 或 device secret。网关不可用只会把状态标为 `unavailable`,不会回滚已验证的客户端安装。
连接器信任和重启属于 Agent 自身的安全边界,安装器不会绕过。卸载默认删除运行时、Skill、安装记录和 OAuth 会话;Agent 拥有的连接器条目由其官方入口移除。旧 npm 入口只在名称和目标包都精确匹配时清理。
兼容 Windows 引导以 UTF-8 BOM 发布,确保 Windows PowerShell 5.1 正确解析中文;传给 `node -e` 的脚本使用 PowerShell 不会吞掉的引号组合。下载优先调用 `curl.exe` 复用代理,并设置 10 秒连接、20 秒低速和 90 秒总时限;`Invoke-WebRequest` 只在没有 curl 时兜底。安装器仍输出稳定 `bridgePath`、`skillPath`、`mcpConfig` 和 `postInstall`,保留原子安装、跨进程锁、明确诊断、更新与卸载能力。
## Agent 领域接口
@@ -44,16 +40,16 @@ Agent 面向统一审批语义,不直接理解钉钉 `processInstanceId/taskId
## 一次登录
安装器在安装完成后立即调用 Bridge 的登录准备模式,不等待首次业务请求。未登录时,`postInstall.authChallenge.directUrl` 直接携带一个钉钉授权链接;用户授权后,Agent 调用 `approval_login` 确认状态。安装结果同时返回轻量 `loginCommand`:连接器尚未加载且链接过期时,它直接复用已安装 Bridge 和本地会话生成新链接,不下载发布物、不改 Agent 配置;连接器已加载时则再次调用 `approval_login`。授权成功后,网关从钉钉身份得到当前企业 `userId`:
远程模式由宿主按 MCP 标准读取网关的 Protected Resource / Authorization Server Metadata,通过动态客户端注册、授权码 + PKCE 和 Token 刷新完成登录。宿主负责呈现授权入口;用户本人完成 consent 和钉钉登录后,网关从已验证 Token 得到当前企业 `userId`:
- 钉钉 OA 直接按该 `userId` 查询本人审批任务;
- 薪福通先把该 `userId` 映射为企业成员,再从本人企业成员档案读取花名册员工号。
两条数据路径共用同一个网关 Token,因此不会出现本地 DWS 与网关分别登录的情况。
Bridge 的受保护会话中只记录 `pending/delivered` 一次性 onboarding 状态,不保存任何审批正文。登录挑战不会消费该状态;首次认证成功响应,或 Agent 跳过登录工具后的首个成功业务响应,会在普通 `content.text` 和 `structuredContent.onboarding` 中同时返回简短用法示例并标记已展示。错误响应、登录过期和后续升级都不会重复展示或自动执行示例。
首次认证后的首个成功业务响应会在普通 `content.text` 和 `structuredContent.onboarding` 中同时返回简短用法示例;错误响应不会自动执行示例。兼容 Bridge 另外在本地受保护会话中记录 `pending/delivered` 状态,避免重复展示,但不保存审批正文。
远程 `https://approval.justconn.top/mcp` 已按 MCP 授权规范提供 HTTP 401 challenge、OAuth Protected Resource Metadata、Authorization Server Metadata、动态客户端注册、PKCE、Token 刷新和撤销;原生支持远程 MCP OAuth 的宿主可以直接接管浏览器授权。面向只支持 stdio 或不能承接 OAuth 回调的宿主,轻量桥使用 device-code 兼容流程。由于部分宿主(例如只展示 `content.text` 的客户端)会丢弃 `structuredContent`,桥会同时在普通文本、标准 `resource_link` 和 `authChallenge.directUrl` 中返回同一个短期登录链接。桥不会调用不存在的消息通道自动推送链接;Agent 必须把 URL 原样写入当前回复,不得只声称已生成或已推送,也不得读取本地会话文件提取它。
远程 `https://approval.justconn.top/mcp` 已按 MCP 授权规范提供 HTTP 401 challenge、OAuth Protected Resource Metadata、Authorization Server Metadata、动态客户端注册、PKCE、Token 刷新和撤销。面向只支持 stdio 或不能承接 OAuth 回调的宿主,轻量桥使用 device-code 兼容流程;桥会在普通文本、标准 `resource_link` 和 `authChallenge.directUrl` 中返回同一个短期登录链接,不会调用不存在的消息通道自动推送。
开放动态客户端注册不等于静默授权。授权码和设备码流程都会先进入网关 consent 页,展示客户端自报名称、回调 origin、权限范围和设备授权码;只有用户显式确认后才生成钉钉登录跳转,回调也会再次检查 consent 状态。OAuth 客户端总量限制为 10,000,180 天未使用且没有活跃授权工件的客户端会被清理;过期登录请求、授权码和 Token 每小时清理。钉钉用户 token 刷新按用户 single-flight,避免并发消费同一个 refresh token;撤销 refresh token 会级联撤销同客户端、同用户的授权。
@@ -86,7 +82,7 @@ Bridge 的受保护会话中只记录 `pending/delivered` 一次性 onboarding
撤回接口若返回 `XFTSYS*` 服务异常或网络级异常,网关会立即只读复核本人单据状态:已撤回则返回 `revoked`,仍为待审批则返回带 `postWriteVerified` 的 `failed`,无法明确归类才返回 `outcome_uncertain`。任何分支都不会自动重试写操作。
截至 `1.1.0-rc.9`,薪福通撤回仍是实验能力:当前企业真实调用 `approve/recall` 会返回 `XFTSYS9999`,写后复核确认单据仍为待审批,尚无成功样本。该限制不影响薪福通查询、审批处理或发起审批;正式版不得把“接口已接通”表述为“撤回已验证成功”。
截至 `1.1.0-rc.13`,薪福通撤回仍是实验能力:当前企业真实调用 `approve/recall` 会返回 `XFTSYS9999`,写后复核确认单据仍为待审批,尚无成功样本。该限制不影响薪福通查询、审批处理或发起审批;正式版不得把“接口已接通”表述为“撤回已验证成功”。
薪福通创建或撤回需要复核时,`approval_get_submission_status` 先用服务器派生的本人员工号和单据详情双重确认目标属于当前用户的已发起单据,再返回状态名称和精简流程历史。只有实时状态仍为 `1(待审批)` 才签发新的短期、用户绑定 `revokeId`;已通过、草稿、拒绝或已撤回单据都不会获得撤回引用。该工具不返回审批正文,也不触发写操作。
+7 -20
View File
@@ -37,7 +37,7 @@ https://approval.justconn.top/oauth/dingtalk/callback
创建接口必须保持权限校验开启。网关统一提交 `APPRV_PEND`,并在写后实时读取本人单据状态:进入待审批时提供撤回引用;按企业流程规则即时通过时返回 `completed`,不提供撤回引用且禁止重复提交。
`1.1.0-rc.9` 中薪福通撤回仍标记为实验能力:权限和调用契约已接通,但当前企业真实请求返回 `XFTSYS9999`,尚未取得成功样本。网关会写后复核并禁止自动重试。面向试用用户时必须保留这一说明;若业务要求撤回必须稳定可用,应等待薪福通定位后再升级为正式能力。
`1.1.0-rc.13` 中薪福通撤回仍标记为实验能力:权限和调用契约已接通,但当前企业真实请求返回 `XFTSYS9999`,尚未取得成功样本。网关会写后复核并禁止自动重试。面向试用用户时必须保留这一说明;若业务要求撤回必须稳定可用,应等待薪福通定位后再升级为正式能力。
## 首次凭证配置
@@ -80,7 +80,7 @@ cd /path/to/dingMCP
脚本自动测试、构建、用 Ed25519 私钥签署 schema v3 清单、重启服务、原子发布静态文件、安装 Nginx 配置并验证公网健康检查、OAuth 元数据和安装链接。首次签证书时,临时 HTTP 配置只开放 ACME challenge,其余请求返回 403;不会在明文 HTTP 上代理 OAuth、Token 或 MCP。证书通过 Certbot webroot 模式签发,正式配置启用 HTTPS 跳转与不带 `includeSubDomains` 的 HSTS。已有证书会自动复用;签名私钥缺失、权限不是 `0600` 或与固定公钥不匹配时发行会失败。
发行物先复制到独立 staging 目录,再通过符号链接原子切换;客户端不会看到新清单配旧 artifact 的中间状态。服务器保留当前版本和最近两个旧版本用于排障,较老版本自动清理。`install.md`、清单、签名、安装器、Skill、校验文件和测试包均以 `no-cache` 提供;内容寻址的客户端 tgz 才使用 immutable 缓存。签名清单的 `createdAt` 超过 180 天时客户端拒绝安装,避免旧签名版本冻结攻击。
发行物先复制到独立 staging 目录,再通过符号链接原子切换;客户端不会看到新清单配旧 artifact 的中间状态。服务器保留当前版本和最近两个旧版本用于排障,较老版本自动清理。`install.md`、`compat-install.md`、清单、签名、安装器、Skill、校验文件和测试包均以 `no-cache` 提供;内容寻址的客户端 tgz 才使用 immutable 缓存。签名清单的 `createdAt` 超过 180 天时兼容客户端拒绝安装,避免旧签名版本冻结攻击。
卸载:
@@ -97,6 +97,7 @@ cd /path/to/dingMCP
```text
release/
├── install.md
├── compat-install.md
├── manifest.json
├── manifest.sig
├── SHA256SUMS
@@ -116,27 +117,13 @@ release/
https://approval.justconn.top/downloads/dingmcp/install.md
```
Agent 先校验当前平台引导脚本的固定 SHA-256,再执行该引导。平台引导选择并校验 Node 运行时,同时校验首次安装器和发布公钥;安装器随后验证 `manifest.sig` 和全部 artifact 哈希,将内置运行依赖的客户端以 npm 离线模式安装到稳定用户目录并返回标准 MCP 配置。终端安装过程不会从 npm registry 下载额外代码。Bridge 的稳定绝对路径不会包含 NVM 的具体 Node 版本,配置也不再携带 `--url`;网关地址由受签名保护的安装状态提供。
公开 `install.md` 是远程优先的短安装说明。Agent 应按宿主官方方式注册名为 `dingtalk-approval` 的远程 Streamable HTTP MCP,URL 为 `https://approval.justconn.top/mcp`,并由宿主使用标准 OAuth 元数据、动态客户端注册和 PKCE 登录。该路径不下载 Node/npm、Bridge 或 Skill;网关 MCP `instructions` 已提供完整业务规则。登录后只读调用 `approval_list_todos(source=all, limit=1)`,钉钉 OA 与薪福通都为 `ok` 才算验收通过。
正式部署会先把同一批不可变安装文件上传到公开 Gitea Release,并把它写成每个 artifact 的首选下载地址;`approval.justconn.top` 静态目录作为签名清单固定的备用地址。黑盒测试包及其动态提示词只发布到自建静态目录,不参与客户端安装镜像。平台引导、首次安装和后续更新都会在网络失败、超时或 404 时自动回退;任何来源一旦返回内容,Ed25519 签名或 SHA-256 不匹配都会立即终止。同一版本重跑会复用 Release Tag 的提交时间,测试包也使用归一化 tar 元数据,保证部署可安全重入。两个域名仍可能共享基础设施,如需机器级容灾,可再向 `release:build` 追加一个或多个 `--download-mirror-base-url` 指向独立的国内 OSS/COS。
仅当宿主明确缺少远程 MCP 或标准 OAuth 能力时,`install.md` 才引导到 `compat-install.md`。兼容页保留签名客户端、平台引导、Skill、stdio MCP、独立登录、更新、卸载和故障恢复步骤。Windows PowerShell 产物必须带 UTF-8 BOM,Node 探测使用外层双引号/内层单引号,避免 PowerShell 5.1 吞掉传给原生程序的双引号。
公开 `install.md` 必须保留从平台检查到双来源验收的完整编号步骤,并分别提供 Windows PowerShell 与 Linux/macOS 的独立路径。三平台都必须支持系统没有 Node 的情况:发布流程固定 Node 精确版本及 Windows/Linux/macOS x64/ARM64 的官方 SHA-256;平台引导依次使用阿里云、npmmirror 和 Node 官方精确版本地址,网络失败才换源,哈希不符立即终止。禁止使用 `latest` 镜像别名、修改系统 PATH 或要求管理员权限。
兼容 Windows 下载优先使用 `curl.exe`,从系统代理变量继承代理,并设置 10 秒连接超时、20 秒低速判定和 90 秒单源总时限;没有 curl 才以 `Invoke-WebRequest -TimeoutSec 90` 兜底。Node 固定版本制品仍按阿里云、npmmirror、官方源顺序尝试并强制校验官方 SHA-256。项目 artifact 由 Ed25519 清单和 SHA-256 保护;来源失败可换源,签名或哈希不符必须立即停止。
Windows 安装说明至少要覆盖 `Invoke-WebRequest` 下载、`Get-FileHash` 校验、JSON 解析、`.cmd` stdio 配置、路径空格、连接器信任与完整重启、独立登录续期、`doctor --json`、更新和卸载。Linux/macOS 必须同时支持 `curl`/`wget` 和 `sha256sum`/`shasum`,并使用系统 gzip tar 解压私有 Node。教程必须明确禁止把网关 HTTPS URL 直接注册为 MCP。
平台引导下载 Node 时使用 300 秒超时,Node 制品不经过本项目的小型网关,避免占用网关带宽。引导只接受固定官方哈希,且把私有 Node 与 npm 保存在客户端专用目录。进入 Node 安装器后,每个项目发布物仍使用 30 秒超时和 25 MB 流式硬上限,不会先把无界响应完整缓冲到内存;互不依赖的客户端包、Skill 和公钥并行下载。
平台引导与安装器把阶段进度写入 stderr,stdout 只保留最终 JSON。Agent 执行首次安装时必须给予至少 10 分钟工具超时;Windows 不论默认 shell 是什么都必须使用 PowerShell bootstrap,禁止直接调用内部 Node 安装器。安装器优先由当前 Node 直接启动相邻的 `npm-cli.js`,不会依赖易受 PATH、shell 或 Node 安全加固影响的隐式 npm shim;离线展开限时 180 秒。跨进程安装锁禁止并发写入,同一 PID 存活时要求等待,进程已死亡时自动回收锁并清理残留 staging。
代理环境不需要 Agent 修改全局 `NODE_OPTIONS`。首次安装和后续更新优先使用系统 `curl` 获取清单与发布物,直接复用 `HTTPS_PROXY`、`HTTP_PROXY`、`ALL_PROXY` 与 `NO_PROXY`;只有系统没有 `curl` 时才使用 Node `fetch`。平台引导和稳定启动器只对登录及 Bridge 等联网 Node 子进程按能力添加 `--use-env-proxy`;npm 子进程会移除该 Node 专用开关和 `NODE_USE_ENV_PROXY`,但保留标准代理变量,由 npm 使用自己的代理实现。禁止用手工预装 `node_modules` 绕过这一流程。
安装器不会识别 Agent 品牌或直接修改其配置。所有 Agent 都使用返回的 `skillPath` 和标准 `mcpConfig`,按自身官方方式安装 Skill、注册并信任名为 `dingtalk-approval` 的本地 stdio MCP;不能热加载连接器时再新建会话或重启。
安装器在返回前通过已安装 Bridge 主动准备登录,并在 JSON 的 `postInstall` 中返回 `authenticated`、`authorization_required` 或 `unavailable`,同时返回独立的 `loginCommand`。Agent 必须立即显示其中的短期 `directUrl`,不得等待首次审批请求;网页授权后调用 `approval_login`,再按 `verifyTool` 用 `source=all` 做双来源只读验证。链接过期时,MCP 已加载就重新调用 `approval_login`,尚未加载就执行 `loginCommand`,禁止为刷新链接重跑安装。首次认证成功会返回一次性 onboarding 示例,普通文本宿主也可见。登录准备失败不回滚安装,且整个流程不提交 consent、不读取审批、不执行写操作。
安装后可用稳定 CLI:`login --json` 只检查登录或生成新授权链接;`print-path bridge` 默认只输出路径;`print-config --format mcp-json` 输出可直接消费的标准 MCP JSON;`doctor --json` 同时检查 Node、npm、运行时、Skill、公钥和网关配置。后续更新直接执行安装结果中 `cliPath` 对应的 `update --json`,它会复用已固定的签名清单地址和本地公钥,并保留 OAuth 会话。更新完成后应重新连接该 MCP;Agent 不能单独重启连接器时,再新建会话或重启。
客户端卸载使用安装结果返回的 `cliPath uninstall --yes --json`,默认删除 OAuth 会话,并安全清理由旧版手工删除留下的四个 npm 入口;只会删除名称精确匹配且目标属于 `dingtalk-approval-mcp` 的链接或 Windows shim。
正式部署会把同一批不可变兼容安装文件上传到公开 Gitea Release,并把自建 HTTPS 作为固定备用。远程默认路径不依赖这些客户端文件,只依赖网关健康、OAuth 元数据和 `/mcp`。同一版本重跑复用 Release Tag 的提交时间和归一化测试包,保持可重入。
## 运维检查
+7 -8
View File
@@ -8,14 +8,13 @@
- `release:build`、`test-bundle:build` 和 `release:verify` 成功,`SHA256SUMS` 校验通过,发行物不包含 `.secrets`、`.runtime`、数据库、私钥或机器私有路径。
- 国内 Gitea 首选源与自建 HTTPS 备用目录的 `manifest.json`、`manifest.sig` 和全部安装附件逐文件哈希一致;黑盒测试包及动态提示词只要求自建目录可用。连续部署同一 Tag 必须复用既有 Release 和固定 `createdAt`,不得重复创建或因测试包时间戳产生哈希漂移。模拟首选源网络失败/404 后能从备用源完成首次安装和更新,模拟首选源返回错误哈希或签名时必须立即停止而不换源。
- Nginx bootstrap 只开放 ACME challenge;正式站点启用 HSTS,mutable 发行文件返回 `no-cache`,客户端 tgz 才返回 immutable。连续两次部署时公开目录始终对应一个完整签名清单,旧版本保留数符合策略。
- 从新生成的公开 `install.md` 在干净的用户级目录安装,不使用 `sudo`;安装结果主动返回 `postInstall`,可发现全部 13 个 MCP 工具。
- 在未安装 Node 的干净 Windows x64/ARM64、Linux x64/ARM64、macOS Intel/Apple Silicon 用户环境验证平台引导。确认只使用固定精确版本、国内镜像失败会依次回退、任一哈希不符立即终止、私有 Node 不修改 PATH 且更新后仍可启动。至少在实际可用的每类操作系统完成一次端到端安装;其余架构用对应 CI 或发行制品校验覆盖。
- 在干净 Windows 用户环境用公开教程的 PowerShell 路径完成引导 SHA-256 校验、安装 JSON 解析和 stdio 注册;实际 `command` 以 `.cmd` 结尾、`args` 为空,不含网关 URL,并通过 `doctor --json`。同时验证路径含空格、连接器信任和完整重启场景。
- 验证 stdout 只有最终 JSON、stderr 持续包含阶段进度;宿主工具超时设为至少 10 分钟。模拟离线 npm 超时、外部终止留下的死亡锁和 staging、并发第二次安装,分别确认明确失败、安全恢复和零并发写入。Windows 从 Git Bash 发起测试时仍须进入 PowerShell bootstrap,不得直接运行内部安装器。
- 在 Windows 代理沙箱中验证系统 `curl` 是安装和更新的首选下载器,并实际使用 `HTTPS_PROXY`;登录和 Bridge 继续可联网。父进程含 `NODE_OPTIONS="--trace-warnings --use-env-proxy"` 与 `NODE_USE_ENV_PROXY=1` 时,npm 子进程只保留无关 Node 选项并继续保留标准代理变量,离线展开不得卡死。
- 验证安装结果返回 `loginCommand`:未加载 MCP 时执行 `login --json` 能复用现有运行时生成或检查登录链接,不下载发布物;链接过期后生成新链接,已登录时不再返回挑战,未安装时明确失败。
- 首次安装不等待业务查询即产生一条可传递链接;挑战阶段 onboarding 仍为 pending,授权后的首次成功响应在普通文本中展示一次示例,此后不重复。
- 授权后钉钉 OA 与薪福通均为 `ok`,网关重启后登录状态仍可恢复;登录准备暂时失败不会回滚安装或删除原 OAuth 会话。
- 从新生成的公开 `install.md` 按宿主官方方式注册远程 `https://approval.justconn.top/mcp`;确认不下载 Node/npm/Bridge、不要求本地命令,并能通过 Protected Resource / Authorization Server Metadata、DCR 和 PKCE 完成宿主原生 OAuth。
- 远程 OAuth 后可发现全部 12 个业务工具,`approval_list_todos(source=all, limit=1)` 中钉钉 OA 与薪福通均为 `ok`;网关重启后宿主能刷新或重新授权,用户身份仍由服务端 Token 决定。
- `install.md` 只有在能力缺失时才链接 `compat-install.md`。用至少一个只支持 stdio 的宿主验证兼容安装可发现 `approval_login` 加 12 个业务工具,且不产生第二套用户身份。
- 在未安装 Node 的干净 Windows x64/ARM64、Linux x64/ARM64、macOS Intel/Apple Silicon 环境验证兼容引导。确认固定版本、国内镜像回退、哈希失败即停止、私有 Node 不改 PATH;至少每类操作系统一次端到端,其余架构由 CI/制品校验覆盖。
- 在 Windows PowerShell 5.1 验证生成的 `.ps1` 具有 UTF-8 BOM,中文可解析,Node 版本和代理能力探测不会因原生程序参数引号被吞而失败。Windows 下载优先 `curl.exe` 并继承 `HTTPS_PROXY`;连接 10 秒、低速 20 秒或总计 90 秒触发明确失败换源,不得出现 300 秒静默等待。
- 兼容安装继续验证 stdout 只有最终 JSON、stderr 有阶段进度;模拟离线 npm 超时、外部终止、死亡锁、staging 和并发安装,确认明确失败、安全恢复和零并发写入。父进程含 Node 代理选项时,npm 子进程不得继承 `--use-env-proxy`。
- 兼容安装结果的 `loginCommand` 能在 MCP 未加载时刷新登录链接;MCP 已加载时 `approval_login` 完成同一操作。不得因链接过期而重装,首次成功响应只展示一次 onboarding 示例。
- 只读验证待办、本人已处理历史、本人发起历史、历史默认最近 30 天及显式时间窗口、搜索、详情、费用结构化字段、动作、模板 Schema、部门/城市选项和越权拒绝;历史引用必须被动作查询和批处理拒绝。
- 发票查重验证钉钉/XFT 跨来源精确匹配、弱匹配、用户隔离、状态更新、来源不可用、历史截断、详情失败、并发确认、35 天过期清理和网关重启恢复;数据库不得出现用户 ID、发票原号、审批正文或附件。重复风险和不完整覆盖未获用户确认时不得签发可提交 `confirmationId`。
- 真实写操作只执行用户明确授权的样本;任何 `outcome_uncertain` 都停止,不自动重试。