dual-extract-mcp
Uses Ollama to run a local Qwen3-VL vision model for visual extraction of PDF fields, tables, and formulas, enabling fully offline AI-powered document understanding.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@dual-extract-mcpExtract all fields from the PDF at C:\docs\sample.pdf"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
双路抽取 MCP Server(dual-extract-mcp)
把「MinerU 文本/版面路 + Qwen3-VL 视觉路 + 双路融合裁决」封装成 MCP 工具集(8 个 Tool), 让 Claude Desktop / Cursor 等 MCP 客户端通过 stdio 调用,对本地 PDF 做结构化文档理解 (字段抽取 / 表格 / 公式 / 探查 / 校验)。完全本地、离线、零外部 API。 V2.0 起升级为形态 2「三源两段」:MinerU 结构主路 + OvisOCR2 按需校验 → 文本路内部融合 → 现有 Fusion Engine 二元契约零改动。
状态:v2.0.1(2026-08-10):形态 2「三源两段」——MinerU 结构主路 + OvisOCR2 按需校验 → 文本路内部融合 → 现有 Fusion Engine 二元契约零改动;OvisOCR2 服务端
POST /parse_page422 修复;D-2 真连实测 PASS(p213 95.71% 201/210、p8 95.45% 84/88,实质错值 0);674 回归全绿(+9 deselected)传输:stdio(本期不监听端口)
语言:Python 3.11+(受管 3.13.14 实测可用)
1. 功能一览(8 个 Tool)
Tool | 说明 | 里程碑 |
| 双路+融合主入口(字段抽取) | M3(T03) |
| 文本路单跑(V2.0 起可选 OvisOCR2 校验,触发规则引擎四信号按需调用) | M2(T02) |
| 视觉路单跑(PDF 或独立图片,v1.3 起支持 | M2(T02) |
| 表格(跨页 + 大表分层 + CSV/XLSX) | M4(T04) |
| 公式(LaTeX + PNG 渲染) | M5(T04) |
| 文档探查(页数/表格/图片/公式统计) | M6(T05) |
| 输出结构校验(schema/manifest) | M6(T05) |
| MinerU + Ollama + OvisOCR2 三服务探活(OvisOCR2 可选) | M1 |
完整输入/输出契约见
docs/api.md。
Related MCP server: mdify-mcp
2. 环境要求
Python 3.11+(Windows 优先,Linux 兼容)
本地已部署:
MinerU 服务
http://127.0.0.1:8000(/health返回{"status":"ok"})Ollama
http://127.0.0.1:11434(含qwen3-vl:30b视觉模型)OvisOCR2(可选,V2.0 文本路校验增强):独立进程
http://127.0.0.1:8010(scripts/ovisocr2_server.py+ 独立 venv;默认text_backend=mineru不加载/ 不调用,DUAL_EXTRACT_TEXT_BACKEND=mineru+ovisocr2显式开启)
OvisOCR2 部署(独立 venv,不进主项目 pyproject 依赖;命令以
scripts/ovisocr2_server.py模块 docstring 为权威,V2.0 真连实测验证):# 1. 建独立 venv(复用系统 CUDA 可选 --system-site-packages;用户本机标准命令) python -m venv .venv-ovisocr2 .\.venv-ovisocr2\Scripts\Activate.ps1 # 2. 安装依赖(版本对齐调研实测,与脚本 docstring 一致) pip install "transformers==5.14.1" "torch>=2.6.0,<3.0" ` "fastapi>=0.110.0" "uvicorn>=0.29.0" "pillow>=10.0.0" "modelscope>=1.15.0" # 3. 启动(默认 127.0.0.1:8010;与 MinerU :8000 / Ollama :11434 错开) # 不传 --model 时默认从 ModelScope 下载 ATH-MaaS/OvisOCR2 python scripts/ovisocr2_server.py # 本地模型快照加载(已下载过时用,免重复下载;快照含 model.safetensors) python scripts/ovisocr2_server.py --host 127.0.0.1 --port 8010 ` --model "C:/Users/Administrator/.cache/modelscope/models/ATH-MaaS--OvisOCR2/snapshots/master" # 4. 健康检查(常驻显存 ~1.6GB;模型加载一次常驻,与 Qwen3-VL 串行不并发) curl http://127.0.0.1:8010/health # → {"status":"ok","model":...,"gpu_mem_mb":1626}⚠️ transformers 5.x 坑位(脚本 docstring 权威,服务端已封装,用户无需传参): 显式
eos_token_id=[248046, 248044]防死循环;temperature参数在 Qwen3_5 架构 无效必须省略;do_sample=False;images_kwargs={"min_pixels":448*448,"max_pixels":2880*2880};enable_thinking=False。
⚠️ 沙箱提示:本沙箱内
python -m venv会静默失败,须用受管 Python 建 venv (C:\Users\Administrator\.workbuddy\binaries\python\versions\3.13.12\python.exe -m venv .venv)。 用户本机无此坑,按下方标准命令即可。
3. 安装
# 1. 建 venv(受管 Python 3.13.14;用户本机可直接 python -m venv .venv)
C:\Users\Administrator\.workbuddy\binaries\python\versions\3.13.12\python.exe -m venv .venv
# 2. 激活 + 安装(含测试依赖)
.\.venv\Scripts\Activate.ps1
pip install -e ".[test]"
# 3. 复制配置模板并按需修改(可选;不配则用默认值)
Copy-Item .env.example .env4. 运行
# 开发期直跑(stdio 交互;起几秒确认无报错即可 Ctrl+C)
python -m dual_extract.server
# 或等价的 console script
mcp-server接入 Claude Desktop(claude_desktop_config.json)
{
"mcpServers": {
"dual-extract": {
"command": "D:/Dual-Extract-MCP/.venv/Scripts/python.exe",
"args": ["D:/Dual-Extract-MCP/src/dual_extract/server.py"]
}
}
}接入 Cursor
~/.cursor/mcp.json:
{
"mcpServers": {
"dual-extract": {
"command": "D:/Dual-Extract-MCP/.venv/Scripts/python.exe",
"args": ["D:/Dual-Extract-MCP/src/dual_extract/server.py"]
}
}
}B1:MCP 客户端 CWD 不可控,建议在
.env中把DUAL_EXTRACT_OUTPUT_DIR配成绝对路径。
5. 测试
# 单元测试(默认跳过 smoke)
pytest -q
# 冒烟:真连本机 MinerU/Ollama(需服务在线)
pytest -m smoke -q当前回归:674 passed + 9 deselected(2026-08-10 v2.0.1 全量回归核实,含新增 OvisOCR2 相关测试)。 历史演进:v0.2.1 353 passed → V1.0 406 passed → V1.3.0 615 passed → V2.0.1 674 passed。
5.1 V1.0 增量说明(2026-08-03)
V1.0 在 v0.2.1 基础上新增 5 项可选/默认关能力(全部 additive,当时 schema_version 为 "1.0";当前统一 "1.1",validate_output 兼容 1.0/1.1 白名单双值,旧客户端零改动):
增量 | 落点 | 说明 |
|
| 生成环境信息: |
|
| 产物唯一身份: |
|
| 字段审计 ID: |
| 抽取类 Tool job 结束自动落盘( | 质量报告:17 顶层键, |
|
| 单元格溯源五字段 |
挂接约定(artifact_manifest,V1.0 P2):产物唯一身份由
artifact_id+manifest.json的 SHA256 + 相对路径 三元组确定——artifact_id标识「哪次抽取」,SHA256 保证「内容未被篡改」,相对路径定位「文件在哪」。详见docs/最终输出说明.md§4 /docs/api.md§2.4。
6. 配置项(全部前缀 DUAL_EXTRACT_,仅 config.py 读取)
键 | 默认值 | 说明 |
|
| MinerU HTTP 端点 |
|
| MinerU 请求超时(秒) |
|
| Ollama 端点 |
|
| 视觉模型 |
|
| Ollama 超时(秒;冷启动模型加载可达) |
|
| 视觉路 thinking 开关(G2,默认关) |
|
| 文本路后端: |
|
| OvisOCR2 独立进程 HTTP 端点(V2.0) |
|
| OvisOCR2 模型(ModelScope 仓库 id,V2.0) |
|
| OvisOCR2 整页超时红线(秒;实测 96s × ~1.9 余量) |
|
| OvisOCR2 单表超时(秒;拆表兜底 P2 预留) |
|
| 表格低置信触发阈值(confidence < 此值 → 触发 OvisOCR2 校验) |
|
| 截断兜底比例(token_count ≥ 上限 × 此值 → 判截断降级用 MinerU) |
|
| 服务端生成上限(< 16384 官方上限,防死循环) |
|
| 输出根目录(建议绝对路径) |
|
| true 时输出加时间戳子目录 |
|
| 低置信阈值 |
|
| 页并行(默认串行防 3090 OOM) |
|
| 输入 PDF 大小上限 |
|
| 页数上限 |
|
| 页图/图片 DPI |
|
| 图表/印章裁剪开关 |
|
| 单路降级开关 |
|
| 表格单元格溯源(V1.0;开启后 |
|
| 模型裁判(默认关,v0.4 前不实现) |
|
| 日志级别 |
|
| 临时目录(退出清理) |
|
| CSV 分片行数 |
7. 真实样例用法
# 1. 探查:先「ls」一份 PDF 再决定抽取策略
# inspect_document 返回 {pages, tables, images, formulas, text_chars}
# 样例:232 页财报 → 421 图 / 213,232 字符(MinerU 不可达时自动降级 PyMuPDF)
# 2. 双路字段抽取
# dual_extract(pdf_path="D:/samples/中芯国际_年报.pdf",
# fields=["公司代码","公司简称","法定代表人","报告期","资产总计"],
# field_types={"资产总计":"money","报告期":"date"})
# 3. 表格(跨页 + 大表分层 + CSV/XLSX)
# extract_table(pdf_path="D:/samples/中芯国际_年报.pdf", pages=[10,11],
# format=["json","csv"], cross_page=true)
# 4. 公式
# extract_formulas(pdf_path="D:/samples/中芯国际_年报.pdf", pages=[20],
# render=true, tex=false)
# 5. 校验结果
# validate_output(output_dir="D:/Dual-Extract-MCP/outputs/中芯_年报")
# → {"schema_version": "1.1", "ok": true, "errors": [], "manifest_ok": true}
# (产物目录含 extraction.json + manifest.json;manifest 记录各产物 SHA256,
# validate_output 会与磁盘实文件比对,防产物漂移/被篡改)
# 6. 独立图片字段抽取(v1.3+,截图/扫描件/名单/表格照片,无需先包 PDF)
# vision_extract(image_path="D:/samples/名单.png",
# fields=["公司代码","公司简称","注册资本"])
# → document.source_image 填充 / source_pdf 空串 / 字段 page:0
# 7. OvisOCR2 文本路校验增强(v2.0+,形态 2「三源两段」)
# DUAL_EXTRACT_TEXT_BACKEND=mineru+ovisocr2 python -m dual_extract.server
# dual_extract(pdf_path="D:/samples/中芯国际_年报.pdf",
# fields=["公司代码","短期借款"],
# verify_pages=[1,2]) # 调用级指定校验页(信号②)
# → meta.generation.text_extractors=["mineru","ovisocr2"];
# warnings 含 ovisocr2_crosscheck:p1:rate=1.0 等校验信号;
# 默认 text_backend=mineru 不加载/不调用(零回归)8. 项目结构(四层架构,依赖单向向下)
MCP Layer server.py → mcp/{tools,handlers,converters}.py
↓
Service Layer services/*.py(extract/parse/vision/table/formula/inspect/validate/health)
↓
Pipeline Layer pipelines/*.py + fusion/*.py
↓
Adapter Layer adapters/base.py(接口缝)+ mineru/ollama/storage/ovisocr2 实现与外部服务唯一耦合点 = 四个 Adapter 的 Protocol 接口(
MinerUAdapter/OllamaAdapter/StorageAdapter/OvisOCR2Adapter)。铁律:不建注册表、不预写第二后端(Docling/云模型/对象存储 v0.4+ 再说)。
9. 常见问题(FAQ)
9.1 VPN 代理导致 localhost 请求 502 / 超时(trust_env 陷阱)
Windows 上挂极光 VPN(端口 29290)时,Python httpx 默认 trust_env=True 会读取系统
注册表代理,把 http://127.0.0.1:8000 的 localhost 请求也走代理 → 502。
本项目所有 Adapter 的 httpx.AsyncClient 一律 trust_env=False,无需手动处理。
若在自定义脚本里直接调 httpx,请同样加 trust_env=False。
9.2 Ollama 冷启动 600s 超时
qwen3-vl:30b(30B 模型)首次加载进显存可能耗时 1-5 分钟,第一请求容易超时。
本项目 DUAL_EXTRACT_OLLAMA_TIMEOUT 默认 600 秒,足够冷启动;
若你的显存/磁盘更慢,可调大该值。探活(health)用固定 8s 短超时,不受此影响。
9.3 3090 24G 显存:默认串行防 OOM
qwen3-vl:30b 在 3090 24G 下并行多页易 OOM。默认 DUAL_EXTRACT_PARALLEL=false(串行),
页图渲染也是串行(F1)。若显存充裕可开并行,但建议先压测单页显存占用。
9.4 MinerU 不可达时怎么办
dual_extract/vision_extract/parse_text:自动降级(视觉路单跑或纯文本), 输出warnings标degraded,不整体失败;inspect_document:自动降级为纯 PyMuPDF 本地统计(页数/图片/文本字符),degraded=true+warnings标注。
9.5 输出目录找不到产物
MCP 客户端 CWD 不可控,务必在 .env 把 DUAL_EXTRACT_OUTPUT_DIR 配成绝对路径
(如 D:/Dual-Extract-MCP/outputs)。产物按 pdf_stem 分目录:
{输出根}/{pdf文件名}/extraction.json + manifest.json。
10. Roadmap
v0.2-alpha gate(T01-T03 = M1-M3):骨架 + 单路 + 双路融合闭环 ✅
T04(M4-M5):表格 + 公式 ✅
T05(M6-M7):inspect/validate + 安全加固 + 降级完善 + 文档 ✅
v0.2.0(2026-08-03 转正):G4 gate 真连验收 PASS(8 Tool 真连全通 + 3 P1 修复闭环 + 349 回归全绿)✅
v0.2.1(2026-08-03 发版):BUG-4 MinerUAdapter 子区间页号偏移修复(
parse(pages=[7])时产物 page_idx 从 0 重编号,blocks 全标 page=1;应按 pages[0] 偏移)——commitbec69aa,353 回归全绿(4 个 BUG-4 专项回归)✅V1.0(2026-08-03 增量):
meta.generation/artifact_id/fields[].field_id/quality_report.json自动产出 /tables[].cell_provenance(默认关)——5 项 additive 增量,406 回归全绿,QA 独立验证 PASS ✅V1.2.0(2026-08-04):对齐《程序输出规范 v1.1》六项增量(source/pipeline/models 镜像、0.95 封顶、字段级 source、schema 1.1、cleaning_report、manifest 收敛)——582 回归全绿 ✅
V1.2.1(2026-08-04):MinerU 适配器降级/异常双 bug 修复(HTTP 相对路径 500 + CLI -p 误传)——586 回归全绿 ✅
V1.2.2(2026-08-05):health asyncio 嵌套修复 + BUG-5/6/7 表格取值修复——608 回归全绿 ✅
V1.3.0(2026-08-09):vision_extract 新增 image_path 独立图片输入——615 回归全绿 ✅
V2.0.0(2026-08-09):OvisOCR2 文本路校验增强接入(形态 2「三源两段」)——MinerU 结构主路 + OvisOCR2 按需校验 → 文本路内部融合 → 现有 Fusion Engine 二元契约零改动;纯 additive,
schema_version保持"1.1",默认text_backend=mineru零加载/零调用——674 回归全绿 ✅V2.0.1(2026-08-10):OvisOCR2 服务端
POST /parse_page422 修复(根因:ParsePageRequest/ParsePageResponse原是create_app()内部局部类,FastAPI 局部 Pydantic model 请求体识别失败 → 提升为模块级)+ D-2 真连实测 PASS(p213 95.71% 201/210、p8 95.45% 84/88,均 ≥95% 达标,实质错值 0)+ D-8 文档同步——bugfix 无 API 变更,674 回归全绿 ✅调研完成:复杂表格页降载策略(docs/复杂表格页降载策略.md)+ OvisOCR2 vs MinerU 对比(docs/OvisOCR2_vs_MinerU_对比报告.md)+ 模型分类与升级路线(docs/模型分类与升级路线.md)
后续登记(保持 roadmap):
OvisOCR2 文本路 Adapter 立项(需先补 16k 截断兜底设计)→ ✅ 已完成(V2.0);VLM 线评估 Qwen3.6-35B-A3B(排在 OvisOCR2 之后);模型裁判(C3 默认关)→ v0.4 前不实现(保留原条目)多后端注册表(Docling/云模型/对象存储)→ 保持 roadmap
详细设计见 docs/技术方案设计_双路抽取MCP.md / docs/双路抽取MCP_架构设计.md /
docs/双路抽取MCP_PRD.md / docs/architecture.md / docs/api.md。
输出质量评估(三层框架 + 可执行脚本)见 docs/输出质量评估指南.md / tools/assess_output_quality.py。
This server cannot be deployed
Maintenance
Related MCP Connectors
Hosted MCP server: convert PDFs to clean, LLM-ready Markdown with tables, formulas and OCR.
Document-to-Markdown MCP server — convert PDF, Office and HTML into LLM-ready Markdown.
High-fidelity PDF to structured Markdown conversion and document field extraction.
- docs2mcpOAuthcom.docs2mcp
Query your own PDFs and documents from any MCP client. Every answer cites the page it came from.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceA local MCP server that extracts text-layer content from PDF files, enabling AI agents to inspect, extract text, outlines, and page content.-
- AlicenseNot gradedqualityDmaintenanceMCP server that gives LLMs the power to convert PDFs to Markdown on the fly using a local Ollama vision model.Apache 2.0
- AlicenseAqualityDmaintenanceA local-first MCP server that ingests PDFs, extracts structure, and provides semantic search and sequential navigation tools for AI clients to query and learn from documents.10MIT
- AlicenseAqualityCmaintenanceFast, local PDF parsing as an MCP server with text extraction, bounding boxes, OCR, and visual citations. No cloud or API key required.5MIT