7e900ebdea
历史清洗删掉了根目录两份 低值易耗品申购*.xls——它们其实是**已填写的真实申购单** (半导体型号、单价、项目名都在),不是模板;同时旧实现「项目根 glob 取名字最大者」会把 上一次生成的产物当模板,所以一并修掉: - 新增 resolve_requisition_template():REQUISITION_TEMPLATE 环境变量 → templates/ → 项目根(兼容旧位置); 环境变量指向不存在的文件时告警并继续回退,不静默失败 - 入库 templates/低值易耗品申购.xls 空白件(由旧文件删掉第 3 行起的全部内容得到,UsedRange 只剩 2 行: 标题 + 表头;真实采购明细不进仓库) - generate_requisition 默认输出改为 <会话>/artifacts/低值易耗品申购<ts>.xls,不再写模板旁边 - mcp/tools/documents.py 的 _find_template 改为复用同一解析函数,避免两处规则漂移 - 模块 docstring 与 CLI help 里 src/web/uploads 的过时示例改为 cases/ - tests:5 个纯单测覆盖解析优先级(env 优先 / templates 胜过根目录 / 根目录取最新 / env 指向不存在的文件时回退 / 全都没有时返回 None),不依赖 COM 验证:真实 Excel COM 端到端 2 项 → 产物 UsedRange 5 行(标题/表头/2 明细/合计),第 6 行起为空, 无旧明细残留;fill_requisition_excel 原本就会先删第 3 行起内容,这条也实测确认过。 门禁:ruff / format --check / mypy src / deptry 全绿,pytest 112 passed,mcp_smoke 17 工具。
last_reviewed
| last_reviewed |
|---|
| 2026-10-19 |
src/mcp — 工具与协议层
MCP 服务器的全部对外面。17 个工具的参数表在 docs/MCP.md(那份表由运行时 schema 生成,与代码同源)。
| 文件 | 职责 |
|---|---|
server.py |
MCPServer(name=auto-reimbursement, instructions=INSTRUCTIONS)、TOOLS 注册表、build_server()、main() 走 stdio |
tools/materials.py |
会话与材料:create / list / status / add_files / inbox / reset |
tools/extraction.py |
抽取交接:render_pages / read_text / save_extraction / patch_extraction / extraction_spec |
tools/analysis.py |
匹配与校验:match_payments / info_skeleton / save_info / validate_info / rules_get |
tools/documents.py |
产物:doc_requisition(经 run_com) |
schemas.py |
七类票据的字段定义、日期与金额规范化;invoice_type 非法直接拒收 |
envelope.py |
ok(**data) / fail(reason, next_action=..., **detail) |
写工具的规矩
- 返回信封,不抛异常穿透协议:文件缺失、参数不合法、COM 失败都转成
ok: false+reason+next_action next_action写给 Agent 看,尽量是具体工具名,让它照着做- 不返回密码、令牌明文等敏感值;上传令牌只从
case_create的页面地址里给一次 - 未实现的能力不要出现在 INSTRUCTIONS 里,也不要在工具描述里暗示存在
- 新增工具后:
make mcp-smoke验 wire 清单;宿主侧要重连(杀掉 stdio 子进程会自动重启并重同步工具)
已知宿主侧坑
- DSH 会清洗 stdio 子进程的环境变量(抹掉含 KEY/PASSWORD/SECRET/TOKEN 的以及全部
DSH_*), 所以凭据只能来自scripts/data/config.json - DSH 的参数绑定要求 JSON 无损:Windows 路径必须正斜杠,反斜杠会被拒
- 结果可能被包在
content[0].text(JSON 字符串)里,同时给structuredContent - 服务器 import 与构造必须无副作用:stdio 协商阶段会先起一个临时探针进程