Files
dingMCP/README.md
T

103 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 钉钉审批 MCP
一个面向 Agent 的统一审批 MCP。用户只登录一次钉钉,即可读取、处理和发起本人在钉钉 OA 与薪福通中的审批:
```text
Agent → 远程 Streamable HTTP MCP / OAuth 统一网关
├─ 钉钉 OA OpenAPI
└─ 薪福通 OpenAPI
```
只有宿主不支持远程 MCP 或标准 OAuth 时,才使用本地 STDIO Bridge 兼容层。
## 工具
- `approval_login`:检查登录或返回唯一授权链接。
- `approval_list_todos`:实时列出本人待办,签发短期 `approvalId`,并为可安全整组处理的结果签发 `selectionId`。
- `approval_list_history`:实时列出本人已经处理过或本人发起的审批;默认最近 30 天,可用 `startDate/endDate` 指定最长 120 天的时间窗口,并签发只能读取详情的短期 `approvalId`。
- `approval_get_detail`:返回摘要、结构化费用明细或受限 raw 分页。
- `approval_get_actions`:检查同意、拒绝与退回能力。
- `approval_process_batch`:一次最多处理 20 条;整批引用预检通过后才逐项执行,并在写后复核。
- `approval_list_submission_templates`:实时列出当前用户的提单候选模板。
- `approval_get_submission_schema`:返回结构化可填写字段,不传输巨大原始 Schema。
- `approval_get_submission_options`:实时查询当前用户可用的薪福通部门、城市和费用类型;所有选项面向用户只展示业务名称,内部映射正式接口值。
- `approval_prepare_submission`:校验内容,自动查重本人近 30 天跨钉钉/薪福通的发票,并在安全时生成完整预览及短期确认引用;不创建单据。
- `approval_submit`:用户确认预览后,使用相同内容正式发起审批。
- `approval_revoke_submission`:使用提单成功后返回的 `revokeId` 撤销本人刚通过 MCP 发起的钉钉或薪福通审批。
- `approval_get_submission_status`:只读核验本人已发起薪福通单据的实时状态。
待办、历史和处理结果使用统一、精简的领域字段,不向 Agent 暴露钉钉任务 ID、薪福通员工号或上游原始响应。历史查询分为 `handled`(本人已经处理过)和 `submitted`(本人发起),结果没有 `selectionId` 和可执行动作。常见 `approvalId` 使用紧凑的 v4 无状态加密格式:薪福通通常约 60 字符、钉钉 OA 通常约 100 字符,并绑定当前用户和 30 分钟有效期;历史引用还绑定查询语义,只能读取详情。旧版未过期的 v2/v3 引用仍可读取。
一次写调用最多处理 20 条。整组同意/拒绝可直接使用 `selectionId`;超过 20 条时,Agent 可从同一次原始列表中按 `approvalId` 分组,不需要 `batchPlan`,也不能重新拉取后把新待办混入原授权。服务器在首个写入前校验整批 `approvalId` 和 `targetId`;任一引用无效时返回 `preflight_failed`、`writesStarted=false`,整批零写入且不自动补偿或重试。普通文本与结构化结果保持同一份精简数据,以兼容不渲染 `structuredContent` 的宿主。
Agent 不传 `userId`、员工号或单据所有者。网关从 OAuth Token 确定用户,再分别映射钉钉 OA 与薪福通身份。钉钉提单中的申请人和部门也由网关通过当前登录用户的通讯录档案实时填写;即使用户修改本地桥,也不能冒用他人身份或部门。
审批读取和处理范围不变;发起入口会列出当前企业的 4 个薪福通模板,以及以下 6 个钉钉模板:
- `北极大_人事假勤`:`出差申请单_北极大`、`外出_北极大`、`业务招待申请_北极大`
- `捷康_费用报销`:`差旅费用报销_捷康`、`业务招待费用报销_捷康`、`业务招待申请_捷康`
范围限制由网关按分类和模板名双重执行,不依赖本地 Skill。同分类中未列出的模板也不能发起。
模板出现在列表中不等于所有控件都能由开放 API 构造。`approval_get_submission_schema` 会返回 `submissionCapability`,准备阶段也会再次安全校验:
- 薪福通:白名单中的申请和报销模板均通过正式创建 API 发起,并在创建后实时核验状态。结果可能进入待审批,也可能因企业流程中没有其他有效审批人等规则即时完成;后者返回 `completed`,不会错误地当成接口失败,也不会签发不可用的撤回引用。
- 钉钉:当前 6 个候选模板均返回 `client_only`,必须在钉钉客户端发起。其中 5 个包含企业 OpenAPI 无法可靠构造的 `DDBizSuite` 考勤或费控套件;`业务招待申请_北极大`虽是普通明细表,但真实创建时新版企业接口返回系统异常、旧版接口拒绝组件格式,因此同样安全降级。
发起审批固定为“列模板 → 取 Schema → 自动查重/预览 → 用户确认 → 正式提交”。准备阶段从新表单提取发票代码与号码、数电票唯一编号、票据号码、附件哈希;没有唯一编号时,金额、日期与商户组合只作为疑似提示。网关实时刷新当前用户本人近 30 天的钉钉和薪福通已发起审批:原单待审批、已通过或状态未知时默认阻止,原单拒绝、撤回、作废或弱匹配时警告。任一来源查询不完整也不会当成“没有重复”。只有用户看过匹配单号、状态和覆盖情况并明确要求继续后,Agent 才能以 `allowDuplicateInvoices=true` 重新准备。
用户不需要理解薪福通的任何内部选择值。实时 Schema 会把部门、城市、费用类型、出行方式、往返、时间范围、币种和酒店星级等字段标记为名称优先的选择项;Agent 只展示“深圳市”“交通费”“飞机”“往返”“人民币”等业务名称,选定后仅在内部写入正式接口值。动态下拉框也会标准化成 `label/code`,表格子字段同样递归处理。无法取得可靠名称映射时安全停止或允许跳过可选项,不退化为向用户索取工号、城市码、组织码、档案编号、数字舱位值或其他内部 ID。
人员、企业自定义档案、关联前置单据、分摊及文档未给出可靠名称映射的舱位字段目前标记为 `client_only`。必填时不生成提交预览并引导薪福通客户端;可选时不会作为普通问题打扰用户。单据公司、部门、字段引用和行程序号等服务器管理或内部派生值也不会作为用户输入项展示。
服务端临时保留不可逆的用户/发票 HMAC 指纹。首次使用时只为最近 30 天尚未索引的审批读取详情;以后准备提单会刷新精简历史状态,并只为新增审批补建指纹,不会重复逐张下载已索引发票。指纹和最小审批索引最多保留 35 天,过期后自动级联删除;10 分钟提单预留到期即删除。
安全准备后,确认引用绑定登录用户、模板版本、完整表单内容、重复风险决定和发票预留,10 分钟有效且只能使用一次;相同发票在另一个有效确认中时不会再签发确认,避免并发重复创建。正文和发票原号不落库。钉钉企业 OpenAPI 支持通过 `POST /v1.0/workflow/processes/forecast` 进行无副作用的流程预测;网关只在预测成功并补齐所有自选处理人后才生成提交确认。薪福通在正式提交时完成最终业务校验,并由网关写后读取 `billSts`:状态 `1(待审批)` 返回 `submitted` 和 `revokeId`,状态 `2(审批通过)` 返回 `completed` 且不提供撤回引用。
用户可以让 Agent 把尚未填完的提单保存为本机草稿。它不是钉钉或薪福通的官方草稿:只写入运行 Agent 的当前 OS 用户私有数据目录,不上传网关,也不跨设备同步。草稿保存用户填写值、可选项决定以及附件的本地路径和 SHA-256,不保存 Token、身份 ID、短期模板/确认/撤回引用或完整上游 Schema;附件在正式准备前重新验哈希。恢复时重新实时列模板和读取 Schema,超过 90 天未更新的普通草稿在下次草稿操作时清理。提交结果不确定的草稿会冻结,核验清楚前禁止重试。宿主没有本地文件能力时不提供持久草稿,也不会改存服务器。当前 MCP 不提供附件上传工具;若实时 Schema 要求上游附件编号,本机路径不能代替,需保留草稿并在原生客户端完成。
> 发布候选版限制:薪福通 `approve/recall` 撤回接口已经接入并具备本人归属校验与写后复核,但当前企业的真实待审批单仍返回 `XFTSYS9999`,尚无撤回成功样本。因此薪福通撤回属于实验能力;失败或结果不确定时绝不自动重试。查询、处理和发起审批不受此限制。
## 部署
服务器首次配置企业凭证和 Ed25519 发布签名私钥后,安装和以后每次更新统一执行:
```bash
./deploy/install.sh
```
卸载网关:
```bash
./deploy/uninstall.sh
```
该卸载命令只处理服务器网关,并默认保留 `.secrets`、`.runtime`、OAuth 数据库和 HTTPS 证书。详细步骤见 [部署文档](docs/deployment.md),安全边界见 [架构文档](docs/architecture.md)。
10 个提单模板的逐项字段与 API 能力结论见 [提单模板能力](docs/submission-templates.md)。
发布候选版的放行条件见 [发布检查清单](docs/release-checklist.md)。
部署完成后,把下面的唯一链接交给用户或其 Agent:
```text
https://approval.justconn.top/downloads/dingmcp/install.md
```
同机交互的默认流程不下载任何客户端: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,或用户通过 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 秒。
## 数据与安全
- 所有写操作重新校验审批仍属于当前登录用户。
- `approvalId` 是绑定用户、来源和有效期的紧凑不透明加密引用;不包含展示字段或用户 ID 明文。
- 每批最多 20 条;引用预检失败时首个上游写调用不会发生。
- 提单的发起人、薪福通员工号和审批状态只能由网关填写。
- 网关不保存审批正文、费用明细、附件和薪福通 Schema;用户明确创建的本机草稿是唯一例外,且只位于 Agent 机器的当前用户私有目录。
- 发票查重库只保存当前用户和发票标识的 HMAC、来源、上游业务单号、状态及时间,最多保留 35 天;不保存发票原号、商户原文或附件。
- 企业 AppSecret 与薪福通 AuthoritySecret 只保存在服务器。
- `failed`、`succeeded` 与 `outcome_uncertain` 有不同重试语义,后者禁止自动重试。
- OAuth 客户端、Token 和 MCP 会话都有数量及生命周期上限;过期数据会周期清理。