doc-redactor
# doc-redactor
本地优先的**多格式文档脱敏**工具:**检测 → 真删除 → 取证审计**,全程零网络调用。
支持 PDF(文字型 + 扫描件)、DOCX、XLSX、PPTX、TXT/MD/CSV/JSON 等。
可作为 MCP server 接入 AgenticX 等任意支持 MCP 的 Agent 框架,或作为 Python 库直接使用。
格式路由采纳 [AgenticX](https://github.com/DemonDamon/AgenticX) KB 的扩展名分类;
检测层格式无关(一份检测代码服务全部格式),执行层逐格式真删除。
## 能力矩阵
| 泄露面 | PDF 文字型 | PDF 扫描件 | DOCX | XLSX | PPTX | TXT/MD |
|---|---|---|---|---|---|---|
| 正文本体 | 内容流物理移除 | OCR 定位 + 图像像素真删除 | 段落/表格 run 级替换(跨 run 重建) | 全 sheet 单元格(含隐藏 sheet) | shape/表格/组合形状递归 | 直接替换 |
| Logo / 嵌入图 | SIFT 模板匹配(宽高比 + NCC 双校验) | 同左 | — | — | — | — |
| 扫描页 | 自动识别(文本量阈值)→ RapidOCR | ✓ | — | — | — | — |
| 元数据 | docinfo + XMP 全清 | 同左 | core.xml 属性 | 属性 + 透视缓存天然清除 | core.xml 属性 | 无 |
| 修订记录 | — | — | w:del/w:ins 全接受 | — | — | — |
| 批注 | 注释/表单 | — | comments.xml 替换 | 单元格批注 | — | — |
| 页眉页脚/备注 | — | — | 页眉页脚(含首页/偶数页) | — | 备注页 | — |
| 取证审计 | 对象流/隐藏文本/增量保存/logo 回扫 | OCR 回扫 | 解压逐部件搜词 + 修订残留检查 | 同左 + 隐藏 sheet | 同左 | 重读全文 |
检测层(全格式共享):关键词词典 + 正则(手机/身份证/邮箱/银行卡)+ spaCy 中文 NER(可选)。
OCR 文本经 NFKC 归一化后再检测(OCR 常把数字识别成全角),命中区域按字符占比切分,宁大勿漏。
## MCP 工具(两阶段安全设计)
- `redact_scan` — 非破坏性扫描(自动识别格式),返回候选清单 + 元数据泄露 + 格式相关清单
- `redact_apply` — **只执行确认过的词条清单**(不吃自动判断)
- `redact_audit` — 取证审计,交付前必须 PASS
- `extract_image` — 提取 PDF 嵌入图像作为 logo 脱敏模板
- `glossary_list / add / remove` — 敏感词词典闭环(`~/.doc-redactor/glossary.json`)
安全原则:Agent 永远不能静默决定"什么算敏感"——scan 出候选、用户确认、apply 只吃确认清单、audit 兜底。
## 安装
```bash
git clone https://github.com/agxhub/doc-redactor && cd doc-redactor
uv venv .venv --python 3.11
uv pip install --python .venv/bin/python -e ".[ner]"
.venv/bin/python -m spacy download zh_core_web_trf # 可选:NER 检测
```
## 注册到 AgenticX
在 `~/.agenticx/mcp.json` 添加:
```json
{
"mcpServers": {
"doc-redactor": {
"command": "/path/to/doc-redactor/.venv/bin/python",
"args": ["mcp_server.py"],
"cwd": "/path/to/doc-redactor",
"timeout": 300.0
}
}
}
```
## Python 库直接使用
```python
from docredactor import scan_document, apply_redaction, audit_document
scan = scan_document("合同.docx", keywords=["张伟"], enable_ner=True)
# 用户确认候选后
apply_redaction("合同.docx", "合同_脱敏.docx", terms=["张伟", "13800138000"])
report = audit_document("合同_脱敏.docx", terms=["张伟", "13800138000"])
assert report["verdict"] == "PASS"
```
## Roadmap
- 旧版二进制 Office(.doc/.ppt/.xls):需 LibreOffice 预转换,评估中
- 图像文件(PNG/JPG)直接脱敏:OCR + 像素涂黑管线已具备,待封装
- .docx 内嵌对象(OLE)与图表 XML 泄露面深化
## License
AGPL-3.0-or-later(PyMuPDF 执行层传染)。检测层与审计思路可参考实现。
TDQS
Scored across 7 tools
Each tool has a clearly distinct role: scanning, applying, auditing, glossary management, and image extraction. Even redact_scan and redact_audit are sharply differentiated as pre-redaction candidate discovery versus post-redaction forensic verification.
Most tools follow a clear domain-prefix pattern: redact_* for document operations and glossary_* for dictionary operations. The exception is extract_image, which uses verb+noun ordering rather than prefix+operation, creating a minor but noticeable inconsistency.
Seven tools is well-scoped for a document redaction server. Each tool fills a necessary role in the workflow without redundancy or bloat, and the count supports a complete redaction pipeline.
The toolkit covers the full redaction lifecycle: scan for candidates, apply redaction, audit the result, and persist confirmed terms in a glossary. Supporting image extraction and glossary management fills the surrounding workflow needs, leaving no obvious dead ends.