feat: prefer remote MCP OAuth installation
This commit is contained in:
+11
-15
@@ -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`;已通过、草稿、拒绝或已撤回单据都不会获得撤回引用。该工具不返回审批正文,也不触发写操作。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user