fix: route cross-device OAuth through device flow
CI / Client installer (macos-latest) (push) Canceled after 0s
CI / Client installer (ubuntu-latest) (push) Canceled after 0s
CI / Client installer (windows-latest) (push) Canceled after 0s
CI / test (22) (push) Canceled after 0s
CI / test (24) (push) Canceled after 0s
CI / release-smoke (push) Canceled after 0s
CI / Client installer (macos-latest) (push) Canceled after 0s
CI / Client installer (ubuntu-latest) (push) Canceled after 0s
CI / Client installer (windows-latest) (push) Canceled after 0s
CI / test (22) (push) Canceled after 0s
CI / test (24) (push) Canceled after 0s
CI / release-smoke (push) Canceled after 0s
This commit is contained in:
@@ -77,11 +77,11 @@ Agent 不传 `userId`、员工号或单据所有者。网关从 OAuth Token 确
|
||||
https://approval.justconn.top/downloads/dingmcp/install.md
|
||||
```
|
||||
|
||||
默认流程不下载任何客户端:Agent 按宿主官方方式把 `https://approval.justconn.top/mcp` 注册为远程 Streamable HTTP MCP,由宿主通过标准 OAuth 元数据、动态客户端注册和 PKCE 完成登录。用户端不需要 Node.js、npm、DWS、企业凭证或本地常驻进程。用户本人确认授权后,Agent 用 `approval_list_todos(source=all, limit=1)` 只读验证钉钉 OA 与薪福通都可用。
|
||||
同机交互的默认流程不下载任何客户端:Agent 按宿主官方方式把 `https://approval.justconn.top/mcp` 注册为远程 Streamable HTTP MCP,由宿主通过标准 OAuth 元数据、动态客户端注册和 PKCE 完成登录。若宿主注册 `127.0.0.1`/`localhost` 回调,授权页必须在运行 Agent 的同一设备打开。用户端不需要 Node.js、npm、DWS、企业凭证或本地常驻进程。用户本人确认授权后,Agent 用 `approval_list_todos(source=all, limit=1)` 只读验证钉钉 OA 与薪福通都可用。
|
||||
|
||||
服务端 MCP `instructions` 和工具描述包含完整审批工作流,因此远程模式不依赖本地 Skill 才能安全使用。宿主需要重新加载连接器时按其官方机制处理;OAuth 过期也由宿主标准刷新/重新授权流程解决,无需重装。
|
||||
|
||||
只有宿主明确不支持远程 Streamable HTTP MCP 或标准 OAuth 时,才使用 `compat-install.md` 安装本地 Bridge。兼容引导仍支持 Windows、Linux、macOS x64/ARM64 和无 Node 环境,并使用固定 Ed25519 清单与 SHA-256 校验。PowerShell 发行脚本带 UTF-8 BOM,Node 探测避免 Windows PowerShell 5.1 吞引号;Windows 下载优先使用 `curl.exe`,连接、低速或 90 秒总超时会明确失败并换固定来源,不再静默等待 300 秒。
|
||||
宿主不支持远程 Streamable HTTP MCP/标准 OAuth,或用户通过 SSH、无头终端、Messenger 等方式跨设备操作而无法完成宿主本机回调时,使用 `compat-install.md` 安装本地 Bridge。Bridge 的 device-code 登录链接可以传到手机或另一台电脑打开。兼容引导仍支持 Windows、Linux、macOS x64/ARM64 和无 Node 环境,并使用固定 Ed25519 清单与 SHA-256 校验。PowerShell 发行脚本带 UTF-8 BOM,Node 探测避免 Windows PowerShell 5.1 吞引号;Windows 下载优先使用 `curl.exe`,连接、低速或 90 秒总超时会明确失败并换固定来源,不再静默等待 300 秒。
|
||||
|
||||
## 数据与安全
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# 钉钉审批兼容客户端安装任务
|
||||
|
||||
仅当当前 Agent 明确不支持远程 Streamable HTTP MCP 或标准 OAuth 时,才使用本兼容安装。支持远程 MCP 的宿主应返回主安装页并直接连接 `{{GATEWAY_URL}}`,不要安装本地 Bridge。
|
||||
仅当当前 Agent 明确不支持远程 Streamable HTTP MCP、标准 OAuth,或用户无法在宿主本机 OAuth 回调所在设备打开授权页面时,才使用本兼容安装。即使宿主支持远程 MCP,只要它使用 `127.0.0.1`/`localhost` 回调,而用户通过 SSH、无头环境或 Messenger 在另一台设备操作,就应使用本地 Bridge 的可跨设备 device-code 登录;同机回调可以完成时才返回主安装页直接连接 `{{GATEWAY_URL}}`。
|
||||
|
||||
用户把本文件或本文件的链接交给你,即表示授权你为当前用户安装或更新“钉钉审批”兼容客户端、Skill 和名为 `dingtalk-approval` 的 MCP。该授权不包含同意、拒绝、退回、撤回或发起任何审批。
|
||||
|
||||
|
||||
@@ -6,14 +6,17 @@
|
||||
|
||||
## 默认安装
|
||||
|
||||
1. 检查当前 Agent 是否支持远程 **Streamable HTTP MCP** 和 MCP 标准 **OAuth 2.0**。按能力判断,不要按 Agent 品牌判断。
|
||||
2. 若支持,按宿主官方方式新增或更新连接器:
|
||||
1. 先同时检查两项条件:
|
||||
- 当前 Agent 支持远程 **Streamable HTTP MCP** 和 MCP 标准 **OAuth 2.0**;
|
||||
- 用户打开授权页面的设备能够完成宿主注册的 OAuth 回调。若回调地址是 `127.0.0.1` 或 `localhost`,用户必须在运行 Agent 的同一台设备上打开页面。通过 SSH、无头终端或 Messenger 操作远程 Agent,而用户会在手机或另一台电脑打开链接时,不满足此条件。
|
||||
按实际能力和交互环境判断,不要按 Agent 品牌判断。若无法确定,只问用户一个问题:是否会在运行 Agent 的这台设备上打开授权页面。
|
||||
2. 仅当两项都满足时,按宿主官方方式新增或更新连接器:
|
||||
- 名称:`dingtalk-approval`
|
||||
- URL:`{{GATEWAY_URL}}`
|
||||
- 传输:Streamable HTTP
|
||||
- 认证:OAuth(允许宿主使用服务端发现元数据和动态客户端注册)
|
||||
3. 不要安装 Node.js、npm、本地 Bridge、DWS 或浏览器自动化;不要索取 AppKey、AppSecret、AuthoritySecret、CorpId、userId、员工号、Cookie、Token 或其他企业凭证。
|
||||
4. 让宿主发起标准 OAuth 登录,把宿主返回的授权页面交给用户本人确认。不得代替用户点击授权,也不得声称链接已通过其他消息通道发送。
|
||||
4. 让宿主发起标准 OAuth 登录,并确保用户在能够完成该回调的设备上本人确认。不得代替用户点击授权,也不得声称链接已通过其他消息通道发送。若此时发现宿主使用本机回调而用户只能跨设备打开链接,应停止等待并改用下面的兼容安装,不要把不可完成的链接交给用户反复尝试。
|
||||
5. 连接成功后调用一次只读 `approval_list_todos`,参数为 `source="all"`、空搜索、`limit=1`。只有响应中的钉钉 OA 与薪福通来源都为 `ok`,才报告安装完成。不得在安装验证中执行任何审批写操作。
|
||||
6. 若宿主需要重启或重新加载才能识别新连接器,按其官方机制操作;不要因为等待加载而改装本地 Bridge。
|
||||
|
||||
@@ -21,14 +24,14 @@
|
||||
|
||||
## 兼容安装
|
||||
|
||||
只有在宿主明确不支持远程 Streamable HTTP MCP,或不能完成 MCP 标准 OAuth 时,才使用本地 STDIO Bridge:
|
||||
只有在宿主明确不支持远程 Streamable HTTP MCP、不能完成 MCP 标准 OAuth,或用户无法在宿主本机回调所在设备打开授权页面时,才使用本地 STDIO Bridge:
|
||||
|
||||
`{{COMPAT_INSTALL_URL}}`
|
||||
|
||||
备用地址:
|
||||
{{COMPAT_INSTALL_MIRROR_URLS_MARKDOWN}}
|
||||
|
||||
不要先尝试兼容安装来“提高成功率”。远程连接失败时应先报告宿主给出的具体错误;只有确认属于能力缺失,才进入兼容路径。
|
||||
本地 Bridge 使用可跨设备完成的 device-code 登录,授权页面可以通过当前对话发给用户并在手机或另一台电脑打开。不要在同机回调明确可用时先安装 Bridge 来“提高成功率”;若已经明确是 SSH、无头或跨设备交互,应直接进入兼容路径,不必先制造一次必然失败的远程 OAuth。
|
||||
|
||||
## 完成后
|
||||
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
|
||||
- 测试包:`{{BUNDLE_URL}}`
|
||||
- SHA-256:`{{BUNDLE_SHA256}}`
|
||||
- 模式:远程 Streamable HTTP MCP + 宿主原生 OAuth;一次钉钉登录同时覆盖钉钉 OA 与薪福通,必须完整验证两个审批源
|
||||
- 模式:同机回调可达时使用远程 Streamable HTTP MCP + 宿主原生 OAuth;跨设备且宿主使用 loopback 回调时使用本地 Bridge + device-code。一次钉钉登录同时覆盖钉钉 OA 与薪福通,必须完整验证两个审批源
|
||||
|
||||
安装必须从包内的 `install.md` 进入。默认不得安装 Node/npm 或本地 Bridge;只有宿主明确不支持远程 MCP 或标准 OAuth 时,才按其中链接的 `compat-install.md` 走签名兼容安装,并在报告中说明能力缺口。
|
||||
安装必须从包内的 `install.md` 进入。同机回调可达时不得安装 Node/npm 或本地 Bridge;只有宿主明确不支持远程 MCP/标准 OAuth,或用户无法在宿主 loopback 回调所在设备打开授权页时,才按其中链接的 `compat-install.md` 走签名兼容安装,并在报告中说明选择原因。
|
||||
|
||||
只通过安装后的 `dingtalk-approval` MCP 读取和处理审批业务,不使用上游接口旁路。验证一次登录、钉钉 OA 与薪福通的待办、详情和动作能力;任何来源显示 `disabled` 都应视为发行配置错误并停止测试。真实写操作仅限用户明确确认的一次同意;可从任一来源选择,但不得因其中一方不可用而跳过。不要真实拒绝或退回。若结果为 `outcome_uncertain`,禁止自动重试。
|
||||
|
||||
|
||||
@@ -8,11 +8,11 @@
|
||||
└─ 薪福通
|
||||
```
|
||||
|
||||
支持远程 MCP 和标准 OAuth 的宿主直接连接网关,不安装客户端运行时。只有宿主缺少远程传输或 OAuth 能力时,才使用本地 Bridge 把 stdio 转换为远程 Streamable HTTP;Bridge 只保存用户自己的短期 access/refresh token,不包含企业密钥、不读取审批上游,也不监听端口。
|
||||
支持远程 MCP 和标准 OAuth,且用户能完成宿主所注册回调的场景直接连接网关,不安装客户端运行时。若宿主使用 `127.0.0.1`/`localhost` 回调,授权页必须在 Agent 所在设备打开。宿主缺少远程传输/OAuth 能力,或用户通过 SSH、无头终端、Messenger 等方式跨设备交互而无法完成本机回调时,使用本地 Bridge 把 stdio 转换为远程 Streamable HTTP,并通过可跨设备的 device-code 登录。Bridge 只保存用户自己的短期 access/refresh token,不包含企业密钥、不读取审批上游,也不监听端口。
|
||||
|
||||
## 客户端安装边界
|
||||
|
||||
默认安装仅在宿主中登记远程 HTTPS MCP URL。OAuth 客户端注册、PKCE、Token 保存和刷新均由宿主的标准 MCP 实现负责,终端不需要 Node/npm、Bridge 或项目安装器。网关的 MCP `instructions` 与工具描述提供业务工作流,终端修改本地提示不能绕过服务器的身份和写前校验。
|
||||
同机回调可达时,默认安装仅在宿主中登记远程 HTTPS MCP URL。OAuth 客户端注册、PKCE、Token 保存和刷新均由宿主的标准 MCP 实现负责,终端不需要 Node/npm、Bridge 或项目安装器。安装 Agent 必须按实际回调拓扑选择路径:能够显示 URL 不等于能够完成回调;回调是 loopback 且用户会在另一台设备打开时直接选择兼容 Bridge。网关的 MCP `instructions` 与工具描述提供业务工作流,终端修改本地提示不能绕过服务器的身份和写前校验。
|
||||
|
||||
兼容发行物只为不支持远程 MCP/OAuth 的宿主保留。它不使用全局 npm prefix:首次安装器以固定 Ed25519 公钥验证 schema v3 清单和 artifact SHA-256,并把内置依赖展开到稳定的用户目录。Windows/Linux/macOS 引导可复用系统 Node 或安装经官方哈希校验的固定私有 Node,不改 PATH、不要求管理员权限。发布物优先使用国内 Gitea 和 Node 固定版本源,自建 HTTPS/官方源作为受同一签名或哈希保护的备用。
|
||||
|
||||
@@ -82,7 +82,7 @@ Agent 面向统一审批语义,不直接理解钉钉 `processInstanceId/taskId
|
||||
|
||||
撤回接口若返回 `XFTSYS*` 服务异常或网络级异常,网关会立即只读复核本人单据状态:已撤回则返回 `revoked`,仍为待审批则返回带 `postWriteVerified` 的 `failed`,无法明确归类才返回 `outcome_uncertain`。任何分支都不会自动重试写操作。
|
||||
|
||||
截至 `1.1.0-rc.13`,薪福通撤回仍是实验能力:当前企业真实调用 `approve/recall` 会返回 `XFTSYS9999`,写后复核确认单据仍为待审批,尚无成功样本。该限制不影响薪福通查询、审批处理或发起审批;正式版不得把“接口已接通”表述为“撤回已验证成功”。
|
||||
截至 `1.1.0-rc.14`,薪福通撤回仍是实验能力:当前企业真实调用 `approve/recall` 会返回 `XFTSYS9999`,写后复核确认单据仍为待审批,尚无成功样本。该限制不影响薪福通查询、审批处理或发起审批;正式版不得把“接口已接通”表述为“撤回已验证成功”。
|
||||
|
||||
薪福通创建或撤回需要复核时,`approval_get_submission_status` 先用服务器派生的本人员工号和单据详情双重确认目标属于当前用户的已发起单据,再返回状态名称和精简流程历史。只有实时状态仍为 `1(待审批)` 才签发新的短期、用户绑定 `revokeId`;已通过、草稿、拒绝或已撤回单据都不会获得撤回引用。该工具不返回审批正文,也不触发写操作。
|
||||
|
||||
|
||||
+3
-3
@@ -37,7 +37,7 @@ https://approval.justconn.top/oauth/dingtalk/callback
|
||||
|
||||
创建接口必须保持权限校验开启。网关统一提交 `APPRV_PEND`,并在写后实时读取本人单据状态:进入待审批时提供撤回引用;按企业流程规则即时通过时返回 `completed`,不提供撤回引用且禁止重复提交。
|
||||
|
||||
`1.1.0-rc.13` 中薪福通撤回仍标记为实验能力:权限和调用契约已接通,但当前企业真实请求返回 `XFTSYS9999`,尚未取得成功样本。网关会写后复核并禁止自动重试。面向试用用户时必须保留这一说明;若业务要求撤回必须稳定可用,应等待薪福通定位后再升级为正式能力。
|
||||
`1.1.0-rc.14` 中薪福通撤回仍标记为实验能力:权限和调用契约已接通,但当前企业真实请求返回 `XFTSYS9999`,尚未取得成功样本。网关会写后复核并禁止自动重试。面向试用用户时必须保留这一说明;若业务要求撤回必须稳定可用,应等待薪福通定位后再升级为正式能力。
|
||||
|
||||
## 首次凭证配置
|
||||
|
||||
@@ -117,9 +117,9 @@ release/
|
||||
https://approval.justconn.top/downloads/dingmcp/install.md
|
||||
```
|
||||
|
||||
公开 `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` 才算验收通过。
|
||||
公开 `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` 才算验收通过。
|
||||
|
||||
仅当宿主明确缺少远程 MCP 或标准 OAuth 能力时,`install.md` 才引导到 `compat-install.md`。兼容页保留签名客户端、平台引导、Skill、stdio MCP、独立登录、更新、卸载和故障恢复步骤。Windows PowerShell 产物必须带 UTF-8 BOM,Node 探测使用外层双引号/内层单引号,避免 PowerShell 5.1 吞掉传给原生程序的双引号。
|
||||
宿主缺少远程 MCP/标准 OAuth,或 loopback 回调与用户打开授权页的设备不一致时,`install.md` 引导到 `compat-install.md`,无需先尝试一次必然失败的远程登录。兼容页保留签名客户端、平台引导、Skill、stdio MCP、可跨设备的 device-code 登录、更新、卸载和故障恢复步骤。Windows PowerShell 产物必须带 UTF-8 BOM,Node 探测使用外层双引号/内层单引号,避免 PowerShell 5.1 吞掉传给原生程序的双引号。
|
||||
|
||||
兼容 Windows 下载优先使用 `curl.exe`,从系统代理变量继承代理,并设置 10 秒连接超时、20 秒低速判定和 90 秒单源总时限;没有 curl 才以 `Invoke-WebRequest -TimeoutSec 90` 兜底。Node 固定版本制品仍按阿里云、npmmirror、官方源顺序尝试并强制校验官方 SHA-256。项目 artifact 由 Ed25519 清单和 SHA-256 保护;来源失败可换源,签名或哈希不符必须立即停止。
|
||||
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
- `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` 按宿主官方方式注册远程 `https://approval.justconn.top/mcp`;确认不下载 Node/npm/Bridge、不要求本地命令,并能通过 Protected Resource / Authorization Server Metadata、DCR 和 PKCE 完成宿主原生 OAuth。
|
||||
- 从新生成的公开 `install.md` 验证两条决策路径:同机浏览器可完成回调时注册远程 `https://approval.justconn.top/mcp`,确认不下载 Node/npm/Bridge、不要求本地命令,并能通过 Protected Resource / Authorization Server Metadata、DCR 和 PKCE 完成宿主原生 OAuth;SSH/无头/Messenger 跨设备打开授权页且宿主使用 loopback 回调时,不先尝试必然失败的远程登录,直接选择兼容 Bridge。
|
||||
- 远程 OAuth 后可发现全部 12 个业务工具,`approval_list_todos(source=all, limit=1)` 中钉钉 OA 与薪福通均为 `ok`;网关重启后宿主能刷新或重新授权,用户身份仍由服务端 Token 决定。
|
||||
- `install.md` 只有在能力缺失时才链接 `compat-install.md`。用至少一个只支持 stdio 的宿主验证兼容安装可发现 `approval_login` 加 12 个业务工具,且不产生第二套用户身份。
|
||||
- `install.md` 只有在远程能力缺失或本机 OAuth 回调对用户不可达时才链接 `compat-install.md`。用至少一个只支持 stdio 的宿主和一个跨设备 loopback 场景验证兼容安装可发现 `approval_login` 加 12 个业务工具,device-code 链接可在另一台设备打开,且不产生第二套用户身份。
|
||||
- 在未安装 Node 的干净 Windows x64/ARM64、Linux x64/ARM64、macOS Intel/Apple Silicon 环境验证兼容引导。确认固定版本、国内镜像回退、哈希失败即停止、私有 Node 不改 PATH;至少每类操作系统一次端到端,其余架构由 CI/制品校验覆盖。
|
||||
- 在 Windows PowerShell 5.1 验证生成的 `.ps1` 具有 UTF-8 BOM,中文可解析,Node 版本和代理能力探测不会因原生程序参数引号被吞而失败;确认 `.zip` 仅去除一次扩展名,解压目录与 `node-v<version>-win-<arch>` 完全一致。Windows 下载优先 `curl.exe` 并继承 `HTTPS_PROXY`;连接 10 秒、低速 20 秒或总计 90 秒触发明确失败换源,不得出现 300 秒静默等待。
|
||||
- 兼容安装继续验证 stdout 只有最终 JSON、stderr 有阶段进度;模拟离线 npm 超时、外部终止、死亡锁、staging 和并发安装,确认明确失败、安全恢复和零并发写入。父进程含 Node 代理选项时,npm 子进程不得继承 `--use-env-proxy`。
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "dingtalk-approval-mcp",
|
||||
"version": "1.1.0-rc.13",
|
||||
"version": "1.1.0-rc.14",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "dingtalk-approval-mcp",
|
||||
"version": "1.1.0-rc.13",
|
||||
"version": "1.1.0-rc.14",
|
||||
"dependencies": {
|
||||
"@modelcontextprotocol/sdk": "^1.30.0",
|
||||
"express": "^5.2.1",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "dingtalk-approval-mcp",
|
||||
"version": "1.1.0-rc.13",
|
||||
"version": "1.1.0-rc.14",
|
||||
"description": "A lightweight Agent bridge for a unified DingTalk OA and XFT approval gateway.",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
|
||||
@@ -94,7 +94,8 @@ try {
|
||||
}
|
||||
const compatibilityInstall = readFileSync(join(releaseDir, "compat-install.md"), "utf8");
|
||||
if (compatibilityInstall.includes("{{") || !compatibilityInstall.includes(`版本:\`${version}\``)
|
||||
|| !compatibilityInstall.includes("仅当当前 Agent 明确不支持远程 Streamable HTTP MCP 或标准 OAuth")
|
||||
|| !compatibilityInstall.includes("仅当当前 Agent 明确不支持远程 Streamable HTTP MCP、标准 OAuth,或用户无法在宿主本机 OAuth 回调所在设备打开授权页面")
|
||||
|| !compatibilityInstall.includes("可跨设备 device-code 登录")
|
||||
|| !compatibilityInstall.includes("postInstall") || !compatibilityInstall.includes("onboarding.firstRun=true")
|
||||
|| !compatibilityInstall.includes("系统无需预装 Node.js") || !compatibilityInstall.includes("Git Bash")
|
||||
|| /TimeoutSec 300|--max-time 300|--timeout=300/.test(compatibilityInstall)
|
||||
|
||||
@@ -9,11 +9,11 @@ Use only the `dingtalk-approval` MCP tools. DingTalk OA and XFT use the same gat
|
||||
|
||||
## Login and first run
|
||||
|
||||
Use the host's native remote-MCP OAuth flow by default. When the remote server requests authentication, let the host open or present the authorization URL and have the user authorize it personally. Never claim that a link was pushed through another channel. After OAuth succeeds, make one read-only `approval_list_todos` call with `source=all` and `limit=1`; both DingTalk OA and XFT must be available before reporting setup complete.
|
||||
Use the host's native remote-MCP OAuth flow when the user can complete its registered callback. If the redirect URI uses `127.0.0.1` or `localhost`, the user must open the authorization page on the same device that runs the Agent. An SSH, headless, Messenger, phone, or other cross-device interaction cannot complete that loopback callback and must use the local STDIO Bridge device-code flow instead. If the interaction topology is unknown during installation, ask only whether the user will open the page on the Agent's device. When native OAuth is suitable, let the host open or present the authorization URL and have the user authorize it personally. Never claim that a link was pushed through another channel. After OAuth succeeds, make one read-only `approval_list_todos` call with `source=all` and `limit=1`; both DingTalk OA and XFT must be available before reporting setup complete.
|
||||
|
||||
When a successful response contains `onboarding.firstRun=true`, show its short examples and write-safety note once. Do not execute an example automatically.
|
||||
|
||||
Only hosts that cannot use remote Streamable HTTP MCP or standard OAuth should use the optional local STDIO Bridge. In that compatibility mode, handle the installer's `postInstall` immediately. If it contains `authChallenge.directUrl`, copy the complete clickable URL into the current reply. If the link expires, call `approval_login`; if the connector is not loaded yet, run the returned `loginCommand`. Never reinstall merely to renew a link, read Bridge state files, or render QR images as ASCII. One successful gateway login covers both sources.
|
||||
Hosts that cannot use remote Streamable HTTP MCP or standard OAuth, and cross-device users who cannot reach a host loopback callback, should use the optional local STDIO Bridge. In that compatibility mode, handle the installer's `postInstall` immediately. If it contains `authChallenge.directUrl`, copy the complete clickable URL into the current reply; the user may open this device-code page on another device. If the link expires, call `approval_login`; if the connector is not loaded yet, run the returned `loginCommand`. Never reinstall merely to renew a link, read Bridge state files, or render QR images as ASCII. One successful gateway login covers both sources.
|
||||
|
||||
## Review and process
|
||||
|
||||
|
||||
@@ -13,8 +13,13 @@ test("customer distribution prefers remote MCP OAuth and keeps a generic compati
|
||||
assert.match(installer, /URL:`\{\{GATEWAY_URL\}\}`/);
|
||||
assert.match(installer, /认证:OAuth/);
|
||||
assert.match(installer, /动态客户端注册/);
|
||||
assert.match(installer, /127\.0\.0\.1.*localhost.*同一台设备/s);
|
||||
assert.match(installer, /SSH.*无头终端.*Messenger.*手机或另一台电脑/s);
|
||||
assert.match(installer, /无法确定.*只问用户一个问题/s);
|
||||
assert.match(installer, /不要安装 Node\.js、npm、本地 Bridge/);
|
||||
assert.match(installer, /只有.*不支持远程 Streamable HTTP MCP.*标准 OAuth.*兼容/s);
|
||||
assert.match(installer, /只有.*不支持远程 Streamable HTTP MCP.*标准 OAuth.*无法.*本机回调.*兼容/s);
|
||||
assert.match(installer, /device-code.*手机或另一台电脑/s);
|
||||
assert.match(installer, /跨设备交互.*直接进入兼容路径.*不必先制造.*失败/s);
|
||||
assert.match(installer, /COMPAT_INSTALL_URL/);
|
||||
assert.match(installer, /approval_list_todos.*source="all".*limit=1/s);
|
||||
assert.match(installer, /钉钉 OA 与薪福通来源都为 `ok`/);
|
||||
@@ -22,7 +27,8 @@ test("customer distribution prefers remote MCP OAuth and keeps a generic compati
|
||||
assert.doesNotMatch(installer, /--host|WorkBuddy|Codex|Claude/);
|
||||
|
||||
const compatibilityInstaller = readFileSync("distribution/agent-compat-install.template.md", "utf8");
|
||||
assert.match(compatibilityInstaller, /仅当.*不支持远程 Streamable HTTP MCP.*标准 OAuth/s);
|
||||
assert.match(compatibilityInstaller, /仅当.*不支持远程 Streamable HTTP MCP.*标准 OAuth.*无法.*本机 OAuth 回调/s);
|
||||
assert.match(compatibilityInstaller, /127\.0\.0\.1.*localhost.*SSH.*无头环境.*Messenger.*device-code/s);
|
||||
assert.match(compatibilityInstaller, /Ed25519/);
|
||||
assert.match(compatibilityInstaller, /使用 `mcpConfig`/);
|
||||
assert.match(compatibilityInstaller, /Windows(PowerShell)/);
|
||||
@@ -72,9 +78,10 @@ test("customer distribution prefers remote MCP OAuth and keeps a generic compati
|
||||
assert.match(skill, /read `references\/create-approval\.md` completely/);
|
||||
assert.doesNotMatch(skill, /XFT recall is experimental/);
|
||||
assert.match(createApproval, /XFT recall is experimental.*XFTSYS9999/s);
|
||||
assert.match(skill, /host's native remote-MCP OAuth flow by default/);
|
||||
assert.match(skill, /native remote-MCP OAuth flow when the user can complete its registered callback/);
|
||||
assert.match(skill, /127\.0\.0\.1.*localhost.*same device.*SSH.*headless.*Messenger.*cross-device.*STDIO Bridge device-code/s);
|
||||
assert.match(skill, /both DingTalk OA and XFT must be available/);
|
||||
assert.match(skill, /Only hosts that cannot use remote Streamable HTTP MCP or standard OAuth.*local STDIO Bridge/s);
|
||||
assert.match(skill, /cannot use remote Streamable HTTP MCP or standard OAuth.*cross-device users.*loopback callback.*local STDIO Bridge/s);
|
||||
assert.match(skill, /authChallenge\.directUrl.*current reply/s);
|
||||
assert.match(skill, /onboarding\.firstRun=true.*Do not execute an example automatically/s);
|
||||
assert.match(skill, /link expires.*approval_login.*Never reinstall/s);
|
||||
|
||||
Reference in New Issue
Block a user