---
title: Docling
description: Convert local documents with DoclingTools through a Docling MCP server or the Docling CLI, and use Docling as the PdfTools rendering fallback.
---

# Docling

`DoclingTools` converts a local document through [Docling](https://github.com/docling-project/docling). TnsAI does not bundle Docling, Python or models. You run one of these yourself:

- the Docling MCP server, on a machine that can read the same file paths as the JVM;
- the `docling` CLI, installed locally.

`DoclingTools` lives in `tnsai-tools`, in the package `com.tnsai.tools.document.docling`.

## Register a configured toolkit

Build the toolkit with a provider and pass the instance to `toolPojos(...)`:

```java
import com.tnsai.agents.AgentBuilder;
import com.tnsai.tools.document.docling.DoclingProvider;
import com.tnsai.tools.document.docling.DoclingTools;

DoclingTools docling = DoclingTools.builder()
    .docling(DoclingProvider.subprocess("docling"))
    .build();

agentBuilder.toolPojos(docling);
```

`BuiltInTool.DOCLING_TOOLS` and `new DoclingTools()` create the toolkit with `DoclingProvider.noOp()`. That toolkit registers, but every call throws `IOException`.

The model sees one tool, `docling_parse`. It takes a local path and returns Markdown, cut at 100,000 characters. For tables, formulas, figures or the Docling JSON, call `parse(Path)` from Java.

## Choose a provider

| | `DoclingProvider.mcp(McpClient)` | `DoclingProvider.subprocess(command)` |
|---|---|---|
| Runtime | A Docling MCP server, reached through a TnsAI `McpClient` | A local `docling` process, started without a shell |
| Setup | You create, connect and initialize the client. The server must read the same paths as the JVM. | `docling` installed, with its Python environment and models |
| `available()` | True while the client is connected and initialized | The result of `docling --version`, run once with a 5-second timeout and cached |
| When unavailable | `parse` throws `IOException` | `parse` throws `IOException` |
| Concurrency | Two conversions per client, at least 200 ms apart. A call waits up to 30 seconds for a slot. | Two conversions per JVM. A call waits up to 30 seconds for a slot. |
| Limits | Markdown up to 1,000,000 characters | 5 minutes per conversion, 64 MiB of temporary output, 10 MiB per output file |
| Page images for `PdfTools` | Not supported | Supported |

`DoclingTools.parse` admits the path through the file guard first. The guard applies a `FileGuardConfig` and `DoclingTools.DEFAULT_EXTENSIONS`: PDF, Office, HTML, Markdown, AsciiDoc, CSV, JSON, text, common image formats, WAV, MP3, VTT, XML and LaTeX. Pass your own `FileGuardConfig` with `builder().fileGuard(...)`.

## Use the MCP server

```java
import com.tnsai.mcp.client.McpClient;
import com.tnsai.tools.document.docling.DoclingProvider;
import com.tnsai.tools.document.docling.DoclingTools;
import com.tnsai.tools.document.docling.DocumentResult;
import java.nio.file.Path;

client.connect();
client.initialize();

DoclingTools tools = DoclingTools.builder()
    .docling(DoclingProvider.mcp(client))
    .build();

DocumentResult result = tools.parse(Path.of("/data/paper.pdf"));
String markdown = result.markdown();
boolean structured = result.hasStructuredContent();
```

`client` is an `McpClient` built for your server's transport. See [MCP client](../mcp/client.md). The provider calls the server's `convert_document_into_docling_document` tool, then `export_docling_document_to_markdown`.

## Use the CLI

```java
import com.tnsai.tools.document.docling.DoclingProvider;
import com.tnsai.tools.document.docling.DoclingTools;
import com.tnsai.tools.document.docling.DocumentResult;
import java.nio.file.Path;

DoclingTools tools = DoclingTools.builder()
    .docling(DoclingProvider.subprocess("docling"))
    .build();

DocumentResult result = tools.parse(Path.of("/data/paper.pdf"));
```

`subprocess` takes the executable name or its full path. The provider runs `docling convert --to md --to json` and reads both outputs.

## `DocumentResult`

| Accessor | Contents |
|---|---|
| `markdown()` | The document as Markdown |
| `tables()` | Tables from the Docling JSON, or from the Markdown when the JSON has none |
| `formulas()` | Formulas from the Docling JSON, or display formulas in the Markdown |
| `figures()` | Pictures from the Docling JSON, or image references in the Markdown |
| `doclingJson()` | Docling's JSON output. The MCP provider leaves it empty. |
| `hasStructuredContent()` | True when there is at least one table, formula or figure |

## `PdfTools` fallback

`PdfTools` renders PDF pages with PDFBox. Give it a Docling provider and it falls back to Docling when PDFBox cannot open the file:

```java
import com.tnsai.tools.document.docling.DoclingProvider;
import com.tnsai.tools.file.FileGuardConfig;
import com.tnsai.tools.file.PdfTools;

PdfTools pdf = new PdfTools(
    FileGuardConfig.defaults(),
    DoclingProvider.subprocess("docling"));
```

Only the CLI provider renders pages. Without a provider, or with the MCP provider, the PDFBox error is thrown.

## Related

- [Catalog](catalog.md): `DOCLING_TOOLS` and the other document toolkits.
- [RAG](../rag/index.md): document formats for knowledge ingestion, which do not use Docling.
- [Docling](https://github.com/docling-project/docling): installing Docling and its MCP server.
