Documents to Markdown for agents: PDF layout, tables and OCR, Office, HTML, scans. docling in Rust.
Runs on your machine from its package; the steps are below.
At most: only reads or looks up information.
Odel charges nothing per call. The publisher may charge for its own service.
Runs locally over stdio
This server isn't hosted — your MCP client launches it from a package registry. Use one of the commands below, or drop the config into your client (e.g. Claude Desktop).
Run
uvx docling-rs-mcp
MCP client config
{
"mcpServers": {
"docling-rs": {
"command": "uvx",
"args": [
"docling-rs-mcp"
]
}
}
}Run
docker run -i --rm ghcr.io/docling-project/docling-rs:2.24.0
MCP client config
{
"mcpServers": {
"docling-rs": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"ghcr.io/docling-project/docling-rs:2.24.0"
]
}
}
}
docling.rs converts documents — PDF, Office, HTML, scans, audio — into Markdown, docling JSON and the other shapes an LLM or a RAG pipeline can read. It is a Rust port of IBM's docling: the same output, byte-for-byte, from one static binary. No Python, no PyTorch.
Pulling text out of a PDF is easy. Keeping its structure — headings in order, tables as tables, scanned pages read — takes layout analysis, table recognition and OCR. docling has the models for that, and a Python stack to match. docling.rs runs the same models from a single binary: PDF 4.3× faster than Python docling at under half the RAM, Office and HTML 20–60× faster, and tables that survive — cell recall 0.94 where MarkItDown gets 0.31 (numbers, method).
# CLI + models (Linux x64/arm64 prebuilt; builds from source elsewhere)
curl -fsSL https://raw.githubusercontent.com/docling-project/docling.rs/master/scripts/install/install.sh | bash
docling-rs example.pdf # Markdown on stdout
# or from crates.io; --cli puts the models where the installed binary looks
cargo install docling-cli
curl -fsSL https://raw.githubusercontent.com/docling-project/docling.rs/master/scripts/install/download_dependencies.sh | sh -s -- --cli
pip install docling-rs # Python — drop-in for docling's and MarkItDown's APIs
npm install docling.rs # Node.js / Bun
cargo add docling # Rust library
# containers, models baked in (-cuda variants for NVIDIA)
docker run --rm -v "$PWD:/data" ghcr.io/docling-project/docling-rs paper.pdf
docker run -p 127.0.0.1:5001:5001 ghcr.io/docling-project/docling-rs-serve
Office, HTML, Markdown and e-mail need no models. PDF, images and audio need
the ONNX models (layout, OCR, TableFormer, Whisper; under 1 GB): install.sh,
--cli and the containers bring them along; with pip, run
python -c "import docling_rs; docling_rs.download_models()" once; with npm
or a checkout, run download_dependencies.sh where you convert
(details). Windows: docs/WINDOWS.md.
▶ Try it in your browser first — the converter as wasm, OCR included; nothing leaves your device.
docling-rs report.pdf > report.md # Markdown (streamed page by page)
docling-rs report.pdf --to json # docling JSON; also html, text, latex, dclx, chunks, images
docling-rs --input ./docs --output ./out # a directory tree; --jobs N in parallel
docling-rs https://example.com/paper.pdf # URLs, data: URIs and stdin (`-`) too
docling-rs --help # every flag: OCR, page ranges, images, enrichment, redaction …
from docling_rs import DocumentConverter # was: from docling.document_converter import …
doc = DocumentConverter().convert("report.pdf").document
print(doc.export_to_markdown())
import { convertFileAsync } from 'docling.rs'
const { content } = await convertFileAsync('report.pdf', { to: 'markdown' })
use docling::{DocumentConverter, SourceDocument};
let result = DocumentConverter::new().convert(SourceDocument::from_file("report.pdf")?)?;
println!("{}", result.document.export_to_markdown());
curl -F file=@report.pdf 'localhost:5001/v1/convert?to=md' # the server; OpenAPI at /openapi.yaml
Same options, same outputs on every surface — every option in
docs/OPTIONS.md.
pip install docling-rs, swap one import —
from docling_rs.markitdown import MarkItDown — and keep its API with real
layout, tables and OCR behind it (guide).from docling_rs import DocumentConverter;
result.document is a genuine DoclingDocument
(migration notes).http://<host>:5001 — and n8n, Dify and LangChain clients work unchanged
(docling-rs serve,
Open WebUI setup).docling-rs mcp gives Claude Desktop, Claude Code,
Cursor or VS Code MarkItDown's convert_to_markdown tool, plus convert
for JSON, chunks and the rest — uvx docling-rs-mcp, or
claude mcp add docling -- docling-rs mcp (MCP server).pip install "docling-rs[langchain]" — langchain-docling's
DoclingLoader on the Rust engine, one import to swap
(details).pip install "docling-rs[autogen]" — DoclingIndexer fills
any AutoGen memory with chunks that carry their pages, DoclingConvertTool
lets an agent read documents (details).docling-rag — chunk, embed and search with a REST API and a web
UI (RAG subsystem).Developed with Claude Code and TENET (minimalistic AI-driven development framework).
Every format in docling's pipeline converts — plus a few docling lacks — and a file that fails under its extension is checked by content and converted as what it really is, with a warning.
| Category | Formats |
|---|---|
| Text & markup | Markdown, AsciiDoc, HTML, MHTML, LaTeX (multi-file arXiv projects, math, tables); plain text and source code (.py, .yaml, .log, … — any text file, as a code block or paragraphs), generic JSON / JSON Lines and XML (kept as code blocks); Jupyter notebooks (.ipynb: markdown cells, code cells in the kernel's language, outputs on request) |
| Word processing | DOCX, Word 97–2004 .doc (and Word 6/95, 1.x/2.0), ODT, OpenOffice / StarWriter, AbiWord, WordPerfect, MS Works, EPUB, RTF |
| Presentations | PPTX, PowerPoint 97–2003, ODP, OpenOffice / StarImpress |
| Spreadsheets | XLSX, XLSB, Excel 97–2004, ODS, CSV / TSV, dBase, DIF, SYLK, Lotus 1-2-3, Quattro Pro, MS Works |
| Diagrams · Apple iWork | Visio, SVG · Pages, Numbers, Keynote |
| PDF & images | PDF (layout, TableFormer, OCR), PNG, JPEG, TIFF, BMP, WebP, GIF, HEIC (opt-in), METS/GBS scans, DjVu |
| XML · docling native | JATS, USPTO, XBRL, DocLang · docling JSON, DocTags, DCLX |
| Email · subtitles · mainframe | .eml, Outlook .msg · WebVTT · EBCDIC records through a COBOL copybook |
| Audio · video | WAV, MP3, M4A, AAC, OGG, FLAC; MP4, AVI, MOV, MKV, WebM, MPEG — local Whisper or Parakeet, plus scene frames from video |
Every extension, with what each backend does:
docs/MIGRATION.md.
Any ffmpeg ≥ 4.x on PATH works; docling.rs shells out to the binary and
parses its output, so no dev headers/libraries are needed.
sudo apt-get install ffmpegsudo dnf install ffmpeg-free (or ffmpeg from RPM Fusion)apk add ffmpegbrew install ffmpegwinget install ffmpeg (or choco install ffmpeg, or
scoop install ffmpeg). Installing from a downloaded zip
(gyan.dev /
BtbN) also works — either
add the extracted bin\ folder to PATH, or skip PATH entirely and point
DOCLING_FFMPEG at the exe:
set DOCLING_FFMPEG=C:\tools\ffmpeg\bin\ffmpeg.exeCheck with ffmpeg -version. DOCLING_FFMPEG overrides the binary used on
any OS; the docling-rs-serve Docker image ships ffmpeg preinstalled.
MarkItDown converts the same kinds
of documents to Markdown for LLMs. Measured side by side — MarkItDown 0.1.8
(markitdown[all]) and docling.rs 2.16.0 (release build), 4 vCPU, no GPU —
on this repository's test corpus and on MarkItDown's own OCR test set
(scripts/conformance/markitdown_compare.py):
| Corpus (files) | MarkItDown, warm | docling.rs, warm | Cold CLI call, MarkItDown / docling.rs | Word F1 | Table-cell recall | Heading recall |
|---|---|---|---|---|---|---|
| DOCX (38) | 5.04 s | 0.55 s | 1441 / 14 ms | 0.93 / 1.00 | 0.81 / 1.00 | 0.78 / 1.00 |
| PPTX (8) | 0.15 s | 0.02 s | 1080 / 9 ms | 0.81 / 0.97 | 0.62 / 1.00 | 0.86 / 1.00 |
| XLSX (14) | 1.08 s | 0.19 s | 1085 / 11 ms | 0.60 / 0.95 | 0.78 / 0.98 | — ¹ |
| HTML (32) | 0.40 s | 0.06 s | 1226 / 7 ms | 0.98 / 1.00 | 0.89 / 1.00 | 0.96 / 1.00 |
| CSV (9) | 0.04 s | 0.01 s | 1086 / 6 ms | 1.00 / 1.00 | 0.78 / 1.00 | — |
| EPUB (1) | 0.06 s | 0.01 s | 1278 / 14 ms | 0.99 / 1.00 | — | 1.00 / 1.00 |
| PDF (18), full layout + tables + OCR | 10.0 s | 49.3 s | 1237 / 1314 ms | 0.63 / 0.997 | 0.31 / 0.94 | 0.00 / 0.91 |
PDF (18), text layer only (--text-layer-only) | 10.0 s | 0.7 s | — | 0.63 / 0.97 | 0.31 / 0.00 | 0.00 / 0.00 |
Accuracy is scored against Python docling's groundtruth, which favours
docling.rs by construction; the timings do not depend on it. Text drawn into
images (MarkItDown's own OCR test set) reads at 1.00 with docling.rs' local
OCR, against 0.00–0.33 for MarkItDown without an LLM. Method, caveats and the full
OCR comparison: docs/MARKITDOWN.md.
Every declarative format is compared against the live library — Markdown
byte for byte, JSON structurally (every key and value but origin/version
and re-encoded image bytes). Latest sweep, docling 2.129.0
(scripts/conformance/full_conformance.py; ✅ all = every file matches):
| Format | Files | Markdown | JSON | Format | Files | Markdown | JSON |
|---|---|---|---|---|---|---|---|
| DOCX | 38 | ✅ all | ✅ all | iWork Pages | 1 | ✅ all | ✅ all |
| HTML | 32 | ✅ all | 31 | iWork Keynote | 5 | ✅ all | ✅ all |
| PPTX | 8 | ✅ all | ✅ all | EBCDIC | 3 | ✅ all | ✅ all |
| XLSX | 14 | 13 ² | 13 ² | JATS | 7 | ✅ all | ✅ all |
| ODF | 7 | ✅ all | ✅ all | DocLang | 15 | ✅ all | ✅ all |
| CSV | 9 | ✅ all | 6 | AsciiDoc | 5 | ✅ all | ✅ all |
| Markdown | 11 | ✅ all | 6 | USPTO | 9 | ✅ all | ✅ all |
| DeepSeek-OCR Markdown | 3 | ✅ all | n/a | EPUB | 1 | ✅ all | ✅ all |
| WebVTT | 4 | ✅ all | ✅ all | LaTeX | 8 | ✅ all | 7 ¹ |
Email (.eml) | 2 | ✅ all | ✅ all |
¹ 1706.03762: one tabular's cells carry consistent row_span/col_span where upstream writes the span into the offsets only; PDF figures carry no image payload (upstream renders them with pypdfium2).
² xlsx_02_sample_sales_data: 20 date cells print by docling PR #4628's number-format rules (#634), which the released docling does not apply yet.
The residuals, with the exact files: docs/MIGRATION.md.
The PDF/image pipeline is pinned by a deterministic snapshot baseline and
scored against docling's groundtruth in
docs/PDF_CONFORMANCE.md.
One fixture per format through published Python docling and the Rust release
binary (scripts/test/performance.sh); docling ÷ docling.rs, so bigger means
Rust wins by more.
| File | Size | Peak-memory ratio | CPU ratio | Warm-conversion speedup |
|---|---|---|---|---|
picture_classification.pdf (PDF) | 208 KB | 6.5× less | 0.8× | 10.6× |
docx_rich_tables_01.docx (DOCX) | 3.1 MB | 39× less | 1.2× | 19× |
wiki_duck.html (HTML) | 240 KB | 57× less | 1.3× | 47× |
elife-56337.nxml (JATS XML) | 180 KB | 59× less | 1.2× | 10× |
xlsx_04_inflated.xlsx (XLSX) | 168 KB | 51× less | 0.9× | 18× |
powerpoint_with_image.pptx (PPTX) | 80 KB | 55× less | 1.2× | 3.1× |
wiki.md (Markdown) | 8 KB | 57× less | 1.2× | 1.2× |
csv-comma.csv (CSV) | 4 KB | 64× less | 1.2× | 0.6× † |
† A 4 KB CSV converts in microseconds, so Rust's own process startup dominates its number; end to end it is 870× faster.
Declarative formats hold a few MB against docling's ~750 MB (it imports torch
even for them) and finish 300–870× sooner end to end; the PDF peaks at
0.37 GB against 2.4 GB and converts 28.5× faster end to end. Where the time
goes, and what was measured not to help:
docs/PDF_CONFORMANCE.md.
One engine, several front doors, the same options and outputs everywhere.
| You write… | Use | Install |
|---|---|---|
| Rust | the docling crate | cargo add docling |
| a shell / CI job | the docling-rs CLI, batch mode included | release binaries · cargo install docling-cli · ghcr.io/docling-project/docling-rs |
| anything that speaks HTTP | docling-serve, OpenAPI 3.1 | ghcr.io/docling-project/docling-rs-serve · cargo install docling-serve |
| Node.js / Bun / Electron | docling.rs, an N-API addon | npm i docling.rs (docling.rs-cuda) |
| Python | docling-rs: docling's and MarkItDown's APIs | pip install docling-rs (docling-rs-cuda) |
| the browser / Tauri / a PWA | docling.rs-wasm, fully client-side | npm i docling.rs-wasm |
| C, C++, C#, Go, Java, Swift, Zig | docling-ffi: one docling.h | release archives docling-ffi-<tag>-<target> |
Rust when you're already in Cargo; the CLI for scripts and batch jobs; serve when several services share one warm pipeline; Node / Python in-process; wasm when the document must not leave the user's machine; FFI for anything that can call C.
use docling::{DocumentConverter, SourceDocument};
let converter = DocumentConverter::new();
let result = converter.convert(SourceDocument::from_file("input.md")?)?;
println!("{}", result.document.export_to_markdown()); // Markdown
println!("{}", result.document.export_to_json()); // docling DoclingDocument JSON
Every conversion knob is one serializable struct, docling::ConvertOptions,
filled the same way by every surface (docs/OPTIONS.md).
The library guide covers the output formats,
error handling, chunking, image extraction, streaming, OCR, the PDF switches
and the remote VLM pipeline.
docling-rs servedocling-serve exposes the converter over
HTTP with one warm PDF/image pipeline shared across requests (repeat PDFs skip
the model load), streamed Markdown, batches, ZIP inputs, async jobs, an
interactive test form at GET / and an OpenAPI 3.1 description at
GET /openapi.yaml. It also serves Python docling-serve's routes, so Open
WebUI, n8n, Dify and LangChain clients work unchanged.
docker run -p 127.0.0.1:5001:5001 ghcr.io/docling-project/docling-rs-serve
curl -F file=@paper.pdf localhost:5001/v1/convert # Markdown
curl -F file=@report.docx 'localhost:5001/v1/convert?to=json' # docling JSON
curl -F file=@a.pdf -F file=@b.docx localhost:5001/v1/convert # a batch
Request options, server flags, async jobs, the docling-serve routes and the
Open WebUI setup: crates/docling-serve/README.md;
containers and sizing: docs/DEPLOYMENT.md.
docling-rs mcpdocling-rs mcp is a Model Context Protocol
server in the default docling-rs binary and image. Agents get MarkItDown's
convert_to_markdown(uri) tool — same name and contract, so a
markitdown-mcp setup switches by changing the command — plus
convert(uri, to, options) and list_input_formats().
{
"mcpServers": {
"docling": { "command": "docling-rs", "args": ["mcp", "--root", "/Users/me/Documents"] }
}
}
claude mcp add docling -- docling-rs mcp --root ~/Documents # Claude Code
uvx docling-rs-mcp --root ~/Documents # the same server from PyPI
Local reads stay under --root; URLs need --allow-url-fetch. Listed in the
official MCP registry
and on Smithery. The PyPI
launcher, Docker, Streamable HTTP (--http), the security model and memory
behaviour:
crates/docling-cli/README.md.
crates/docling-rag turns documents into
chunks, embeds them (Ollama, Gemini or a local ONNX model), stores them
(SQLite + sqlite-vec or PostgreSQL + pgvector) and searches them — hybrid,
multi-query and HyDE retrieval, an evaluation harness, a REST API and a
built-in search UI.
docling-wasmThe declarative converters and the PDF text layer compile to WebAssembly:
npm i docling.rs-wasm, then convert(bytes, filename, to) runs fully
client-side — no server, a ~3.4 MB gzipped module, optional in-browser OCR.
Details and the demo page: crates/docling-wasm.
docling.rs on npm, a
prebuilt N-API addon: sync and async conversion, streaming, chunking, ZIP
batches, a warm Pipeline.docling-rs on PyPI
(docling-rs-cuda for NVIDIA): docling's DocumentConverter with a genuine
docling-core DoclingDocument, MarkItDown's API, and the LangChain and
AutoGen integrations.docling-ffi: one library and
one docling.h for C, C++, C#/.NET, Go, Java, Swift and Zig, prebuilt in
every published release.| Image | What it is |
|---|---|
ghcr.io/docling-project/docling-rs-serve | the HTTP API, models baked in (linux/amd64, linux/arm64) |
ghcr.io/docling-project/docling-rs | the CLI, entrypoint docling-rs, working directory /data |
…-serve-cuda · …-rs-cuda | the same on CUDA 13 + cuDNN 9 (linux/amd64) |
Compose files (standalone, Caddy TLS, CUDA), environment variables, sizing
and observability: docs/DEPLOYMENT.md.
The PDF/image pipeline needs ONNX models — RT-DETR layout, PP-OCR, and
TableFormer — and audio needs Whisper. download_dependencies.sh fetches
them from this repository's
releases into
./.models, where every surface looks (--cli: beside a cargo-installed
binary instead):
scripts/install/download_dependencies.sh # from a checkout
curl -fsSL https://raw.githubusercontent.com/docling-project/docling.rs/master/scripts/install/download_dependencies.sh | sh # anywhere
Every asset and option (ASR presets, enrichment models, NER for PII
redaction, INT8, fonts), GPU execution providers and the environment
overrides: docs/MODELS.md. IBM Z and other targets
without a prebuilt ONNX Runtime: docs/IBMZ.md.
Bug reports and pull requests are welcome — see CONTRIBUTING.md for the build and test commands, the conformance workflow, and the conventions a change is expected to follow.
MIT, matching upstream docling.