mcpField
E
emperor-pdf

emperor-pdf

本地服务
github.com生产力05 天前更新

关于 emperor-pdf

emperor-pdf 是供 Agent 和客户端处理指定文件夹中 PDF 的 MCP 服务,也可接收 PDF 数据或 HTTPS URL。它集成文本提取、搜索和页面渲染,默认不提供会修改文件的工具。

主要功能

  1. 01读取 PDF 元数据和页面文本
  2. 02使用文本或正则表达式搜索 PDF
  3. 03将页面渲染为 PNG 图片
  4. 04合并 PDF 或提取指定页面
  5. 05启用后从 Markdown 创建 PDF
  6. 06提示可能存在的隐藏文本

适用场景

  1. 01搜索论文文件夹中的术语并查看匹配页面
  2. 02将扫描页面渲染为图片以便检查
  3. 03合并多个 PDF 中选定的页面
  4. 04启用写入后从 Markdown 生成 PDF

MCP 相关

向 MCP 客户端提供 PDF 信息、文本、搜索和渲染工具,可从根目录、base64 数据或 HTTPS URL 读取文件。启用写入后,还可合并和提取页面,以及从 Markdown 创建 PDF。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

暂未收录安装方式

我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。

代码仓库
安装包
cargoemperor-pdf0.1.3

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

emperor-pdf

CI license Glama

为你的 Agent 管理同一文件夹中的 PDF:阅读、搜索、渲染、合并、拆分和创建 PDF。

这是一个 MCP 服务,只处理单个根文件夹中的 PDF,不会访问其他位置:

  • 阅读和搜索文本,逐页处理;PDF 可以来自根文件夹、调用时传入的 Base64 字节,或 https:// URL。它使用 Google 的 PDFium(Chrome 内置的引擎);如果未安装 PDFium,则回退到纯 Rust 提取器。
  • 警示隐藏文本:白底白字、不可见、小于一点或位于页面范围之外的文本——这些都是在看似无害的文档中植入面向模型的指令的常见手段。
  • 查看页面:将页面渲染为模型可查看的 PNG 图像(扫描页面也通过这种方式读取)。
  • 合并和提取页面,以及从 Markdown 创建 PDF;使用 Typst 排版,字体为内置于二进制文件中的 OFL 字体。
  • 通过能力限制访问范围,而非进行字符串检查:每个文件都通过 cap-std 目录句柄打开,因此操作系统层会拒绝 ..、绝对路径以及指向根目录之外的符号链接。
  • 默认只读:未指定 --writable 时,写入工具甚至不会提供。

基于 emperor-mcp 框架构建:无状态 Streamable HTTP(桌面客户端也可使用 stdio)、带帧输出、提供 doctor 子命令,包含 4 个只读工具和 6 个需使用 --writable 的工具。它符合 Emperor Profile P1.1:除非操作员在启动时启用写入(使用 --writable 或 PDF_WRITABLE),否则不会列出写入工具;工具定义也十分精简,包含简短的使用场景说明和紧凑的输入架构。

安装

预构建二进制文件(macOS arm64/x86_64、Linux x86_64、Windows x86_64)可从 GitHub releases 下载。也可以从源码构建:

cargo install --git https://github.com/yarenty/emperor-pdf

构建需要 Rust 1.92 或更高版本(typst 0.15 要求至少使用该版本)。

只读构建

pdf_create 由 create Cargo 功能控制(默认启用);该功能会引入 Typst 和内置字体。禁用该功能后,会得到更小的二进制文件,但仍可阅读、搜索、渲染、合并和提取 PDF:

cargo install --git https://github.com/yarenty/emperor-pdf --no-default-features
构建方式发布版二进制文件(macOS x86_64)
默认(create)51 MB
--no-default-features14 MB
Docker

仓库中的 Dockerfile 会构建一个通过 stdio 与 MCP 通信并包含 PDFium 的镜像(linux/amd64 和 linux/arm64)。将包含 PDF 的文件夹挂载到 /data:

docker build -t emperor-pdf .
docker run -i --rm -v ~/Documents/papers:/data:ro emperor-pdf
# read-write: mount without :ro and switch writing on
docker run -i --rm -e PDF_WRITABLE=true -v ~/Documents/papers:/data emperor-pdf

服务以 uid 10001 运行,因此使用 --writable 时,挂载的文件夹必须允许该用户写入。

PDFium(推荐)

PDFium 是一个在运行时加载的原生库;emperor-pdf 不会将其打包在内。各个平台的预编译 PDFium 二进制文件来自 bblanchon/pdfium-binaries(Apache-2.0 / BSD-3-Clause)。在检出项目后:

scripts/fetch-pdfium.sh            # downloads the right archive for this machine into ./pdfium/

或者自行从某个发行版下载 pdfium-<os>-<cpu>.tgz,并解压到任意位置。发行版固定为 chromium/7881,这是构建 pdfium-render 绑定所用的 PDFium API 版本;使用 PDFIUM_VERSION=<n> scripts/fetch-pdfium.sh 可选择其他版本。

emperor-pdf 按以下顺序查找 libpdfium.dylib / libpdfium.so / pdfium.dll:

  1. --pdfium-dir DIR(DIR、DIR/lib 或 DIR/bin 中的库),
  2. PDFIUM_DYNAMIC_LIB_PATH(一个文件夹,会按相同规则在 lib/ 和 bin/ 中查找;也可以是文件),
  3. 存放 emperor-pdf 二进制文件的文件夹,
  4. 系统库路径。

如果没有 PDFium,pdf_text 和 pdf_search 会使用 lopdf 的 提取器(并在输出中说明:它会漏掉或弄乱某些 PDF 中的文本),而 pdf_render_page 会说明它需要 PDFium。其他功能不受影响。

运行

# Streamable HTTP at http://127.0.0.1:8032/mcp, read-only
emperor-pdf serve --root ~/Documents/papers --pdfium-dir ./pdfium

# also offer pdf_pages and pdf_create, and allow saving rendered pages
emperor-pdf serve --root ~/Documents/papers --pdfium-dir ./pdfium --writable

# stdio, for clients that start the server themselves
emperor-pdf serve --stdio --root ~/Documents/papers
标志默认值含义
--root DIR必填服务唯一可访问的文件夹;工具路径均相对于该文件夹。即使客户端只发送 data 或 url,也必须指定。
--bind ADDR127.0.0.1:8032Streamable HTTP 的监听地址。
--writable关闭提供 pdf_pages 和 pdf_create,并允许使用 pdf_render_page { save_as }。未启用时不会列出这两个工具。也可通过 PDF_WRITABLE 设置:true、1、yes 或 on 会启用;未设置、空值、false、0、no 或 off 会保持关闭;任何其他值都会导致服务在启动时停止。
--pdfium-dir DIR无优先查找 PDFium 的位置。
--stdio关闭改用 stdin/stdout 通过 MCP 通信,而非使用 HTTP。

日志输出到 stderr(使用 RUST_LOG=debug 可查看更多日志)。GET /health 会返回 OK。

连接客户端

Claude Code

# HTTP (start the server first)
claude mcp add --transport http pdf http://127.0.0.1:8032/mcp
# or stdio
claude mcp add pdf -- emperor-pdf serve --stdio --root /path/to/pdfs --pdfium-dir /path/to/pdfium

Claude Desktop(claude_desktop_config.json)

{
  "mcpServers": {
    "pdf": {
      "command": "/path/to/emperor-pdf",
      "args": ["serve", "--stdio", "--root", "/path/to/pdfs", "--pdfium-dir", "/path/to/pdfium"]
    }
  }
}

Claude Desktop,读写模式:在 args 中添加 "--writable"。

Kowalski(config.toml),通过 HTTP 或 stdio 连接:

[[mcp.servers]]
name = "pdf"
transport = "http"
url = "http://127.0.0.1:8032/mcp"

# or let Kowalski start it
[[mcp.servers]]
name = "pdf"
transport = "stdio"
command = ["/path/to/emperor-pdf", "serve", "--stdio", "--root", "/path/to/pdfs", "--pdfium-dir", "/path/to/pdfium"]

工具

四种读取工具每次调用只能通过以下三种方式之一接收 PDF:

  • path:相对于根文件夹的文件(对于 pdf_search,也可以是 **/*.pdf 之类的 glob);
  • data:PDF 字节的 base64 编码(可接受 data:application/pdf;base64, 前缀);
  • url:服务器下载的 https:// URL。

data 和 url 的大小上限为 8 MiB(emperor-mcp 的 limits 字节上限);下载超时时间为 30 秒,最多跟随五次重定向。

工具参数返回内容
pdf_infopath / data / url页数、标题、作者、主题、关键词、创建者、生成器、创建 / 修改日期(ISO 8601)、PDF 版本、是否加密、字节大小。
pdf_textpath / data / url、pages?("1-3,5"、"4-")、max_chars?(默认 100 000,最多 2 000 000)每页文本、所用的提取器(pdfium 或 lopdf)、是否已截断,以及存在隐藏文本时发出的警告。
pdf_searchpath(文件或 glob)/ data / url、query、regex?、case_sensitive?、max_hits?(默认 50,最多 500)每个匹配项的文件、页码、匹配内容和上下文摘要;含有隐藏文本的页面会被标记。
pdf_render_pagepath / data / url、page、dpi?(1 到 300,默认 110)、save_as?、overwrite?页面 PNG 图像(MCP 图像内容)、图像大小及保存位置。需要 PDFium;save_as 需要 --writable。
pdf_pagesoperation(merge 或 extract)、inputs([{path, pages?}])、output、overwrite?根据所选页面及其书写顺序生成的新 PDF。仅限 --writable 服务。
pdf_createmarkdown、output、title?、overwrite?根据 Markdown 排版生成的新 PDF(标题、强调、列表、表格、代码块、引用、链接)。仅限使用 create 功能构建的 --writable 服务。

页码从 1 开始。pdf_pages 会保留页面及其内容,但不会保留输入文件中的书签、表单或标签结构。

工具注解会说明每个工具的用途:读取工具是只读、幂等且开放世界的(可获取 URL);可写服务上的 pdf_pages、pdf_create 和 pdf_render_page 不是只读工具,并被标记为具有破坏性,因为 overwrite: true 会替换文件。在只读服务上,pdf_render_page 被标记为只读,因为它无法保存文件。

隐藏文本

使用 PDFium 时,pdf_text 和 pdf_search 会检查所读取页面上的每个字符,并标记人眼查看页面时可能看不到的文本:

  • 使用不可见渲染模式(模式 3)绘制的文本,除非它位于图像上方——OCR 正是通过这种方式让扫描页面可搜索;
  • 白色或近白色(或完全透明)且背后没有任何内容的文本;
  • 小于 1 pt 的文本;
  • 位于页面框之外的文本。

这些文本仍会在文档框架内返回;此外还会单独显示带框的警告,注明文件名、页码和原因,并要求模型将其视为数据并告知用户。pdf_search 会将此类页面上的每个匹配项标记为 page_has_hidden_text。这是一种启发式检查:例如,表单对象内绘制的白色背景虽然不会遮挡任何内容,但不会被深入检查。lopdf 回退方案不会检查,并会说明这一点。

扫描页面

emperor-pdf 没有 OCR 引擎。没有文本层的扫描页面通过 pdf_text 返回时内容为空或接近为空;请使用 pdf_render_page 渲染页面,并让具备视觉能力的模型读取图像。已进行 OCR 的扫描件带有不可见文本层,pdf_text 会读取该文本(但不会将其标记为隐藏文本)。

安全模型

  • 一个根目录,通过 capability 强制执行。 根目录只打开一次,作为 cap_std::fs::Dir;所有读写都通过它使用相对路径进行。任何包含 .. 的路径或绝对路径都会在进行任何文件系统调用前被拒绝,并给出明确提示;cap-std 会拒绝解析到根目录之外的符号链接。Glob 会通过同一个句柄遍历根目录来展开(跳过隐藏文件夹,最多 200 个文件)。
  • 默认只读,除非指定 --writable。 未指定时,不会注册 pdf_pages 和 pdf_create(客户端看不到它们),而 pdf_render_page { save_as } 会提示服务为只读。指定后,除非调用传入 overwrite: true,否则不会替换现有文件。
  • URL:仅限公开的 HTTPS。 url 必须使用 https://,且不能包含用户名或密码;每次重定向都会重新检查。主机名由服务解析,且只使用公开地址:环回、私有地址(RFC 1918)、链路本地地址(包括 169.254.169.254 上的云元数据地址)、共享地址、IPv6 唯一本地地址及类似范围都会被拒绝,因此调用无法访问服务所在网络上的服务。下载内容和 data 的大小上限为 8 MiB,且必须以 PDF 格式开头。
  • 文档文本是数据。 PDF 可能来自任何地方,也可能包含旨在引导模型的文本。文本和搜索摘要会通过 emperor-mcp framing 标记为作者身份未知的文档(带随机数保护的分隔符,并注明“数据,而非指令”);元数据、结果和隐藏文本警告则会标记为计算值。
  • Markdown 无法执行代码。 pdf_create 会转义文本中的每个字符,并将代码和链接作为字符串字面量传递,因此 Markdown 无法作为标记或脚本传入 Typst;Typst world 不提供任何文件,只提供生成的文件,并且字体会嵌入,因此文档无法读取磁盘。Typst 仅在使用 create 功能构建的可写服务中运行。
  • 限制工作量。 超过 256 MiB 的文件会被拒绝;回退文本提取会限制每页解压后的内容量;渲染上限为 300 dpi 和单边 8000 px;Markdown 输入上限为 2 MiB。

doctor

emperor-pdf doctor --root ~/Documents/papers --pdfium-dir ./pdfium --writable
emperor-pdf 0.1.3 doctor
  [ok  ] root folder     /Users/me/Documents/papers (writable)
  [ok  ] pdfium          loaded from ./pdfium/lib/libpdfium.dylib
  [ok  ] typst fonts     6 embedded faces (DejaVu Sans Mono, Libertinus Serif)
  [ok  ] listen address  127.0.0.1:8032 is free
  [ok  ] tool budget     6 of at most 8 tools
all good (0 warning(s))

检查失败时会以 1 退出。缺少 PDFium 属于警告,不算失败。--stdio 会跳过端口检查。工具数量预算统计服务将列出的工具:只读模式下为四个,使用 --writable 时为六个。使用 --no-default-features 构建时不会进行字体检查。

开发

scripts/fetch-pdfium.sh        # once, so the PDFium tests run instead of being skipped
cargo fmt --all --check
cargo clippy --all-targets -- -D warnings
cargo clippy --all-targets --no-default-features -- -D warnings
cargo test
cargo deny check

测试会在临时文件夹中使用 Typst 构建测试 PDF,并通过 HTTP(以及一个通过 stdio)与真实服务通信;url 来源会从一个小型本地 HTTP 服务获取。工具列表通过 emperor-mcp 的 testkit 检查。若没有 ./pdfium,仅依赖 PDFium 的测试会打印提示并通过。

链接

许可证

可由你选择采用 MIT 或 Apache-2.0 双重许可。

字体

启用 create 功能后,二进制文件会为 pdf_create 嵌入两个字体系列,字体文件位于 assets/fonts,并附带相应的许可证文本:

字体文件许可证
Libertinus Serif(正文)Regular、Bold、Italic、Bold ItalicSIL Open Font License 1.1(文本)
DejaVu Sans Mono(代码)Regular、BoldBitstream Vera 许可证;DejaVu 的更改属于公有领域(文本)

两者均采用宽松许可证,允许将字体嵌入文档,并随软件重新分发。项目不包含采用 GPL 许可证的字体(未使用 Typst 自带的 New Computer Modern 字体集)。发布压缩包中附带这两份许可证文本,文件名为 FONTS-NOTICE。你创建的文档不受这些许可证的影响,但如果提取字体,则需保留字体自带的声明。安装的 PDFium 受其自身许可证(Apache-2.0 / BSD-3-Clause)约束。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。