npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@vandoor2/mineru-mcp

v0.4.0

Published

MinerU document parsing MCP server — PDF / Office / image / URL to Markdown, via local MinerU client + cloud API hybrid.

Readme

mineru-mcp

基于 MinerU 的文档解析 MCP Server —— 把 PDF、Office 文档、图片和网页 URL 解析为 Markdown 与图片文件,直接接入 Claude Code 等 MCP 客户端。

功能特点

  • 多格式解析:PDF(.pdf)、Word(.doc/.docx)、PPT(.ppt/.pptx)、Excel(.xls/.xlsx)、图片(.png/.jpg/.jpeg/.jp2/.webp/.gif/.bmp)
  • URL 解析:支持 http(s) 网页链接与文件直链
    • 网页链接 → MinerU 云端直连解析(云端自动抓取页面,无需本地浏览器或 Playwright)
    • 文件直链 → 自动下载后按本地文件流程解析
  • 自动路由:根据页数 / 是否含图 / 文件大小自动选择解析方式
    • 无图片且 ≤20 页、≤10MB → Agent 轻量解析 API(免 token,仅输出 Markdown)
    • 有图片且页数 ≤200(或页数未知)→ Precision Extract API(输出 Markdown + 图片 + 中间 JSON)
    • 页数 >200 → 自动按 ≤200 页切分,分别解析后合并 Markdown
  • 异步任务:document_parse 提交后立即返回 task_id,解析在后台执行;用 get_task_progress 查询进度、是否完成、输出路径,以及未完成时的剩余时间与预计完成时间
  • 凭证自动获取:优先使用项目配置中的 token → MinerU 客户端本地 config.json → 静默唤起客户端 → 内置访客额度
  • TUN 环境可用:解析请求以 trust_env=False 直连,并在被 Clash Verge 等 TUN 模式劫持到 fake-ip 时,用 DoH 解析出的真实 IP 重试(证书校验全程开启)
  • 零中断:MCP 工具调用不干扰主对话上下文

安装

方式一:npm 包(推荐,客户端零配置)

npx -y @vandoor2/mineru-mcp

MCP 客户端里直接这样写即可,不需要克隆仓库、不需要手动装依赖。

launcher(bin/cli.js)按以下优先级选择运行时:

  1. uv(若已安装):uv run --directory <包目录> mcp_server.py,自动创建虚拟环境并安装依赖(首次较慢,之后复用缓存)
  2. python(兜底):在 ~/.mineru-mcp/venv 建一个持久虚拟环境并安装依赖,之后复用

两者至少要有其一:

  • uv:Windows powershell -c "irm https://astral.sh/uv/install.ps1 | iex";macOS / Linux curl -LsSf https://astral.sh/uv/install.sh | sh
  • 或 Python 3.10+(自带 venv 与 pip)

launcher 环境变量:

| 变量 | 说明 | |---|---| | MINERU_MCP_VENV | python 兜底时持久 venv 的位置(默认 ~/.mineru-mcp/venv) | | MINERU_MCP_PIP_INDEX | python 兜底安装依赖时的 pip 源,如 https://pypi.tuna.tsinghua.edu.cn/simple;不设则沿用 pip 自身配置(PIP_INDEX_URL / pip.ini) | | MINERU_MCP_UV | 手动指定 uv 可执行文件路径 | | MINERU_MCP_CONFIG_PATH | 配置目录。npm 安装时默认 ~/.mineru-mcp/config(避免 npx 缓存清理 / 升级丢配置),显式设置时以显式值为准 |

方式二:克隆源码

git clone https://gitee.com/vandoor2/mineru-mcp.git
cd mineru-mcp
uv sync

在 MCP 客户端中接入

npm 包方式(推荐):

{
  "mcpServers": {
    "mineru-mcp": {
      "command": "npx",
      "args": ["-y", "@vandoor2/mineru-mcp"]
    }
  }
}

Windows 上 npx 实际是 npx.cmd,部分 MCP 客户端不会自动过 shell,需要显式包装:

{
  "mcpServers": {
    "mineru-mcp": {
      "command": "cmd",
      "args": ["/c", "npx", "-y", "@vandoor2/mineru-mcp"]
    }
  }
}

⚠️ 已知限制:npx 方式不能在「本仓库源码目录内」使用。 若客户端的工作目录是本仓库(或它的任意子目录),npx -y @vandoor2/mineru-mcp 会失败并报 'mineru-mcp' is not recognized as an internal or external command。

原因:npm 发现当前目录 package.json 的 name 就是 @vandoor2/mineru-mcp, 判定「本地已有这个包」,于是跳过安装、直接去跑本地 bin;而本仓库不含 node_modules/.bin,就退化成裸命令名交给 cmd,必然找不到。

影响范围:仅当工作目录是该 npm 包的源码目录(含子目录)时发生;在其它任何项目中都正常。

两种规避方式(择一):

  1. 在本仓库内改用下面的「源码方式」配置;

  2. 强制换到中立目录再跑 —— 注意这会把进程的工作目录一并改掉, 因此相对路径的 output_dir 会解析到 %TEMP%,产物会落到临时目录:

    {
      "mcpServers": {
        "mineru-mcp": {
          "command": "cmd",
          "args": ["/c", "cd /d %TEMP% && npx -y @vandoor2/mineru-mcp"]
        }
      }
    }

实测环境:npm 11.12.1 / node v24.14.1 / Windows(2026-09-30)。

源码方式:

{
  "mcpServers": {
    "mineru-mcp": {
      "command": "uv",
      "args": [
        "--directory",
        "<你的项目路径>",
        "run",
        "mcp_server.py"
      ]
    }
  }
}

也可以直接运行 uv run mcp_server.py(stdio 协议),或用 uv run mcp dev mcp_server.py 调试。

在项目中给模型的使用约定示例:

## 文档解析
- 解析 PDF、Office 文档、图片、网页 URL 时,只使用 `mineru-mcp` MCP 中的 `document_parse` 工具。
- `document_parse` 是异步提交,立即返回 `task_id`;不要因为没看到结果就重复提交。
- 提交后优先用 `wait_for_task(task_id="...")` 阻塞等待完成(自动转后台、完成即唤醒,不必轮询);
- 用 `get_task_progress(task_id="...")` 查询进度、是否完成、输出路径与剩余时间;
  不传 `task_id` 可一次列出所有未完成任务。

MCP 工具说明

本服务提供 4 个工具。

document_parse

提交一个解析任务,立即返回任务编号(不等待解析完成)。

| 参数 | 类型 | 必填 | 说明 | |---|---|---|---| | input_path | string | 是 | 待解析文件路径或 URL | | output_dir | string | 是 | 输出目录,结果写入 <文件名>.md 与 images/ | | keep_intermediate | bool | 否 | 是否保留中间文件(layout.json、content_list.json、原始文档副本等)。默认使用 config/features.json 中的全局设置 | | timeout_seconds | int | 否 | 后台解析的总超时(秒)。默认使用 config/features.json 中的全局设置(默认 0 = 不超时)。超时会把已完成部分落盘,任务状态记为 timeout |

返回字段(JSON 字符串,通常 < 0.1 秒返回):

  • status:固定为 submitted
  • task_id:任务编号,后续用它查询进度与取结果
  • input_path / output_dir / keep_intermediate / timeout_seconds:本次任务实际采用的参数
  • hint:下一步怎么做(优先 wait_for_task 等待完成,或用 get_task_progress 查询)

⚠️ 返回值里没有 Markdown 正文。解析结果要通过 wait_for_task / get_task_progress(task_id=...) 获取。

wait_for_task

阻塞等待一个解析任务进入终态(completed / failed / timeout / cancelled), 返回与 get_task_progress(task_id=...) 同形的单条结果。

| 参数 | 类型 | 必填 | 说明 | |---|---|---|---| | task_id | string | 是 | 任务编号(document_parse 提交时返回) | | timeout_seconds | int | 否 | 最长等待秒数(夹取到 1-3600),默认 1800 | | include_text | bool | 否 | 已完成任务是否返回完整 Markdown 正文(text_content) |

三种返回:

  • 已终态:立即返回,wait_timed_out=false,条目结构与 get_task_progress 完全一致
  • 等待超时:返回当前进度快照,wait_timed_out=true;任务仍在后台运行,可再次调用续等
  • 任务不存在 / 等待中被清理:count=0 + error,不抛异常

等待期间每 30 秒上报一次进度用于保活。与 Claude Code 的配合:工具调用跑过客户端的 自动转后台阈值(默认 2 分钟,属 Claude Code 侧配置 CLAUDE_CODE_MCP_AUTO_BACKGROUND_MS, 不是本项目的配置)会自动转为后台任务,模型立即继续其它工作,调用落定时以 task notification 唤醒——所以提交后直接 wait_for_task 即可,不需要轮询。 该工具只受自身 timeout_seconds 约束,没有全局超时(agent_timeout_seconds 机制已移除)。

get_task_progress

查询解析任务的进度:是否完成、输出路径、剩余时间与预计完成时间。

| 参数 | 类型 | 必填 | 说明 | |---|---|---|---| | task_id | string | 否 | 任务编号。留空则返回所有未完成(pending / running)任务 | | limit | int | 否 | 最多返回条数(1-100),默认 20 | | include_finished | bool | 否 | 不传 task_id 时,是否把已结束任务也列出来 | | include_text | bool | 否 | 已完成任务是否返回完整 Markdown 正文(text_content) |

每条任务的关键字段:

| 字段 | 含义 | |---|---| | status | pending / running / completed / failed / timeout / cancelled | | finished | 是否已结束 | | output_md、images_dir | 产物路径(完成后有值) | | summary | 一句话进度描述,如 第 2/3 分片 \| 共 500 页 | | elapsed_seconds | 已用时(秒) | | remaining_seconds、eta_at | 剩余时间(秒)与预计完成时间(本地时间文本),未完成时给出 | | eta_basis | 估算依据:chunk(分片进度,最准)/ pages(云端页数进度)/ history(同类型历史均值)/ heuristic(页数经验值)/ deadline(超时上限)/ finished | | progress | 原始进度字典(state、chunk、total_chunks、page_count、extract_progress、updated_at…)。注意其中的 mineru_task_id / mineru_batch_id 是 MinerU 云端单号,与工具返回的任务编号无关 | | progress_updated_at | 最近一次进度心跳时间(服务端每 5 秒刷新) | | text_content / text_content_preview | Markdown 正文(include_text=true 时给全文,否则给前 500 字预览) | | stale_warning | 运行中任务超过 90 秒没有进度更新时的提示(可能已中断) |

get_recent_logs

查询最近的解析任务与调用记录,用于排查状态和历史。

| 参数 | 类型 | 必填 | 说明 | |---|---|---|---| | limit | int | 否 | 返回记录数量,默认 10 | | tool_name | string | 否 | 按工具名过滤(如 document_parse),为空返回全部 |

返回 {"logs": [...]},每条记录包含 source(task=进行中任务 / usage=已完成调用)、time、tool、status、latency、progress、progress_updated_at、task_id、error 等。

task_id 只在 document_parse 的调用记录里非空(提交时生成的任务编号), 可以用它反查任务结果:get_task_progress(task_id=...)。

进行中的任务永远排在前面且不会被截断(它们的 time 取最近一次进度心跳时间), 因此解析进行中也能在日志里直接看到该任务。

配置

配置位于项目根目录的 config/ 目录(已被 .gitignore 忽略)。文件不存在时会自动使用默认值。

config/features.json

{
  "document_parse": {
    "enabled": true,
    "keep_intermediate": false,
    "timeout_seconds": 0,
    "allow_private_hosts": false,
    "task_retention_hours": 24
  }
}

| 字段 | 说明 | |---|---| | enabled | 文档解析总开关。关闭后 MCP 不再暴露 document_parse,直接调用会返回「未启用」错误 | | keep_intermediate | 是否保留中间文件(layout.json、content_list.json、原始文档副本等),默认 false | | timeout_seconds | 后台解析的总超时(秒),0 表示不设超时,默认 0。MCP 工具与 cli.py parse 都读这个值 | | allow_private_hosts | 是否允许解析指向内网 / 回环 / 云元数据地址的 URL,默认 false(SSRF 防护开启)。确有内网自建服务时才打开 | | task_retention_hours | 任务与调用记录的保留小时数,默认 24;0 表示永不清理。服务端每小时维护一次:清理结束超过该时长的任务与同样超期的调用记录。心跳静默超过 2 小时的僵尸任务会被置为 failed(不受此值影响) |

config/app_settings.json

{
  "mineru_client_token": ""
}

| 字段 | 说明 | |---|---| | mineru_client_token | 从 MinerU 客户端提取的 client_api_token;留空则回退到访客额度 |

环境变量

| 变量 | 说明 | |---|---| | MINERU_MCP_CONFIG_PATH | 覆盖配置目录位置(默认 <项目根>/config;npm 安装方式下由 launcher 默认到 ~/.mineru-mcp/config,显式设置时以显式值为准) |

MinerU 凭证获取顺序

  1. config/app_settings.json 中手动填写的 mineru_client_token
  2. MinerU 客户端本地配置 ~/MinerU/config.json 中的 client_api_token(在客户端登录一次即可)
  3. 静默唤起 MinerU 客户端,等待其写回新 token 后自动关闭
  4. 内置访客 JWT(兜底,额度有限)

如需完整额度:在 mineru.net 下载并登录一次桌面客户端;或自行把客户端配置里的 client_api_token 复制到 config/app_settings.json。

命令行工具(可选)

删掉 GUI / HTTP 配置后端之后,凭证管理与排查入口就落在 cli.py 上。它不改变 MCP 工具面,对外始终只有 document_parse、wait_for_task、get_task_progress、get_recent_logs 四个工具。

# 查看客户端是否安装、token 来自哪一层、配置目录与功能开关(纯只读,不会唤起 MinerU 客户端)
uv run python cli.py status            # 加 --json 便于脚本读取

# 手工管理 MinerU 凭证
uv run python cli.py token set <TOKEN>
uv run python cli.py token clear

# 不走 MCP,在终端直接跑一次解析,看到 status / method / error / progress 原始字段
uv run python cli.py parse <输入> <输出目录> [--json] \
    [--keep-intermediate|--no-keep-intermediate] [--timeout N]

执行过 uv sync 后也可以直接用 mineru-mcp-cli ...(由 pyproject.toml 的 [project.scripts] 注册)。

⚠️ 非 ASCII 项目路径下 console script 会启动失败。 若项目目录含中文等非 ASCII 字符(例如 D:\文档\...),mineru-mcp 与 mineru-mcp-cli 都会以 ModuleNotFoundError: No module named 'mcp_server'(或 cli)结束。 原因:可编辑安装生成的 .pth 由 uv 以 UTF-8 写入,而 CPython 的 site.py 按 系统区域编码(中文 Windows 为 GBK)读取它,路径解码成 D:\鑲愬銆\... 这类乱码, 因目录不存在被静默丢弃,于是 sys.path 里根本没有项目根。 规避方式二选一:

  1. 用 uv run python cli.py ... 代替(始终可用,推荐);
  2. uv sync --no-editable —— 把文件实际复制进 site-packages,不再依赖 .pth 路径。代价是之后改源码需重新 uv sync 才会被 console script 看到。

MCP 链路不受影响:客户端配置走的是 uv --directory <目录> run mcp_server.py, 直接执行脚本文件,不经过 console script。

| 子命令 | 用途 | |---|---| | status | 客户端路径与版本、当前 token 的来源层级与前 12 位预览、配置目录、功能开关 | | token set <TOKEN> | 写入 config/app_settings.json 的 mineru_client_token | | token clear | 清空,退回自动获取(客户端本地配置 → 静默唤起 → 内置访客 JWT) | | parse <输入> <输出目录> | 直接调用解析核心,输出原始字段 |

退出码(parse):0 completed、1 failed(或配置/IO 错误)、2 timeout(任务仍在后台跑)、3 cancelled、64 参数用法错误。

MCP 与 CLI 的一致与差异:两条链路都读 config/features.json 的全局设置 (keep_intermediate / timeout_seconds)。差别只在是否等待:document_parse 工具立即返回 task_id,解析在服务端后台继续;cli.py parse 则同步等待到解析结束再打印结果。

常见问题

解析请求失败但浏览器能正常访问? 解析请求以 trust_env=False 直连 MinerU 服务,不走系统代理环境变量(HTTP_PROXY / HTTPS_PROXY)。 注意 trust_env=False 绕不过 Clash Verge 等工具的 TUN 模式:TUN 在网络层把域名劫持到 fake-ip 段(198.18.0.0/15),表现为 TLS 握手失败或上传中断。本项目的对策是 DoH 解析真实 IP 后重试(_request_with_tun_bypass),并保持证书校验开启。

解析超时了? timeout_seconds 到期不会中断已完成的产出:任务状态记为 timeout,已完成分片的结果照常落盘 (output_md 指向部分产物)。用 get_task_progress(task_id=...) 查看 progress 与 output_md。

提交后怎么拿结果? document_parse 只返回 task_id。优先 wait_for_task(task_id="...") 阻塞等待(自动转后台、 完成即唤醒,无需轮询);要随时看进度用 get_task_progress(task_id="..."):finished=true 时 output_md 就是产物路径;正文可用 include_text=true 取回,或直接读取该文件。

任务一直卡在 running? 后台解析跑在 MCP 服务进程里,客户端退出会终止它。若 get_task_progress 返回 stale_warning (超过 90 秒没有进度心跳),说明任务很可能已中断,需要重新提交。

URL 解析被拒绝了? URL 输入会做 SSRF 校验(拒绝内网 / 回环 / 云元数据地址,重定向逐跳复检)。 确有内网自建服务需要解析时,在 config/features.json 打开 document_parse.allow_private_hosts。

200 页以上的 PDF 会不会解析不了? 不会:会自动按 ≤200 页切分,逐片解析后合并为一份 Markdown,耗时随页数增长,建议适当调大 timeout_seconds。

任务和调用记录会不会一直堆积? 不会。服务端每小时自动维护一次:清理结束超过 task_retention_hours(默认 24 小时)的任务与调用记录, 并把心跳静默超过 2 小时的僵尸任务置为 failed。要长期保留就把该值调大,设为 0 则永不清理。

任务一直卡在 running? 后台解析跑在 MCP 服务进程里,进程退出会留下僵尸任务。超过 2 小时没有心跳的任务会被维护动作置为 failed(原因写明「任务已中断」);在此之前查询会带 stale_warning 提示。

需要注册页面/开关文件? 不需要。本项目是纯 stdio MCP Server,无 GUI、无后台常驻服务。

开发

# 安装依赖
uv sync

# 调试 MCP Server
uv run mcp dev mcp_server.py

# 运行测试
uv run pytest tests/

测试用配置目录已通过 MINERU_MCP_CONFIG_PATH 隔离到临时目录,不会污染 config/ 下的运行数据。

发布(维护者)

npm 包与 Python 包共用同一个仓库根目录:package.json 的 files 字段声明打进 npm 包的文件(Python 源码 + launcher),.npmignore 排除 __pycache__ 等本地产物。

版本号必须三处一致:pyproject.toml、package.json、mcp_server.py 的 version=。

方式一:一键发布脚本(本机,推荐)

uv run python scripts/release.py --check-only                    # 体检:版本 + 测试 + 打包清单
uv run python scripts/release.py --bump patch                    # 提版本 → 测试 → 提交 → 推送
uv run python scripts/release.py --bump minor --publish --yes    # 连发布一起(会要 npm 2FA)

脚本按顺序执行:版本三处一致性校验 → uv run pytest → npm pack --dry-run 清单体检 (拒收 __pycache__ / tests/ / config/ / .venv / output/)→ git add/commit/push → (带 --publish 时)npm publish --access public → 发布后核验 registry 版本与 tarball integrity 是否与本地打包逐字节一致。--dry-run 演练、--no-push 只提交、--check-only 只体检。

方式二:GitHub Actions 自动发布(OIDC / Trusted Publishing,零密钥)

.github/workflows/release.yml 在推送 v* tag 时触发(也可手动 workflow_dispatch,支持只演练)。它跑完测试与清单体检后,用 npm Trusted Publishing(OIDC) 发布,不需要任何 token 或密码。

启用前提(缺一不可):

  1. 仓库在 GitHub 上有一份 —— npm 的 Trusted Publisher 只支持 GitHub Actions / GitLab CI, 本项目主仓库在 Gitee,Gitee Go 走不了 OIDC;
  2. npmjs.com → 该包 → Settings → Trusted Publisher → 选 GitHub Actions,填 organization/user、repository、workflow filename = release.yml(必须逐字一致);
  3. npm CLI ≥ 11.5.1(trusted publishing 自该版本起支持)。

之后发布变成:git tag v0.4.0 && git push origin v0.4.0(或 push 到 GitHub 触发)→ Actions 自动发布并附带 provenance 签名(用户可看到"由哪个 commit 构建")。tag 必须等于三处版本号, workflow 会先校验再发布。

首次登录与 2FA

npm login                       # 只需一次
npm publish --access public     # 开了 2FA 的账号会要求 OTP 或弹网页认证

npm 已开始收紧 bypass-2FA 令牌:账号/包管理操作与(约 2027-01 起)直接发布都会逐步 受限,官方推荐的长期方案就是上面的 Trusted Publishing。

发布前自检清单

  • 版本三处一致(scripts/release.py 会校验)
  • npm pack --dry-run 输出中不包含 __pycache__、.venv、tests/、config/、output/
  • 本地验证:npm pack 后把 tarball 装进临时目录,用 node <安装目录>/bin/cli.js 跑一次 MCP initialize 握手
  • npx 冷启动验证:在包源码目录之外的任意目录执行 npx -y @vandoor2/mineru-mcp, 跑一次 initialize + tools/list(期望恰好 4 个工具)。不要在本仓库内验证,见上方「已知限制」

License

MIT