Skip to main content
Glama

@ai-zen/pdf-parse-mcp

English | 简体中文

An MCP server that takes PDFs apart precisely for agents: coordinates and sizes for text, vector shapes, and bitmaps — plus on-demand raster rendering.

Built for the "reconstruct a design file from a PDF" use case — you get the position, size, color, and stroke width of every glyph, line, and rectangle in the file, instead of one blob of plain text.

npx -y @ai-zen/pdf-parse-mcp

What it actually gives you

You want

You get

Where a glyph is, how big it is

Baseline origin x/y, bounding box bbox, fontSize, rotation, color

The shape of a rect / line / curve

Subpath geometry (M/L/C/Q/close flags) plus bbox

What it looks like

Fill color, stroke color, alpha, line width, cap/join/dash

Where the images are

Placement box of every bitmap plus its intrinsic pixel size

To just look at it

Rasterize the whole page or any region to PNG/JPEG

All coordinates use a top-left origin, y down, in points (1pt = 1/72 inch) — the intuitive coordinate system of screens and design tools, instead of PDF's internal "bottom-left origin, y up".

Related MCP server: MCP PDF

Install / wiring

Add a snippet to any MCP client (Claude Desktop, Cline, Cursor, your own agent…):

{
  "mcpServers": {
    "pdf-parse": {
      "command": "npx",
      "args": ["-y", "@ai-zen/pdf-parse-mcp"]
    }
  }
}

No system dependencies: the canvas implementation (@napi-rs/canvas) and all font/cmap/wasm assets ship as prebuilt artifacts inside the package.

Requires Node.js ≥ 22.13 (pdfjs 6 requirement).

Tools

pdf_info

Document-level information: page count, per-page size and rotation, metadata.

{
  "path": "design.pdf",
  "pages": 3,
  "unit": "pt",
  "coord": "top-left origin, y down",
  "metadata": { "Title": "Home screen design", "Producer": "Figma" },
  "pageSizes": [{ "page": 1, "width": 595.28, "height": 841.89, "rotation": 0 }]
}

Parameters: path (required), password, maxPages (default 100).

pdf_extract

Extract everything on a single page. This is the core tool.

Parameters:

Parameter

Description

path

PDF path (required)

page

Page number, 1-based (required)

include

Return only a subset of ["text"|"shapes"|"images"]; all by default

detail

full (default, with complete path segments) or box (boxes + styles only, much smaller output)

precision

Decimal places for coordinates, default 3

limit

Max items per category, default 5000 (exceeding it is flagged in truncated)

password

Password for encrypted documents

Return shape (truncated):

{
  "page": 1,
  "width": 595.28, "height": 841.89, "rotation": 0,
  "unit": "pt", "coord": "top-left origin, y down",
  "counts": { "text": 42, "shapes": 17, "images": 2 },

  "text": [
    {
      "text": "Hello World",
      "x": 72, "y": 92,                    // baseline origin
      "width": 124.008, "height": 26.813,  // visual width / line height
      "fontSize": 24, "rotation": 0,
      "bbox": [72, 70.28, 196.01, 97.09],
      "color": "#000000",
      "fontName": "g_d0_f1", "fontFamily": "sans-serif"
    }
  ],

  "shapes": [
    {
      "paint": "fill",                     // fill | stroke | fillStroke | clip | shading
      "bbox": [100, 542, 300, 692],
      "fill": "#3366e6", "fillAlpha": 1,
      "subpaths": [
        { "closed": true, "bbox": [100, 542, 300, 692],
          "segments": [
            { "t": "M", "x": 100, "y": 692 },
            { "t": "L", "x": 300, "y": 692 },
            { "t": "L", "x": 300, "y": 542 },
            { "t": "L", "x": 100, "y": 542 }
          ] }
      ]
    },
    {
      "paint": "stroke",
      "bbox": [98.5, 490.5, 401.5, 493.5],  // stroke box already expanded by line width
      "stroke": "#ff0000", "strokeWidth": 3,
      "lineCap": 0, "lineJoin": 0, "miterLimit": 10,
      "subpaths": [ /* … */ ]
    }
  ],

  "images": [
    { "kind": "image", "name": "img_p0_1",
      "intrinsicWidth": 800, "intrinsicHeight": 600,
      "bbox": [400, 132, 550, 232] },
    { "kind": "image", "name": "img_p0_3",            // bitmap from a tiling pattern cell
      "intrinsicWidth": 300, "intrinsicHeight": 300,
      "bbox": [24, 668, 56, 700], "pattern": true }
  ],

  "fonts": { "g_d0_f1": { "family": "sans-serif", "ascent": 0.905, "descent": -0.212 } }
}

A few conventions:

  • bbox is always [x0, y0, x1, y1], top-left origin, y down.

  • Path segment coordinates are already in device space (page CTM and current transform applied), so you can use them directly as design-file coordinates.

  • Curve segments keep their control points (C = cubic Bézier, Q = quadratic); bbox is the tight box of the whole path.

  • A null stroke color means a pattern/gradient stroke; paint: "shading" means the region was originally a gradient fill (render gradients with pdf_render).

  • Text color is recovered by nearest-in-paint-order matching; if it can't be determined we omit it rather than inventing one.

  • paint: "clip" is a clip region that was never painted (it only constrains visibility), not visible artwork.

  • A bitmap tagged "pattern": true comes from a tiling pattern (TilingPattern) cell — the "use an image as fill" trick (very common in Skia/Chrome exports). The cell is tiled across the page by XStep/YStep; we report only the visible part of that one cell, not the full tiled extent.

pdf_render

Rasterize a single page to an image.

Parameter

Description

path / page

Required

scale

Zoom factor (relative to 72dpi), default 1

dpi

Target DPI (equivalent to scale = dpi/72; wins if both are given)

region

[x0,y0,x1,y1], pt, top-left origin — render only this region

background

Default #ffffff; pass transparent to keep alpha

format

png (default) / jpeg

save

If given, write the file and return path info only; otherwise the image itself is returned to the agent

region plus a large scale is a magnifying glass: checking whether an icon or a line is really aligned beats a full-page thumbnail by a mile.

Typical workflow for reconstructing a design

1. pdf_info                      → how many pages, how big each page is
2. pdf_extract(page, detail:"box")
                                 → all boxes and styles first, to see the layout skeleton
3. pdf_extract(page, include:["text"])
                                 → copy, font size, weight, color
4. pdf_render(page, scale:1)     → full-page thumbnail to verify layout
5. pdf_render(page, region:[x0,y0,x1,y1], scale:4)
                                 → zoom in on a detail to verify alignment
6. rebuild the design from 1–5, then render and compare

Overlay debug images (visual check)

To find out "is the extracted geometry actually accurate", an overlay image is the fastest answer — the render as backdrop, the geometry drawn on top:

npm run overlay -- pdfs/demo1.pdf                         # → tmp/overlay/demo1-p1-overlay.png
npm run overlay -- pdfs/demo3.pdf --page all --scale 3
npm run overlay -- design.pdf --layers render,shapes,text,labels
npm run overlay -- design.pdf --region 0,0,300,300 --line 2

Layer

Draws

Default

render

rendered page as backdrop

text

text boxes (blue) + baseline origin and width (pink)

shapes

shape outlines: fill magenta / stroke green / shading red / clip gray dashed

images

image boxes (orange, labeled with intrinsic pixel size)

legend

legend with per-layer counts (top-right)

labels

text content of each item (yellow)

shapeBoxes

shape bounding boxes (dashed)

Programmatic interface:

import { renderOverlay } from "@ai-zen/pdf-parse-mcp";

const { buffer, counts } = await renderOverlay(page, { scale: 2 });

Great for regression: after changing extraction logic, run the overlay on real documents and any drift or missed item is obvious at a glance.

Programmatic usage

The main use of this package is the MCP server, but the core is exported as well:

import { openPage, extractPage, renderPage } from "@ai-zen/pdf-parse-mcp";

const page = await openPage("design.pdf", 1);
const content = await extractPage(page, { precision: 2 });
const png = await renderPage(page, { scale: 2, region: [0, 0, 300, 300] });

Documents are cached and reused by "path + mtime"; call closeAllDocuments() to release them.

Hidden text layers (important)

Chrome/Skia-style exporters commonly do this: visible text is painted as vector outlines, with an invisible text object underneath (for searchability/selection). That text layer's color — sometimes even its position — has nothing to do with what is visible.

This tool detects the pattern and does two things:

  1. Text fully covered by later, opaque artwork is marked "covered": true (don't treat it as visible content);

  2. If a "text outline" shape sits at the same spot, its color is used to recover color, and "colorFrom": "outline" is set; if none is found, no color is reported at all.

{ "text": "Mailboxes", "x": 24, "y": 56.64, "fontSize": 24,
  "color": "#e8e8ea", "covered": true, "colorFrom": "outline",
  "bbox": [24, 37.44, 141.79, 61.44] }

In other words: for text with covered: true, the string content is trustworthy; color and geometry should be taken from the recovered values. Measured on real documents (mobile design exports from Skia/PDF m117): 13/13 and 20/23 text items had their colors recovered correctly.

Known limitations

  • Text color: regular PDFs use the color from the drawing operators directly; hidden text layers go through the recovery logic above, and if recovery fails no color is reported (never a wrong one).

  • Gradients are only marked positionally (paint: "shading"); color stops are not extracted.

  • Pattern (TilingPattern) fills: fill is null (a pattern has no single color); bitmaps painted inside the pattern cell are extracted and tagged pattern: true, but only the portion of that one cell intersecting the filled area is reported — tiled copies are not expanded into separate entries.

  • Transparency groups (isolated): inner coordinates are mapped through to the final composited position and are correct in normal cases; rare form XObjects with a custom group.matrix may be slightly off.

  • Bitmaps report placement and intrinsic pixel size only, not pixel data (use pdf_render to look at them).

  • When artwork is covered by later opaque fills, text is marked covered; shapes do not track occlusion yet.

  • Mind the output size on very large pages: control it with detail: "box", include, and limit.

Development

npm install
npm run build     # tsc → dist/
npm test          # build + core assertions + MCP stdio end-to-end
npm run overlay -- pdfs/demo1.pdf   # generate an overlay for visual inspection

scripts/make-sample.mjs generates three minimal PDFs on the fly as golden fixtures:

  • tmp/sample.pdf — vector shapes / text / bitmaps / CTM transforms;

  • tmp/sample-hidden.pdf — hidden text layer + covered by an opaque background + outline-recovered color;

  • tmp/sample-pattern.pdf — a rectangle filled with a tiling pattern (TilingPattern) whose cell embeds a bitmap.

npm test also uses pdfs/demo1~3.pdf (real design exports from Skia/PDF m117) as golden fixtures: it asserts semantics only (page size, hidden-text color recovery, pattern bitmap placement) and never locks item counts, so normal extraction improvements will not turn it red.

License

MIT

Available Tools

3 tools
pdf_extractA

抽取 PDF 某一页的全部内容,用于从 PDF 精确还原设计稿:

  • text:文本片段(字符串、基线坐标 x/y、宽高、字号、旋转角、颜色、外框 bbox)

  • shapes:矢量图形(填充/描边色、透明度、线宽、外框 bbox、以及子路径几何:M/L/C/Q/Z 线段;paint="clip" 是不可见的裁剪区)

  • images:位图贴图(外框 bbox、原始像素尺寸、对象名) 坐标:左上原点、y 向下、单位 pt(1pt=1/72 英寸)。 注意:Chrome/Skia 导出的 PDF 常把可见文字画成矢量轮廓,另垫一层不可见的文本对象;这类文本会被标 "covered":true,颜色则由同位置的轮廓反推并标 "colorFrom":"outline"。 建议先整体抽取一次看清结构,图形很多时用 detail="box" 只取外框与样式,再对重点区域用 pdf_extract + pdf_render 局部细看。

ParametersJSON Schema
NameRequiredDescriptionDefault
pageYes页码,从 1 开始
pathYesPDF 文件路径(绝对或相对当前工作目录)
limitNo每类结果条数上限,默认 5000
detailNo图形细节级别:full(默认)含完整路径线段;box 只给外框+样式,输出更小
includeNo只返回指定类别,默认全部
passwordNo若 PDF 已加密,提供打开密码
precisionNo坐标保留小数位,默认 3

TDQS

A4.3/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full behavioral burden and succeeds. It discloses the coordinate system (top-left origin, y down, pt units), the Chrome/Skia quirk where visible text is rendered as vector outlines with an invisible text layer (marked 'covered':true and color inferred via 'colorFrom':'outline'), and clarifies that paint='clip' represents invisible clipping regions. These non-obvious traits are exactly what an agent needs to interpret output safely.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but well-structured, with a one-line purpose, bullet lists for content categories, a coordinate note, a quirk note, and a usage recommendation. Each section provides necessary context for a complex extraction tool, so the length is justified, though a bit dense. The core purpose is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given there is no output schema and no annotations, the description does a strong job of explaining what the tool returns (categories, attributes, coordinate conventions) and common rendering pitfalls. It does not explicitly cover error behavior such as out-of-range pages or corrupted/encrypted files, but the password parameter is already documented in the schema. Overall, an agent has enough to invoke the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description mostly repeats what the schema already states about detail ('box' vs 'full') in the usage recommendation ticket, and it adds no meaningful new semantics for path, page, limit, include, password, or precision. The schema is the primary source for parameter meaning.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a clear verb and resource: '抽取 PDF 某一页的全部内容' (extract all content of a given PDF page). It then enumerates the three output categories (text, shapes, images) with their specific attributes, making the tool's purpose concrete and easily distinguishable from the sibling pdf_info and pdf_render tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The final paragraph gives explicit workflow guidance: extract the whole page first, use detail='box' when shapes are numerous, and combine pdf_extract with pdf_render for focused inspection. This provides clear context and references a sibling tool for a complementary use, though it never explicitly says when to prefer pdf_info over pdf_extract.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

pdf_infoA

读取 PDF 的文档级信息:页数、每页尺寸与旋转角、元数据(标题/作者/生成器等)。用于在抽取前了解文档结构、确定要处理哪些页。坐标:左上原点、y 向下、单位 pt(1pt=1/72 英寸)。

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesPDF 文件路径(绝对或相对当前工作目录)
maxPagesNo最多列出多少页的尺寸,默认 100(文档很大时可调小)
passwordNo若 PDF 已加密,提供打开密码

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the burden of behavioral disclosure. It clearly signals read-only behavior ('读取') and, more importantly, specifies the coordinate system (top-left origin, y-down, pt units), which is behavioral information not available in the schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three compact sentences with no filler. The output scope and usage context are front-loaded, and the coordinate convention is a purposeful addition rather than redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, but the description enumerates the return content and gives the coordinate convention, which is essential for interpreting results. It is sufficient for a read-only inspection tool, though exact output field names/types are left unspecified.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema fully documents path, maxPages, and password. The description adds no parameter-level detail beyond that, matching the baseline for high schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('读取') and resource ('PDF') and enumerates the exact outputs: page count, per-page dimensions/rotation, and metadata. This clearly differentiates it from sibling tools pdf_extract and pdf_render by framing it as document-level inspection.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly gives a concrete use case: understand structure and decide which pages to process before extraction. It doesn't explicitly say when not to use it or name alternatives, but the stated pre-extraction context is strong enough to guide selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

pdf_renderA

把 PDF 某一页栅格化成图片(PNG/JPEG)。可用于:整体查看版面、放大局部核对细节、验证还原结果。

  • 默认返回图片本身(base64),Agent 可直接查看;给 save 则写入文件并只返回路径信息。

  • region 可只渲染局部([x0,y0,x1,y1],pt,左上原点),配合较大 scale 相当于「放大镜」。 坐标:左上原点、y 向下、单位 pt(1pt=1/72 英寸)。

ParametersJSON Schema
NameRequiredDescriptionDefault
dpiNo目标 DPI,等价于 scale=dpi/72;与 scale 同时给出时以 dpi 为准
pageYes页码,从 1 开始
pathYesPDF 文件路径(绝对或相对当前工作目录)
saveNo保存到该路径(不给则直接返回图片内容)
scaleNo缩放倍数(相对 72dpi),默认 1
formatNo输出格式,默认 png
regionNo只渲染该矩形区域 [x0,y0,x1,y1],pt,左上原点
passwordNo若 PDF 已加密,提供打开密码
backgroundNo背景色,默认 "#ffffff";传 "transparent" 保留透明

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full behavioral burden and largely succeeds: it discloses the default return mode (base64 image viewable by the agent), the save-alternative (writes file and returns only path info), the region subsetting behavior with the magnifier effect, and the full coordinate convention (top-left origin, y-down, pt units). Minor gaps remain around error behavior (wrong password, invalid page number) and file-overwrite semantics, but the core behavior is clearly disclosed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tightly packed lines: the lead sentence states purpose and use cases, then two bullet-style lines cover return modes and region/coordinate semantics. Every sentence earns its place, key behavior is front-loaded, and there is zero filler or restatement of the schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 9-parameter tool with no annotations and no output schema, the description covers the essentials an agent needs: return formats in both modes, region semantics, and coordinate units, while the schema handles dpi/scale precedence and default values. What's missing is error-behavior context (e.g., behavior on wrong password or out-of-range page) that would fully complete the picture for a tool with two required parameters.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description nevertheless adds genuine value beyond the schema: it explains the region+scale synergy as a '放大镜' (magnifying glass), generalizes the coordinate system beyond the region parameter, and defines pt units (1pt=1/72 inch) — none of which the schema states. This justifies one point above baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb+resource+output: '把 PDF 某一页栅格化成图片(PNG/JPEG)' (rasterize a specific PDF page into an image). It further lists concrete use cases — viewing layout, zooming into details, verifying restoration results — which collectively distinguish it from the siblings pdf_info (metadata) and pdf_extract (content extraction) without ambiguity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit use-context through '可用于:整体查看版面、放大局部核对细节、验证还原结果', telling the agent when rendering is the right operation. However, it never names the sibling alternatives (pdf_info/pdf_extract) nor states when NOT to use this tool, so it stops short of the explicit when/when-not/exclusion standard.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 3 tool updatesv0.1.0
    • First observedpdf_extract
    • First observedpdf_info
    • First observedpdf_render

TDQS

A4.4/5.0

Scored across 3 tools

Disambiguation5/5

Each tool has a clearly distinct purpose: pdf_info inspects document-level metadata, pdf_extract pulls structured content from a page, and pdf_render rasterizes a page or region to an image. There is no overlap in their primary functions.

Naming Consistency5/5

All three tools follow a consistent pdf_<verb> pattern: pdf_info, pdf_extract, pdf_render. The naming clearly communicates the action and is uniform across the set.

Tool Count5/5

Three tools is well-scoped for a PDF parsing server: inspect, extract structured content, and render. Each tool covers a distinct need without redundancy or bloat.

Completeness4/5

The set covers the core PDF inspection workflow: document info, page content extraction, and rasterization. Minor gaps exist such as no direct text search or page-range extraction, but the described workflow is complete for design-reconstruction use cases.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    F
    maintenance
    Enables AI-powered extraction and analysis of PDF documents with 40+ specialized tools for text, tables, images, layout analysis, security assessment, and document intelligence. Supports both text-based and scanned PDFs with OCR capabilities.
    134 PyPI
    10
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides intelligent OCR and PDF processing capabilities that automatically detect whether PDFs contain digital text or scanned images and apply appropriate extraction methods. Supports text extraction, OCR processing, structure analysis, and batch operations.
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides random access to PDF contents with selective page extraction, text search, outline navigation, image extraction, and page rendering capabilities. Reduces token usage by allowing targeted content extraction instead of processing entire documents.
    4
    MIT