pdfmux
The pdfmux server provides an orchestrator for comprehensive PDF processing, enabling AI agents to analyze, convert, and extract structured data from PDFs with automatic backend selection.
Get PDF Metadata (
get_pdf_metadata): Instantly retrieve basic PDF info — page count, file size, document type, and table presence — without full extraction. Useful as a first step to determine subsequent processing.Convert PDF to Markdown (
convert_pdf): Convert a PDF to AI-readable Markdown with automatic type detection and best-method selection. Supports configurable quality levels (fast,standard,high) and returns a confidence score with warnings.Analyze PDF Quality (
analyze_pdf): Perform a quick triage — classify PDF type, audit per-page quality, and estimate extraction difficulty without full conversion. A cost-effective initial assessment.Batch Convert Directory (
batch_convert): Convert all PDFs in a directory to Markdown in one call, with per-file results and configurable quality levels.Extract Structured Data (
extract_structured): Extract tables as JSON, key-value pairs with auto-normalization (dates, amounts, rates), and optionally map output to a JSON schema or built-in preset (invoice, receipt, contract, resume, paper).
Utilizes Google Gemini Flash as an optional API-based extraction engine for handling complex PDF layouts, handwriting, and image-heavy pages.
Converts PDF documents into clean Markdown, featuring automatic heading detection via font-size analysis and support for table extraction.
pdfmux
Self-healing PDF extraction that flags the pages it can't read instead of dropping them — and now certifies any extractor's output for silent drops. Open-source LlamaParse alternative for RAG pipelines, MCP server for Claude Desktop, LangChain + LlamaIndex loaders.
pdfmux extracts PDFs and checks its own work — and now certifies any extractor's, telling you which pages it silently dropped. Free, MIT. Patent-pending method.
pip install pdfmux.
Two jobs, one tool:
Self-healing extraction. The only PDF extractor that audits its own output. Catches blank pages, scrambled columns, broken tables — re-extracts them with a stronger backend, and flags what it still can't read instead of silently dropping it. So your LLM gets clean data, not silent garbage. Routes each page to the best of 7 built-in extraction backends + BYOK LLM fallback (Gemini / Claude / GPT-4o / Ollama). One CLI. One API. Zero config.
Certify Anything — new in v1.8.1.
pdfmux verifyaudits any extraction engine's output against the source PDF — Reducto, Mistral OCR, LlamaParse, Docling, your in-house parser — and tells you which pages it silently dropped. Free, MIT, patent-clean.
PDF ──> pdfmux router ──> best extractor per page ──> audit ──> re-extract failures ──> Markdown / JSON / chunks
|
├─ PyMuPDF (digital text, 0.01s/page)
├─ OpenDataLoader (complex layouts, 0.05s/page)
├─ RapidOCR (scanned pages, CPU-only)
├─ Docling (tables, 97.9% TEDS)
├─ Surya (heavy OCR fallback)
├─ Marker (academic papers, neural)
├─ Mistral OCR ($0.002/page, 96.6% tables)
└─ YOUR LLM (Gemini / Gemma 3 / Claude / GPT-4o / Ollama / Mistral — BYOK via YAML)Install
pip install pdfmuxThat handles digital PDFs. For any real-world batch, install pdfmux[ocr] too — almost every directory of PDFs has at least one scan, and without OCR those pages return empty text:
pip install "pdfmux[ocr]" # ⭐ recommended — RapidOCR for scanned pages (~200MB, CPU)Other backends, by document type:
pip install "pdfmux[tables]" # Docling — table-heavy docs (~500MB)
pip install "pdfmux[opendataloader]" # OpenDataLoader — complex layouts (Java 11+)
pip install "pdfmux[marker]" # Marker — neural extraction for academic papers
pip install "pdfmux[llm]" # Gemini fallback (default LLM)
pip install "pdfmux[llm-claude]" # Claude (Sonnet / Opus)
pip install "pdfmux[llm-openai]" # GPT-4o family
pip install "pdfmux[llm-ollama]" # Ollama (any local model)
pip install "pdfmux[llm-mistral]" # Mistral OCR API ($0.002/page)
pip install "pdfmux[llm-all]" # all LLM providers (incl. Gemma via Gemini key)
pip install "pdfmux[watch]" # `pdfmux watch <dir>` auto-convert on change
pip install "pdfmux[all]" # everythingRequires Python 3.11+.
Related MCP server: ConvertAgent
Quick Start
CLI
# zero config — just works
pdfmux convert invoice.pdf
# invoice.pdf -> invoice.md (2 pages, 95% confidence, via pymupdf4llm)
# RAG-ready chunks with token limits
pdfmux convert report.pdf --chunk --max-tokens 500
# cost-aware extraction with budget cap
pdfmux convert report.pdf --mode economy --budget 0.50
# schema-guided structured extraction (5 built-in presets)
pdfmux convert invoice.pdf --schema invoice
# BYOK any LLM for hardest pages
pdfmux convert scan.pdf --llm-provider claude
# use a built-in or saved profile (invoices, receipts, papers, contracts, bulk-rag)
pdfmux convert invoice.pdf --profile invoices
# predict cost before running anything
pdfmux estimate big-report.pdf --llm-provider gemini
# stream pages as NDJSON as they finish (great for long documents)
pdfmux stream report.pdf --quality high
# auto-convert any new PDFs that land in a folder
pdfmux watch ./inbox/ -o ./output/
# diff two extractions side-by-side
pdfmux diff old.pdf new.pdf
# batch a directory — writes manifest.json with per-doc confidence
pdfmux convert ./docs/ -o ./output/
# CI mode: fail the run if any document is below 0.20 confidence
pdfmux convert ./docs/ -o ./output/ --strict --min-confidence 0.20
# pre-flight a directory: which extras do you actually need for THIS batch?
pdfmux doctor --check ./docs/
# results are cached by file hash — re-runs are instant; bypass with --no-cache
pdfmux convert report.pdf --no-cache
pdfmux convert report.pdf --clear-cachePython
For batch processing, use batch_extract() — not a subprocess.run(['pdfmux', ...]) loop. Same pipeline, no per-file process spawn, handles non-ASCII filenames:
import pdfmux
from pathlib import Path
# Batch extract — yields (path, result) tuples as each PDF completes.
pdfs = list(Path("./inbox").glob("*.pdf"))
for path, result in pdfmux.batch_extract(pdfs, quality="standard"):
if isinstance(result, Exception):
print(f"FAILED {path.name}: {result}")
continue
if result.confidence < 0.50:
print(f"REVIEW {path.name} ({result.confidence:.2f})")
else:
print(f"OK {path.name} ({result.confidence:.2f})")
# Single-file helpers.
text = pdfmux.extract_text("report.pdf") # markdown string
data = pdfmux.extract_json("report.pdf") # locked schema dict
chunks = pdfmux.chunk("report.pdf", max_tokens=500) # RAG-ready chunksDon't wrap pdfmux with your own pypdf/pdfplumber fallback. pdfmux already routes per page through PyMuPDF → RapidOCR → vision LLM. PyMuPDF tolerates malformed PDFs that pypdf rejects ("Stream has ended unexpectedly"), so a downstream pypdf fallback turns recoverable PDFs into failures. Trust the router; check the confidence score on the result.
Certify Anything
pdfmux verify audits any extraction engine's output against the source PDF and tells you which pages it silently dropped — not just pdfmux's own extraction. Point it at the output of Reducto, Mistral OCR, LlamaParse, Docling, or your in-house parser and it re-derives the source text with pdfmux's own audit pass, aligns the extraction to it, and scores every page.
The failure it catches: a page where the source has real text but the engine returned nothing — while reporting success. That "silent drop" is the exact failure that poisons a RAG index without a single error in the logs.
# Certify pdfmux's own extraction of a document
pdfmux verify --source report.pdf --engine pdfmux
# Certify ANOTHER engine's output (JSON / Markdown / text)
pdfmux verify --source report.pdf --extracted reducto.json --engine-name reducto
# Batch a whole directory — the "M pages silently dropped across N docs" report
pdfmux verify --source ./pdfs/ --extracted ./engine-outputs/ -o certification.json
# CI gate: exit non-zero unless the overall verdict is PASS
pdfmux verify --source report.pdf --extracted out.json --strictEvery run prints a PASS / REVIEW / FAIL verdict, overall confidence and coverage, and — when it finds them — the silently dropped pages by number:
pdfmux verify — report.pdf · engine: reducto
FAIL confidence 71% · coverage 68%
reducto: FAIL; 3 page(s) SILENTLY DROPPED (pages 7, 12, 31); overall
confidence 71%, coverage 68% across 40 page(s).
❌ 3 page(s) SILENTLY DROPPED: 7, 12, 31Per page you get a verdict (pass / review / fail), confidence, coverage, alignment, hallucination-risk, and table/heading integrity. Batch mode rolls that up into a single "N pages silently dropped across M documents" line — the report you run on 100 of your own PDFs to find the silent failures already in your pipeline.
It works on any engine's output
--extracted accepts JSON, Markdown, or plain text (--extracted-format auto | json | markdown | text). When the extraction exposes real per-page structure, pdfmux compares page-by-page; when it's a single blob, it falls back to content-presence checks so it never fabricates a "silent drop" from a pagination mismatch.
Python API
from pdfmux import verify_extraction, verify_batch
# Single document → a CertificationManifest
manifest = verify_extraction("report.pdf", "reducto.json", engine="reducto")
print(manifest.verdict) # "PASS" | "REVIEW" | "FAIL"
print(manifest.silent_drops) # e.g. (7, 12, 31) — 1-indexed page numbers
print(manifest.coverage) # 0.0–1.0
# Many documents → a BatchCertification ("M pages dropped across N docs")
batch = verify_batch([("a.pdf", "a.json"), ("b.pdf", "b.json")], engine="llamaparse")
print(batch.total_silent_drops, "pages dropped across", batch.doc_count, "docs")Each manifest carries a tamper-evident SHA-256 content signature over its canonical body and an embedded, honest limitations list: the certifier is lexical, not linguistic — it detects missing and garbled content, not faithful paraphrase or translation.
MCP
verify_extraction is exposed as an MCP tool (the 7th — see MCP Server), so an agent can certify an engine's output in the same session it extracts.
Free, MIT, patent-clean
Certify Anything reuses only pdfmux's shipped MIT audit layer. It does not include, and does not require, the patent-pending decision-trace method — that stays in pdfmux Cloud/Pro. pip install pdfmux gives you the full verify command at no cost.
Full reference: docs/CERTIFY-ANYTHING.md.
When you need to prove it to someone else
A local install can audit an extraction, but it cannot attest to one — anything it signs, anyone could forge. pdfmux Cloud returns an Ed25519-signed manifest over the extraction: your auditor verifies it offline, against a published public key, without an account and without trusting pdfmux.
pdfmux verify-manifest manifest.json # free, MIT, offline — no accountVerification is free and open forever; only generation is paid ($49/mo). That asymmetry is deliberate — you should never need our permission to check our work.
Free tool, no signup: app.pdfmux.com/audit — upload a PDF and see which pages your current extractor silently dropped. Measured accuracy (and its blind spots) published in pdfmux-bench.
Architecture
┌─────────────────────────────┐
│ Segment Detector │
│ text / tables / images / │
│ formulas / headers per page │
└─────────────┬───────────────┘
│
┌────────────────────────────────────────┐
│ Router Engine │
│ │
│ economy ── balanced ── premium │
│ (minimize $) (default) (max quality)│
│ budget caps: --budget 0.50 │
└────────────────────┬───────────────────┘
│
┌──────────┬──────────┬────────┴────────┬──────────┐
│ │ │ │ │
PyMuPDF OpenData RapidOCR Docling LLM
digital Loader scanned tables (BYOK)
0.01s/pg complex CPU-only 97.9% any provider
layouts TEDS
│ │ │ │ │
└──────────┴──────────┴────────┬────────┴──────────┘
│
┌────────────────────────────────────────┐
│ Quality Auditor │
│ │
│ 4-signal dynamic confidence scoring │
│ per-page: good / bad / empty │
│ if bad -> re-extract with next backend│
└────────────────────┬───────────────────┘
│
┌────────────────────────────────────────┐
│ Output Pipeline │
│ │
│ heading injection (font-size analysis)│
│ table extraction + normalization │
│ text cleanup + merge │
│ confidence score (honest, not inflated)│
└────────────────────────────────────────┘Key design decisions
Router, not extractor. pdfmux does not compete with PyMuPDF or Docling. It picks the best one per page.
Agentic multi-pass. Extract, audit confidence, re-extract failures with a stronger backend. Bad pages get retried automatically.
Segment-level detection. Each page is classified by content type (text, tables, images, formulas, headers) before routing.
4-signal confidence. Dynamic quality scoring from character density, OCR noise ratio, table integrity, and heading structure. Not hardcoded thresholds.
Document cache. Each PDF is opened once, not once per extractor. Shared across the full pipeline.
Data flywheel. Local telemetry tracks which extractors win per document type. Routing improves with usage.
Features
Feature | What it does | Command |
Zero-config extraction | Routes to best backend automatically |
|
RAG chunking | Section-aware chunks with token estimates |
|
Cost modes | economy / balanced / premium with budget caps |
|
Schema extraction | 5 built-in presets (invoice, receipt, contract, resume, paper) |
|
Profiles | Save and re-use config; built-ins for invoices/receipts/papers/contracts/bulk-rag |
|
BYOK LLM | Gemini, Gemma 3, Claude, GPT-4o, Ollama, Mistral, any OpenAI-compatible API |
|
Cost estimate | Predict spend before running |
|
Streaming output | NDJSON events page-by-page for long docs |
|
Smart cache | Hash-keyed result cache, 30-day TTL, 1 GB LRU |
|
Watch mode | Auto-convert any PDF added to a folder |
|
Diff | Compare two extractions |
|
Benchmark | Eval all installed extractors against ground truth |
|
Doctor | Show installed backends, coverage gaps, recommendations |
|
MCP server | AI agents read PDFs via stdio or HTTP |
|
Batch processing | Convert entire directories |
|
Page-level streaming API | Bounded-memory page iteration for large files |
|
Retry with backoff | Every LLM provider auto-retries with exponential backoff + | (built-in) |
CLI Reference
pdfmux convert
pdfmux convert <file-or-dir> [options]
Options:
-o, --output PATH Output file or directory
-f, --format FORMAT markdown | json | csv | llm (default: markdown)
-q, --quality QUALITY fast | standard | high (default: standard)
-s, --schema SCHEMA JSON schema file or preset (invoice, receipt, contract, resume, paper)
--chunk Output RAG-ready chunks
--max-tokens N Max tokens per chunk (default: 500)
--mode MODE economy | balanced | premium (default: balanced)
--budget AMOUNT Max spend per document in USD
--llm-provider PROVIDER LLM backend: gemini | claude | openai | ollama
--confidence Include confidence score in output
--stdout Print to stdout instead of filepdfmux serve
Start the MCP server for AI agent integration.
pdfmux serve # stdio mode (Claude Desktop, Cursor)
pdfmux serve --http 8080 # HTTP modepdfmux doctor
pdfmux doctor
# ┌──────────────────┬─────────────┬─────────┬──────────────────────────────────┐
# │ Extractor │ Status │ Version │ Install │
# ├──────────────────┼─────────────┼─────────┼──────────────────────────────────┤
# │ PyMuPDF │ installed │ 1.25.3 │ │
# │ OpenDataLoader │ installed │ 0.3.1 │ │
# │ RapidOCR │ installed │ 3.0.6 │ │
# │ Docling │ missing │ -- │ pip install pdfmux[tables] │
# │ Surya │ missing │ -- │ pip install pdfmux[ocr-heavy] │
# │ LLM (Gemini) │ configured │ -- │ GEMINI_API_KEY set │
# └──────────────────┴─────────────┴─────────┴──────────────────────────────────┘pdfmux benchmark
pdfmux benchmark report.pdf
# ┌──────────────────┬────────┬────────────┬─────────────┬──────────────────────┐
# │ Extractor │ Time │ Confidence │ Output │ Status │
# ├──────────────────┼────────┼────────────┼─────────────┼──────────────────────┤
# │ PyMuPDF │ 0.02s │ 95% │ 3,241 chars │ all pages good │
# │ Multi-pass │ 0.03s │ 95% │ 3,241 chars │ all pages good │
# │ RapidOCR │ 4.20s │ 88% │ 2,891 chars │ ok │
# │ OpenDataLoader │ 0.12s │ 97% │ 3,310 chars │ best │
# └──────────────────┴────────┴────────────┴─────────────┴──────────────────────┘pdfmux estimate
Predict spend (and which backends will run) before processing.
pdfmux estimate report.pdf --quality high --llm-provider gemini
# Pages : 47
# Extractors : pymupdf4llm + gemini-2.5-flash on 9 pages
# Estimated : $0.0234
# Cache hit? : no (first run for this file)pdfmux stream
Emit NDJSON events as pages complete — useful for very long PDFs and live UIs.
pdfmux stream long.pdf --quality high
# {"event":"classified","page_count":312,"plan":"pymupdf+gemini-fallback"}
# {"event":"page","page_num":0,"confidence":0.97,"chars":1842}
# {"event":"page","page_num":1,"confidence":0.92,"chars":1611,"ocr":true}
# ...
# {"event":"complete","confidence":0.94,"cost_usd":0.0712}pdfmux watch
Auto-convert any PDFs that land in a directory. Survives until Ctrl+C.
pdfmux watch ./inbox/ -o ./output/ --profile bulk-ragpdfmux diff
Side-by-side extraction comparison (quality, content, cost).
pdfmux diff a.pdf b.pdf --quality standardpdfmux profiles
Saved configs at ~/.config/pdfmux/profiles.yaml. Built-ins ship for the
common shapes; save your own for project defaults.
pdfmux profiles list
# invoices quality=standard, schema=invoice, format=json
# receipts quality=fast, schema=receipt, format=json
# papers quality=high, chunk=true, max_tokens=500
# contracts quality=high, schema=contract
# bulk-rag quality=standard, format=llm, chunk=true
pdfmux profiles show invoices
pdfmux profiles save my-default --quality high --format llm --chunk
pdfmux profiles delete my-default
# use a profile when converting
pdfmux convert file.pdf --profile invoicesPython API
Text extraction
import pdfmux
text = pdfmux.extract_text("report.pdf") # -> str (markdown)
text = pdfmux.extract_text("report.pdf", quality="fast") # PyMuPDF only, instant
text = pdfmux.extract_text("report.pdf", quality="high") # LLM-assistedStructured extraction
data = pdfmux.extract_json("report.pdf")
# data["page_count"] -> 12
# data["confidence"] -> 0.91
# data["ocr_pages"] -> [2, 5, 8]
# data["pages"][0]["key_values"] -> [{"key": "Date", "value": "2026-02-28"}]
# data["pages"][0]["tables"] -> [{"headers": [...], "rows": [...]}]RAG chunking
chunks = pdfmux.chunk("report.pdf", max_tokens=500)
for c in chunks:
print(f"{c['title']}: {c['tokens']} tokens (pages {c['page_start']}-{c['page_end']})")Schema-guided extraction
data = pdfmux.extract_json("invoice.pdf", schema="invoice")
# Uses built-in invoice preset: extracts date, vendor, line items, totals
# Also accepts a path to a custom JSON Schema fileStreaming (bounded memory)
from pdfmux.extractors import get_extractor
ext = get_extractor("fast")
for page in ext.extract("large-500-pages.pdf"): # Iterator[PageResult]
process(page.text) # constant memory, even on 500-page PDFsTypes and errors
from pdfmux import (
# Enums
Quality, # FAST, STANDARD, HIGH
OutputFormat, # MARKDOWN, JSON, CSV, LLM
PageQuality, # GOOD, BAD, EMPTY
# Data objects (frozen dataclasses)
PageResult, # page: text, page_num, confidence, quality, extractor
DocumentResult, # document: pages, source, confidence, extractor_used
Chunk, # chunk: title, text, page_start, page_end, tokens
# Errors
PdfmuxError, # base -- catch this for all pdfmux errors
FileError, # file not found, unreadable, not a PDF
ExtractionError, # extraction failed
ExtractorNotAvailable,# requested backend not installed
FormatError, # invalid output format
AuditError, # audit could not complete
)Framework Integrations
LangChain
pip install langchain-pdfmuxfrom langchain_pdfmux import PDFMuxLoader
loader = PDFMuxLoader("report.pdf", quality="standard")
docs = loader.load() # -> list[Document] with confidence metadataLlamaIndex
pip install llama-index-readers-pdfmuxfrom llama_index.readers.pdfmux import PDFMuxReader
reader = PDFMuxReader(quality="standard")
docs = reader.load_data("report.pdf") # -> list[Document]MCP Server (AI Agents)
Listed on mcpservers.org. One-line setup:
{
"mcpServers": {
"pdfmux": {
"command": "npx",
"args": ["-y", "pdfmux-mcp"]
}
}
}Or via Claude Code:
claude mcp add pdfmux -- npx -y pdfmux-mcpTools exposed: convert_pdf, analyze_pdf, extract_structured,
extract_streaming, get_pdf_metadata, batch_convert.
BYOK LLM Configuration
pdfmux supports any LLM via 5 lines of YAML. Bring your own keys -- nothing leaves your machine unless you configure it to.
# ~/.pdfmux/llm.yaml
provider: claude # gemini | claude | openai | ollama | any OpenAI-compatible
model: claude-sonnet-4-20250514
api_key: ${ANTHROPIC_API_KEY}
base_url: https://api.anthropic.com # optional, for custom endpoints
max_cost_per_page: 0.02 # budget capSupported providers:
Provider | Models | Local? | Cost |
Gemini | 2.5 Flash, 2.5 Pro | No | ~$0.01/page |
Gemma 3 | 27B IT, 12B IT (great for Arabic) | No (via Gemini key) | ~$0.0002/page |
Claude | Sonnet, Opus | No | ~$0.015/page |
GPT-4o | GPT-4o, GPT-4o-mini | No | ~$0.01/page |
Mistral |
| No | $0.002/page |
Ollama | Any local model | Yes | Free |
Custom | Any OpenAI-compatible API | Configurable | Varies |
Every provider's extract_page() is wrapped in @with_retry(max_attempts=3, backoff_base=2.0), which honors Retry-After headers on 429s and skips
retries on auth failures so a bad key fails fast.
Arabic & RTL Support
pdfmux ships first-class support for Arabic, Persian, Urdu, and Hebrew. Out of the box, RTL detection runs on every PDF and PyMuPDF-extracted pages are passed through the Unicode Bidirectional Algorithm so glyphs that were stored in left-to-right order render in correct reading order.
# Default install — already includes python-bidi for RTL reordering
pip install pdfmux
# Recommended for Arabic-heavy docs — adds Gemma vision OCR
# (Gemma speaks the OpenAI protocol, so it needs the openai SDK)
pip install "pdfmux[llm-openai]"
# One credential covers Gemma + Gemini (same Google endpoint)
export GEMINI_API_KEY=...What happens automatically:
pdfmux convertdetects Arabic content and routes pages with >5% Arabic characters through the Arabic-aware extractor chain.PyMuPDF, RapidOCR, and Docling outputs are post-processed with the Bidi algorithm — markdown headings (
#) and pipe-table rows preserve structure, only inner text is reordered.DocumentResult.has_arabicis set toTruewhenever any page contains Arabic script.
What requires opt-in:
Vision LLM extraction. Set
--llm-provider gemma(or any vision provider) to route Arabic pages through Gemma instead of PyMuPDF.Aggressive normalization (Tatweel removal, Alef/Yeh unification, Tashkeel stripping) — call
pdfmux.arabic.normalize_arabic(text)on extracted strings if you need canonicalized output for search or embedding.
from pdfmux.arabic import (
is_arabic_text,
is_rtl_dominant,
fix_bidi_order,
normalize_arabic,
)
text = "مرحبا بالعالم"
assert is_arabic_text(text)
assert is_rtl_dominant(text)
# Fix glyph order from PyMuPDF / OCR engines
visual = fix_bidi_order(text)
# Canonicalize for indexing — strip Tatweel, unify Alef variants, drop diacritics
indexable = normalize_arabic("أَحْمَدْ") # → "احمد"Proof: a real customer batch
We measured pdfmux on 433 real customer documents — technical and safety data sheets, mixed digital and scanned, some encoding-corrupted. Run the naive way first (an early pdfmux CLI in a subprocess, pypdf fallback, no OCR), the pipeline silently dropped 16 documents — 11 of them with no log line at all. That was our own tool failing at the exact thing it promises.
Rebuilt with the per-page audit + budgeted OCR cascade: 433 of 433 processed, zero silent failures. Every unrecoverable page is flagged, not dropped.
(A small internal confidence-calibration set also ships under eval/ — it's a regression guard on the confidence gate, not a competitive benchmark; see eval/README.md.)
Benchmark
On opendataloader-bench — 200 real-world PDFs (financial filings, academic papers, legal contracts, government reports) — pdfmux scores 0.903 overall — #2 of the 8 engines measured, behind opendataloader-hybrid (0.909). Re-run 2026-07-16 (reproduction below).
Rank | Engine | Overall | Reading order | Tables (TEDS) | License | GPU |
1 | opendataloader-hybrid | 0.909 | 0.935 | 0.928 | Apache-2.0 | No |
2 | pdfmux | 0.903 | 0.920 | 0.911 | MIT | No |
3 | Docling | 0.877 | 0.900 | 0.887 | MIT | Optional |
4 | marker | 0.861 | 0.890 | 0.808 | free | GPU |
5 | mineru | 0.831 | 0.857 | 0.873 | free | GPU |
Full per-document scores: the 200-PDF head-to-head · methodology: best PDF extraction library, benchmarked.
Smart Result Cache
Re-running the same extraction is instant. pdfmux hashes every input PDF
(SHA-256) and keys results on (file_hash, quality, format, schema). Cache
files live under ~/.cache/pdfmux/results/, expire after 30 days, and are
LRU-evicted at 1 GB.
pdfmux convert big-report.pdf # first run: 14.2s
pdfmux convert big-report.pdf # cache hit: 0.05s
pdfmux convert big-report.pdf --no-cache # bypass cache (still writes back)
pdfmux convert big-report.pdf --clear-cache # purge and re-runThe cache also speeds up --profile, --schema, and --format switches —
each combination is keyed independently, so you can flip between Markdown
and JSON for the same document for free after the first extraction.
Confidence Scoring
Every result includes a 4-signal confidence score:
95-100% -- clean digital text, fully extractable
80-95% -- good extraction, minor OCR noise on some pages
50-80% -- partial extraction, some pages unrecoverable
<50% -- significant content missing, warnings included
When confidence drops below 80%, pdfmux tells you exactly what went wrong and how to fix it:
Page 4: 32% confidence. 0 chars extracted from image-heavy page.
-> Install pdfmux[ocr] for RapidOCR support on 6 image-heavy pages.Cost Modes
Mode | Behavior | Typical cost |
economy | Rule-based backends only. No LLM calls. | $0/page |
balanced | LLM only for pages that fail rule-based extraction. | ~$0.002/page avg |
premium | LLM on every page for maximum quality. | ~$0.01/page |
Set a hard budget cap: --budget 0.50 stops LLM calls when spend reaches $0.50 per document.
Why pdfmux?
pdfmux is not another PDF extractor. It is the orchestration layer that picks the right extractor per page, verifies the result, and retries failures.
Tool | Good at | Limitation |
PyMuPDF | Fast digital text | Cannot handle scans or image layouts |
Docling | Tables (97.9% accuracy) | Slow on non-table documents |
Marker | Neural extraction for academic papers | Needs GPU for speed; overkill for digital PDFs |
Mistral OCR | Tables (96.6% TEDS), $0.002/page | Cloud-only API |
Unstructured | Enterprise platform | Complex setup, paid tiers |
LlamaParse | Cloud-native | Requires API keys, not local |
Reducto | High accuracy | $0.015/page, closed source |
pdfmux | Orchestrates all of the above | Routes per page, audits, re-extracts |
Open source Reducto alternative: what costs $0.015/page elsewhere is free with pdfmux's rule-based backends, or ~$0.002/page average with BYOK LLM fallback.
Development
git clone https://github.com/NameetP/pdfmux.git
cd pdfmux
python3.12 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pytest # 659 tests
ruff check src/ tests/
ruff format src/ tests/Contributing
Fork the repo
Create a branch (
git checkout -b feature/your-feature)Write tests for new functionality
Ensure
pytestandruff checkpassOpen a PR
License
The pdfmux library and MCP server in this repository are MIT licensed — free for any use, and every released version stays MIT.
The confidence-budgeted decision-trace method (the persisted per-page decision trace with retained rejected candidates, and the monotonic repair guard) is patent-pending (US Provisional App No. 64/106,302) and is reserved for pdfmux Cloud/Pro under a separate commercial license — it is not part of the MIT grant. See LICENSING.md and NOTICE.
Available Tools
7 toolsanalyze_pdfA
Quick PDF triage — classify type and audit page quality without full extraction. Returns page count, type detection, per-page quality breakdown, and estimated extraction difficulty. Much cheaper than convert_pdf for initial assessment.
| Name | Required | Description | Default |
|---|---|---|---|
| file_path | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description is sole source. Discloses return values and non-destructive nature, but lacks details on prerequisites, errors, or limitations. Adequate but not comprehensive.
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 sentences, front-loaded with purpose and key differentiator. No unnecessary words; every sentence adds value.
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?
Tool is simple (1 param, has output schema), and description covers purpose, returned data, and cost comparison. Minor gaps (e.g., file limitations) but overall sufficient for a triage tool.
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?
Input schema has one parameter (file_path) with 0% description coverage. Description does not add detail about the parameter type, format, or constraints beyond what the schema already shows, missing opportunity to clarify.
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?
Description clearly states tool does PDF triage, classifying type and auditing page quality without full extraction. It explicitly differentiates from sibling convert_pdf by noting it is cheaper and for initial assessment.
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?
Explicitly recommends use over convert_pdf for initial assessment and notes it avoids full extraction, providing clear context. Does not cover all sibling tools but adequately guides when to use this one.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
batch_convertC
Convert all PDFs in a directory to Markdown. Returns a summary with per-file results.
| Name | Required | Description | Default |
|---|---|---|---|
| quality | No | standard | |
| directory | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full burden. It discloses batch conversion and a summary return, but omits side effects (e.g., file modifications), error handling, and dependencies. The behavioral disclosure is minimal.
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 sentences are concise, but the brevity sacrifices needed detail. While not verbose, missing parameter explanations and behavioral context reduce effectiveness.
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?
The output schema exists but is not explained (summary with per-file results is vague). Sibling tools provide contrast, but the description lacks completeness on error handling, output format, and parameter details for quality.
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 0%, yet the description only mentions 'directory' implicitly and does not explain the 'quality' parameter (e.g., standard vs high). No added meaning beyond the raw 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 'Convert all PDFs in a directory to Markdown', specifying the verb (convert), resource (all PDFs in a directory), and output format (Markdown). This distinguishes it from sibling tools like convert_pdf (single file) and extract_streaming (streaming extraction).
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 guidance on when to use this tool vs alternatives, no prerequisites (e.g., directory existence, permissions), and no exclusions. It simply states what it does without context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
convert_pdfA
Convert a PDF to AI-readable Markdown. Automatically detects the PDF type and picks the best extraction method. Returns confidence score and warnings when extraction is limited.
| Name | Required | Description | Default |
|---|---|---|---|
| format | No | markdown | |
| quality | No | standard | |
| file_path | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description transparently discloses key behaviors: automatic PDF type detection, best extraction method selection, and return of confidence scores and warnings. This adds value beyond the schema, though it doesn't mention potential side effects or permissions.
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 sentences, zero wasted words. Essential information is front-loaded: action, resource, then additional features. Highly concise.
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?
While purpose and output details are covered, the lack of parameter descriptions (especially for 'format' and 'quality') leaves the tool incomplete for effective use. An output schema exists but is not shown; description should compensate but does not.
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 0%, placing full burden on the description to explain parameters like 'format' and 'quality'. The description fails to provide any details about these parameters, offering no guidance on valid values or behavior.
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 ('Convert a PDF to AI-readable Markdown') and resource, distinguishing it from siblings like analyze_pdf or extract_streaming. The verb 'Convert' and target format 'Markdown' make the purpose 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?
Implies usage for general PDF-to-Markdown conversion with automatic detection, but does not explicitly state when to use alternatives like extract_structured or batch_convert. No when-not or exclusions provided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
extract_streamingA
Stream extraction events for a PDF as NDJSON.
Use for large documents (100+ pages) where waiting for the full extraction is impractical. The response body is newline-delimited JSON with one object per line:
{"type":"classified","data":{"page_count":N,"page_types":[...]}}
{"type":"page","data":{"page_num":0,"text":"...","confidence":0.92,...}}
{"type":"warning","data":{"message":"..."}} (zero or more)
{"type":"complete","data":{"total_confidence":0.94,"ocr_pages":[...],...}}The first event is always classified; the last is always complete.
Each page event arrives as soon as that page is extracted, including
OCR re-extraction in standard/high quality modes.
| Name | Required | Description | Default |
|---|---|---|---|
| quality | No | standard | |
| file_path | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Since no annotations are provided, the description carries the full burden. It details the streaming format (NDJSON), event types (classified, page, warning, complete), and ordering. It also mentions OCR re-extraction in standard/high quality. However, it does not cover error handling or authorization, which would improve transparency.
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 front-loaded with the main purpose and includes a detailed event format example. While the code block is somewhat lengthy, it provides essential context. Every sentence adds value, making it appropriately sized.
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?
For a streaming tool, the description covers event types, ordering, and use case. It implicitly defines the output schema through examples. It does not cover error scenarios or timeouts, but given the tool's nature, it is largely complete.
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 0%, so the description must compensate. It mentions quality modes but does not explicitly explain the file_path parameter or possible quality values beyond 'standard/high'. The description adds little meaning beyond the schema's names and defaults.
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 streams extraction events for a PDF as NDJSON, with a specific use case for large documents. However, it does not explicitly distinguish itself from sibling tools like extract_structured, which would have earned a 5.
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 explicitly recommends use for large documents (100+ pages) where waiting is impractical, providing clear context. However, it does not mention when NOT to use it or suggest alternatives, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
extract_structuredA
Extract structured data from a PDF — tables as JSON, key-value pairs, and optionally map to a JSON schema. Returns tables with headers/rows, detected key-value pairs with auto-normalization (dates, amounts, rates), and schema-mapped output if a schema is provided.
| Name | Required | Description | Default |
|---|---|---|---|
| schema | No | ||
| quality | No | standard | |
| file_path | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full burden. It mentions auto-normalization and return types but does not disclose read-only behavior, permissions, or error handling. It provides moderate transparency.
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, well-structured sentence that is front-loaded with key actions and outputs, containing no unnecessary words.
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 existence of an output schema, the description sufficiently explains return values. It covers main features but lacks details on error conditions or prerequisites. Overall, it is fairly complete for a data extraction tool.
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 0% (no parameter descriptions in schema). The description adds context for the schema parameter (optional mapping) but does not explain file_path or quality. It partially compensates for the gap.
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 extracts structured data from PDFs, specifying outputs like tables as JSON and key-value pairs with auto-normalization. It distinguishes from sibling tools by focusing on structured extraction.
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 for structured data extraction but lacks explicit guidance on when to use this tool versus alternatives like extract_streaming or analyze_pdf. No exclusions or prerequisites are mentioned.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_pdf_metadataA
Get PDF metadata instantly — page count, file size, document type, and whether it has tables. No extraction performed. Use this first to decide which tool to call next: convert_pdf for full text, analyze_pdf for quality audit, or extract_structured for tables.
| Name | Required | Description | Default |
|---|---|---|---|
| file_path | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Clearly states no extraction, implying read-only behavior, and lists metadata returned. While it doesn't cover all behavioral details (e.g., file existence requirements), it is transparent enough for a simple metadata tool.
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 sentences covering purpose, output, and usage guidelines with zero wasted words; information is front-loaded and clearly structured.
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 output schema exists, the description adequately covers what the tool returns and how to use it in a workflow. Lacks error handling details but is sufficient for its simplicity.
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?
The only parameter 'file_path' has no schema description (0% coverage), and the description does not add details about valid file types, path format, or access requirements, leaving interpretation to the field name.
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?
Explicitly states it retrieves PDF metadata (page count, file size, document type, table presence) and distinguishes from siblings by clarifying no extraction is performed.
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?
Directs to use this first and lists specific alternatives (convert_pdf, analyze_pdf, extract_structured) based on the need, providing clear decision guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
verify_extractionA
Audit an extraction of a PDF for silently-dropped pages — the failure where an extractor returns nothing for a page that has real text while reporting success. Pass extracted_text with another engine's output (Reducto, Mistral OCR, LlamaParse, Docling, an in-house parser — as JSON, Markdown, or plain text) to certify THAT engine against the source PDF; omit it to have pdfmux extract the document itself and certify its own read. Returns the per-page audit — each page marked usable / silently-empty / recovered / review / unverifiable — the "N of M pages silently dropped" headline, and an overall PASS/REVIEW/FAIL verdict with a tamper-evident signature. Reuses pdfmux's own audit pass as the ground truth.
| Name | Required | Description | Default |
|---|---|---|---|
| fmt | No | auto | |
| engine | No | external | |
| file_path | Yes | ||
| extracted_text | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses behavioral traits such as returning per-page audit statuses (usable/silently-empty/recovered/review/unverifiable), a headline with count of silently dropped pages, and an overall verdict with tamper-evident signature. It also explains the ground truth method (reusing pdfmux's audit pass). No annotations exist, so the description carries full burden and meets it well.
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 paragraph that introduces the core concept first ('Audit an extraction of a PDF...') and then adds detail. It is efficient with no wasted words, though slightly dense.
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 presence of an output schema, the description does not need to detail return values but still summarizes them. It covers main use cases and parameter semantics. Complexity is moderate and all key aspects are addressed, with minor gaps like error scenarios.
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?
The schema has 0% description coverage, but the description adds meaning: it explains that extracted_text can be from another engine or omitted, and names the engine as a parameter. It could be more specific about fmt and engine values, but overall it compensates for schema gaps.
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 audits a PDF extraction for silently-dropped pages, specifying the verb 'audit', resource 'extraction of a PDF', and unique failure mode. It distinguishes from sibling tools like convert_pdf or extract_structured by focusing on verification rather than conversion or extraction.
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 explains when to use the tool: pass extracted_text from another engine for certification, or omit it for self-certification. It provides clear context but does not explicitly state when not to use or list alternatives beyond the two modes.
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.
1 tool update
v1.8.7- Added
verify_extraction
1 tool update
v1.6.4- Added
extract_streaming
5 tool updates
v1.5.0- First observed
analyze_pdf - First observed
batch_convert - First observed
convert_pdf - First observed
extract_structured - First observed
get_pdf_metadata
TDQS
Each tool has a clearly distinct purpose: metadata extraction, full conversion, quality analysis, batch processing, structured data extraction, streaming extraction, and verification. No two tools overlap in functionality, and descriptions guide selection.
Tool names mostly follow a verb_noun pattern (e.g., get_pdf_metadata, convert_pdf), but batch_convert reverses the order and extract_structured/extract_streaming use adjective noun after verb. This minor inconsistency lowers the score slightly.
Seven tools cover the core PDF extraction workflow—metadata, analysis, conversion, batch, structured extraction, streaming, and verification—without redundancy. The scope is well-balanced for the domain.
The tool set covers the main PDF processing tasks (metadata, conversion, analysis, extraction, streaming, verification) but lacks basic operations like merging or splitting. For an extraction-focused server, the coverage is very good.
Maintenance
Related MCP Connectors
Hosted MCP server: convert PDFs to clean, LLM-ready Markdown with tables, formulas and OCR.
High-fidelity PDF to structured Markdown conversion and document field extraction.
Turn any PDF into structured JSON via AI + OCR: invoices, bank statements, contracts.
OCR, transcription, file extraction, and image generation for AI agents via MCP.
Related MCP Servers
- AlicenseNot gradedqualityFmaintenanceEnables 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.10MIT
- AlicenseNot gradedqualityCmaintenanceFile conversion built for AI agents. CLI, REST API, and MCP server — all sharing one engine.141MIT

flexorch-mcpofficial
AlicenseAqualityAmaintenanceEnables Claude and other MCP-compatible agents to process documents, extract structured data, detect PII, and export LLM-ready datasets through natural language tool calls.81MIT- AlicenseNot gradedqualityBmaintenanceMCP server that extracts clean text, tables, and structured data from documents, images, code, and audio files, supporting 97 formats with OCR, transcription, and code intelligence.MIT
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/NameetP/pdfmux'
If you have feedback or need assistance with the MCP directory API, please join our Discord server