docs: 文档全面对齐 MCP 架构,并脱敏公开操作指南
接口与入门: - 新增 docs/MCP.md:注册方法(DSH patch + 通用 client)、返回信封、会话目录布局、标准流程、 硬约束与未实现清单;工具参考段由**运行时 input_schema 自动生成**,与代码同源不会漂移 - 删除 docs/API.md(856 行 Flask 路由/SSE 文档,描述的端点已不存在) - 重写根 README.md:为什么放弃自带前端、职责分工表、快速开始、注册配置、流程链、结构与风险 - 重写 AGENTS.md:命令表换成 mcp/mcp-smoke/upload;mypy 目标改 src;新增「提交纪律」 (pre-commit 的 stash 窗口会回滚未暂存改动)、COM 与 Playwright 线程约束、多进程共存提醒 包文档:src/README.md 与各包 README 按现状重写;新增 src/mcp/README.md(写工具的规矩、 宿主侧四个坑)与 src/upload/README.md(路由表与安全边界);tests/scripts/config 三处索引更新。 提示词迁移:src/infra/llm/ 整个删除,三份系统提示词迁到 .agents/skills/reimbursement/references/ (invoice-fields / travel-info-fields / normal-info-fields),删掉 can_submit 与 suggestion (save_info 也会主动剥离),「严格只输出 JSON」改为「交给对应工具落盘」;新增 SKILL.md 作为 宿主侧操作纪律(已被 DSH 热加载为 reimbursement 技能)。 作废处理:删除 .agents/docs/guides/系统事件流全景图.md(SSE 与 file_events/agent_events 通道已整体 移除,现在没有任何事件流);给项目架构全景图与架构分析-2026-06-15 加「已过时」横幅保留历史; config.example.json 去 consumable_storage 加 upload_pin;.env.example 去 LLM 段并说明已不再自动加载 .env。 安全:docs/报销操作指南.md 的示例配置里原来写着**真实姓名、16 位公务卡号、内网 LLM 地址与工号** (自 9fe5d70/2026-05-25 起在版本历史里),本次全部换成占位符。历史清洗与令牌轮换另议。 门禁(改动含 src/infra/llm 删除,故重跑全部门禁): ruff check PASS | ruff format --check PASS(42) | mypy src PASS(34) | deptry PASS(36) | pytest 107 passed | scripts/mcp_smoke.py PASS(17 工具 / instructions 1449 字节 / case_list ok) 申购单在依赖清理后另已实机复测:2.4s 生成,产物单元格读回正确。
This commit is contained in:
+304
@@ -0,0 +1,304 @@
|
||||
---
|
||||
last_reviewed: 2026-10-19
|
||||
---
|
||||
|
||||
# MCP 接口文档
|
||||
|
||||
本项目的**唯一业务入口**是 MCP 服务器:`python -m src.mcp.server`(stdio 传输),工具名在宿主里表现为 `mcp__arb__<tool>`。
|
||||
没有 Web 界面,没有 CLI 产品入口,本项目也不调用任何大模型——**读图与综合判断由宿主 Agent 完成**,
|
||||
本项目只提供确定性工具(渲染、金额匹配、规则校验、文档生成、浏览器填报)。
|
||||
|
||||
## 注册到宿主
|
||||
|
||||
DSH(profile patch,`~/.dsh/profiles/<profile>/cordis.patch.yml`):
|
||||
|
||||
```yaml
|
||||
- insert:
|
||||
- id: mcp-arb
|
||||
name: '@deepseek-ai/dsh-mcp-client'
|
||||
config:
|
||||
serverName: arb
|
||||
transport: stdio
|
||||
command: 'D:/Code/AI Agent/自动报销系统/.venv/Scripts/python.exe'
|
||||
args: ['-m', 'src.mcp.server']
|
||||
cwd: 'D:/Code/AI Agent/自动报销系统'
|
||||
```
|
||||
|
||||
> 注意:DSH 对 stdio 子进程做了环境变量清洗(抹掉 `*KEY|PASSWORD|SECRET|TOKEN` 与全部 `DSH_*`),
|
||||
> 所以财务系统凭据只能来自 `scripts/data/config.json`,不能靠环境变量注入。
|
||||
|
||||
通用 MCP 客户端等价配置:
|
||||
|
||||
```json
|
||||
{ "mcpServers": { "arb": { "command": "<项目根>/.venv/Scripts/python.exe", "args": ["-m", "src.mcp.server"], "cwd": "<项目根>" } } }
|
||||
```
|
||||
|
||||
改完 Python 代码需要让宿主重连(DSH 会热插拔新工具条目,但**不会**重载已运行子进程里的代码;
|
||||
杀掉 stdio 子进程即可自动重启并重同步工具)。
|
||||
|
||||
## 返回信封
|
||||
|
||||
所有工具返回统一信封,宿主判类型看 `ok`:
|
||||
|
||||
```json
|
||||
{ "ok": true, "case_id": "...", "next_action": "..." }
|
||||
{ "ok": false, "reason": "缺少 payment_records.csv", "next_action": "先 mcp__arb__match_payments 生成汇总" }
|
||||
```
|
||||
|
||||
- **不抛异常穿透协议**:文件缺失、参数不合法、COM 失败都转成 `ok: false` + `reason` + `next_action`。
|
||||
- `next_action` 是给 Agent 的下一步指令,通常是具体工具名,照做即可。
|
||||
- 部分客户端会把结果包在 `content[0].text`(JSON 字符串)里,同时提供 `structuredContent`;两者内容一致。
|
||||
|
||||
## 会话目录
|
||||
|
||||
一个报销任务 = 一个 `cases/<case_id>/` 目录(`case_id` 形如 `20261019-6月毕业采集`)。
|
||||
**阶段完全由产物推导**,没有状态机文件,可随时断电重来、可人工改文件后继续。
|
||||
|
||||
```
|
||||
cases/<case_id>/
|
||||
├── case.json 名称、类型、上传令牌(切勿提交)
|
||||
├── config.json 可选,会话级凭据覆盖(白名单字段)
|
||||
├── <材料>.pdf|jpg 发票、支付截图、申请单原件
|
||||
├── inbox/ 手机扫码上传落地点,case_add_files(source="inbox") 收取
|
||||
├── pages/<stem>/p01.png 渲染页面 + text.txt(PDF 文本层)+ meta.json(dpi/转正角/字符数)
|
||||
├── .invoice_cache/*.json 单张票据抽取结果(宿主产出,本服务规范化后落盘)
|
||||
├── match_result.json 匹配结果
|
||||
├── invoice_groups.json 差旅/普通分组与计数
|
||||
├── invoice_summary.csv 发票级汇总
|
||||
├── payment_records.csv 支付记录汇总(申购单取数)
|
||||
├── travel_applications.json 出差申请单
|
||||
├── travel_info.json 差旅报销结构化数据
|
||||
├── normal_info.json 普通报销结构化数据
|
||||
├── artifacts/ 申购单等文档产物
|
||||
├── screenshots/ (P3 落地后出现)填报过程截图
|
||||
└── submit_preview.json (P4 落地后出现)提交前快照与摘要
|
||||
```
|
||||
|
||||
`cases/` 整个目录都在 `.gitignore` 里:发票含身份证号与卡号。
|
||||
|
||||
## 标准流程
|
||||
|
||||
1. `case_create` → 记下 `case_id` 与返回的 `upload_page`(手机扫码上传页)
|
||||
2. `case_add_files`(本地路径用**正斜杠**)或 `case_add_files(source="inbox")` 收手机上传
|
||||
3. `case_render_pages` → `text_chars>0` 先 `case_read_text`,否则读 `pages/**.png`
|
||||
4. 逐张按 `extraction_spec` 出 JSON → `case_save_extraction`;核对后小改用 `case_patch_extraction`
|
||||
5. `match_payments` → **逐条处理 `review_required`**(未匹配、发票总额小于支付总额、一对多凑额)
|
||||
6. `info_skeleton` 取骨架 → 填值 → `save_info`(自动跑校验);`validate_info` 可反复试算不落盘
|
||||
7. 普通发票再 `doc_requisition` 生成申购单
|
||||
8. 每步之后 `case_status` 复查;`case_reset(scope)` 清派生产物重跑
|
||||
|
||||
## 硬约束
|
||||
|
||||
- **不得回显密码**,不得把凭据写进产物或日志
|
||||
- **不得臆造财务数据**:拿不准的字段标出来问用户,禁止自己宣布"可以提交"
|
||||
- 产物只写 `cases/<case_id>/`
|
||||
- 文本层与读图结论冲突时(尤其编号、卡号、金额位数)必须复核,不要默认信任某一路
|
||||
|
||||
## 尚未实现(不要调用,也不要在回答里承诺)
|
||||
|
||||
浏览器填报(`browser_*`)、提交预览与执行(`submit_*`)。需要这些步骤时告知用户该环节还在建设中,
|
||||
可临时用旧的 Web 流程(代码在提交 `5f57400` 里)。
|
||||
|
||||
---
|
||||
|
||||
# 工具参考
|
||||
|
||||
以下内容由运行中的服务器 schema 自动生成,与代码同源(`scripts/mcp_smoke.py` 会打印同一份清单)。
|
||||
|
||||
## 会话与材料
|
||||
|
||||
每个报销任务是一个会话目录 `cases/<case_id>/`,阶段由产物推导。
|
||||
|
||||
### `mcp__arb__case_create`
|
||||
|
||||
新建报销会话目录,返回 case_id 与目录路径。
|
||||
|
||||
name 是本次报销的人类可读名称(如「6月毕业采集」);
|
||||
invoice_type 可选 travel|normal,未定时留空,抽取后由发票分类决定。
|
||||
|
||||
| 参数 | 类型 | 必填 | 默认 | 说明 |
|
||||
|------|------|------|------|------|
|
||||
| `name` | string | 是 | — | — |
|
||||
| `invoice_type` | null/string | 否 | — | — |
|
||||
|
||||
### `mcp__arb__case_list`
|
||||
|
||||
列出所有报销会话及其推导阶段、计数与待收文件数。
|
||||
|
||||
无参数。
|
||||
|
||||
### `mcp__arb__case_status`
|
||||
|
||||
单个会话的完整态势:材料数、抽取完成/缺失/陈旧、匹配、信息、产物、收件箱、下一步建议。
|
||||
|
||||
| 参数 | 类型 | 必填 | 默认 | 说明 |
|
||||
|------|------|------|------|------|
|
||||
| `case_id` | string | 是 | — | — |
|
||||
|
||||
### `mcp__arb__case_add_files`
|
||||
|
||||
把材料拷入会话目录。
|
||||
|
||||
paths 传绝对路径列表(从手机下载目录、微信文件目录等任意位置取文件);
|
||||
source='inbox' 表示收取手机扫码上传落在 inbox 的文件。
|
||||
|
||||
| 参数 | 类型 | 必填 | 默认 | 说明 |
|
||||
|------|------|------|------|------|
|
||||
| `case_id` | string | 是 | — | — |
|
||||
| `paths` | array/null | 否 | — | — |
|
||||
| `source` | null/string | 否 | — | — |
|
||||
|
||||
### `mcp__arb__case_inbox`
|
||||
|
||||
列出手机/PC 上传进来但尚未进入流程的文件。
|
||||
|
||||
| 参数 | 类型 | 必填 | 默认 | 说明 |
|
||||
|------|------|------|------|------|
|
||||
| `case_id` | string | 是 | — | — |
|
||||
|
||||
### `mcp__arb__case_reset`
|
||||
|
||||
清理派生产物以便重跑。scope=extractions|match|info|pages|artifacts|all。
|
||||
|
||||
| 参数 | 类型 | 必填 | 默认 | 说明 |
|
||||
|------|------|------|------|------|
|
||||
| `case_id` | string | 是 | — | — |
|
||||
| `scope` | string | 否 | `"extractions"` | — |
|
||||
|
||||
## 抽取交接
|
||||
|
||||
渲染页面与读文本层由宿主 Agent 自己判断,本服务不调用任何模型。
|
||||
|
||||
### `mcp__arb__case_render_pages`
|
||||
|
||||
为材料准备可读取的页面图片与 PDF 文本层。
|
||||
|
||||
返回每项材料的页 PNG 路径、文本层字符数与自动转正角度。
|
||||
有文本层(text_chars > 0)时应优先读文本层,比读图更准且省 token。
|
||||
|
||||
| 参数 | 类型 | 必填 | 默认 | 说明 |
|
||||
|------|------|------|------|------|
|
||||
| `case_id` | string | 是 | — | — |
|
||||
| `files` | array/null | 否 | — | — |
|
||||
| `dpi` | integer | 否 | `150` | — |
|
||||
| `force` | boolean | 否 | `false` | — |
|
||||
|
||||
### `mcp__arb__case_read_text`
|
||||
|
||||
读取某材料渲染时提取的 PDF 文本层;无文本层时返回空。
|
||||
|
||||
| 参数 | 类型 | 必填 | 默认 | 说明 |
|
||||
|------|------|------|------|------|
|
||||
| `case_id` | string | 是 | — | — |
|
||||
| `file` | string | 是 | — | — |
|
||||
|
||||
### `mcp__arb__extraction_spec`
|
||||
|
||||
返回抽取字段定义。kind 省略给全部文档类型;'info' 给 travel_info/normal_info 骨架。
|
||||
|
||||
| 参数 | 类型 | 必填 | 默认 | 说明 |
|
||||
|------|------|------|------|------|
|
||||
| `kind` | null/string | 否 | — | — |
|
||||
|
||||
### `mcp__arb__case_save_extraction`
|
||||
|
||||
把单张票据的抽取结果写入会话缓存(按 <stem><suffix>.json 约定)。
|
||||
|
||||
日期会规范成 YYYY-MM-DD、金额规范成两位小数字符串;
|
||||
返回 warnings 提示必填缺失,但不阻断写入(完整性由 arb_validate_info 判定)。
|
||||
|
||||
| 参数 | 类型 | 必填 | 默认 | 说明 |
|
||||
|------|------|------|------|------|
|
||||
| `case_id` | string | 是 | — | — |
|
||||
| `source_file` | string | 是 | — | — |
|
||||
| `data` | object | 是 | — | — |
|
||||
|
||||
### `mcp__arb__case_patch_extraction`
|
||||
|
||||
局部修正已落盘的抽取结果(人工核对后改字段用)。
|
||||
|
||||
只合并传入的键,返回每个被改字段的 from/to,避免静默覆盖;
|
||||
未在 schema 中出现的键会告警但仍写入(有些字段是给下游自定义用的)。
|
||||
|
||||
| 参数 | 类型 | 必填 | 默认 | 说明 |
|
||||
|------|------|------|------|------|
|
||||
| `case_id` | string | 是 | — | — |
|
||||
| `source_file` | string | 是 | — | — |
|
||||
| `patch` | object | 是 | — | — |
|
||||
|
||||
## 匹配与校验
|
||||
|
||||
匹配与校验都是确定性代码;结论以 `validate_info` 为准,不要自己宣布可提交。
|
||||
|
||||
### `mcp__arb__match_payments`
|
||||
|
||||
按缓存做发票与支付记录的金额匹配,并写出 CSV 与 invoice_groups.json。
|
||||
|
||||
返回 matched / unmatched_invoices / unmatched_payments / review_required。
|
||||
未匹配与一对多凑额项必须复核,不要盲信贪心结果。
|
||||
|
||||
| 参数 | 类型 | 必填 | 默认 | 说明 |
|
||||
|------|------|------|------|------|
|
||||
| `case_id` | string | 是 | — | — |
|
||||
| `tolerance` | null/number | 否 | — | — |
|
||||
|
||||
### `mcp__arb__info_skeleton`
|
||||
|
||||
按校验规则生成「形状完整、值为空」的可填骨架。
|
||||
|
||||
规则里 required 为 true 的字段(含 remark 这类备注)要求键必须存在,
|
||||
所以别凭记忆拼 JSON:先取骨架再逐个填值。骨架与 validation_rules.json 同源,不会漂移。
|
||||
|
||||
| 参数 | 类型 | 必填 | 默认 | 说明 |
|
||||
|------|------|------|------|------|
|
||||
| `info_type` | string | 是 | — | — |
|
||||
|
||||
### `mcp__arb__save_info`
|
||||
|
||||
写 travel_info 或 normal_info 到缓存,并立刻跑一次规则校验。
|
||||
|
||||
info_type 取 travel|normal。完整性以返回的 validation 为准,
|
||||
不要自己在 data 里塞 can_submit。
|
||||
|
||||
| 参数 | 类型 | 必填 | 默认 | 说明 |
|
||||
|------|------|------|------|------|
|
||||
| `case_id` | string | 是 | — | — |
|
||||
| `info_type` | string | 是 | — | — |
|
||||
| `data` | object | 是 | — | — |
|
||||
|
||||
### `mcp__arb__validate_info`
|
||||
|
||||
校验报销信息完整性。省略 draft 时校验缓存里已存的 info。
|
||||
|
||||
也可传 draft 先试校验不落盘,适合改字段时反复迭代。
|
||||
|
||||
| 参数 | 类型 | 必填 | 默认 | 说明 |
|
||||
|------|------|------|------|------|
|
||||
| `case_id` | string | 是 | — | — |
|
||||
| `info_type` | null/string | 否 | — | — |
|
||||
| `draft` | null/object | 否 | — | — |
|
||||
|
||||
### `mcp__arb__rules_get`
|
||||
|
||||
返回声明式校验规则(config/validation_rules.json),供补字段前对照。
|
||||
|
||||
| 参数 | 类型 | 必填 | 默认 | 说明 |
|
||||
|------|------|------|------|------|
|
||||
| `info_type` | null/string | 否 | — | — |
|
||||
|
||||
## 文档产物
|
||||
|
||||
Excel COM,需本机装有 Microsoft Excel;仅普通发票需要。
|
||||
|
||||
### `mcp__arb__doc_requisition`
|
||||
|
||||
生成低值易耗品申购单(Excel,仅普通发票)。
|
||||
|
||||
exclude 传物品名关键词可剔除不参与申购的发票;project 覆盖「对应实验实训项目」,
|
||||
默认取 normal_info 的报销事由。需要 Windows + 已安装 Microsoft Excel。
|
||||
|
||||
| 参数 | 类型 | 必填 | 默认 | 说明 |
|
||||
|------|------|------|------|------|
|
||||
| `case_id` | string | 是 | — | — |
|
||||
| `exclude` | array/null | 否 | — | — |
|
||||
| `project` | null/string | 否 | — | — |
|
||||
Reference in New Issue
Block a user