跳转至

11 - MCP 产品定义(Agent 操作面)

本文定义 Clip票夹 对 AI Agent 暴露的产品能力:定位、边界、工具清单、鉴权与安全、异步约定、分阶段落地。
实现仍走现有 REST(08-api.md);MCP 是意图层包装,不平行造第二套业务 API。
机器可读请求/响应形状以 packages/shared 的 zod 为准;本文与代码冲突时先改文档达成共识再动代码(见 AGENTS.md)。


1. 产品定位

项 定义
名称 Clip票夹 MCP(工作名:clip-invoice)
形态 符合 Model Context Protocol 的 Tools 服务器;由宿主(Claude Desktop、Cursor、自研 Agent 运行时等)通过 stdio 或内网 HTTP/SSE 连接
服务对象 代表已授权用户操作其工作区的 Agent(个人助理、团队报销 bot、内部编排流水线)
解决的问题 浏览器 UI 适合人点选;Agent 需要稳定、可组合、可机器解析的「报销操作系统」入口,避免让模型直接拼 REST 路径与头字段
核心价值 用自然语言完成「收票 → 核对 → 组批 → 导出」闭环,且不越权、不碰凭据、不自动对外提交
非目标 公有云多租户开放平台、任意第三方 OAuth 应用市场、无人值守 OA 提交、跨组织数据联邦

一句话:MCP 是工作区上下文下的报销工具箱;人确认边界内的写操作,系统保留与 Web 相同的隔离与审计红线。


2. 与现有产品的关系

┌─────────────┐     session cookie      ┌──────────┐
│  Web (人)   │ ───────────────────────►│          │
└─────────────┘                         │  API     │
                                        │ /api/v1  │──► PostgreSQL / 队列 / 文件
┌─────────────┐  Bearer + workspace     │          │
│ MCP Server  │ ───────────────────────►│          │
│ (Agent 面)  │   意图 → REST 映射      └──────────┘
└─────────────┘
       ▲
       │ MCP tools/list · tools/call
┌─────────────┐
│ Agent 宿主  │
└─────────────┘
原则 说明
单一事实源 业务状态只在 PostgreSQL;MCP 不缓存权威数据,读必打 API
契约复用 金额(分)、错误码、角色能力、工作区头语义与 08-api.md 一致
意图收敛 宿主侧暴露 少量高内聚 tool(约 12–20 个),内部再调一个或多个 REST 端点
权限同构 Agent 令牌绑定用户身份与工作区成员角色;能力不超过该成员在 Web 上能做的事,并可再收窄
UI 仍是主路径 设置凭据、成员治理、排障下载继续以 Web 为准;MCP 不替代管理控制台

3. 用户与场景

3.1 典型使用者

角色 诉求
教职工 / 学生 「把这几张票上传并归到交通费,按额度组一单,导出 Excel」
课题组助理 「看看共享工作区未入批发票,按项目额度拆两批」
内部 Agent 编排 定时摘要待办、失败任务重试提醒、导出物就绪后通知人下载

3.2 主旅程(Agent)

  1. 定位上下文:列出可访问工作区 → 选定当前 workspaceId(后续写操作默认落在此空间)。
  2. 感知状态:工作区摘要(待报销金额/张数、队列积压、未匹配附件、额度剩余)。
  3. 收票:上传文件 → 轮询解析任务 → 处理失败/重复。
  4. 核对:检索发票 → 必要时修正白名单字段、配对附件、重放 OCR(优先免费 replay)。
  5. 组单:建批 → 入批/拆批 → 排序 →(可选)标记已报销 paid(需确认)。
  6. 交付:触发导出 → 轮询导出任务 → 取得受控下载信息,交还人或下游系统。
  7. 收尾:查看通知、标记已读;异常用机器可读 code 决定重试或升级给人。

3.3 明确不做的旅程

  • 配置或读取邮箱授权码、财务门户密码、Webhook secret。
  • 创建/删除工作区、转让 owner、管理系统用户。
  • 管理员跨工作区排障下载。
  • OA/财务系统自动提交报销单(半自动填报若落地,仅允许「生成预填结果 + 人确认」)。

4. 设计原则

  1. 工作区钉死:会话级或 tool 级必须有明确 workspaceId;禁止用「猜默认空间」跨空间扫数据。
  2. 金额只传分:tool 入参与出参中的金额字段均为 integer 分;展示文案可由 Agent 自行格式化。
  3. 异步可轮询:上传解析、导出均为任务型;tool 返回 taskId / exportId,另提供状态查询;MCP 层不要求宿主支持 SSE(SSE 为可选增强)。
  4. 默认瘦响应:列表与摘要省略 ocr_raw_json、完整附件二进制等大字段;详情按 flag 增量拉取。
  5. 错误可分支:失败返回与 API 对齐的 code(如 DUPLICATE_FILE、BATCH_STATE_INVALID),message 给人读,details 给模型结构化重试。
  6. 危险写二次确认:软删发票、批次标 paid、删批等 tool 要求显式 confirm: true(或宿主侧 human-in-the-loop 批准)。
  7. 凭据零暴露:任何 tool 响应不得出现解密后的密钥、完整 session、信封主密钥;账户类只读若开放,仅掩码元数据。
  8. 幂等友好:上传/入批/导出支持可选 idempotencyKey(产品层约定;落地时与 API 幂等策略对齐),避免 Agent 重试造成双批或双导出。
  9. 审计可区分:经 MCP 的写操作标记 actor_type=agent(及 token id),与浏览器操作区分,便于追责与限流。

5. 能力分层

层级 名称 产品含义 默认
L0 探活与发现 健康、协议版本、当前身份与可访问工作区 必开
L1 只读报销面 摘要、发票/任务/批次/额度/导出状态/通知 必开
L2 写报销闭环 上传、重试、修正、附件配对、组批、导出触发 默认开(受角色与 token scope)
L3 增强只读 财务门户概览、历史单打印 JSON、额度快照 可选,只读
L4 触发类运维 手动触发邮件拉取 / 财务同步(不改凭据) 可选,manager+
— 治理与密钥 成员、凭据 CRUD、频道 secret、admin 排障 永不进 MCP

角色下限与 08-api.md §3.7 一致:viewer 仅 L0–L1(及 L3 若开);member 可达 L2;manager 才涉及 L4 与批次删/改名等。


6. 工具目录(产品契约)

命名采用 动词_名词 蛇形,稳定后不轻易改名;新增 tool 只追加。
下列「映射 REST」指语义归属,实现可聚合多次调用。

6.1 L0 — 上下文

Tool 说明 主要入参 主要出参 映射 REST 最低角色
get_health 服务是否可达 — 状态 GET /healthz 无
get_caller 当前身份与 token 能力集 — user、scopes、默认 workspace session/token 内省 登录
list_workspaces 可访问工作区列表与摘要 — items[] GET /workspaces 登录
set_workspace 设定后续调用的当前工作区(会话态)或校验 id workspaceId 确认后的上下文 本地会话 + 成员校验 member 关系

若实现选择「无会话态、每 tool 必传 workspaceId」,可取消 set_workspace,改为强制参数;产品上二选一写死,避免混用。

6.2 L1 — 只读

Tool 说明 主要入参 主要出参 映射 REST 最低角色
get_workspace_summary 仪表盘 + 额度摘要合一 workspaceId? 待报销金额分/张数、已解析数、未匹配附件、队列积压、quota[] GET /stats/dashboard + GET /quota/summary viewer
search_invoices 发票检索分页 status、category、日期、batchId、keyword、uncategorized、page… 瘦字段 items + total GET /invoices viewer
get_invoice 发票详情 invoiceId、includeOcrRaw?(默认 false) 字段、附件清单、可选 raw GET /invoices/:id viewer
list_tasks 解析任务列表 status、page… items GET /tasks viewer
get_task 单任务状态 taskId status、invoiceId?、error? GET /tasks/:id viewer
list_batches 批次列表 status?、page… items(含聚合金额分) GET /batches viewer
get_batch 批次详情与票列表 batchId 聚合 + invoices[] GET /batches/:id viewer
list_unmatched_attachments 待配对附件 page… items(信号字段,全文可截断) GET /attachments?status=unmatched viewer
get_export 导出任务状态 exportId status、kind、错误或就绪元信息 GET /exports/:id viewer
list_notifications 站内通知 unreadOnly? items GET /notifications 登录
list_rules 分类规则 scope? items GET /rules viewer

6.3 L2 — 写闭环

Tool 说明 主要入参 主要出参 映射 REST 最低角色 确认
upload_invoices 上传并入解析队列 files[](路径或 blob 由宿主传入)、idempotencyKey? 逐文件 accepted / taskId / reason / restored POST /uploads member 否
retry_task 重试失败任务 taskId 新状态 POST /tasks/:id/retry member 否
update_invoice 白名单字段修正 invoiceId + 允许字段子集 更新后摘要 PATCH /invoices/:id member 否
reparse_invoice 重解析 invoiceId、mode: replay\|refetch taskId POST /invoices/:id/re-parse member refetch 建议确认
match_attachment 附件挂到发票 attachmentId、invoiceId 挂载结果 POST /attachments/:id/match member 否
create_batch 建批 name、note?、targetAmountFen? batch POST /batches member 否
add_invoices_to_batch 入批 batchId、invoiceIds[] 结果 POST /batches/:id/invoices member 否
remove_invoice_from_batch 拆批 batchId、invoiceId 结果 DELETE .../invoices/:invoiceId member 否
reorder_batch 批内排序 batchId、invoiceIds[](全量序) 结果 PATCH /batches/:id/order member 否
update_batch 改名或状态流转 batchId、name?、status?(仅 paid) batch PATCH /batches/:id manager(删/状态)/ 改名按 API status=paid 要 confirm
delete_batch 删批(票回归集区) batchId、confirm: true 空 DELETE /batches/:id manager 是
delete_invoice 软删发票 invoiceId、confirm: true 空 DELETE /invoices/:id member 是
export_batch 触发导出 batchId、kind: xlsx\|pdf\|zip exportId POST .../export/{kind} member 否
get_download_url 导出物或原件受控下载信息 exportId 或 workspaceFileId 等 短时可用下载描述(非永久公网链) GET /exports/:id/download 等 viewer 否
create_rule 新建分类规则 scope、匹配条件、category… rule POST /rules member(scope 内) 否
mark_notifications_read 已读 ids[] 或 all 空 PATCH /notifications/read 登录 否

补传附件(POST /invoices/:id/attachments)可并入 upload_invoices 的 invoiceId 可选参数,或单独 attach_file_to_invoice;产品实现时择一,避免两个入口语义漂移。

6.4 L3 — 增强只读(可选)

Tool 说明 映射 REST 最低角色
get_finance_portal 门户现场概览(余额、在途单等),不落库、不回密码 GET /finance-accounts/:id/portal viewer
get_finance_claim_print 历史报销单打印数据 JSON GET .../claims/:serialNo/print viewer
list_quota_snapshots 额度快照序列 GET /quota/plans/:id/snapshots viewer

6.5 L4 — 触发类(可选)

Tool 说明 映射 REST 最低角色
trigger_mail_fetch 手动拉邮 POST /mail-accounts/:id/fetch manager
trigger_finance_sync 手动同步财务 POST /finance-accounts/:id/sync manager

6.6 永不暴露的能力(产品黑名单)

能力域 代表端点/动作 原因
认证管理 改密、admin 建号/封禁 身份治理须人
工作区治理 建/删空间、成员 CRUD、owner 转让 组织变更
凭据写 mail/finance/notify-channel 的 secret 读写与 test 中的敏感回显 密钥红线
排障 /admin/files/...、跨工作区 access 审计特权
原始队列/SQL 直接操作 BullMQ 或数据库 绕过领域不变量
OA 自动提交 无人值守提交报销 02-features.md 明确排除

7. 鉴权与令牌产品

7.1 身份模型

项 定义
主体 始终是真实用户(或显式的服务账号用户),MCP 不发明独立于成员表的幽灵身份
传输 Authorization: Bearer <token> 调 API;MCP 进程持有 token,不把 cookie 塞进通用 LLM 日志
工作区 每个业务 tool 校验:token 对应用户是该空间活动成员,且角色满足 tool 下限
与 Web 关系 用户可在 Web「设置 → 开发者 / Agent」创建、吊销、查看令牌;吊销立即生效

7.2 Token 能力集(scope)

签发时可子集化,默认建议:

Scope 含义
workspace:list 列出工作区
invoice:read / invoice:write 发票与附件读/写
task:read / task:write 任务查询与重试
batch:read / batch:write 批次与导出触发
quota:read 额度
rule:read / rule:write 规则
notification:read / notification:write 通知
finance:read L3 门户只读
ops:trigger L4 拉取/同步
admin 禁止出现在 MCP 令牌

另可选约束:

  • 单工作区钉死:token 仅允许一个 workspace_id,忽略或拒绝其它 id。
  • 只读令牌:仅 L0–L1(+L3),适合「问答式」Agent。
  • TTL 与轮换:短有效期 + 刷新或重新签发;支持用户一键吊销。

7.3 限流(产品口径)

维度 建议
上传 与 API 相同文件限制;Agent token 可额外按小时计次
reparse refetch 严格限次(消耗 OCR 配额)
导出 按工作区并发/日限额,防止打爆 worker
全局 429 + RATE_LIMITED,Agent 应退避而非紧密重试

8. 数据与错误约定

8.1 字段口径

与 08-api.md §1 一致:

  • ID:uuid 字符串
  • 金额:integer 分
  • 业务日期:YYYY-MM-DD
  • 时间戳:ISO 8601 UTC
  • 分页:page / pageSize / sort,响应含 total

8.2 Tool 结果形状(逻辑)

成功:直接返回资源 JSON(可与 REST 同形或经 MCP 层做字段裁剪)。
失败:

{
  "code": "BATCH_STATE_INVALID",
  "message": "批次非 collecting,无法入批",
  "details": {/* 可选 */},
}

跨工作区或无权限资源:表现为不存在(404 语义 / NOT_FOUND 类 code),不泄露其它空间是否持有该 id。

8.3 异步模式

upload_invoices / reparse_invoice / export_batch
        → 立即返回 taskId 或 exportId
        → Agent 调 get_task / get_export 直到终态
        → done 后再 get_invoice / get_download_url

终态枚举与 API 对齐:任务 done | failed | duplicate | ...;导出 done | failed。
产品要求:tool 描述(description)中写清「须轮询」,降低模型误判同步完成。

8.4 文件如何进 MCP

宿主与 MCP 之间的文件传递依赖 MCP 实现能力(path、base64、资源 URI 等)。产品要求:

  • 仅允许约定扩展名:pdf / jpg / jpeg / png
  • 单文件大小上限与 API 一致(默认 ≤ 10MB)
  • 单次上传 ≤ 20 个文件
  • MCP Server 将文件转为对 API 的 multipart,不在磁盘上留下可被其它租户读取的明文缓存(临时文件用完即删)

9. 安全与合规红线

  1. 多用户数据必须带工作区边界;复合外键 + RLS + 成员校验与 Web 共用。
  2. 密钥与 OCR key 不进 MCP 日志、trace、tool 回显。
  3. ocr_raw_json 默认不下发;需要时显式 includeOcrRaw 且仍受工作区权限约束。
  4. 下载只给受控、短时、需鉴权的获取方式,不做永久公开 URL。
  5. Agent 写操作全量审计:谁、哪个 token、哪个工作区、哪个 tool、关键资源 id、结果 code。
  6. 内网部署默认:MCP 只在内网或 localhost 暴露;若 HTTP 传输须 TLS 与内网 ACL。
  7. 提示注入:tool 返回的发票备注、商户名、OCR 文本视为不可信数据,系统提示中应要求模型不得将其当作指令执行(实现侧可在 description 与 wrapper 中重复此约束)。

10. 宿主集成(产品体验)

10.1 连接方式(目标形态)

模式 适用 说明
stdio 桌面宿主本机 用户配置 command + env(CLIP_API_BASE、CLIP_TOKEN)
内网 HTTP 团队 Agent 网关 统一入口,token 按用户下发

10.2 配置项(用户可见)

配置 含义
API Base URL 如 https://clip.example.edu/api/v1
Access Token Web 签发的 Agent 令牌
Default Workspace ID 可选;与 token 钉死策略一致时只读展示

10.3 Agent 系统提示(产品侧建议文案要点)

  • 先 list_workspaces / get_workspace_summary,再改数据。
  • 金额按分计算;展示给人时再换算元。
  • 解析与导出必须轮询至终态。
  • 标 paid、删除类操作前向用户确认。
  • 不要索要或保存用户邮箱/门户密码。
  • 不要声称已向学校财务系统提交成功(本系统不提供该能力)。

11. 成功指标(产品)

指标 意图
主闭环完成率 Agent 从上传到导出成功的会话占比
危险操作确认率 需 confirm 的调用在无确认时被拒绝的比例(护栏有效)
越权尝试 跨工作区 / 超 scope 调用应为 0 成功
平均 tool 轮次 完成「组一单并导出」的中位调用次数(工具是否够复合)
人机升级率 因凭据、歧义附件、额度策略而转人工的比例(预期存在,用于改进 L3/配对)

12. 分阶段落地

与 06-roadmap.md 业务里程碑解耦,MCP 可并行推进,但依赖对应 REST 已可用。

阶段 目标 范围 验收
MCP-0 契约与鉴权 OpenAPI/ zod 导出、Agent token 模型、审计字段、本文档评审 能签发只读 token;无业务 tool 也可
MCP-1 只读可用 L0 + L1 tools;stdio 连接样例 Agent 正确回答「待报销多少、有哪些失败任务」
MCP-2 写闭环 L2 主路径(上传→任务→票→批→导出);confirm 护栏 端到端导出物可下载;重复上传/入批行为与 Web 一致
MCP-3 增强 L3/L4、可选 SSE 订阅桥、智能组单 tool(若 M3 组单 API 就绪) 门户只读与触发拉取可用;自动提交仍不存在
MCP-4 生态 官方 MCP 包发布说明、宿主配置模板、限流与用量面板 内网文档可自助接入

智能组单(suggest_batch)作为 L2 增强 tool 单列:只返回建议 invoiceIds 与金额分,不自动入批;入批须用户确认后再调 add_invoices_to_batch。(后端 POST /batches/suggest 已落地,见 03 §5.6。)


13. 文档与实现同步

变更类型 同步动作
新增/改名/删除 tool 更新本文 §6 + MCP server 注册表 + 集成测试
入参出参字段 packages/shared zod → 生成 tool schema → 本文示例
角色或黑名单 本文 §5–§6 与 08 §3.7
REST 路径变更 08 与本文映射表同一 commit

相关文档:


14. 名词表

术语 含义
MCP Model Context Protocol,宿主与工具服务器之间的标准协议
Tool Agent 可调用的具名操作,含 JSON Schema 入参与结构化出参
Agent 令牌 用户签发的、带 scope 与可选工作区钉死的 Bearer 凭证
瘦字段 列表默认返回的最小字段集,省略 raw OCR 与大文本
确认(confirm) 危险写操作的显式布尔入参或宿主人工批准门闩
报销闭环 上传解析 → 核对 → 组批 → 导出 的完整路径

15. 开放问题(写入时未锁死,实现前需拍板)

  1. 会话态 workspace:set_workspace 会话缓存 vs 每 tool 必传 workspaceId。
  2. 下载交付:MCP 直接返回短时 URL vs 返回「请到 Web 下载」的占位(内网 Agent 无浏览器时前者更必要)。
  3. 服务账号:是否允许非自然人的 bot 用户加入工作区(审计与责任主体)。
  4. Idempotency-Key:先做 MCP 层去重表,还是并入 API 正式契约。
  5. 多文件上传在 MCP 的编码:path 引用(stdio 本机)与远程宿主的 base64 体积上限。

拍板后更新本节为「已决」并改 §6/§8 正文,避免实现分叉。