mcpField
P
pdfmux — PDF extraction that actually works

pdfmux — PDF extraction that actually works

ローカル
pdfmux.comファイル・ストレージ862 週間前に更新

pdfmux — PDF extraction that actually works について

pdfmux は、ページごとに抽出結果を検証し、読み取れないページを黙って欠落させず明示する PDF 抽出 MCP サーバーです。RAG パイプラインや、信頼できる PDF テキストを必要とするAIエージェント向けで、verify コマンドによって他の抽出ツールの出力も検証できます。

主な機能

  1. 01ページごとの検証と失敗ページの自動再抽出
  2. 02ページ内容に応じた抽出バックエンドの選択
  3. 03RAG 向けチャンク分割と Markdown・JSON 出力
  4. 04他エンジンの出力における欠落ページの検出
  5. 05スキャン PDF の OCR と任意の LLM フォールバック

活用シーン

  1. 01RAG インデックス用に PDF テキストを準備し欠落ページを確認
  2. 02AIエージェントがセッション内で PDF を読み取り変換
  3. 03サードパーティ製PDF抽出ツールの出力完全性を一括確認

MCP 対応

pdfmux serve により stdio または HTTP モードの MCP サーバーとして動作します。PDF のメタデータ取得、変換、分析、一括変換、構造化抽出のツールと、他エンジンの出力を検証する verify_extraction ツールを MCP クライアントに提供します。

設定

ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。

mcp.json · 共通設定
{
"mcpServers": {
"pdfmux": {
"command": "uvx",
"args": [
"pdfmux"
],
"env": {
"GEMINI_API_KEY": "<GEMINI_API_KEY>"
}
}
}
}
起動コマンドuvx pdfmux
設定が必要な環境変数
GEMINI_API_KEYシークレットOptional Google AI API key. Enables the paid Gemini Flash fallback for pages where all local backends report low confidence. pdfmux runs 100% locally without this.

ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。

パッケージ
pypipdfmux1.8.7

ツール

ツール一覧はまだ取得されていません

ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。

詳細

pdfmux

CI PyPI Python 3.11+ License: MIT Downloads

読み取れなかったページを削除せずに報告する、自己修復型 PDF 抽出ツールです。さらに、あらゆる抽出ツールの出力で、見落とされたページがないかを検証できます。 RAG パイプライン向けのオープンソース LlamaParse 代替ツールで、Claude Desktop 用 MCP サーバー、LangChain および LlamaIndex ローダーも提供します。

pdfmux は PDF を抽出して結果を自己検証します。さらに、あらゆる抽出ツールの出力を検証し、見落とされたページを知らせます。無料、MIT ライセンス。特許出願中の手法です。pip install pdfmux。

1 つのツールで 2 つの役割を実現:

  • 自己修復型の抽出。 出力を自己監査する唯一の PDF 抽出ツールです。空白ページ、列の乱れ、表の崩れを検出し、より強力なバックエンドで再抽出します。それでも読み取れないページは、黙って削除せずに報告します。これにより、LLM には見えないゴミデータではなく、クリーンなデータが渡されます。組み込みの 7 つの抽出バックエンドから各ページに最適なものを選択し、BYOK の LLM フォールバック(Gemini / Claude / GPT-4o / Ollama)も利用できます。CLI は 1 つ、API も 1 つ。設定は不要です。
  • あらゆる出力を検証 — v1.8.1 の新機能。 pdfmux verify は、元の PDF と照合して、あらゆる抽出エンジンの出力を監査します。Reducto、Mistral OCR、LlamaParse、Docling、自社製パーサーなどの出力から、見落とされたページを知らせます。無料、MIT ライセンスで、特許上の問題はありません。

pdfmux のターミナルデモ

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)

インストール

pip install pdfmux

これでデジタル PDF に対応できます。実際の PDF を一括処理する場合は、pdfmux[ocr] もインストールしてください。 PDF のフォルダーにはほぼ必ずスキャン画像が含まれます。OCR がない場合、これらのページからは空のテキストが返されます。

pip install "pdfmux[ocr]"             # ⭐ recommended — RapidOCR for scanned pages (~200MB, CPU)

ドキュメントの種類に応じて、ほかのバックエンドも利用できます。

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]"             # everything

Python 3.11 以降が必要です。

クイックスタート

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-cache
Python

一括処理には subprocess.run(['pdfmux', ...]) のループではなく、batch_extract() を使用してください。同じパイプラインを使いながら、ファイルごとのプロセス起動を避け、ASCII 以外のファイル名にも対応します。

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 chunks

pdfmux を独自の pypdf/pdfplumber フォールバックでラップしないでください。 pdfmux はページごとに PyMuPDF → RapidOCR → vision LLM の順で処理を振り分けます。PyMuPDF は pypdf が拒否する不正な PDF("Stream has ended unexpectedly")にも対応できるため、後段に pypdf のフォールバックを追加すると、復旧可能な PDF がエラーになってしまいます。ルーターを信頼し、結果の信頼度スコアを確認してください。

あらゆる出力を検証

pdfmux verify は、元の PDF と照合してあらゆる抽出エンジンの出力を監査し、見落とされたページを知らせます。pdfmux 自身の抽出結果だけが対象ではありません。Reducto、Mistral OCR、LlamaParse、Docling、自社製パーサーなどの出力を指定すると、pdfmux 独自の監査処理で元のテキストを再導出して抽出結果と照合し、すべてのページを評価します。

検出する問題: 元の PDF には実際のテキストがあるのに、エンジンが何も返さず、それでも処理成功と報告するページです。この「サイレントドロップ」は、ログにエラーを一切残さず RAG インデックスを汚染する、まさにその問題です。

# 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 --strict

実行するたびに PASS / REVIEW / FAIL の判定、全体の信頼度と網羅率が表示されます。また、見つかった場合は、黙って削除されたページの番号も表示されます。

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, 31

ページごとに、判定(pass / review / fail)、信頼度、網羅率、照合結果、ハルシネーションリスク、表や見出しの整合性を確認できます。一括モードでは結果をまとめ、**「M 件のドキュメントで N ページが見落とされました」**という 1 行で表示します。これは、自社の PDF 100 件を対象に実行し、既存のパイプラインに潜む見えない失敗を見つけるためのレポートです。

あらゆるエンジンの出力に対応

--extracted は JSON、Markdown、プレーンテキストを受け付けます(--extracted-format auto | json | markdown | text)。抽出結果に実際のページ単位の構造がある場合、pdfmux はページごとに比較します。単一の塊の場合は、コンテンツの有無を確認する方式に切り替えるため、ページ分割の不一致から「欠落」を捏造することはありません。

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")

各マニフェストには、正規化された本文に対する改ざん検知可能な SHA-256 コンテンツ署名と、誠実な制限事項リストが埋め込まれています。認証機能は言語的ではなく字句的なもので、欠落や文字化けは検出しますが、忠実な言い換えや翻訳は検出しません。

MCP

verify_extraction は MCP ツールとして公開されています(7 番目のツールです。MCP サーバーを参照)。これにより、エージェントは抽出と同じセッション内でエンジンの出力を検証できます。

無料、MIT、特許上の懸念なし

Certify Anything は、pdfmux に同梱された MIT ライセンスの監査レイヤーのみを再利用しています。特許出願中の判定トレース方式は含まず、必要ともしません。この方式はpdfmux Cloud/Proで引き続き提供されます。pip install pdfmux を実行すると、verify コマンドを無料でフルに利用できます。

詳細なリファレンス:docs/CERTIFY-ANYTHING.md。

誰かに証明する必要がある場合

ローカルインストールで抽出結果を監査することはできますが、証明することはできません。署名したものは誰でも偽造できるためです。pdfmux Cloud は、抽出結果に対するEd25519 署名付きマニフェストを返します。監査担当者は、アカウントを作成する必要も pdfmux を信頼する必要もなく、公開鍵を使ってオフラインで検証できます。

pdfmux verify-manifest manifest.json      # free, MIT, offline — no account

検証は今後も永続的に無料かつオープンです。有料なのは生成のみです(月額 $49)。この非対称性は意図的なものです。私たちの作業を確認するのに、私たちの許可が必要になることは決してありません。

無料ツール、登録不要:app.pdfmux.com/audit — PDF をアップロードすると、現在の抽出ツールがどのページを見落としているか確認できます。測定済みの精度とその盲点は、pdfmux-benchで公開されています。

アーキテクチャ

                           ┌─────────────────────────────┐
                           │     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)│
                    └────────────────────────────────────────┘
主な設計上の決定
  • 抽出器ではなくルーター。 pdfmux は PyMuPDF や Docling と競合しません。ページごとに最適なものを選択します。
  • エージェントによるマルチパス処理。 抽出、信頼度の監査、失敗したページをより強力なバックエンドで再抽出します。品質の低いページは自動的に再試行されます。
  • セグメントレベルの検出。 ルーティングの前に、各ページをコンテンツの種類(テキスト、表、画像、数式、ヘッダー)で分類します。
  • 4 シグナルによる信頼度評価。 文字密度、OCR ノイズ比、表の整合性、見出し構造から動的に品質をスコアリングします。しきい値はハードコードされていません。
  • ドキュメントキャッシュ。 PDF は抽出器ごとに開くのではなく、一度だけ開きます。パイプライン全体で共有されます。
  • データフライホイール。 ローカルのテレメトリーが、ドキュメントの種類ごとにどの抽出器が優れているかを記録します。使用するほどルーティングが改善されます。

機能

機能説明コマンド
ゼロ設定での抽出最適なバックエンドに自動で振り分けますpdfmux convert file.pdf
RAG チャンク分割セクションを考慮したチャンクとトークン数の推定pdfmux convert file.pdf --chunk --max-tokens 500
コストモードeconomy/balanced/premium と予算上限pdfmux convert file.pdf --mode economy --budget 0.50
スキーマ抽出5 つの組み込みプリセット(請求書、レシート、契約書、履歴書、論文)pdfmux convert file.pdf --schema invoice
プロファイル設定を保存して再利用できます。請求書/レシート/論文/契約書/一括 RAG 用の組み込みプロファイルもありますpdfmux convert file.pdf --profile invoices
BYOK LLMGemini、Gemma 3、Claude、GPT-4o、Ollama、Mistral、OpenAI 互換 APIpdfmux convert file.pdf --llm-provider claude
コスト見積もり実行前にコストを予測しますpdfmux estimate file.pdf --llm-provider gemini
ストリーミング出力長い文書向けに、ページごとに NDJSON イベントを出力しますpdfmux stream file.pdf
スマートキャッシュハッシュキー方式の結果キャッシュ、TTL は 30 日、LRU は 1 GBpdfmux convert file.pdf(自動)、バイパスするには --no-cache
監視モードフォルダーに追加された PDF を自動変換しますpdfmux watch ./inbox/
差分2 つの抽出結果を比較しますpdfmux diff a.pdf b.pdf
ベンチマークインストール済みのすべての抽出器を正解データと照合して評価しますpdfmux benchmark
診断インストール済みのバックエンド、未対応の範囲、推奨事項を表示しますpdfmux doctor
MCP サーバーAI エージェントが stdio または HTTP 経由で PDF を読み取りますpdfmux serve
バッチ処理ディレクトリ全体を変換しますpdfmux convert ./docs/
ページ単位のストリーミング API大容量ファイルを、メモリ使用量を抑えてページ単位で反復処理しますfor page in ext.extract("500pg.pdf")
バックオフ付き再試行すべての LLM プロバイダーが指数バックオフと Retry-After を使って自動再試行します(組み込み)

CLI リファレンス

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 file
pdfmux serve

AI エージェント連携用の MCP サーバーを起動します。

pdfmux serve              # stdio mode (Claude Desktop, Cursor)
pdfmux serve --http 8080  # HTTP mode
pdfmux 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

処理を開始する前に、コストと実行されるバックエンドを予測します。

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

ページの処理完了に応じて NDJSON イベントを出力します。非常に長い PDF やライブ UI に便利です。

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

ディレクトリに追加された PDF を自動変換します。Ctrl+C が押されるまで動作します。

pdfmux watch ./inbox/ -o ./output/ --profile bulk-rag
pdfmux diff

抽出結果を並べて比較します(品質、内容、コスト)。

pdfmux diff a.pdf b.pdf --quality standard
pdfmux profiles

保存済みの設定は ~/.config/pdfmux/profiles.yaml にあります。一般的な用途向けの組み込みプロファイルが付属しています。プロジェクトのデフォルト設定として独自のプロファイルを保存できます。

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 invoices

Python API

テキスト抽出
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-assisted
構造化抽出
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 チャンク分割
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']})")
スキーマに基づく抽出
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 file
ストリーミング(メモリ使用量を抑制)
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 PDFs
型とエラー
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
)

フレームワーク連携

LangChain
pip install langchain-pdfmux
from langchain_pdfmux import PDFMuxLoader

loader = PDFMuxLoader("report.pdf", quality="standard")
docs = loader.load()  # -> list[Document] with confidence metadata
LlamaIndex
pip install llama-index-readers-pdfmux
from llama_index.readers.pdfmux import PDFMuxReader

reader = PDFMuxReader(quality="standard")
docs = reader.load_data("report.pdf")  # -> list[Document]
MCP サーバー(AI エージェント)

mcpservers.org に掲載されています。1 行でセットアップできます。

{
  "mcpServers": {
    "pdfmux": {
      "command": "npx",
      "args": ["-y", "pdfmux-mcp"]
    }
  }
}

または Claude Code 経由で設定します。

claude mcp add pdfmux -- npx -y pdfmux-mcp

公開されるツール:convert_pdf、analyze_pdf、extract_structured、 extract_streaming、get_pdf_metadata、batch_convert。

BYOK LLM の設定

pdfmux は 5 行の YAML であらゆる LLM に対応します。独自のキーを使用できます。設定しない限り、データがマシンの外に送信されることはありません。

# ~/.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 cap

対応プロバイダー:

プロバイダーモデルローカル?コスト
Gemini2.5 Flash、2.5 Proいいえ約 $0.01/ページ
Gemma 327B IT、12B IT(アラビア語に最適)いいえ(Gemini キー経由)約 $0.0002/ページ
ClaudeSonnet、Opusいいえ約 $0.015/ページ
GPT-4oGPT-4o、GPT-4o-miniいいえ約 $0.01/ページ
Mistralmistral-ocr-latestいいえ$0.002/ページ
Ollamaあらゆるローカルモデルはい無料
カスタムあらゆる OpenAI 互換 API設定可能変動

各プロバイダーの extract_page() は @with_retry(max_attempts=3, backoff_base=2.0) でラップされており、429 応答の Retry-After ヘッダーに従います。また、認証エラーではリトライをスキップするため、無効なキーはすぐに失敗します。

アラビア語と RTL のサポート

pdfmux はアラビア語、ペルシャ語、ウルドゥー語、ヘブライ語を標準でサポートしています。 標準設定では、すべての PDF で RTL 検出が実行され、PyMuPDF で抽出したページには Unicode 双方向アルゴリズムが適用されます。これにより、左から右の順序で保存されていたグリフも正しい読み順で表示されます。

# 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=...

自動で行われる処理:

  • pdfmux convert はアラビア語のコンテンツを検出し、アラビア文字が 5% を超えるページをアラビア語対応の抽出チェーンに振り分けます。
  • PyMuPDF、RapidOCR、Docling の出力には後処理として Bidi アルゴリズムが適用されます。Markdown の見出し(#)とパイプ形式の表の行は構造を維持し、並べ替えられるのは内部のテキストのみです。
  • いずれかのページにアラビア文字が含まれる場合、DocumentResult.has_arabic は True に設定されます。

明示的な有効化が必要な処理:

  • ビジョン LLM による抽出。--llm-provider gemma(または任意のビジョンプロバイダー)を設定すると、アラビア語のページを PyMuPDF ではなく Gemma に振り分けます。
  • 積極的な正規化(Tatweel の削除、Alef/Yeh の統一、Tashkeel の除去)。検索や埋め込み用に正規化された出力が必要な場合は、抽出した文字列に pdfmux.arabic.normalize_arabic(text) を呼び出してください。
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("أَحْمَدْ")  # → "احمد"

実証:実際の顧客バッチ

技術データシートや安全データシートなど、デジタル形式とスキャン形式が混在し、エンコーディングが破損したものも含む実際の顧客文書 433 件で pdfmux を測定しました。まずは素朴な方法で実行しました(初期の pdfmux CLI をサブプロセスで実行し、pypdf にフォールバック、OCR なし)。するとパイプラインは**16 件の文書を警告なしに取りこぼし、そのうち 11 件はログ行すら出力されませんでした。**これは、まさに約束している機能で自社のツールが失敗したということです。

ページ単位の監査と予算に基づく OCR カスケードを使って再構築したところ、**433 件中 433 件を処理し、警告なしの失敗はゼロでした。**復旧できないページにはすべてフラグが付けられ、破棄されることはありません。

(小規模な内部信頼度キャリブレーション用セットも eval/ に含まれています。これは信頼度ゲートのリグレッションを防ぐためのもので、競合ベンチマークではありません。詳細は eval/README.md をご覧ください。)

ベンチマーク

opendataloader-bench — 実世界の PDF 200 件(財務報告書、学術論文、法的契約書、政府報告書)で、pdfmux は総合 0.903 を記録し、測定対象 8 エンジン中 2 位でした。1 位は opendataloader-hybrid(0.909)です。2026-07-16 に再実行しました(再現手順は以下を参照)。

順位エンジン総合読み順表(TEDS)ライセンスGPU
1opendataloader-hybrid0.9090.9350.928Apache-2.0いいえ
2pdfmux0.9030.9200.911MITいいえ
3Docling0.8770.9000.887MIT任意
4marker0.8610.8900.808無料GPU
5mineru0.8310.8570.873無料GPU

文書ごとの全スコア:200 PDF の直接比較 · 方法論:最適な PDF 抽出ライブラリをベンチマーク。

スマートな結果キャッシュ

同じ抽出を再実行する場合、瞬時に完了します。pdfmux は入力された各 PDF のハッシュ(SHA-256)を計算し、(file_hash, quality, format, schema) をキーとして結果を管理します。キャッシュファイルは ~/.cache/pdfmux/results/ に保存され、30 日後に期限切れとなり、1 GB に達すると LRU 方式で削除されます。

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-run

キャッシュは --profile、--schema、--format の切り替えも高速化します。各組み合わせが個別にキーとして管理されるため、最初の抽出後は、同じドキュメントを Markdown と JSON の間で無料で切り替えられます。

信頼度スコア

すべての結果に、4 つのシグナルに基づく信頼度スコアが含まれます。

  • 95-100% -- デジタルテキストが明瞭で、完全に抽出可能です
  • 80-95% -- 抽出精度は良好で、一部のページに軽微な OCR ノイズがあります
  • 50-80% -- 抽出は部分的で、一部のページは復元できません
  • <50% -- コンテンツが大幅に欠落しており、警告が含まれます

信頼度が 80% を下回ると、pdfmux は問題の内容と解決方法を正確に示します。

Page 4: 32% confidence. 0 chars extracted from image-heavy page.
  -> Install pdfmux[ocr] for RapidOCR support on 6 image-heavy pages.

コストモード

モード動作一般的なコスト
economyルールベースのバックエンドのみを使用します。LLM 呼び出しはありません。$0/ページ
balancedルールベースの抽出に失敗したページに限り、LLM を使用します。平均 ~$0.002/ページ
premium最高品質を得るため、すべてのページで LLM を使用します。~$0.01/ページ

上限予算を設定できます。--budget 0.50 を指定すると、ドキュメントごとの支出が $0.50 に達した時点で LLM の呼び出しを停止します。

pdfmux を選ぶ理由

pdfmux は単なる PDF 抽出ツールではありません。ページごとに最適な抽出ツールを選び、結果を検証し、失敗した場合に再試行するオーケストレーションレイヤーです。

ツール得意分野制限
PyMuPDFデジタルテキストの高速処理スキャンや画像レイアウトには対応できません
Docling表(精度 97.9%)表のないドキュメントでは低速です
Marker学術論文向けのニューラル抽出高速処理には GPU が必要です。デジタル PDF には過剰です
Mistral OCR表(TEDS 96.6%)、$0.002/ページクラウド専用 API
Unstructuredエンタープライズプラットフォーム設定が複雑で、有料プランがあります
LlamaParseクラウドネイティブAPI キーが必要で、ローカルでは利用できません
Reducto高精度$0.015/ページ、クローズドソース
pdfmux上記すべてをオーケストレーションしますページごとに振り分け、監査し、再抽出します

オープンソースの Reducto 代替製品です。他のサービスで $0.015/ページかかる処理を、pdfmux のルールベースのバックエンドなら無料で、BYOK LLM フォールバックを使っても平均 ~$0.002/ページで実行できます。

開発

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/

コントリビューション

  1. リポジトリをフォークします
  2. ブランチを作成します(git checkout -b feature/your-feature)
  3. 新機能のテストを作成します
  4. pytest と ruff check が成功することを確認します
  5. PR を作成します

ライセンス

このリポジトリの pdfmux ライブラリと MCP サーバーは MIT ライセンスのもとで提供されており、あらゆる用途で無料で使用できます。また、リリースされたすべてのバージョンは MIT ライセンスのままです。

信頼度に基づいて予算を管理する decision-trace メソッド(却下した候補を保持する永続化されたページごとの意思決定トレースと、単調性を保つ修復ガード)は特許出願中(米国仮出願番号 64/106,302)であり、別途の商用ライセンスのもと、pdfmux Cloud/Pro 専用として留保されています。これは MIT ライセンスの許諾対象には含まれません。LICENSING.md と NOTICE をご覧ください。

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。