PDFBLOCK
MCP server that lets Claude Code and other AI agents read and search large PDFs, one file or a whole folder: agentic RAG with hybrid semantic + keyword search, selective page reads, tables, images, OCR, chart data, and multi-column/CJK layouts.
Overview
From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.
[](https://pypi.org/project/pdf-mcp/) [](https://www.python.org/downloads/) [](https://opensource.org/licenses/MIT) [](https://github.com/jztan/pdf-mcp/issues) [](https://github.com/jztan/pdf-mcp/actions/workflows/ci.yml) [](https://codecov.io/gh/jztan/pdf-mcp) [](https://pepy.tech/project/pdf-mcp)
Agentic RAG over your PDFs, one file or a whole folder, as a single MCP tool.
The agent decides when to search; pdf-mcp does the retrieval and hands back excerpts. It is an MCP server that lets Claude Code and other AI agents search one PDF or a whole folder by meaning or keyword, read only the pages that matter, and cleanly pull out tables, images, and scanned text, even from multi-column and Japanese layouts, with optional CUDA acceleration for warming large corpora.
mcp-name: io.github.jztan/pdf-mcp
Try it in your browser
[See what your AI agent sees →](https://pdf-mcp.jztan.com/)
Drop in any PDF, or a whole folder of them, and watch an agent triage the corpus, search across every document at once, and read only the pages that matter, using a fraction of the tokens. 100% client-side, no install required.
##
7648662eb779OBSERVED · 2026-10-07Connect
Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control. Replace the environment placeholders with a token scoped to the least it needs.
claude mcp add pdf-mcp -- None pdf-mcp==3.5.0
Exposed tools (3)
2 read · 0 write · 1 destructive. Blast radius: 1 tool can delete or overwrite — an agent that can be talked into calling a tool can be talked into calling this one.
| Tool | Risk | Description |
|---|---|---|
pdf_cache_clear | destructive | |
pdf_info | read | Page count. |
pdf_search | read | Search. |
Trust audit
BLOCKgrade D · trust 63/100 Do not install this without reading the findings. The audit found something that could harm you or your machine.
| Layer | What it checks | Result |
|---|---|---|
| L0 | Provenance & inventory | PASS |
| L1 | Static analysis of the code | FAIL |
| L2 | Instruction surface (what it tells the agent) | PASS |
| L3 | Class-specific surface | WARN |
| L4 | Behavioural (sandbox) | SKIPPED |
What the source does
- Filesystem
- declared (8 observation(s))
- Network
- declared (7 observation(s))
- Shell
- declared (1 observation(s))
- Dependencies
- not all pinned
- Secrets in source
- found
Findings (25)
const F = new Function(`${m[1]}\nreturn corpusFusion;`)();secret = "sk-super-secret-value"
pdf_cache_clear
.flake8
.pre-commit-config.yaml
.mcpbignore
clone = pickle.loads(pickle.dumps(_warm_extract_worker))
return hashlib.sha1(text.encode("utf-8")).hexdigest()[:12]else (lambda d: hashlib.sha1(f"{seed}:{d}".encode()).hexdigest()[:12])return hashlib.sha1(f"{seed}:{doc_id}".encode()).hexdigest()[:12]return hashlib.sha1(json.dumps(hints or {}, sort_keys=True).encode()).hexdigest()[const PAGES_DIR = resolve(HERE, "../../pages");
const OUT = process.env.OUT_GIF || resolve(HERE, "../../docs/images/demo.gif");
const L = require('../../packaging/mcpb/server/launcher.js');const pins = require('../../packaging/mcpb/server/uv-pins.json');const launcher = path.resolve(__dirname, '../../packaging/mcpb/server/launcher.js');
- **SSRF via URL fetch.** A prompt-injected PDF can instruct the agent to fetch attacker-chosen URLs (`http://169.254.169.254/...`, DNS-rebinding hosts, IPv6 link-local, etc.). In scope: local-network
return_value=[(2, 1, 6, "", ("169.254.169.254", 0))],redirect_url = "https://169.254.169.254/latest/meta-data/"
if "169.254" in hostname or hostname == "169.254.169.254":
return [(2, 1, 6, "", ("169.254.169.254", 0))]"$py" scripts/smoke_mcpb.py bundle-smoke/unpacked --expect-fallback --timeout 120 --extra-env "PDF_MCP_CACHE_DIR=$RUNNER_TEMP/pdfmcp-blocked" --extra-env "PDF_MCP_UV_DOWNLOAD_BASE=https://127.0.0.1:9/
if curl -fsS http://127.0.0.1:8802/health >/dev/null 2>&1; then
MCP=http://127.0.0.1:8802/mcp
http://127.0.0.1:8802/mcp \
Gates applied: no_behavioural_pass.
7648662eb779full audit observations/trust-audit/mcp-server/jztan__pdf-1.json · Report an issue / request a re-scanAudit history
Every audit this server has had. A grade with a past is a grade somebody is still checking.
| Date | Source | Verdict | Grade | Score | Change |
|---|---|---|---|---|---|
| 2026-10-07 | 7648662eb779 | BLOCK | D | 63 | first audit |
Questions
What is the PDF MCP server?
MCP server that lets Claude Code and other AI agents read and search large PDFs, one file or a whole folder: agentic RAG with hybrid semantic + keyword search, selective page reads, tables, images, OCR, chart data, and multi-column/CJK layouts.
What tools does PDF expose?
3 in total: 2 read-only, 0 that write, and 1 that can delete or overwrite (pdf_cache_clear). Every one is listed on this page with its risk.
Is PDF safe to connect to an agent?
No — not without reading the findings first. The audit graded it D (63/100) and found 1 critical or high issue in the source. Each one is listed on this page with the file and line it is on. Separately from the audit: 1 of its tools can destroy data, so scope the token you give it to what you actually need.
What credentials does PDF need?
It reads PDF_MCP_AUTH_TOKEN from the environment. Give it a token scoped to the least it needs — an agent that can be talked into calling a tool can be talked into calling it with your credentials.
How does PDF run?
It speaks stdio, so it runs as a local process your client starts. It is published on npm as pdf-mcp-demo-recorder at 3.5.0.
How current is this page?
The grade is for one exact copy of the source (7648662eb779), read on 2026-10-07. The repository is watched and re-audited when it changes.