Skip to content

Benchmarks ​

anymd against MarkItDown, Docling, Kreuzberg, and pdftotext on the same documents and the same machine.

Benchmark run 2026-09-25 on 4 CPUs (x86_64), median of 3 runs (docling: 1).

documentanymdmarkitdownkreuzbergdoclingpdftotext
attention0.13s · 9,889 tok · text 4/4 · tables 14/143.00s · 11,994 tok · text 0/4 · tables 9/140.47s · 9,602 tok · text 4/4 · tables 0/1475.94s · 10,023 tok · text 4/4 · tables 14/140.12s · 10,164 tok · text 4/4 · tables 0/14
bert0.09s · 16,627 tok · text 3/3 · tables 2/22.99s · 28,087 tok · text 0/3 · tables 0/20.43s · 15,695 tok · text 3/3 · tables 0/280.79s · 16,201 tok · text 2/3 · tables 2/20.08s · 16,528 tok · text 3/3 · tables 0/2
h80.08s · 34,741 tok · text 1/1 · tables 3/35.35s · 33,491 tok · text 1/1 · tables 0/30.60s · 32,610 tok · text 1/1 · tables 0/3657.95s · 46,669 tok · text 1/1 · tables 2/30.08s · 33,524 tok · text 1/1 · tables 0/3
cjk0.02s · 2,515 tok · text 1/1 · tables 1/11.45s · 2,574 tok · text 1/1 · tables 0/10.34s · 2,502 tok · text 1/1 · tables 0/125.19s · 2,595 tok · text 1/1 · tables 1/10.02s · 2,524 tok · text 1/1 · tables 0/1
plz0.02s · 1,689 tok · text 1/11.45s · 1,942 tok · text 1/10.15s · 1,738 tok · text 1/120.91s · 1,713 tok · text 1/10.02s · 1,835 tok · text 1/1
w90.03s · 8,785 tok · text 1/12.48s · 9,022 tok · text 1/10.20s · 8,550 tok · text 1/136.55s · 8,533 tok · text 1/10.03s · 8,933 tok · text 1/1
borderless0.00s · 623 tok · text 1/1 · tables 6/60.92s · 771 tok · text 1/1 · tables 6/60.10s · 532 tok · text 1/1 · tables 0/624.22s · 809 tok · text 1/1 · tables 6/60.01s · 582 tok · text 1/1 · tables 0/6
docx0.00s · 994 tok0.95s · 1,045 tok0.09s · 1,034 tok8.32s · 1,032 tokn/a
pptx0.00s · 582 tok0.92s · 630 tok0.09s · 527 tok8.31s · 563 tokn/a
xlsx0.00s · 351 tok0.90s · 464 tok0.09s · 464 tok8.24s · 554 tokn/a
epub0.00s · 83 tok0.90s · 126 tok0.08s · 59 tok8.20s · 87 tokn/a
html0.02s · 21,733 tok1.17s · 54,577 tok0.15s · 51,730 tok9.20s · 37,622 tokn/a
tooltotal time (s)total tokenssentences intacttable rows recoveredreading order ok
anymd0.4098,61212/1226/265/5
markitdown22.47144,7235/1215/263/5
kreuzberg2.79125,04312/120/265/5
docling963.80126,40111/1225/263/5
pdftotext0.3674,09012/120/265/5

The official @modelcontextprotocol/server-pdf is left out because it has no headless text path: it renders PDFs in an interactive viewer, and its read_pdf_bytes tool returns base64-encoded bytes.

Method ​

  • Fresh process per run. Every tool runs as a new process, so start-up time is included, as an agent would pay it.
  • Median of 3. Each document is converted 3 times per tool; the table shows the median time.
  • Tokens are counted with tiktoken's o200k_base encoding.
  • Sentences intact counts reference sentences that come out verbatim after whitespace and Markdown normalization. Glued words or split columns fail the check.
  • Table rows counts ground-truth rows that come out as one Markdown table row with the cells in order.
  • Reading order: on multi-column documents, key passages must also appear in the right order.

The reference sentences and table rows are in bench/truth.json. Competitor versions are pinned in bench/requirements.txt.

Corpus ​

From bench/corpus.json:

DocumentKind
attention.pdfPDF: paper, 15 pages, tables
bert.pdfPDF: two-column paper, 16 pages
h8.pdfPDF: statistical tables, 22 pages
cjk.pdfPDF: Traditional Chinese + table
plz.pdfPDF: designed guide
w9.pdfPDF: IRS form
SPARSE-2024-INV-1234_borderless_table.pdfPDF: borderless tables
test.docxWord
test.pptxPowerPoint
test.xlsxExcel
test.epubEPUB
test_wikipedia.htmlHTML: Wikipedia article

The PDFs are SHA-256 verified from corpus/markdown-regression.json. The Office and web samples are microsoft/markitdown's MIT-licensed test files at a pinned commit.

Reproduce ​

bash
# 1. Fetch the corpus
bash bench/fetch.sh .cache/bench-corpus

# 2. Build anymd and install the other tools
cargo build --release -p pdf-reader-mcp-server
python3 -m venv .venv && .venv/bin/pip install -r bench/requirements.txt

# 3. Run and print the table
.venv/bin/python bench/run.py --corpus .cache/bench-corpus --anymd target/release/anymd \
  --tools anymd,markitdown,kreuzberg,docling,pdftotext --runs 3 --out bench-results.json
.venv/bin/python bench/report.py bench-results.json

pdftotext comes from poppler (apt install poppler-utils). Add --docs attention,bert to run a subset, or --save-outputs DIR to keep every tool's Markdown for inspection.

The Benchmark workflow runs the same steps on GitHub-hosted runners, on demand and whenever the harness changes, and posts the table to the job summary.

MIT licensed · local, no API key