pdf-card-mcp
PDF Card MCP converts local PDFs into portable, source-linked HTML readers, and provides tools for annotation validation and static publishing.
Convert PDFs to HTML readers (
convert_pdf_to_card_html): Transform a local PDF into a standalone HTML file with embedded assets, source-page previews, and image crops for tables, figures, and formulas. Configurable options include:OCR fallback for image-only PDFs
Custom reader title, theme, and page limits
Style engine:
fixed,pdf, orsampling(LLM-assisted)Table engine:
auto,pdfplumber, orgmftText engine:
char_geometryorpdfplumber_wordsPost-processing engine:
noneorsampling(LLM-assisted card boundary polish, no source text rewriting)Offline mode using only cached ML models
Validate annotations (
validate_reader_annotations): Check a notes/highlights sidecar JSON file against a generated reader HTML to ensure all annotations can be correctly anchored, with optional validation of private annotations.Publish reader bundles (
publish_reader_bundle): Export a read-only static HTML file or directory bundle with annotations, with options to redact the local source PDF path, include/exclude private annotations, and enable/disable annotation editing.
Click on "Install 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., "@pdf-card-mcpconvert /Users/me/paper.pdf to a card-based HTML reader"
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.
PDF Card MCP
PDF Card MCP is a local-first MCP server and CLI for turning dense local PDFs into portable, source-linked HTML readers. An MCP host can ask it to convert a PDF path, validate notes/highlights, or publish a static annotated reader bundle. The converter preserves source text, renders source pages for verification, crops detected tables, figures, and display formulas as images, derives safe reader styling from the original PDF palette, and writes a standalone HTML file that can be moved across devices without losing assets.
Default conversion runs locally and does not require a hosted service. Optional MCP sampling is deliberately bounded: the host model may choose validated style tokens or suggest card-boundary polish operations, but raw CSS and source-text rewrites are rejected.
The default reader is designed for comfortable reading: large type, small cards, search, section navigation, next/previous controls, keyboard navigation, a font-size slider, and source-page previews.
PDF Card MCP is meant for PDFs you actually need to read, cite, or inspect. It turns long documents into smaller source-linked cards, keeps tables/figures/formulas as faithful image crops, and lets you export your own notes and highlights as Markdown.
Quick Install (one-click)
PDF Card MCP is a Python server, so it needs a runtime. The one thing to install first is
uv — it manages Python for you, so you do not have to. This is
the only prerequisite for every install path below:
# macOS / Linux
curl -LsSf https://astral.sh/uv/install.sh | sh# Windows (PowerShell)
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"Then add the server with one click. The buttons run the published
pdf-card-mcp package through uv:
Claude Code (terminal):
claude mcp add pdf-card -- uvx --from pdf-card-mcp pdf-card-mcp-serverClaude Desktop (no terminal, no prerequisites): download pdf-card-mcp-desktop.mcpb from the
latest release and double-click it to
install as an extension. This bundle declares the uv runtime, so Claude Desktop installs Python
and dependencies for you — you do not need the uv step above for this path.
After installing, restart (or reload MCP servers in) your client so it picks up the new server.
Related MCP server: liteparse-mcp
Real Screenshots
These screenshots are from a generated reader for Agents in Software Engineering and the same source PDF opened side by side for comparison.
Generated reader | Original PDF |
Quick Examples
Convert a local PDF into one portable HTML reader:
pdf-card-mcp ./paper.pdf --output ./out/paper-reader.htmlUse the explicit subcommand form with PDF-derived styling:
pdf-card-mcp convert ./paper.pdf \
--output ./out/paper-reader.html \
--style-engine pdfRun the MCP server so a compatible host can generate readers from local PDF paths:
python -m pdf_card_mcp.serverPublish a read-only static reader with selected public annotations:
pdf-card-mcp publish ./out/paper-reader.html \
--annotations ./paper.annotations.json \
--output ./published/paper-reader.htmlOutput At A Glance
Output | What it contains |
| Standalone reader with embedded CSS, JavaScript, page images, and detected crops. |
| Structured metadata for cards, pages, warnings, and source anchors. |
Markdown export | User-authored notes and highlights from the reader UI. |
Published bundle | Read-only static HTML or a directory bundle for sharing public annotations. |
Status
This is an early open-source implementation. It is useful for text-layer PDFs now, with
best-effort table detection via pdfplumber, permissive raster rendering via pypdfium2,
and optional richer local table detection via gmft. Scanned PDFs need optional OCR support.
Install
Most people should use the one-click install above. To install the package directly instead, from PyPI:
python -m pip install pdf-card-mcpOr install the latest unreleased changes directly from the repository:
python -m pip install "pdf-card-mcp @ git+https://github.com/velyan/pdf-card-mcp.git"For local development:
git clone https://github.com/velyan/pdf-card-mcp.git
cd pdf-card-mcp
python3 -m venv .venv
. .venv/bin/activate
python3 -m pip install -e ".[dev]"uv is recommended for MCPB packaging:
uv sync
uv run pdf-card-mcp path/to/document.pdf --output out/document.htmlInstall the optional local ML table detector when you want stronger table crops:
uv sync --extra table-ml
uv run --extra table-ml pdf-card-mcp path/to/document.pdf --table-engine gmftUse In An MCP Client
Add it to Claude Code or another CLI-compatible MCP client with uvx (requires
uv):
claude mcp add pdf-card -- uvx --from pdf-card-mcp pdf-card-mcp-serverGeneric MCP host configuration:
{
"mcpServers": {
"pdf-card": {
"command": "uvx",
"args": ["--from", "pdf-card-mcp", "pdf-card-mcp-server"]
}
}
}For local development before the PyPI release, point the client at this checkout:
{
"mcpServers": {
"pdf-card-local": {
"command": "uv",
"args": [
"--directory",
"/path/to/pdf-card-mcp",
"run",
"python",
"-m",
"pdf_card_mcp.server"
]
}
}
}Claude Desktop can also install the .mcpb bundle from the latest GitHub release.
Docker / Registry Scanners
The repository includes a minimal Dockerfile so registries such as Glama can build the
server, start it over stdio, and inspect its MCP tool schemas. The server still works on local
file paths, so container users must mount any PDFs and output directories they want the tool to
read or write:
docker build -t pdf-card-mcp .
docker run --rm -i \
-v "$PWD/examples:/docs" \
pdf-card-mcpCLI Usage
pdf-card-mcp path/to/document.pdf --output examples/out/document.htmlThe command writes:
document.html: standalone reader with embedded CSS, JavaScript, table crops, figure crops, formula crops, and source-page images.document.manifest.json: structured metadata without embedded image payloads.
The explicit subcommand form is also supported:
pdf-card-mcp convert path/to/document.pdf --output examples/out/document.htmlNotes, Highlights, And Static Publishing
Generated readers include a local annotation overlay:
A highlight is selected source text.
A note is selected source text plus your own typed note text.
Select text in a text card, choose Highlight or Note, and use Export Markdown to download
a readable .annotations.md file. Import is intentionally not exposed in the reader UI yet.
Notes and highlights are user-authored data and are kept separate from the source-derived
document.manifest.json.
The lower-level CLI and MCP publishing tools still accept a structured annotation bundle when you need to build a read-only static reader with embedded annotations. Validate that bundle against a reader:
pdf-card-mcp validate-annotations examples/out/document.html document.annotations.jsonPublish a shareable static reader with public annotations:
pdf-card-mcp publish examples/out/document.html \
--annotations document.annotations.json \
--output published/document-reader.htmlIf --output is a directory instead of an .html file, the command writes a static bundle:
index.htmlreader.manifest.jsonreader.annotations.jsonbundle.json
Publishing includes only visibility: public annotations by default, redacts the local
source_pdf path by default, and renders the published reader read-only by default. Use
--include-private only when you intentionally want private local notes included in the
published output. Publishing fails if any included annotation cannot be anchored to the reader;
run validate-annotations to inspect mismatches before publishing.
MCP Tool
The MCP server is the automation layer around the same local converter. It accepts local file paths from an MCP client and returns generated reader paths, manifest metadata, warnings, and publishing/validation results.
The server exposes three tools:
convert_pdf_to_card_html
validate_reader_annotations
publish_reader_bundleInputs:
pdf_path: local PDF path.output_path: optional HTML output path.title: optional title override.standalone: defaults totrue; asset-folder output is reserved for a later release.ocr: optional OCR fallback ifpytesseractis installed.max_pages: optional processing limit.theme: defaults tosoft.style_engine:fixed,pdf, orsampling; defaults topdf.fixedpreserves the original soft palette,pdfderives bounded colors and typography hints locally from the source PDF, andsamplingasks the host LLM to choose validated style tokens from those local hints.table_engine:auto,pdfplumber, orgmft;autousesgmftwhen installed.text_engine:char_geometryorpdfplumber_words; defaults tochar_geometryso missing spaces are repaired from PDF character positions instead of trusting fused words.postprocess_engine:noneorsampling; defaults tonone. When set tosampling, the MCP server asks the host LLM for boundary-only card polish operations, validates exact source-text preservation, and rewrites the generated reader. If the MCP client does not support sampling, deterministic output is returned with a warning.model_cache_dir: optional cache directory for local ML table model weights.offline: use only already-cached optional ML models.
validate_reader_annotations checks a notes/highlights sidecar against a generated reader.
publish_reader_bundle writes a publish-ready static HTML file or directory bundle from an
existing generated reader and an optional annotation sidecar.
Sampling post-processing is intentionally narrow. For card boundaries, the host LLM may
suggest merges, heading extraction, or front-matter/footnote classification, but Python
validation rejects any operation that rewrites, deletes, invents, or reorders source text.
For style_engine=sampling, the host LLM may only choose bounded style tokens and palette
candidate IDs; it cannot return raw CSS, JavaScript, or arbitrary colors. If sampling is
unavailable, the reader keeps deterministic PDF-derived styling and returns a warning.
Run the server locally:
python -m pdf_card_mcp.serverMCPB Packaging
This repo is arranged so the root can be packed directly:
python scripts/build_mcpb.py --variant allThis builds three bundles:
dist/pdf-card-mcp-lite.mcpbanddist/pdf-card-mcp.mcpbdeclareserver.type = "python"for MCP registry and Smithery directory compatibility. The full bundle additionally installs thetable-mlextra. These execute throughuv, so the host (or user) must provideuv.dist/pdf-card-mcp-desktop.mcpbdeclaresserver.type = "uv"(frommanifest.uv.json). Claude Desktop manages Python and dependencies itself, so end users can double-click to install with no prerequisites. This is the bundle linked from the one-click install section above.
No bundle vendors ML model weights; gmft downloads and caches them locally on first use unless
offline=true is set with a prewarmed cache.
Privacy
Default PDF processing is local. The deterministic converter does not upload document contents or call external APIs. Optional OCR runs locally when the user has installed OCR dependencies.
When style_engine=sampling or postprocess_engine=sampling is enabled through MCP, the host
LLM may receive bounded style hints or card text snippets so it can return validated style-token
or boundary-operation plans. Use deterministic fixed/pdf style and postprocess_engine=none
when no document-derived text should leave the local process.
Published readers may contain extracted PDF text, source-page images, table/figure/formula crops, and any included public notes or highlights. Only publish generated readers when you have the rights to share the source document content and your annotations.
How It Works
See docs/how-it-works.html for a self-contained visual explainer
of the conversion pipeline, including page rendering, table/figure crops, overlap suppression,
text-card merging, and standalone HTML output.
How Tables Are Handled
All detected tables are rendered as image cards. The converter uses pdfplumber to find table
regions and can optionally use gmft/Table Transformer for stronger local detection. It then
uses pypdfium2 to rasterize only the source table region into PNG. Captions are preserved as
reader text and alt text, but the table itself remains an image so layout and numeric alignment
survive conversion.
If a document mentions tables but no reliable table regions are found, the manifest includes a warning so callers can decide whether to inspect the source pages.
How Formulas Are Handled
Display formulas are treated as image cards when the PDF exposes them as centered, formula-like text blocks. The extracted formula string is retained for alt/search metadata, but the reader shows the source crop so subscripts, superscripts, arrows, and math spacing remain faithful.
License
MIT
Available Tools
3 toolsconvert_pdf_to_card_htmlA
Convert a local PDF into a portable, source-linked HTML reader.
The generated reader is static HTML with embedded assets. It keeps source text intact, includes source-page previews for verification, and crops detected tables, figures, and display formulas as images. Optional MCP sampling is limited to validated style-token choices or boundary-only card polish; raw CSS and source-text rewrites are rejected.
| Name | Required | Description | Default |
|---|---|---|---|
| ocr | No | Try optional OCR fallback for image-only PDFs. | |
| theme | No | Reader theme name. The default soft theme is calm and minimal. | soft |
| title | No | Optional reader title override. | |
| offline | No | Use only already-cached optional ML models. | |
| pdf_path | Yes | Absolute or relative path to the input PDF. | |
| max_pages | No | Optional limit for very large PDFs. | |
| standalone | No | Keep true to embed images, CSS, and JavaScript in one HTML file. | |
| output_path | No | Optional path for the generated HTML file. | |
| text_engine | No | "char_geometry" or "pdfplumber_words". Defaults to geometry-based spacing. | char_geometry |
| style_engine | No | "fixed", "pdf", or "sampling". Fixed preserves the original soft reader palette. PDF derives a bounded style from local PDF visuals. Sampling asks the host LLM to choose validated style tokens from local PDF style hints. | |
| table_engine | No | "auto", "pdfplumber", or "gmft". Auto uses gmft when installed. | auto |
| model_cache_dir | No | Optional cache directory for local ML table model weights. | |
| postprocess_engine | No | "none" or "sampling". Sampling asks the host LLM for boundary-only card polish operations, validates exact text preservation, and rewrites the reader. | none |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description discloses key behaviors: preserves source text, includes previews, crops tables/figures, and rejects raw CSS/rewrites. This is thorough but could mention output format details.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two concise paragraphs front-load the main purpose, then detail constraints. Every sentence adds value with no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (13 params) and presence of an output schema, the description sufficiently covers behavior and output. Minor addition: could explicitly mention PDF path requirement.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
All 13 parameters have schema descriptions (100% coverage), so baseline is 3. The description does not add further parameter context beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Convert a local PDF into a portable, source-linked HTML reader.' This is specific and distinguishes it from sibling tools (publish/validate).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage context (converting PDF to HTML) but lacks explicit when-to-use or alternative guidance. Siblings are different operations, so the gap is minor.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
publish_reader_bundleB
Publish a static reader bundle with selected notes and highlights.
| Name | Required | Description | Default |
|---|---|---|---|
| read_only | No | Disable local annotation editing in the published reader. Defaults to true. | |
| output_path | Yes | Output .html path or directory for a static bundle. | |
| include_private | No | Include private annotations and mark them public. Defaults to false. | |
| annotations_path | No | Optional annotation sidecar JSON path. | |
| reader_html_path | Yes | Path to a standalone reader generated by this tool. | |
| redact_source_path | No | Redact local source_pdf path in the published payload. Defaults to true. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of disclosing behavioral traits such as destructiveness, permissions, or side effects. It only states the action without elaborating on behaviors like file overwriting or privacy implications.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence that is front-loaded with the core action. It is efficient but somewhat under-specified for a tool with six parameters.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite the presence of an output schema, the description fails to explain the overall bundling process, how selection works, or the interaction between parameters like read_only and include_private. The tool's complexity warrants more context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents each parameter. The tool description adds no extra meaning beyond the schema descriptions, thus it meets the baseline of 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('Publish') and the resource ('static reader bundle'), and specifies the content ('selected notes and highlights'). This is specific and distinct from sibling tools like convert_pdf_to_card_html and validate_reader_annotations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is given on when to use this tool versus its siblings or when not to use it. The description lacks any contextual advice for tool selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
validate_reader_annotationsB
Validate a notes/highlights sidecar against a generated reader HTML file.
| Name | Required | Description | Default |
|---|---|---|---|
| include_private | No | Validate private annotations too. Defaults to true. | |
| annotations_path | Yes | Path to a pdf-card annotation sidecar JSON file. | |
| reader_html_path | Yes | Path to a standalone reader generated by this tool. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of disclosing behavioral traits. The verb 'validate' implies a read-only check, but it does not state whether the tool mutates anything, what happens on validation failure (e.g., errors vs. success), or any side effects. The description adds no behavioral detail beyond the core action.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence that starts with the action verb 'Validate'. It is concise, contains no redundant words, and immediately conveys the tool's purpose. Every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's moderate complexity (3 parameters, output schema exists), the description adequately sets the context. The output schema is not required to be described per the rubric. However, it could mention that validation is typically performed after generating the HTML with 'convert_pdf_to_card_html', which would tie it better to sibling tools. Slight gap in completeness.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all three parameters. The description adds context by mapping 'notes/highlights sidecar' to annotations_path and 'generated reader HTML file' to reader_html_path, which reinforces the schema descriptions but does not provide new semantic details. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Validate' and identifies the two resources: a 'notes/highlights sidecar' (annotation file) and a 'generated reader HTML file'. This distinguishes it from sibling tools like convert_pdf_to_card_html (which generates HTML from PDF) and publish_reader_bundle (which publishes a bundle). The purpose is specific and unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no explicit guidance on when to use this tool versus alternatives. It does not mention typical use cases, prerequisites (e.g., that the HTML must be generated first), or when not to use it. The agent must infer the context from the tool name and siblings.
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. Dates show when Glama detected each change.
2 tool updates
v0.1.3- Added
publish_reader_bundle - Added
validate_reader_annotations
1 tool update
v0.1.0- First observed
convert_pdf_to_card_html
TDQS
Each tool has a distinct purpose: conversion, publishing, and validation. No overlap between them.
All tools follow snake_case verb_noun pattern consistently (convert_pdf_to_card_html, publish_reader_bundle, validate_reader_annotations).
Three tools is appropriate for the focused domain of PDF-to-card HTML conversion and management.
Covers core workflow (create, publish, validate) but lacks operations for updating or deleting bundles/annotations.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
High-fidelity PDF to structured Markdown conversion and document field extraction.
- blinkpdfOAuthio.blinkpdf
Render Markdown and LLM output into accessible PDF/UA-1 PDFs. No headless Chromium.
Extract PDFs to Markdown, RAG chunks and cited tables; publish tracked Doc Links with read stats.
Extract tables, text and formulas from PDFs, including scanned pages and broken text layers.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI-driven PDF document processing including PDF to Markdown conversion, intelligent text and table extraction, image extraction, format conversion between PDF/Word/Markdown, batch processing, and fuzzy search - optimized for LLM context and RAG workflows.2MIT
- AlicenseAqualityCmaintenanceFast, local PDF parsing as an MCP server with text extraction, bounding boxes, OCR, and visual citations. No cloud or API key required.5MIT
- AlicenseAqualityAmaintenanceA local-first PDF tool for merging, splitting, rotating, watermarking, Bates-numbering, cleaning metadata, and counting pages — all operations happen on your machine with no network transmission.7721MIT
- FlicenseAqualityCmaintenanceEnables local analysis of unstructured documents (PDF, DOCX, PPTX, SVG, PNG) by extracting text and structure with citation anchors, and verifies summaries against source material before a human approves saving a report.9-
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/velyan/pdf-card-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server