Skip to main content
ClaudeWave

An MCP (Model Context Protocol) server specialized in deciphering PDF internal structures.

MCP ServersOfficial Registry2 stars0 forksTypeScriptMITUpdated today
ClaudeWave Trust Score
95/100
Verified
Passed
  • Open-source license (MIT)
  • Actively maintained (<30d)
  • Clear description
  • Topics declared
  • Documented (README)
Last scanned: 9/19/2026
Install in Claude Code / Claude Desktop
Method: NPX · @shuji-bonji/pdf-reader-mcp
Claude Code CLI
claude mcp add pdf-reader-mcp -- npx -y @shuji-bonji/pdf-reader-mcp
claude_desktop_config.json (Claude Desktop)
{
  "mcpServers": {
    "pdf-reader-mcp": {
      "command": "npx",
      "args": ["-y", "@shuji-bonji/pdf-reader-mcp"]
    }
  }
}
1. Run the command above in your terminal (Claude Code), or paste the JSON config into claude_desktop_config.json (Claude Desktop).
2. Replace any <placeholder> values with your API keys or paths.
3. Restart Claude. The MCP server and its tools appear automatically.
Use cases

MCP Servers overview

# PDF Reader MCP Server

[![npm version](https://img.shields.io/npm/v/@shuji-bonji/pdf-reader-mcp)](https://www.npmjs.com/package/@shuji-bonji/pdf-reader-mcp)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Built with Claude Code](https://img.shields.io/badge/Built%20with-Claude%20Code-blueviolet?logo=anthropic)](https://claude.ai/code)

**English** | [日本語](./README.ja.md)

An MCP (Model Context Protocol) server specialized in **deciphering PDF internal structures**.

While typical PDF MCP servers are thin wrappers for text extraction, this project focuses on **reading and analyzing the internal structure** of PDF documents. Pair it with [pdf-spec-mcp](https://github.com/shuji-bonji/pdf-spec-mcp) for specification-aware structural analysis and validation.

### PDF family

| Server | Role |
|--------|------|
| [pdf-spec-mcp](https://github.com/shuji-bonji/pdf-spec-mcp) | PDF specification knowledge (ISO 32000, PDF/A, PDF/UA) |
| **pdf-reader-mcp** (this) | Read and inspect PDF internal structure — *what is in* a PDF |
| [pdf-verify-mcp](https://github.com/shuji-bonji/pdf-verify-mcp) | Authenticity verification — *whether it is genuine*: cryptographic signature verification, tamper detection, PAdES level, PDF/A validation, encrypted-PDF decryption |

`pdf-reader-mcp` inspects signature **structure** (`inspect_signatures`); for **cryptographic** signature verification, trust/revocation evaluation, and PDF/A conformance validation, use `pdf-verify-mcp`.

## Features

**19 tools** organized into three tiers:

### Tier 1: Basic Operations

| Tool             | Description                                              |
| ---------------- | -------------------------------------------------------- |
| `get_page_count` | Lightweight page count retrieval                         |
| `get_metadata`   | Full metadata extraction (title, author, PDF version...) |
| `read_text`      | Text extraction with Y-coordinate reading order (opt-in `split_columns: 2 \| 3` for untagged multi-column PDFs, `compact_whitespace` for Japanese forms). Resolves `/ActualText` replacements (§14.9.4, both the structure-element and the `Span` marked-content path). Reports **text extractability** per page (§9.10.1) so an empty result is never mistaken for an empty page. For **logical** order in tagged PDFs, prefer `extract_structured_text` |
| `search_text`    | Full-text search with surrounding context. Searches the same text `read_text` returns, `/ActualText` included, so a hit means what a reader sees (a `note` names any page whose marked content could not be aligned) |
| `read_images`    | Embedded image XObjects as **PNG or JPEG files**, returned as MCP image content blocks so a vision model can read them. `max_width` / `max_height` downscale by area average; the response has a byte budget and names anything it leaves out |
| `read_url`       | Fetch a remote PDF and extract its **text** — nothing more. The bytes are not saved; to use the other 18 tools on a URL's PDF, download it first and pass the local path (see "read_url and the read-only boundary") |
| `render_page`    | Rasterise pages to **PNG/JPEG** via PDFium-WASM (optional dependency `@hyzyla/pdfium`). The next step when text extractability says `no_text_layer` / `not_extractable` — draws the whole page, vector art and forms included |
| `summarize`      | Quick overview report (metadata + text + image count + per-document text extractability) |

### Tier 2: Structure Inspection

| Tool                  | Description                                                         |
| --------------------- | ------------------------------------------------------------------- |
| `inspect_structure`   | Object tree and catalog dictionary analysis                         |
| `inspect_tags`        | Tagged PDF structure tree visualization                             |
| `inspect_fonts`       | Font inventory (embedded/subset/type detection)                     |
| `inspect_annotations` | Annotation listing (categorized by subtype)                         |
| `inspect_signatures`  | Digital signature field structure analysis                          |
| `extract_structured_text` | Tagged PDF text in **logical content order** (ISO 32000-2 §14.8.2.5), each piece labelled with its structure type (`H1` / `P` / `Table` …). Resolves `/ActualText`, separates `/Alt` and list labels, keeps page-spanning elements whole. `include_bbox: true` adds **where each element is drawn** — one rectangle per page, in the form `add_annotation` takes |
| `extract_tables`      | Tagged PDF `<Table>` subtree → Markdown table (preserves columns). A table continuing across a page break is ONE table (`pages` array) |
| `locate_objects`      | Object number → page and rectangle, in the coordinate form [pdf-writer-mcp](https://github.com/shuji-bonji/pdf-writer-mcp) `add_annotation` takes. Bridges [pdf-verify-mcp](https://github.com/shuji-bonji/pdf-verify-mcp) `verify_integrity`'s "which objects changed" to "where they are". Each location names its `basis`: an annotation's own `/Rect` is exact, a content stream can only say "the whole page" |

### Tier 3: Validation & Analysis

| Tool                | Description                                          |
| ------------------- | ---------------------------------------------------- |
| `validate_tagged`   | **Deprecated** — PDF/UA pass/fail belongs to [pdf-verify-mcp](https://github.com/shuji-bonji/pdf-verify-mcp) `validate_conformance` (`flavour: "pdfua-1"`). Kept until the next major |
| `validate_metadata` | **Deprecated** — same migration path as above. Kept until the next major |
| `compare_structure` | Structural diff between two PDFs (properties + fonts)|

### read_url and the read-only boundary (#25)

`read_url` returns text, and only text. This is a decision, now stated rather than implied:
the fetched bytes are discarded after extraction, because saving them would make a reader
tool write to the file system, and every tool of this server is read-only
(`readOnlyHint: true` — all 19 of them).

To run `search_text`, `inspect_structure`, `extract_tables`, `render_page` or anything else
against a PDF that lives at a URL, download the file first — with whatever fetch capability
the calling environment has — and pass the local path. Fetching is the caller's
responsibility, deliberately: an agent environment always has a way to download a file, and a
reader that also writes files has stopped being a pure observer.

`read_url` remains the right tool for the one-shot question: *what does the document at this
URL say?*

### Pages can be rendered when text cannot be read (#23)

`summarize` reporting `hasText: false` used to be a dead end: nothing in this server could
read the document any further. `render_page` closes that — it rasterises pages to PNG or JPEG
and returns them as MCP image content blocks, so a vision model can read a scan, a diagram, a
filled form, or handwriting.

```
render_page({ file_path: "/path/to/scan.pdf", pages: "1-3", format: "jpeg" })
```

`pages` is required: rendering is the most expensive operation here, and "all pages" of a
500-page scan should be a decision, not a default. The same 4 MB response budget as
`read_images` applies, with omissions named.

Rendering runs on **PDFium compiled to WebAssembly** (`@hyzyla/pdfium`, an optional
dependency). A WASM binary is the same bytes on every platform, so the published package still
behaves identically wherever `npx` runs it — the reason native addons are not used here.
Without the dependency installed, `render_page` reports what to install and every other tool
works normally. PDFium (BSD-3-Clause) is a different engine from the pdf.js this server reads
text with; the tool description says so, because a rendering difference between engines must
not be attributed to the file.

> Measured before choosing this: pdf.js + `@napi-rs/canvas` (1.0.7 and 0.1.80) segfaults the
> whole process on pages that draw images — exactly the pages this tool exists for — and
> renders blank pages when `standardFontDataUrl` is not configured.

### Images come back as image files (#22)

`read_images` used to base64 `imgData.data` — pdfjs's *decoded pixels*. An 8×8 RGB image was
192 bytes with no PNG or JPEG signature anywhere in it, so the result could not be opened by
any viewer and could not be read by a vision model, which is the reason to extract an image in
the first place.

Images are now encoded (PNG by default, lossless; `format: "jpeg"` with `quality` when smaller
matters) and returned as MCP `image` content blocks, with the metadata alongside in a text
block. Both encoders are written out here — no native addon, no per-platform binary.

The response is bounded at 4 MB of encoded image data. A 200 dpi A4 scan is ~11.6 MB of pixels
on its own, so images past the budget are **named with the reason** rather than dropped:

```
read_images({ file_path: "/path/to/scan.pdf", pages: "1", max_width: 1200, format: "jpeg" })
```

`read_images` returns the image XObjects a page draws. It is not a picture of the page — vector
drawings and text are not covered by it.

### Text extractability — three states, not two (#21)

`read_text` used to answer with text or with nothing, and nothing meant three different things.
ISO 32000-2 §9.10.1 separates them, so this server does too. Every text-returning tool —
`read_text`, `read_url`, `search_text`, `extract_structured_text`, `summarize` — reports, per
page:

| State | Condition | What to do next |
| --- | --- | --- |
| `extracted` | Every font used has a route to Unicode under §9.10.2 | Use the text |
| `no_text_layer` | No text-showing operator (`Tj` `TJ` `'` `"`), image content present | The page is pixels. OCR or a rendered image is needed; this server does neither |
| `not_extractable` | A font used has no `/ToUnicode`, no standard encoding and no known CID collection | Text is missing or wrong. The report names the fonts 
mcp-serverpdf-decipherpdf-reader

What people ask about pdf-reader-mcp

What is shuji-bonji/pdf-reader-mcp?

+

shuji-bonji/pdf-reader-mcp is mcp servers for the Claude AI ecosystem. An MCP (Model Context Protocol) server specialized in deciphering PDF internal structures. It has 2 GitHub stars and its last recorded update is dated 2026-09-19.

How do I install pdf-reader-mcp?

+

You can install pdf-reader-mcp by cloning the repository (https://github.com/shuji-bonji/pdf-reader-mcp) or following the README instructions on GitHub. ClaudeWave also provides quick install blocks on this page.

Is shuji-bonji/pdf-reader-mcp safe to use?

+

Our security agent has analyzed shuji-bonji/pdf-reader-mcp and assigned a Trust Score of 95/100 (tier: Verified). See the full breakdown of passed checks and flags on this page.

Who maintains shuji-bonji/pdf-reader-mcp?

+

shuji-bonji/pdf-reader-mcp is maintained by shuji-bonji. The last recorded GitHub activity is dated 2026-09-19, with 0 open issues.

Are there alternatives to pdf-reader-mcp?

+

Yes. On ClaudeWave you can browse similar mcp servers at /categories/mcp, sorted by popularity or recent activity.

Deploy pdf-reader-mcp to your cloud

Ship this repo to production in minutes. Each platform spins up its own environment with editable env vars.

Maintain this repo? Add a badge to your README

Drop the badge into your GitHub README to show it's tracked on ClaudeWave. Each badge links back to this page and reflects the live Trust Score.

Featured on ClaudeWave: shuji-bonji/pdf-reader-mcp
[![Featured on ClaudeWave](https://claudewave.com/api/badge/shuji-bonji-pdf-reader-mcp)](https://claudewave.com/repo/shuji-bonji-pdf-reader-mcp)
<a href="https://claudewave.com/repo/shuji-bonji-pdf-reader-mcp"><img src="https://claudewave.com/api/badge/shuji-bonji-pdf-reader-mcp" alt="Featured on ClaudeWave: shuji-bonji/pdf-reader-mcp" width="320" height="64" /></a>

More MCP Servers

pdf-reader-mcp alternatives