# Devlog · N2 服务化收官:MCP(零依赖)+ REST(axum)——agent 可直连

> 日期:2026-06-10 · plan:[plans/n2-serving.md](../plans/n2-serving.md) · 验收:[testresults/2026-06-10-n2-serving.md](../testresults/2026-06-10-n2-serving.md)
> 本日另两项前置工作:chunk 栏序修复([devlog](2026-06-10-chunk-order-fix.md),NID vs ODL 0.722→0.761 / vs Docling 0.763→0.832)、roadmap 记分牌两档化改写。

## 决策记录

1. **次序反转:MCP 先于 REST**(原计划 REST 先)。依据:MCP stdio 只是行分隔 JSON-RPC 2.0 的三个方法(initialize/tools/list/tools/call),`serde_json` 手写即可——**零新依赖**先兑现"agent 可直连";REST 需要 axum+tokio,按 CLAUDE.md §4 征询后才动工(用户当日批准)。
2. **不引 MCP SDK**:协议面钉在 rev 2025-03-26 最小集,模块 `//!` 注明;spec 大改再评估 `rmcp`。
3. **跨接口字节一致是验收门**:REST 响应 body 与 CLI stdout `cmp` 逐字节相同;为此 source 注释用上传文件名替换暂存路径(顺带不泄露服务器 temp 路径、保确定性),计时走 `x-docparse-ms` 头不污染 body。
4. **同机信任模型**:MCP 吃本地路径、REST 绑 127.0.0.1;认证/对外暴露/资源防护显式划给 N5,不过早造编排机器。

## 落点

- `crates/docparse-cli/src/mcp.rs`:`docparse mcp`,tool 面 `parse_document`/`get_chunks`(provenance+quality 信封)/`locate`(坐标反查引用)。协议错误走 JSON-RPC error,工具失败走 `isError: true`,server 永不因坏输入退出(对齐"坏页出空 Page")。
- `crates/docparse-cli/src/server.rs`:`docparse serve --port`,`POST /parse`(multipart,json/markdown/text/chunks)+`GET /healthz`;解析跑 `spawn_blocking`;400/422 错误语义。
- `main.rs`:`parse_path` 抽为四接口(CLI/库/MCP/REST)共用入口;clap 子命令与位置参数 `args_conflicts_with_subcommands` 共存。
- 依赖:workspace 加 axum(multipart)+tokio(rt-multi-thread,net),特性裁剪;二进制 5.39→6.60MB(差异化门 20MB 余量充足)。

## 验收摘要(详见 testresults)

MCP:真 PDF 111 chunks 全带 bbox,locate 取 bbox 中心反查命中同一 chunk;坏路径 isError 后 ping 仍活;同请求逐字节一致(单测钉死)。REST:curl 上传与 CLI 输出 cmp 一致;未知 format 422/无文件 400/损坏 PDF 422 全程存活。63 单测、clippy 零 warning、三件套零回归。

## review 加固(commit 后自查)

表格拼接谓词对已插入表格原来只比 y 不查 x 重叠——左右栏各一张表时右栏表会跳到左栏表前。统一为 `follows`(x 重叠 + 上缘更低);基准集无此场景,分数不动,属正确性加固。

## 剩余 / 下一步

- N2 范围内不做:认证、多租户、任务队列、流式(YAGNI 按需)。
- 近期仅剩 **N3 真实 enhancer**(需 OCR/模型选型征询)与 **N5 安全预检**(隐藏文本过滤/资源防护——有了对外接口后优先级上升)。
