file-analysis
读取指定文件夹中的非结构化文档(pdf docx pptx svg png),帮助进行主要内容摘要和文件结构分析的个人本地 MCP。可挂载到 Claude Code · Codex · Claude Desktop。
文档 | 内容 |
README.md(本文档) | 如何使用 |
要构建什么 — 数据契约 · 工具契约 · 护栏 · 永久拒绝列表 | |
编码代理工作流程 — 工作流 · 审查清单 · 常见错误 |
如果同一事实出现在两处,以 AGENTS.md 为准。
此服务器不做摘要
这是最重要的设计决策。
层级 | 职责 |
MCP 服务器 | 提取 · 结构分析 · 附加证据锚点 · 摘要核对验证 |
宿主模型(Claude Code / Codex) | 撰写摘要 — 同时引用锚点 |
人 | 批准 |
如果服务器连摘要也做,服务器就得用自己的 API 密钥再调用一次模型,而宿主只能拿到摘要结果,无法核对证据。这就会打开一条错误摘要悄悄通过的路径。因此服务器只输出原文和锚点。
Related MCP server: file-analyzer
快速开始
必需环境:Python 3.11 及以上,uv
uv sync --extra devuv run python scripts/make_samples.pyuv run python scripts/smoke_stdio.py如果 smoke_stdio.py 输出 PASS,说明服务器正常 — 它会用真实的 MCP 协议启动服务器,检查 17 条护栏契约,并从 DISCOVER 到 SAVED 完整跑一圈。
如果想用 MCP Inspector 直观查看工具:
uv run mcp dev src/file_mcp/server.py指定要分析的文件夹
修改 config/roots.toml 中的 allowed_roots。这个文件就是服务器的安全边界。
allowed_roots = [
"data/samples",
"C:/Users/<사용자>/Desktop/분석대상",
]不要像 C:/Users/<用户> 这样把整个上级文件夹都放进去 — 那等于没有护栏。服务器在任何情况下都不会打开此列表之外的路径。
宿主连接
Claude Code
claude mcp add file-analysis -- uv --directory "<이-저장소를-클론한-절대경로>" run python src/file_mcp/server.pyCodex — 将 config/codex-config.example.toml 的内容粘贴到 ~/.codex/config.toml 中。
Claude Desktop — 参考 config/claude_desktop_config.example.json。
流水线
flowchart LR
S["scan_folder<br/><i>추정 등급 B?</i>"] --> I["inspect_document<br/><i>확정 등급 A/B/C</i>"]
I --> P["build_analysis_prompt<br/><i>앵커 붙은 원문</i>"]
P --> D(["초안 작성<br/><i>호스트 모델</i>"])
D --> G["check_summary_grounding<br/><i>GR-01 … GR-04</i>"]
G --> V["preview_save_report<br/><i>승인 토큰 발급</i>"]
V --> H{{"사람의 승인"}}
H --> W["save_approved_report<br/><i>유일한 쓰기</i>"]
classDef server fill:#ddf4ff,stroke:#54aeff,color:#1f2328
classDef notserver fill:#ffffff,stroke:#afb8c1,stroke-dasharray:5 4,color:#656d76
classDef write fill:#fff8c5,stroke:#d4a72c,color:#1f2328
class S,I,P,G,V server
class D,H notserver
class W write虚线表示服务器不做的事情。草稿由宿主模型撰写,批准由人来完成。
阶段 | Tool | 读/写 |
DISCOVER |
| 读 |
DISCOVER |
| 读 |
INSPECT |
| 读 |
READ |
| 读 |
READ |
| 读 |
DRAFT |
| 读 |
CHECK |
| 读 |
PREVIEW |
| 读 |
APPROVE | (人) | — |
SAVED |
| 写 |
写工具只有 save_approved_report 一个。 没有批准令牌就不会写入。scripts/smoke_stdio.py 会检查写工具列表,所以如果新增工具,必须同步修改冒烟测试。
等级按内容而非扩展名划分
flowchart TD
X["파일"] --> Y{"확장자"}
Y -->|"docx · pptx"| A["<b>등급 A</b><br/>구조까지"]
Y -->|"png"| C1["<b>등급 C</b><br/>이미지 판독"]
Y -->|"pdf"| PQ{"공백 제거 후 페이지 텍스트<br/>8자 이상?"}
Y -->|"svg"| SQ{"내용 있는<br/>text 노드?"}
PQ -->|"있음"| B1["<b>등급 B</b><br/>본문만"]
PQ -->|"없음"| C2["<b>등급 C</b><br/>스캔 PDF"]
SQ -->|"있음"| B2["<b>등급 B</b><br/>본문만"]
SQ -->|"없음"| C3["<b>등급 C</b><br/>그림"]
classDef ga fill:#dafbe1,stroke:#2da44e,color:#1f2328
classDef gb fill:#ddf4ff,stroke:#54aeff,color:#1f2328
classDef gc fill:#fff8c5,stroke:#d4a72c,color:#1f2328
class A ga
class B1,B2 gb
class C1,C2,C3 gc等级 | 含义 | 读取方式 |
A | 提取到结构(标题层级 · 表格 · 幻灯片单位) |
|
B | 仅提取正文文本 |
|
C | 无文本 |
|
| 未确定。 需要打开才能知道 | 仅存在于 |
scan_folder 不会打开文件,因此无法确定等级。pdf·svg 保持 B?,由 inspect_document 打开后确定。不要把扫描结果中的 B? 当作已确定的值。
样本的布置就是为了证明这一点 — 流程图.svg 包含 text 节点所以是 B,仅图形.svg 只有图形所以是 C。相同的扩展名,不同的等级。
使用宿主模型的视觉能力读取。无需额外依赖,韩文准确度优于 tesseract。如果将来需要离线批量处理,再单独添加 extract_text_ocr 工具。
扫描版 PDF 也无需光栅化器即可读取。 扫描页整体是一张嵌入图片,用 pypdf 取出该图片即可 — 不需要 PyMuPDF(AGPL),也不需要 poppler 二进制文件。
纯矢量绘制的页面无法取出,此时 PDF_PAGE_HAS_NO_IMAGE 错误会提示"需要人工截屏"。不会静默返回空结果。
只返回目录 · 块数 · 字符数 · 确定等级和 estimated_read_calls(读取全部内容所需的调用次数)。它的存在意义就是防止为了了解 300 页 PDF 的概况而把正文灌进上下文。
打开文件的成本与 read_document 相同 — 节省的不是时间,而是上下文。
引用锚点契约
格式 | 锚点 | 含义 |
|
| 第 14 个块(段落或表格行) |
|
| 第 7 张幻灯片第 2 行 / 演讲者备注 |
|
| 第 3 页 |
|
| 第 2 个 |
| (无) | 没有文本,因此也没有锚点 |
每种格式的单位不同,但 read_document 的接口只有一个。所有格式都被扁平化为块的一维列表,只需使用 start/end 即可。一个块具体是什么,由响应中的 unit 告知。
如果更改锚点格式,必须同时修改 grounding.ANCHOR_PATTERN 和黄金集。一旦不一致,正常的引用也会全部被 GR-02 拦截。
证据核对能确认什么、不能确认什么
句子是否引用了锚点 —
GR-01该锚点是否存在于文档中 —
GR-02数字·日期是否在引用块的原文中 —
GR-03直接引用(引号内)是否与原文一致 —
GR-04
摘要是否正确传达了原文的含义
是否遗漏了重要内容
引用的锚点是否是恰当的锚点 (
GR-05只是词汇重叠提示)
通过不代表"正确"。 响应中的 not_verifiable 每次都明确说明这一局限 — 如果假装确认了无法确认的内容,人就会相信"既然通过了应该没错",这比没有验证更危险。
对原文进行润色改写是正常的。核对只检查锚点·数字·直接引用。
保存门禁
preview_save_report 同时检查结构(ST-*)和证据(GR-*),只有在没有任何错误时才发放批准令牌。令牌是 sha256(原始相对路径 + 草稿),所以草稿哪怕改一个字都会失效 — 这样就堵住了"用干净草稿预览、保存另一个草稿"的路径。
save_approved_report 会全部重新检查门禁。它不信任模型所说的"预览已通过"。
顺序 | 检查 | 失败时 |
0 |
|
|
1 | 结构( |
|
2 | 证据( |
|
3 | 批准令牌 |
|
如果已有产物,会覆盖,并在审计记录中保留之前内容的哈希。审计记录(data/outputs/_audit.jsonl)是 append-only 的。
护栏分层(CAR)
分为 Control–Agency–Runtime 三个轴。先确定要修改的文件属于哪个轴。 如果轴不明确,就是设计有问题的信号。
轴 | 问题 | 文件 |
Control | 阻止什么不能做 |
|
Agency | 模型如何选择什么 |
|
Runtime | 发生了什么被记录下来 |
|
各轴的详细契约和依赖方向见 AGENTS.md 第 2 章。
进度状态(读到哪里了)不由服务器持有。 由模型拥有,服务器只在 next_actions 中提示 从 start=N 继续。因此服务器是无状态的,写工具也只有一个保存操作。
自校验
在返回响应之前检查不变量,如果被破坏,返回错误而不是错误答案。
检查 | 阻止什么 |
锚点唯一性·非空 | 证据核对指向错误的块 |
正文行 ↔ 块一致 | 截断在块中间断开导致证据核对失败 |
聚合和 = 行数 | 数量未被代码计算或重复计算 |
等级 ↔ 块矛盾 | 等级为 B 却报告没有可读的块 |
这里被拦截的不是用户输入问题,而是服务器 bug。因此错误消息也不是"请检查文件",而是"这是服务器缺陷,请停止工作并报告"。
可观测性
每次工具调用都会在 data/traces/YYYY-MM-DD.jsonl 中留下一行记录。
uv run python scripts/trace_report.py不记录什么更重要。 分析真实内部文档时,trace 可能会变成该文档的副本。
规则 | 强制方式 |
无正文·摘录·目录文本 |
|
无草稿( | 未注册到 |
无绝对路径 | 折叠为 |
无错误 | 只保留 |
不是靠契约,而是用代码强制并用测试确认(tests/test_trace.py)。如果 trace_dir 位于 allowed_roots 内,trace 会自动关闭 — 这是为了避免用自身记录污染分析目标文件夹。
8 个读工具都带有 readOnlyHint: True,但 trace 会写入文件。
该提示的意思是不修改分析目标文档。trace 是 allowed_roots 之外的仪表日志,也不会通过工具暴露。通过写工具暴露的只有 save_approved_report 一个,冒烟测试会检查这个列表。
评估
uv run python scripts/eval_extract.py将 evals/golden/samples.json 中的期望值与实际提取结果进行对比,并将结果记录到 evals/reports/。pytest 只告诉你"现在是否通过",而这个报告记录的是何时通过了什么。
期望值是 scripts/make_samples.py 向文件中写入了什么之后手工编写的。不是复制提取器的输出。 如果为了让结果通过而修改黄金集,评估就是在让自己通过。唯一正当的修改时机是锚点契约·等级定义·样本内容发生变化时。
依赖
包 | 许可证 | 用途 |
MIT | FastMCP 服务器 | |
BSD | pdf 文本·嵌入图片 | |
MIT | docx | |
MIT | pptx | |
MIT-CMU | png 元数据·图片缩小 |
svg 使用标准 xml.etree 读取 — 零依赖。
为什么不用
PyMuPDF(fitz):性能更好,但因为是 AGPL-3.0,放进内部工具会带来分发条件。如果确实需要表格提取,请添加pdfplumber(MIT)。
不提交的内容
路径 | 原因 |
| 由 |
| 分析结果和审计记录。包含真实文档的摘要 |
| 执行记录。没有正文,但会留下文件名·路径 |
| 本地执行结果。黄金集会提交 |
| 个人路径 |
不要把要分析的真实文档放在这个仓库里。
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- FlicenseNot gradedqualityCmaintenanceEnables AI assistants to interact with local documents (PDF, Markdown, TXT) through tools for discovery, reading, extraction, summarization, comparison, keyword extraction, search, and analysis, ensuring privacy and offline capability.
- FlicenseAqualityCmaintenanceEnables read-only analysis of local unstructured documents by scanning a folder, extracting text and structural metadata, and passing content with truncation and error-awareness to an LLM for summarization.9
- AlicenseAqualityCmaintenanceEnables reading and extracting text from local documents (PDF, Word, Excel, PowerPoint, HWP, Markdown, CSV, etc.) without network access, and provides approval-gated summary saving and file organization.11MIT
- FlicenseNot gradedqualityCmaintenanceEnables local, read-only extraction of text and structure from PDF, DOCX, PPTX, SVG, and PNG files, including OCR for images, directory tree and metadata reporting, with strict path isolation and audit logging.
Related MCP Connectors
AI reasoning checks any document against known international standards before your agent acts on it.
Turn any PDF into structured JSON via AI + OCR: invoices, bank statements, contracts.
Certified SEC EDGAR fact memory for AI agents with zero hallucination and filing provenance.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/goods9999-ai/personal-file-analysis-mcp_test_20260826'
If you have feedback or need assistance with the MCP directory API, please join our Discord server