benspdf
An MCP server that gives AI agents local, privacy-preserving PDF tools — inspect, render, create, and manage PDFs without uploading them.
PDF inspection: count pages, read metadata (title/author/dates/producer), check whether pages are text or scanned, extract text page by page, and OCR scans (optionally adding a searchable text layer).
Layout and access: report page sizes, orientation, rotation, and page boxes; check encryption and permissions such as printing, copying, and editing.
Rendering: render PDF pages to PNG images for visual inspection.
Test files: create blank test PDFs with configurable page count and title.
Artifact workflow: temporary results are stored as artifacts; list them, discard them, or export them to real disk paths — the only tool that writes to the user's filesystem.
Local/offline friendly: files stay on the machine, and with Ollama the whole stack can run offline.
Pairs the PDF tools with a local Ollama model so questions about PDFs are answered entirely offline. The bundled benspdf-cli connects to Ollama (e.g. llama3.1, selectable via --model or BENSPDF_MODEL) and drives the PDF tools — page counts, metadata, layout, rendering — without any data leaving the machine.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@benspdf how many pages are in ~/Downloads/report.pdf?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Ben's PDF tools for AI agents, exposed over the Model Context Protocol (MCP).
Your PDFs are read on your own machine and never uploaded. With a hosted model your questions still reach that model; pair the tools with a local Ollama model and nothing leaves the machine at all.
Works with Claude Desktop, Claude Code, VS Code, Kiro, Cursor, the ChatGPT desktop app, and any other MCP client. The one-click buttons above need uv; for every other client, or to do it by hand, see Setup.
Tools
Tool | What it does |
| Counts the pages in a PDF |
| Reads document properties: title, author, dates, producer |
| Says whether a PDF is readable text or a scan that needs OCR |
| Reads the text a PDF holds, page by page |
| Page sizes, orientation, rotation and page boxes |
| Encryption, and what the file permits: printing, copying, editing |
| Renders pages to images, so a page can be looked at |
| Reads a scan with OCR, and can add a searchable text layer to it |
| Generates a throwaway PDF, handy for trying things out |
| Saves results to a real location on disk |
| Lists recent temporary results |
| Deletes temporary results now |
Every tool but one needs nothing beyond the package. pdf_ocr uses
tesseract, a system program rather
than a Python package, and only looks for it when you actually call it — so
install it if and when you want OCR (brew install tesseract, sudo apt install tesseract-ocr, or winget install UB-Mannheim.TesseractOCR), and everything else
works either way.
Related MCP server: pdf-inspector-mcp
Where results go
When a tool makes a new PDF, it goes into a scratch folder instead of your own
folders, and you get back a short id like art_a1b2c3d4.pdf. Tools accept those
ids anywhere they accept a file path, so several steps can be chained together.
Results carry the artifact's path as well as its id, so you can open a rendered
page or an intermediate file straight away without exporting it first.
export is the only tool that writes into your folders, so nothing shows up
until you ask for it. Each time the server starts it clears out scratch files
older than 7 days. Set BENSTOOLS_WORKSPACE to put the scratch folder somewhere
other than ~/.benstools/work.
Setup
Install uv
once, then point your client at uvx benspdf-mcp and uv fetches the package,
plus a suitable Python, on first run.
# macOS and Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"On macOS, brew install uv works too.
Add the server to your client with one of the configs below, then restart the server from your client's UI. Once connected, just ask in plain language:
How many pages are in ~/Downloads/report.pdf?
Claude Desktop
Edit claude_desktop_config.json, which lives at
~/Library/Application Support/Claude/ on macOS and %APPDATA%\Claude\ on
Windows. You can also open it from Settings → Developer → Edit Config.
{
"mcpServers": {
"benspdf": {
"command": "uvx",
"args": ["benspdf-mcp"]
}
}
}Claude Code
One command, no config file. Add --scope user to enable it everywhere rather
than just the current project.
claude mcp add benspdf -- uvx benspdf-mcpCheck it connected with claude mcp list.
VS Code
.vscode/mcp.json in your workspace, or the same file in your user profile.
Note VS Code uses servers rather than mcpServers, and wants an explicit
type.
{
"servers": {
"benspdf": {
"type": "stdio",
"command": "uvx",
"args": ["benspdf-mcp"]
}
}
}Kiro
.kiro/settings/mcp.json in your workspace, or ~/.kiro/settings/mcp.json to
enable it everywhere. autoApprove skips the confirmation prompt for tools you
trust.
{
"mcpServers": {
"benspdf": {
"command": "uvx",
"args": ["benspdf-mcp"],
"autoApprove": ["pdf_page_count"]
}
}
}Cursor
The button at the top does this for you. By hand, it's ~/.cursor/mcp.json to
enable it everywhere, or .cursor/mcp.json in a project.
{
"mcpServers": {
"benspdf": {
"type": "stdio",
"command": "uvx",
"args": ["benspdf-mcp"]
}
}
}Windsurf
~/.codeium/windsurf/mcp_config.json. You can also reach it from Cascade:
Settings → Cascade → Manage MCPs → View raw config, which is worth using
since the path has moved between versions.
{
"mcpServers": {
"benspdf": {
"command": "uvx",
"args": ["benspdf-mcp"]
}
}
}Continue
~/.continue/config.yaml, or a .yaml file under .continue/mcpServers/ in a
project. Continue is the one client here that doesn't take the JSON shape above:
its config is YAML, and mcpServers is a list rather than an object keyed by name.
mcpServers:
- name: benspdf
command: uvx
args:
- benspdf-mcpChatGPT desktop app, Codex CLI, Codex IDE extension
All three are Codex clients and share one config file, ~/.codex/config.toml,
so adding the server once covers all of them. Note this one is TOML, not JSON.
[mcp_servers.benspdf]
command = "uvx"
args = ["benspdf-mcp"]Any other MCP client
Almost every client uses the same JSON as Claude Desktop above — an mcpServers
object, with command set to uvx and args to ["benspdf-mcp"]. Some want an
explicit "type": "stdio"; adding it is harmless where it isn't required.
If a client just asks for a command to run, it's:
uvx benspdf-mcpFully offline with Ollama
The clients above keep your PDFs local, but they answer using a hosted model. Pair the tools with a local model instead and nothing leaves your machine.
You'll need Ollama with a model pulled, plus this package:
pip install benspdf-mcp ollama
ollama pull llama3.1Then run the bundled CLI:
benspdf-cli # uses the first model you have
benspdf-cli --model llama3.1 # or pick one
BENSPDF_MODEL=llama3.1 benspdf-cli # or set it oncepython -m benspdf.cli does the same thing, handy from a source checkout.
You: how many pages in ~/Downloads/report.pdf?
[Using tool: pdf_page_count]
[Result: 12 pages in report.pdf]
Assistant: The PDF has 12 pages.Reference
Each tool's own description tells your client what it does and when to use it, so in normal use there is nothing to look up. If you want the detail — every field a tool returns, and the reasoning behind the answers it gives — see the tool reference.
To work on the code, see CONTRIBUTING.md.
License
Apache 2.0
Available Tools
12 toolscreate_test_pdf_fileA
Create a test PDF, handy for trying the other tools without hunting for one.
The pages are blank, so this is for exercising tools rather than for anything that needs real content.
Args: output_path: Optional path to also write the PDF to. Omit to keep it as a temporary artifact. num_pages: Number of blank pages to create (default: 3) title: Optional title for the PDF metadata
Inputs: title, num_pages, output_path. Returns: result
discardA
Delete temporary artifacts from the workspace now.
Only accepts artifact ids, never file paths, so this cannot delete the user's own files. Artifacts expire on their own, so this is only needed when the user explicitly asks to clean up.
Args: refs: Artifact id, or list of artifact ids, to delete.
Inputs: refs (required). Returns: result
exportA
Save one or more results to a real location on disk.
The only tool that writes to the user's filesystem, so call it once at the end, when they have said where the output should go. Never hand an artifact id back as if it were a finished file; artifacts expire.
Args:
refs: Artifact id, or list of artifact ids, to export.
dest: Where to write. For a single artifact this may be a full file
path. For several artifacts, or when name is given, this is a
directory and is created if missing.
name: Filename template used when writing into a directory.
Placeholders: {n} 1-based index (e.g. "page_{n:03d}{ext}"),
{ext} extension, {id} artifact id, {stem} id without extension.
Defaults to "{n:03d}{ext}".
overwrite: Replace existing files instead of failing. Defaults to
False so nothing is destroyed by accident.
Inputs: dest (required), refs (required), name, overwrite. Returns: result
list_artifactsA
List recent temporary artifacts in the workspace, newest first.
Useful when you have lost track of an artifact id from earlier in the conversation, so you can find it again instead of redoing the work.
Args: limit: Maximum number of artifacts to return.
Inputs: limit. Returns: result
pdf_check_accessA
Check a PDF's encryption and what it permits: printing, copying, editing.
Answers "is this locked, and what am I allowed to do with it?".
encrypted and needs_password are separate answers and the difference
matters: most encrypted files have no user password, so they open silently and
only carry restrictions. permissions gives a boolean per action,
restrictions lists what is denied, and an unencrypted file permits
everything — a PDF has nowhere to keep restrictions but its encryption
dictionary.
Treat restrictions as what the file asks of viewers, not as enforcement: once a document is open nothing stops the bits being ignored, and a file that denies copying still yields its text to pdf_extract_text. Report them as the author's intent, never as an action being impossible.
Worth reaching for when another tool reports a file as encrypted; this one still answers, since the encryption dictionary is readable when the pages are not.
Args: ref: PDF file path, or a workspace artifact id.
Inputs: ref (required). Returns: result
pdf_check_textA
Check whether a PDF has a text layer, looks scanned, or needs OCR.
Answers "can I read this, or is it a picture of a document?". Worth running before extracting text from a file you have not seen.
verdict is "text", "scanned", "mixed", or "no_text" — the last meaning
nothing readable but nothing scan-like either, so blank, vector-only, or
illustrated pages that OCR cannot help. needs_ocr follows from it, summary
is a sentence worth quoting, and the per page evidence behind the verdict
comes back alongside, including each page's image_coverage (the largest
image's share of the page area).
Samples up to 10 pages spread across the document, so a true sampled means
the answer is an estimate for the pages in between. It does not return the
text (use pdf_extract_text) and it does not run OCR.
Args: ref: PDF file path, or a workspace artifact id.
Inputs: ref (required). Returns: result
pdf_extract_textA
Read the text of a PDF that has one, page by page.
The cheap and exact way to read a document: milliseconds a page, and the characters are the ones the file holds. Prefer it to pdf_ocr, which is for pages carrying no text, and to pdf_render_pages, which costs an image a page. pdf_check_text says which path a file needs; page numbers come back with the text, so quote page 8 rather than "the document".
A long document arrives in ranges: one call returns about 50,000 characters
and names the pages it did not reach, so when truncated, do what the summary
says. output="txt" writes the whole extraction to an artifact and returns
the counts alone, which is the way to read a book.
Text on a text_suspect page came back partly undecodable, because the fonts
carry no character map: say so rather than quoting it, and look at the page
with pdf_render_pages.
Args: ref: PDF file path, or a workspace artifact id. pages: Which pages: "1-10", "3", "1,5,9-12" or "all". Defaults to all. output: "text", "txt" for the text as an artifact, or "both". layout: Keep the page's spacing, for forms and tables. Costs characters.
Inputs: ref (required), pages, layout, output. Returns: result
pdf_metadataA
Read a PDF's document properties: title, author, dates, producer, keywords.
Answers "who made this, when, and with what". It does not count pages (use pdf_page_count) and says nothing about whether the pages hold readable text (use pdf_check_text).
A PDF can store these fields in two independent places, the legacy Info
dictionary and an XMP packet, and the two often disagree. The normalized
answer is at the top level, preferring XMP, with sources naming the store
each value came from and conflicts listing every field where the two differ,
both values included. Both stores also come back verbatim as info and xmp.
When has_conflicts is true, say so rather than quoting one value as fact.
Args: ref: PDF file path, or a workspace artifact id.
Inputs: ref (required). Returns: result
pdf_ocrA
Read a scanned PDF with OCR, and optionally add a real text layer to it.
The way to read a page with no text: a scan, or an export that lost its text. Prefer it to pdf_render_pages for reading; run pdf_check_text when unsure. Tesseract is a system install, and a missing binary or language errors with how to install it.
OCR can be confidently wrong, so pages report mean_confidence and
low_confidence_words: say when confidence is low rather than presenting text as
certain, and look at a bad page with pdf_render_pages.
Text pages are skipped unless force. A long document may stop early; when
truncated, do exactly what the summary says, artifact and range included.
Args: ref: PDF file path, or a workspace artifact id. pages: Which pages: "1-10", "3", "1,5,9-12" or "all". Defaults to all. lang: Tesseract language code, or several as "eng+deu". dpi: Resolution, 72 to 600. 200 suits printed text; higher is slower, not better. output: "text", "pdf" for a searchable copy as an artifact, or "both". force: OCR pages that already have text instead of skipping them.
Inputs: ref (required), dpi, lang, force, +2 more. Returns: result
pdf_page_countA
Count the pages in a PDF. Answers "how many pages is this?".
Reads only the document's page tree, so it stays cheap on large files. It does not read page text, page sizes, or document properties.
Args: ref: PDF file path, or a workspace artifact id.
Inputs: ref (required). Returns: result
pdf_page_layoutA
Measure a PDF's page sizes, orientation and rotation.
Answers "what size is this, is it all the same, and why does one page come out sideways?". Reads page geometry only, so it stays cheap on long documents.
sizes groups the pages by shape, most pages first, each carrying the page
numbers it covers as a range like "1-16,18", so a 300 page document answers in
one entry instead of 300 rows.
Sizes are the page as a reader sees it: CropBox clipped to MediaBox with
/Rotate applied, so a landscape box rotated 90 degrees reports as portrait.
Pages within 3pt of a known paper are grouped and named together, since real A4
varies by a millimetre.
Pass pages for per page rows carrying the raw boxes: "1-20", "3", "1,5,9-12"
or "all", capped at 100 rows.
It does not look at page content; for whether the pages hold readable text use pdf_check_text.
Args: ref: PDF file path, or a workspace artifact id. pages: Optional page range for per page detail. Omit for groups only.
Inputs: ref (required), pages. Returns: result
pdf_render_pagesA
Render PDF pages to images, so a page can be looked at rather than read.
Use it to see what a page looks like: checking a change landed (did a redaction remove content, did a split cut where intended), previewing, and pages where appearance is the content — handwriting, signatures, charts, checkbox state.
For reading a scan prefer pdf_ocr, whose text layer is searchable and needs no vision model; render when OCR is unavailable or would mangle what matters.
Every page is saved as a PNG artifact and its id returned. With view, the
default, the first few images also come back to be looked at, since images are
expensive in context. Limits are explicit: 20 pages per call, and resolution is
reduced for a page that would be enormous — both reported, never silent.
Args: ref: PDF file path, or a workspace artifact id. pages: Which pages: "1-20", "3", "1,5,9-12" or "all". Defaults to all, up to the per-call limit. dpi: Resolution, 36 to 600. 150 suits reading and previewing. view: Return the images to look at, not just artifact ids.
Inputs: ref (required), dpi, view, pages.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 12 tools
Each tool targets a distinct PDF inspection or artifact management action. The pdf_* tools are clearly separated by function (page count, metadata, text check, extraction, access, layout, render, OCR), and the artifact tools (discard, list, export) serve unique purposes. No overlapping responsibilities.
PDF tools follow a consistent 'pdf_' prefix with descriptive names (pdf_page_count, pdf_extract_text), but artifact management tools (discard, export, list_artifacts, create_test_pdf_file) lack the prefix and follow a different verb/noun style. The split is understandable but slightly inconsistent.
12 tools is well-scoped for a PDF utility server. Each tool fills a distinct role in inspecting and processing PDFs, plus artifact lifecycle management. The count is neither bloated nor thin for the apparent domain.
The surface covers the essential PDF inspection workflows: determining page count, text presence, extraction, OCR, metadata, access restrictions, page layout, and rendering. Artifact handling (create, list, discard, export) is complete. No obvious missing operations for the server's stated purpose.
Maintenance
Related MCP Connectors
PDF and image tools for AI agents: compress, merge, split, OCR, sign. Runs locally, never uploads.
PDF tools for AI agents: inspect, fill, merge, split, rotate, watermark, protect and invoice PDFs.
PDF tools for AI agents: validate, extract, merge, split, compress, OCR, sign and redact.
Generate and read PDFs for AI agents: a generate_pdf and a read_pdf tool, priced per document.
Related MCP Servers
- AlicenseAqualityDmaintenanceEnables AI agents to securely read and extract information from PDF files including text content, metadata, and page counts from both local files and URLs within the project context.15,035 npmMIT
- AlicenseAqualityDmaintenanceEnables AI agents to process and inspect PDFs by detecting document type, extracting text, and generating Markdown with layout information.71MIT
- FlicenseNot gradedqualityBmaintenanceEnables AI agents to perform comprehensive PDF operations locally, including compression, text extraction, PII redaction, page organization, splitting, merging, watermarking, creation, and form filling, all without cloud uploads.13 npm-
- AlicenseAqualityCmaintenanceEnables AI agents to inspect PDFs, merge or extract pages, and clean text entirely offline through the Model Context Protocol, with no uploads, API keys, or network calls.463 npmMIT