The Docling MCP server is the docling-mcp package, which gives an MCP client tools to convert documents with Docling and read the result as Markdown. It worked in our tests over stdio and HTTP, from Claude Code, Codex and a script using the official MCP Python SDK. Two defaults will trip up a first setup. The conversion mode defaults to remote, so a plain install has nothing to convert with until you point it at Docling Serve or install the local extra. The transport defaults to streamable-http, so a client config without --transport stdio never connects.
We installed docling-mcp 3.5.0, released on November 4, 2026, and ran its tools on five PDFs. We also ran 3.2.0, the version locked by docling-serve 1.32.0. Everything below was run on our machine unless it is labeled untested. Disclosure: Parsebridge, which publishes this blog, sells a hosted Docling API.
Docling MCP at a glance
| Result | |
|---|---|
| Package | docling-mcp 3.5.0, MIT license, Python 3.10 or newer |
| Command | docling-mcp-server |
| Transports | stdio, sse, streamable-http (the default). All three ran. |
| Default address | localhost:8000, endpoint /mcp |
| Conversion modes | remote (the default, needs Docling Serve) or local (needs the local extra) |
| Default tools | 21, plus 7 prompts |
| Install size | 151 MB for remote only, 1.1 GB with local, plus 506 MB of Hugging Face models on first use |
| Local server memory | 2,969 to 4,023 MB peak across three runs that included a 60-page PDF |
| 60-page report, local | 249 to 337 seconds to convert on an Apple M4 CPU, with 715,071 characters of Markdown |
| Clients we ran | Claude Code 2.1.318, Codex CLI 0.166.0, MCP Python SDK 2.3.0 |
| Clients not tested | Claude Desktop, Cursor, LM Studio |
Hosted Docling API
Parsebridge, which runs this blog, does not have an MCP server. It is a hosted Docling API. You send a PDF as a file upload or a URL and get Markdown back in a JSON response, with no models or Docling process on your machine. Agents that can call an HTTP endpoint can use it directly, and you would write that tool yourself. It also cannot serve as DOCLING_MCP_SERVICE_URL, because it has its own request shape and does not expose the Docling Serve routes. Signing up gives you 50 free pages, and plans start at $17 a month for 5,000 pages. Where each option fits has the detail.
How we tested
The machine was a Mac mini with an Apple M4 and 16 GB RAM, on macOS 26.6 and Python 3.12.15, using the CPU and no GPU.
| Setup | docling-mcp | MCP SDK | Docling | docling-core |
|---|---|---|---|---|
| Local mode | 3.5.0 | 2.3.0 | 2.147.0 | 2.106.0 |
| Remote client | 3.5.0 | 2.3.0 | conversion runs on the server | 2.106.0 |
docling-serve 1.32.0, from its uv.lock | 3.2.0 | 2.1.1 | 2.124.0 | 2.93.0 |
The two docling-serve 1.32.0 containers we run in production also report docling-mcp 3.2.0 and MCP SDK 2.1.1, and set no DOCLING_MCP_ variables. We did not run the server inside a container, because the test machine has no Docker. We ran the same docling-mcp-server command from the environment installed from that lockfile.
We used the same PDFs as our Docling chunking guide:
- Table: Table 1 from page 31 of the EIA Short-Term Energy Outlook, October 2026, with 15 numeric columns.
- Form: page 1 of the 2026 IRS Form W-4.
- Scan: our scanned order fixture, one image-only page with a small table.
- Paper: PubTables-1M, 10 pages, two columns (CC BY 4.0).
- Report: the full 60-page EIA report.
Install docling-mcp
For local conversion, install the local extra. We used uv:
uv venv --python 3.12 venv-local
uv pip install --python venv-local/bin/python 'docling-mcp[local]==3.5.0'
That environment was 1.1 GB after install and 1.3 GB after use, with the OCR models stored inside it. For remote mode only, leave out the extra, and the environment was 151 MB:
uv venv --python 3.12 venv-remote
uv pip install --python venv-remote/bin/python 'docling-mcp==3.5.0'
You can also let the client start it through uvx, which is how the project’s README does it:
DOCLING_MCP_CONVERSION_MODE=local uvx --from 'docling-mcp[local]==3.5.0' docling-mcp-server --transport stdio
With an empty uv cache and a busy machine (load average around 20), uvx took 55 seconds to answer the MCP initialize request and left 2.4 GB in the cache. The next start took 2.9 seconds. A client with a short startup timeout could give up on that first start, so it helps to run the command once in a terminal first.
Local mode downloads its models on the first conversion. With an empty Hugging Face cache, also on a busy machine, the first conversion of the one-page table took 64 seconds and put 506 MB in the cache. The server log showed Auto OCR model selected rapidocr with torch.
Connect a client
Claude Code (tested)
We saved this file as docling-mcp.json, using the absolute path to the installed server:
{
"mcpServers": {
"docling": {
"command": "/absolute/path/to/venv-local/bin/docling-mcp-server",
"args": ["--transport", "stdio"],
"env": {
"DOCLING_MCP_CONVERSION_MODE": "local",
"CACHE_DIR": "/absolute/path/to/docling-cache"
}
}
}
}
We then ran it non-interactively:
claude -p --mcp-config docling-mcp.json --strict-mcp-config \
--allowedTools "mcp__docling__*" \
"Use the docling MCP tools to convert /absolute/path/to/table.pdf and export it to Markdown. Then tell me the first line of the document and the name of the first row label under the table header. Answer in two short lines."
Claude Code reported the server as connected with 21 tools, called the conversion tool and then the export tool, and answered:
First line: `## Table 1. U.S. Energy Markets Summary`
First row label under the header: `Energy Production`
The same client also connected to a running HTTP server with this entry:
{ "mcpServers": { "docling": { "type": "http", "url": "http://localhost:8765/mcp" } } }
Codex CLI (tested, with one failed attempt)
We passed the server config as -c overrides and did not edit config.toml:
codex exec --skip-git-repo-check -s read-only \
-c 'mcp_servers.docling.command="/absolute/path/to/venv-local/bin/docling-mcp-server"' \
-c 'mcp_servers.docling.args=["--transport","stdio"]' \
-c 'mcp_servers.docling.env={DOCLING_MCP_CONVERSION_MODE="local",CACHE_DIR="/absolute/path/to/docling-cache"}' \
-c 'mcp_servers.docling.default_tools_approval_mode="approve"' \
"Use the docling MCP tools to convert /absolute/path/to/form.pdf and export it to Markdown. Tell me the first heading in the document. One line." < /dev/null
Three details came out of the runs:
- Our Codex config sets
approval_policy = "never". Without thedefault_tools_approval_modeline, the call failed withMCP tool call requires approval, but approval policy is never. - With that line set, two of three small-PDF runs worked, and they answered
The first heading is "Form W-4".The third reported that the Docling tools were not available in the session. We did not find the cause. The Codex docs list a defaultstartup_timeout_secof 10, and our warm server starts took 2.9 to 4.5 seconds. - The same docs list a default
tool_timeout_secof 60. With that setting unset, a report conversion ran to completion anyway, in a 294-second Codex run. A second run withtool_timeout_sec=900also completed. We would set the value explicitly and would not rely on either behavior.
Without the < /dev/null, codex exec printed Reading additional input from stdin... and did not proceed.
MCP Python SDK (tested)
This script uses the official mcp package, version 2.3.0, with docling-mcp-server on the PATH:
import asyncio
import sys
from mcp.client.session import ClientSession
from mcp.client.stdio import StdioServerParameters, stdio_client
server = StdioServerParameters(
command="docling-mcp-server",
args=["--transport", "stdio"],
env={"DOCLING_MCP_CONVERSION_MODE": "local"},
)
async def main(pdf: str) -> None:
async with stdio_client(server) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
tools = await session.list_tools()
print(len(tools.tools), "tools")
converted = await session.call_tool(
"convert_document_into_docling_document", {"source": pdf}
)
print(converted.structured_content)
exported = await session.call_tool(
"export_docling_document_to_markdown",
{"document_key": converted.structured_content["document_key"]},
)
print(exported.structured_content["markdown"][:300])
asyncio.run(main(sys.argv[1]))
On the scanned order, it printed:
21 tools
{'from_cache': False, 'document_key': 'ef846439fd43fc30c126c3497975b035'}
## SAMPLE ORDER
Synthetic OCR test fixture - no real customer data
Order number: PB-1042
Order date: 2026-09-11
## Ship to
Example Research Lab 42 Sample Street Zurich, Switzerland
| Item | Quantity | Amount |
|-----------------|------------|-----------|
| Archive folders |
Claude Desktop and Cursor (untested)
We did not run either of these. The MCP docs place the Claude Desktop file at ~/Library/Application Support/Claude/claude_desktop_config.json on macOS, and the Cursor docs use .cursor/mcp.json in a project or ~/.cursor/mcp.json globally. Both document the mcpServers shape with command, args and env, so this entry follows their formats:
{
"mcpServers": {
"docling": {
"command": "/absolute/path/to/venv-local/bin/docling-mcp-server",
"args": ["--transport", "stdio"],
"env": { "DOCLING_MCP_CONVERSION_MODE": "local" }
}
}
}
The config in the docling-mcp README passes only --from=docling-mcp docling-mcp-server to uvx, with no --transport stdio and no conversion mode. In our tests, running that server command with no transport flag started an HTTP server on localhost:8000, and our stdio client was still waiting on initialize when we stopped at 30 seconds. Claude Code listed the server as pending with 0 tools. We ran that test with the installed binary, without uvx.
The tools docling-mcp exposes
docling-mcp 3.5.0 loads 21 tools from three groups by default:
| Group | Tools |
|---|---|
conversion (5) | convert_document_into_docling_document, convert_directory_files_into_docling_document, check_document_in_local_cache, list_cached_documents, remove_document_from_local_cache |
generation (11) | export_docling_document_to_markdown, save_docling_document, get_page_thumbnail, create_new_docling_document, add_title_to_docling_document, add_section_heading_to_docling_document, add_paragraph_to_docling_document, open_list_in_docling_document, close_list_in_docling_document, add_list_items_to_list_in_docling_document, add_table_in_html_format_to_docling_document |
manipulation (5) | get_overview_of_document_anchors, search_for_text_in_document_anchors, get_text_of_document_item_at_anchor, update_text_of_document_item_at_anchor, delete_document_items_at_anchors |
It also registers 7 prompts, such as convert_and_summarize and find_and_replace_in_document.
You can load fewer tools by listing groups after the options. The Markdown export lives in generation, so conversion alone gave 5 tools and no way to read a document as Markdown:
docling-mcp-server --transport stdio conversion generation # 16 tools
The CLI also accepts llama-index-rag, llama-stack-rag and llama-stack-ie groups. We did not test them.
Version 3.2.0, the one in docling-serve 1.32.0, has 19 tools and uses older names for two of them: is_document_in_local_cache and page_thumbnail. It has neither list_cached_documents nor remove_document_from_local_cache. A prompt or script written against one version can break on the other.
How the tools behave on real PDFs
Conversion returns a key and no text:
{ "from_cache": false, "document_key": "7251e74440cf663770423f4f01301301" }
You pass the key to the other tools. The export of the EIA table kept its structure, with quarters in the header:
## Table 1. U.S. Energy Markets Summary
U.S. Energy Information Administration | Short-Term Energy Outlook - October 2026
| | 2025 - Q1 | 2025 - Q2 | 2025 - Q3 | ...
|-|-----------|-----------|-----------| ...
| Energy Production | | | | ...
| Crude Oil Production (a) (million barrels per day) ........ | 13.32 | 13.58 | 13.82 | ...
| Dry Natural Gas Production (billion cubic feet per day) ... | 105.5 | 106.9 | 108.3 | ...
We collapsed the column padding and dot leaders above to fit the page and cut the rows at .... On the W-4, the anchor overview gave an agent a map of the document before it read any text:
[anchor:#/texts/0] section_header-1: Form W-4
[anchor:#/texts/1] text
[anchor:#/texts/2] section_header-1: Employee's Withholding Certificate
[anchor:#/texts/3] text
We trimmed that output and its indentation. Other behavior we confirmed:
- Cache keys: the key stayed the same across server restarts, and an absolute and a relative path to the same file gave the same key, so repeat conversions in one process came back in 0.08 to 0.53 seconds with
from_cache: true. - Cache lifetime: the cache lives in the server’s memory. After a restart,
list_cached_documentswas empty and exporting the old key failed, so you have to convert again. The README sets the default capacity to 10 documents throughDOCLING_MCP_CACHE_MAX_DOCUMENTS. We did not test eviction. - Shared cache over HTTP: a second HTTP session saw the document the first session converted. Over stdio, each client process starts its own server, with its own cache.
- Directories:
convert_directory_files_into_docling_documentconverted the files directly in the folder and skipped a PDF in a subfolder. - URLs and other formats: a public PDF URL converted in 7.7 seconds. A short Markdown file, HTML file and text file also returned keys, and we did not inspect their output.
- Saving files:
save_docling_documentwrites one.mdand one.jsonfile. WithoutCACHE_DIR, ours landed insite-packages/_cacheinside the virtual environment, so setCACHE_DIRif you want to keep them. - Thumbnails:
get_page_thumbnailneedsDOCLING_MCP_KEEP_IMAGES=true. With it set, a 256-pixel request returned a PNG image. Without it, the call failed. - Truncation:
max_size=200cut the W-4 Markdown mid-word, atfrom your p.
Large documents
The full export of the 60-page report was 715,071 characters. Claude Code did not pass it to the model and returned this instead:
Error: result (717,517 characters) exceeds maximum allowed tokens. Output has been saved to [a file under ~/.claude/projects/]
Claude Code then read page 5 inline through page_no. Exporting each page with page_no gave a median of about 3,300 characters per page, a minimum of 14 and a maximum of 85,649 on page 55. Most of the size in this report is table padding and dot leaders. Removing runs of dots and repeated spaces took the full export from 715,071 to 244,308 characters. For long documents, have the agent read the 23,348-character anchor overview, or search with search_for_text_in_document_anchors, and then export only the pages it needs.
Timings
These are wall times for convert_document_into_docling_document as measured by the MCP client, with a single server process per run and the PDFs converted in the order shown. The first row of each run includes loading the models. Local mode ran three times over stdio, and the “Local” column is the run with the lowest machine load (load average 2 to 5). Other work on the machine overlapped the other runs, which is why the range is wide.
| Pages | Local, seconds | Local, range over 3 runs | Remote via docling-serve 1.32.0, seconds | Markdown, characters | |
|---|---|---|---|---|---|
| Table | 1 | 9.3 | 9.3 to 32.2 | 13.6 | 10,555 |
| Form | 1 | 5.5 | 5.5 to 26.9 | 5.5 | 4,720 |
| Scan | 1 | 6.1 | 5.4 to 22.7 | 2.8 | 494 |
| Paper | 10 | 12.8 | 11.6 to 41.3 | 13.9 | 50,469 |
| Report | 60 | 248.8 | 248.8 to 336.8 | 437.5 | 715,071 |
The remote column is one run on a load average of 5 to 8, with a different Docling version on the server (2.124), so do not read the two columns as a speed comparison. Markdown export took between 0.002 and 0.6 seconds in every run. Server start to initialize took 2.9 to 4.5 seconds in local mode with models cached. The server’s peak memory was 4,023, 3,294 and 2,969 MB across the three local runs.
Run it over HTTP
Streamable HTTP is the default transport, so this is all it takes:
DOCLING_MCP_CONVERSION_MODE=local docling-mcp-server --transport streamable-http --port 8765
From the Python SDK, connecting with streamable_http_client("http://localhost:8765/mcp") listed 21 tools and converted the table PDF in 10.1 seconds. The sse transport at http://localhost:8765/sse also listed 21 tools and converted the same PDF.
A long conversion did not block other sessions. While one session converted the 60-page report, a second session initialized in 0.01 seconds, listed the cache in 0.06 seconds and converted the W-4 in 11.1 seconds. The report took 700 seconds in that run, with a load average of 20 to 30 from other work on the machine, so we can’t say how much of that came from the overlap.
The server has no authentication option on its command line, and we connected without credentials in every HTTP test. On the default localhost binding, a request with Host: evil.example.com got 421 Invalid Host header. With --host 0.0.0.0, the port listened on all interfaces, and an initialize request to the machine’s LAN address returned 200 with no credentials. The conversion tools accept local file paths, so anyone who can reach an exposed port can read documents the server’s user can open. Put your own authentication in front if it has to leave the machine.
Remote mode with Docling Serve
In remote mode, the MCP server stays small and sends conversions to Docling Serve. We started docling-serve 1.32.0 on port 5001 and used the 151 MB install:
export DOCLING_MCP_SERVICE_URL=http://127.0.0.1:5001
docling-mcp-server --transport stdio
Local file paths work, because the MCP server uploads the file. The server’s log showed each upload as POST /v1/convert/file/async returning 422 and then 200, and the conversions completed, so that first 422 is safe to ignore. With DOCLING_SERVE_API_KEY set on the server, conversion failed without DOCLING_MCP_SERVICE_API_KEY (a 401 in the logs) and worked with it.
The important setting here is DOCLING_MCP_SERVICE_TIMEOUT, which defaults to 300 seconds. Our first remote run on the 60-page report failed at 301.4 seconds. The client saw only the generic error, and the server log said:
TaskTimeoutError: Timed out waiting for task e47120a2-0b2f-4588-80b5-e9b3998b119f after 300.00s.
With DOCLING_MCP_SERVICE_TIMEOUT=1200, the same PDF finished in 437.5 seconds. Our Docling Serve guide covers setting up the server.
The MCP server inside docling-serve
The docling-serve 1.32.0 docs start the MCP server from the serve image with this command, which we did not run because we had no Docker:
podman run -p 8000:8000 quay.io/docling-project/docling-serve -- docling-mcp-server --transport streamable-http --port 8000 --host 0.0.0.0
That page sets neither a conversion mode nor a service URL. We ran the same docling-mcp-server arguments from an environment installed from the docling-serve 1.32.0 lockfile. The client connected and listed 19 tools, and conversion failed because version 3.2.0 also defaults to remote. Setting DOCLING_MCP_CONVERSION_MODE=local fixed it in that environment, and the table PDF converted in 15.5 seconds. Pointing it at a running Docling Serve with DOCLING_MCP_SERVICE_URL worked too, in 13.7 seconds.
The version difference also changed the Markdown. In remote mode the MCP server renders Markdown itself from the JSON that Docling Serve returns, so the output depends on the docling-core in the MCP environment. From the same server, 3.5.0 (docling-core 2.106) wrote one header row with 2025 - Q1, while 3.2.0 (docling-core 2.93) wrote 2025 in the header and put Q1 in the first body row.
What failed
Most failures reached the client as one generic line, Error executing tool convert_document_into_docling_document. The reason is only in the server’s stderr, so check there first. In Claude Desktop, the MCP docs say server logs are under ~/Library/Logs/Claude on macOS.
| What we did | What the client saw | What the server log said |
|---|---|---|
| Default install, no service URL | Generic error | DOCLING_MCP_SERVICE_URL is not set but DOCLING_MCP_CONVERSION_MODE=remote, followed by the two ways to fix it |
DOCLING_MCP_CONVERSION_MODE=local without the local extra | Generic error | ModuleNotFoundError: No module named 'packaging', which does not mention the missing extra |
| Service URL with nothing listening | Generic error | ServiceUnavailableError: Service transport request failed. |
| Remote conversion over 300 seconds | Generic error | TaskTimeoutError, as shown above |
| Missing file | Generic error | ConversionError: Conversion failed for: does-not-exist.pdf |
| Export with an unknown key | Generic error | ValueError: document-key: nope is not found. |
Thumbnail without DOCLING_MCP_KEEP_IMAGES | Generic error | ValueError: The DoclingDocument does not have page images. |
Export with page_no=99 on a one-page PDF | page_no=99: not found in the document. Available pages are: 1 | This one reached the client |
Client config with no --transport stdio | initialize never returned | Uvicorn running on http://localhost:8000 |
Where a hosted API fits
Run docling-mcp when you want an agent to work inside a document with anchors, search, edits and page thumbnails. These need a DoclingDocument, and a Markdown-only API can’t provide them. Local mode also converts on your machine, although a cloud-based client still sends whatever the agent reads to its model provider. The costs we measured were 1.1 GB of packages, 506 MB of models, up to 4 GB of memory, and 4 to 6 minutes of conversion time on our CPU for the 60-page report. Remote mode moves that work to a Docling Serve instance you operate.
Parsebridge fits when you only need PDF to Markdown in an application and would prefer not to run any of that. It runs Docling 2.124 inside docling-serve 1.32.0, accepts PDFs up to 50 MB as an upload or URL, and returns Markdown. There is no MCP server, so an agent would call it through a tool you write. There are no DoclingDocument results, anchors, or edit tools, and your PDF is sent to our service. New accounts get 50 free pages once, and plans start at $17 a month for 5,000 pages.
To see Docling’s output on one of your own PDFs first, the free PDF to Markdown converter converts the first page of a PDF up to 10 MB without an account, five times per hour. For Python without MCP, see Getting started with Docling in Python.
Every command and result above was run on November 4, 2026, using docling-mcp 3.5.0 and the 3.2.0 locked by docling-serve v1.32.0, except where a section says untested. Defaults, tool names and environment variables were read from the docling-mcp v3.5.0 source.