mcpField
S
Sezzlee PDF

Sezzlee PDF

本地服务
docs.sezzlee.app生产力11 天前更新

关于 Sezzlee PDF

Sezzlee PDF 是面向本地 PDF 的只读 MCP 服务,可在指定目录沙箱中提取文本、按页读取并搜索内容。它默认不启用 OCR,可通过注入的组件按需处理扫描页,服务本身不访问网络。

主要功能

  1. 01列出并描述 PDF 文档
  2. 02按页提取文本并以 Markdown 返回
  3. 03搜索文本并返回页码和上下文
  4. 04通过可插拔组件按需执行 OCR
  5. 05使用游标分页并缓存提取结果

适用场景

  1. 01读取本地 PDF 的指定页面
  2. 02在文档中定位关键词及其上下文
  3. 03为扫描页面配置 OCR 识别
  4. 04在受限目录中处理文档

MCP 相关

它向 MCP 客户端提供列出、描述、读取和搜索本地 PDF 的工具。访问受指定目录限制;OCR 默认关闭,启用后由外部注入的组件处理,服务自身不会访问网络。

配置

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

mcp.json · 通用配置
{
"mcpServers": {
"sezzlee-pdf": {
"command": "npx",
"args": [
"-y",
"@sezzlee/pdf-mcp"
]
}
}
}
启动命令npx -y @sezzlee/pdf-mcp

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
npm@sezzlee/pdf-mcp0.1.2

工具

还没有获取到工具列表

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

详细介绍

@sezzlee/pdf-mcp

用于本地 PDF 文档的只读、沙盒化 MCP 服务。它基于 @sezzlee/file-core 构建,由后者提供沙盒路径解析、响应预算、错误封装、游标和文档缓存。文本提取使用 @firecrawl/pdf-inspector。此服务绝不会连接网络:OCR 为可选功能;启用后,连接决策完全由提供这两个注入端口的一方决定。

快速开始

{
  "mcpServers": {
    "pdf": {
      "command": "npx",
      "args": ["-y", "@sezzlee/pdf-mcp", "/path/to/documents"]
    }
  }
}

要启用 OCR,请将 --ocr 指向一个默认导出为 OcrBinding 的模块(参见配置和 OCR):

{
  "mcpServers": {
    "pdf": {
      "command": "npx",
      "args": [
        "-y",
        "@sezzlee/pdf-mcp",
        "/path/to/documents",
        "--ocr",
        "/path/to/ollama-binding.js"
      ]
    }
  }
}

工具

工具功能关键参数
list_documents列出根目录下可读取的 PDF 候选文件;不会打开文件subdirectory、pattern、maxResults
describe_document页面数量、文档类型、每页是否需要 OCR、服务功能filePath
read_pages将选定页面读取为 Markdown,页码从 1 开始filePath、pages、maxPages、ocr、cursor
find_in_document在提取的文本中进行字面搜索,并返回页码和匹配上下文filePath、query、matchMode、caseSensitive、ocr、cursor

如果已知文件路径,describe_document 是可选的:read_pages 和 find_in_document 只需提供 filePath 即可使用。

配置

CLI(sezzlee-pdf <pdf-source-root> [--ocr <module>]):

参数默认值含义
<pdf-source-root>必填沙盒根目录;每个可读取路径都会解析并检查是否位于该目录下。
--ocr <module>无模块的路径或包说明符,该模块的默认导出为 { rasterizer, provider }。未提供时不启用 OCR:read_pages/find_in_document 会拒绝 ocr: true,且 describe_document 会报告 capabilities.ocr: false。

程序化配置(createPdfMcpServer(root, options)):

选项默认值含义
documentCacheSize2同时保留在内存中的已提取文档数量,范围为 1–16。这是预算,而非保护措施:每个缓存文档都会将所有页面的 Markdown 保存在堆内存中。
maxConcurrentListings4拒绝请求前允许并发执行的 list_documents 调用数。
maxConcurrentExtractions2拒绝请求前允许并发执行的 PDF 提取数。
ocr无一个 OcrBinding({ rasterizer, provider, dpi?, maxPagesPerCall?, timeoutMs? })。此包不依赖这两个端口。

OCR

服务器不会执行 OCR;它只提供支持。服务器会注入两个端口——栅格库和模型客户端都不是此软件包的依赖项。

interface PageRasterizer {
  render(job: {
    bytes: Buffer;
    pages: readonly number[];
    dpi: number;
    signal?: AbortSignal;
  }): Promise<readonly RenderedPage[]>; // { page, image, mediaType }
}

interface OcrProvider {
  readonly name: string;
  recognize(job: {
    pages: readonly RenderedPage[];
    signal?: AbortSignal;
  }): Promise<readonly RecognizedPage[]>; // { page, markdown, confidence? }
}

服务器只会执行以下操作:对文本层无法解答的页面进行 render,识别生成的图像,用结果替换该页面,并将其标记为 source: "ocr"。

程序化绑定:

createPdfMcpServer(root, {
  ocr: { rasterizer: pdfjsRasterizer, provider: ollamaProvider, dpi: 200 },
});

CLI 绑定——加载默认导出与 OcrBinding 匹配的模块,并使用 --ocr <module>(有关可用示例,请参阅此软件包中的 examples/ollama-binding.ts,该示例基于 @sezzlee/pdf-raster-pdfjs 和 @sezzlee/ocr-ollama 构建):

import { createPdfjsRasterizer } from "@sezzlee/pdf-raster-pdfjs";
import { createOllamaOcrProvider } from "@sezzlee/ocr-ollama";
import type { OcrBinding } from "@sezzlee/pdf-mcp";

const binding: OcrBinding = {
  rasterizer: createPdfjsRasterizer(),
  provider: createOllamaOcrProvider({
    baseUrl: process.env["SEZZLEE_PDF_OCR_URL"] ?? "http://127.0.0.1:11434",
    model: process.env["SEZZLEE_PDF_OCR_MODEL"] ?? "deepseek-ocr:3b",
  }),
  dpi: 200,
};

export default binding;
OCR 规则
  • 设置 ocr: true 却未绑定提供程序时会报错(ocr_unavailable),绝不会静默回退到文本层。否则,请求 OCR 的 Agent 可能会把“没人转录此文档”误认为“没有匹配项”。describe_document → capabilities.ocr 会报告是否已绑定提供程序。
  • 空转录内容不算作答案。 如果提供程序返回空文本,该页面仍会保持 needsOcr——“模型没有返回内容”不等于“此页面为空白”。
  • 未请求的页面会被忽略。 端口可能会重排、跳过或虚构页面;结果会与请求的页码匹配,因此提供程序无法覆盖文本层已信任的页面。
  • 数据会离开进程。 绑定提供程序意味着这些页面的像素会被发送到其他地方。因此,OCR 默认关闭,且每次调用都必须显式请求。
  • 每次调用不会重复转录同一页面。 转录内容按文档指纹和页码缓存。缓存不是进度日志:搜索只会将游标之后的页面发送给 OCR,并在游标中延续覆盖范围,因此即使是大型文档,最终也能通过缓存遍历至末尾。
  • 作业过期不会释放其槽位。 引擎和注入的端口都无法取消已经开始的工作;槽位会一直被占用,直到工作实际完成。对于始终不返回的提供程序,只能通过重启服务器来恢复——通过计时器回收槽位只会延后触及限制的时间。

规则

  • **公共接口中的所有页码均从 1 开始。**底层库在同一个结果对象中返回的字段,有些从 0 开始,有些从 1 开始。所有转换都在 src/engine/ 中进行,并且 lint 禁止在该目录之外导入 @firecrawl/pdf-inspector——第二个导入位置会再次引入这个问题(在 1.23.0 中测得:PageMarkdownResult.page 从 0 开始,同级字段 pagesNeedingOcr 从 1 开始)。
  • **页码选择在传入库之前就会进行验证。**否则,超出范围的索引会以标记为 needsOcr 的虚假页面返回;负索引则会通过 u32 回绕。两种情况都会让 Agent 误以为这是真实页面。
  • describe_document 绝不会根据分类器构建 OCR 页面列表。classifyPdf 会将包含单个扫描页面的文档中的每一页都标记出来。页面列表来自逐页提取结果。classificationConfidence 表示分类器对自身判定的置信度,而不是对任何提取文本准确性的置信度。
  • **无法读取的页面绝不会被呈现为空白页。**扫描页面会返回 needsOcr:true;只有引擎确认并判定确实为空白的页面,empty 才为 true。
  • **每个响应都会报告搜索覆盖情况。**只要有页面需要 OCR,coverageComplete 就为 false;匹配列表为空并不能证明整个文档中都没有该查询内容。
  • **文档会完整提取一次,响应则采用分页形式。**测量结果显示,只请求单页只能将提取成本降低三分之一,而不是 200 倍——固定成本占主导。游标标识取决于文档内容和 OCR 模式,而非页面大小。显式的 pages 选择会在游标中保留:游标会继续处理该选择中剩余的页面,不会延伸到未选页面。若游标从某页中间恢复,它会携带该页的文本指纹;如果转录后文本发生变化,响应会返回 stale_cursor,而不是静默跳过内容。
  • 服务绝不会访问网络。fetch、node:http、node:net 及其同类项在 src/ 中都被 lint 禁止,并且每一层的 override 中也重复设置了此禁令——后续的 oxlint override 会替换 no-restricted-imports,而不是与之合并,因此仅在顶层设置一次禁令无法覆盖所有位置。
  • **平台支持范围有限。**引擎不提供 darwin-x64 二进制文件,且其 wasm 回退版本尚未发布。在不受支持的主机上,服务会在启动时停止,并输出一行提示信息(退出代码为 3)。

开发

pnpm turbo run build --filter=@sezzlee/pdf-mcp
node packages/servers/pdf-mcp/dist/cli.js /path/to/documents

测试:pnpm turbo run test --filter=@sezzlee/pdf-mcp(Vitest)。实时 Ollama 测试套件(test/ocr-live.spec.ts)只有在设置了 SEZZLEE_PDF_OCR_URL 时才会运行;它还会读取 SEZZLEE_PDF_OCR_MODEL(默认值为 deepseek-ocr:3b)。test/ocr.spec.ts 中的其他所有测试都使用模拟端口运行;实时测试套件仅用于验证两个真实适配器能够组合使用。

评论

支持 Markdown

第一次接触 MCP?

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

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