钉钉审批 MCP

一个面向 Agent 的统一审批 MCP。用户只登录一次钉钉,即可读取、处理和发起本人在钉钉 OA 与薪福通中的审批:

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 重新准备。

服务端临时保留不可逆的用户/发票 HMAC 指纹。首次使用时只为最近 30 天尚未索引的审批读取详情;以后准备提单会刷新精简历史状态,并只为新增审批补建指纹,不会重复逐张下载已索引发票。指纹和最小审批索引最多保留 35 天,过期后自动级联删除;10 分钟提单预留到期即删除。

安全准备后,确认引用绑定登录用户、模板版本、完整表单内容、重复风险决定和发票预留,10 分钟有效且只能使用一次;相同发票在另一个有效确认中时不会再签发确认,避免并发重复创建。正文和发票原号不落库。钉钉企业 OpenAPI 支持通过 POST /v1.0/workflow/processes/forecast 进行无副作用的流程预测;网关只在预测成功并补齐所有自选处理人后才生成提交确认。薪福通在正式提交时完成最终业务校验,并由网关写后读取 billSts:状态 1(待审批) 返回 submitted 和 revokeId,状态 2(审批通过) 返回 completed 且不提供撤回引用。

发布候选版限制:薪福通 approve/recall 撤回接口已经接入并具备本人归属校验与写后复核,但当前企业的真实待审批单仍返回 XFTSYS9999,尚无撤回成功样本。因此薪福通撤回属于实验能力;失败或结果不确定时绝不自动重试。查询、处理和发起审批不受此限制。

部署

服务器首次配置企业凭证和 Ed25519 发布签名私钥后,安装和以后每次更新统一执行:

./deploy/install.sh

卸载网关:

./deploy/uninstall.sh

该卸载命令只处理服务器网关,并默认保留 .secrets、.runtime、OAuth 数据库和 HTTPS 证书。详细步骤见 部署文档,安全边界见 架构文档。

10 个提单模板的逐项字段与 API 能力结论见 提单模板能力。 发布候选版的放行条件见 发布检查清单。

部署完成后,把下面的唯一链接交给用户或其 Agent:

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 与薪福通都可用。

服务端 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 秒。

数据与安全

  • 所有写操作重新校验审批仍属于当前登录用户。
  • approvalId 是绑定用户、来源和有效期的紧凑不透明加密引用;不包含展示字段或用户 ID 明文。
  • 每批最多 20 条;引用预检失败时首个上游写调用不会发生。
  • 提单的发起人、薪福通员工号和审批状态只能由网关填写。
  • 审批正文、费用明细、附件和薪福通 Schema 不落库。
  • 发票查重库只保存当前用户和发票标识的 HMAC、来源、上游业务单号、状态及时间,最多保留 35 天;不保存发票原号、商户原文或附件。
  • 企业 AppSecret 与薪福通 AuthoritySecret 只保存在服务器。
  • failed、succeeded 与 outcome_uncertain 有不同重试语义,后者禁止自动重试。
  • OAuth 客户端、Token 和 MCP 会话都有数量及生命周期上限;过期数据会周期清理。
S
Description
Unified DingTalk OA and XFT approval MCP gateway
Readme
1 MiB
Languages
TypeScript 81.2%
JavaScript 16.2%
Shell 1.8%
PowerShell 0.8%