MCP server exposing PaddleOCR remote jobs for PDF/image-to-Markdown conversion
Project description
PaddleOCR MCP Server
通过 PaddleOCR 官方 API 将 PDF 或图片转换为 Markdown。服务直接暴露 PaddleOCR 远端任务的提交、查询和保存三个阶段,不创建第二套本地后台任务。
设计概览
ocr_submit(file_path 或 file_url)
↓ 返回 PaddleOCR 远端 job_id
ocr_status(job_id)
↓ 调用方按需重复查询,直到 state=done
ocr_save(job_id, output_dir)
↓ 下载 JSONL、逐页 Markdown 和图片
full.md
PaddleOCR 的 job_id 是唯一任务状态源。MCP Server 不保存本地 job 表,因此进程
重启后仍可继续查询或保存已有远端任务。每个 MCP 调用都是一次短请求,不依赖 MCP
Host 是否支持 progressToken。
本 Server 只暴露 Tools,不提供 Resources 或 Prompts。
环境要求
- Python >= 3.13
- PaddleOCR AI Studio access token
- 推荐使用 uv /
uvx运行
获取 token:https://aistudio.baidu.com/account/accessToken
Server 从环境变量读取 token:
PADDLEOCR_ACCESS_TOKEN
不要把 token 写入提示词、提交到 Git,或输出到 MCP 日志。
安装与 MCP Host 配置
推荐固定版本,避免未来破坏性升级影响现有 Host:
{
"mcpServers": {
"paddle-ocr": {
"command": "uvx",
"args": ["paddle-ocr-server==0.3.0"],
"env": {
"PADDLEOCR_ACCESS_TOKEN": "your-token"
}
}
}
}
运行最新版本时可使用:
PADDLEOCR_ACCESS_TOKEN=your-token uvx paddle-ocr-server
本地开发配置:
{
"mcpServers": {
"paddle-ocr": {
"command": "uv",
"args": [
"--directory",
"/absolute/path/to/servers/paddle-ocr",
"run",
"paddle-ocr-server"
],
"env": {
"PADDLEOCR_ACCESS_TOKEN": "your-token"
}
}
}
}
Tool:ocr_submit
提交本地文件或远程 URL,立即返回 PaddleOCR 的远端任务 ID。本 Tool 不等待 OCR 完成。
参数
| 参数 | 类型 | 必需 | 默认值 | 说明 |
|---|---|---|---|---|
file_path |
string | null |
二选一 | null |
MCP Server 所在机器可读取的 PDF/图片路径 |
file_url |
string | null |
二选一 | null |
PaddleOCR 服务可访问的文件 URL |
use_chart_recognition |
boolean |
否 | true |
是否启用图表识别 |
model |
string |
否 | PaddleOCR-VL-1.6 |
PaddleOCR 模型名称 |
file_path 和 file_url 必须且只能提供一个。本地路径是 Server 机器上的路径,
不是远程 MCP Host 或用户电脑上的任意路径。
当前固定关闭以下 PaddleOCR 可选处理:
useDocOrientationClassify = false
useDocUnwarping = false
返回值
{
"job_id": "remote-paddle-job-id",
"state": "submitted"
}
这里的 submitted 表示 MCP 已取得远端 job_id,不是 PaddleOCR 的实时任务状态。
后续状态以 ocr_status 为准。
Tool:ocr_status
查询一次 PaddleOCR 远端状态,不在 Server 内循环等待。推荐由 Agent 或 Host 每 5 秒左右调用一次;没有必要每秒高频查询。
参数
| 参数 | 类型 | 必需 | 说明 |
|---|---|---|---|
job_id |
string |
是 | ocr_submit 返回的远端任务 ID |
返回值
{
"job_id": "remote-paddle-job-id",
"state": "running",
"extracted_pages": 92,
"total_pages": 343,
"start_time": "2026-07-10 10:26:57",
"end_time": null,
"result_url": null,
"error": null
}
| 字段 | 类型 | 说明 |
|---|---|---|
job_id |
string |
远端任务 ID |
state |
string |
PaddleOCR 返回的原始状态;实测处理中为 running,完成为 done |
extracted_pages |
number |
已处理页数;远端尚未返回进度时为 0 |
total_pages |
number | null |
总页数;任务刚提交时可能为 null |
start_time |
string | null |
远端 startTime 原值;不猜测或转换时区 |
end_time |
string | null |
远端 endTime 原值;通常完成后才存在 |
result_url |
string | null |
完成后的 JSONL 下载地址;处理中通常为 null |
error |
string | null |
远端错误信息 |
任务刚提交时,PaddleOCR 可能只返回 jobId 和 state,暂时没有页数和时间字段;
这是正常状态,不应当视为解析失败。页数按远端批次更新,可能连续几次查询保持不变。
result_url 可能是临时签名地址,不要记录或分享完整 URL。通常无需直接使用它,
将 job_id 传给 ocr_save 即可。
Tool:ocr_save
重新查询远端状态,确认 state=done 后下载并保存结果。如果任务仍在处理中,本
Tool 会明确报错,不会在内部等待。
参数
| 参数 | 类型 | 必需 | 说明 |
|---|---|---|---|
job_id |
string |
是 | 已完成的远端任务 ID |
output_dir |
string |
是 | MCP Server 所在机器上的输出目录 |
返回值
返回生成的 full.md 路径,例如:
/data/ocr/book/full.md
输出结构
output_dir/
├── full.md
├── pages/
│ ├── page_0.md
│ ├── page_1.md
│ └── ...
└── imgs/
└── ...
pages/page_N.md:按所有 JSONL 批次中的layoutParsingResults连续编号full.md:使用\n\n---\n\n连接全部页面imgs/:Markdown 引用的远端图片
PaddleOCR 的 JSONL 一行可能包含多个页面,不能假设“一行等于一页”。Server 会
遍历所有 layoutParsingResults 后连续编号。
复用同一个 output_dir 时,Server 会覆盖本次页面并删除不再存在的
pages/page_数字.md,但不会删除其他人工文件。为避免保留不再引用的旧图片,生产
使用中仍推荐每个文档使用独立输出目录。
Markdown 后处理
保存前会进行以下轻量处理:
- 去掉行内公式
$ ... $边界处的空格 - 将块公式整理为独立的
$$行 - 将三个及以上连续换行压缩为两个
因此输出并非远端 Markdown 的逐字节原样副本。
推荐的 Agent 调用策略
1. 调用 ocr_submit,保存 job_id。
2. 等待约 5 秒。
3. 调用 ocr_status:
- state=done:进入第 4 步;
- state=failed/error:向用户报告 error;
- 其他状态:报告 extracted_pages/total_pages,继续等待。
4. 调用 ocr_save。
5. 返回 full.md 路径,并按需要交给后续翻译或摘要工具。
不要在 Agent 内另造一套本地 job ID;直接持有 PaddleOCR 的 job_id 即可。
错误行为
- 缺少 token:抛出环境变量未设置错误
file_path与file_url未提供或同时提供:拒绝提交- 本地路径不存在或不是普通文件:拒绝提交
job_id为空:拒绝查询或保存- 远端任务未完成:
ocr_save返回当前状态和页数 - 远端任务失败:返回 PaddleOCR 错误信息
- 完成响应缺少
result_url:拒绝生成不完整结果 - 图片路径试图逃逸
output_dir:拒绝写入
网络错误和 PaddleOCR HTTP 错误会直接传递给 MCP 调用方。目前不在 Server 内自动 重试提交请求,以避免创建重复远端任务。
从 0.2.x 升级
0.3.0 是破坏性升级:
- 删除阻塞式
ocr_pdf - 新增
ocr_submit、ocr_status、ocr_save - 不再使用 MCP progress notification
- 轮询责任从 Server 移到 Agent/Host
旧调用方必须按新的三阶段流程调整。
本地开发
cd servers/paddle-ocr
uv sync
uv run pytest -v
uv run paddle-ocr-server
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file paddle_ocr_server-0.3.0.tar.gz.
File metadata
- Download URL: paddle_ocr_server-0.3.0.tar.gz
- Upload date:
- Size: 62.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
99713e01c7bbf9bcb8a6c877ed873c8a23d4566e47be4adc62bd159a1eb08a65
|
|
| MD5 |
910c802acf1691639af1220f5d0acf73
|
|
| BLAKE2b-256 |
f1635ccfe902985a9c6ce0925e89ca1a13a2212e972be34989907396d2cccddd
|
File details
Details for the file paddle_ocr_server-0.3.0-py3-none-any.whl.
File metadata
- Download URL: paddle_ocr_server-0.3.0-py3-none-any.whl
- Upload date:
- Size: 9.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
425448e8681690f4554a69e46775e4a65abc082674f5d3141d667311296d4c78
|
|
| MD5 |
16724c4dd900fc2c92f5a194eb91bdac
|
|
| BLAKE2b-256 |
eed81e354361dc99282d78519cb2c2f154c8e008c24882a07e3e8b8919d8bb54
|