Documents Server¶
document_processing_server (doc_processing_std_tools.document_processing, MCP name
document-processing-tools) gives an agent 13 tools to read PDFs, Word, Excel and PowerPoint files
and images, to OCR scans, to render pages as images the model can look at, and to convert documents
between formats.
from doc_processing_std_tools import document_processing_server
Writing documents from scratch is not part of this server: an agent creates them with code through
the Code Execution server, and can then convert them with convert_document.
Install¶
| Need | Install |
|---|---|
| The readers, renderers and image tools | the docs extra (pdfplumber, python-docx, openpyxl, python-pptx, Pillow, pymupdf) |
ocr_pdf, ocr_image |
the ocr extra (llmwhisperer-client 2.x) and LLMWHISPERER_API_KEY |
convert_document, and rendering Word, Excel, PowerPoint or OpenDocument files |
LibreOffice: on Debian or Ubuntu, apt-get install libreoffice-core libreoffice-writer libreoffice-calc libreoffice-impress. std-tools runs libreoffice, then soffice, from PATH, or the executable in DPTTOOLS_SOFFICE_BIN |
PDFs render with pymupdf alone; LibreOffice is only needed to convert Office files.
Tools¶
Reading text¶
| Tool | Key parameters | Returns |
|---|---|---|
read_pdf |
path, pages="all", extract_tables=False |
Text with --- Page N --- headers; tables as |-separated rows. Says so, and suggests ocr_pdf, when no page has text |
read_word |
path (.docx) |
Text: headings as Markdown # lines, then header and footer lines, tables, text boxes, and an embedded-image count when there are images |
read_excel |
path (.xlsx), sheet (default: the active sheet), range (for example "A1:D10") |
JSON: sheet, headers (first row), rows, total_rows, merged_ranges, has_images, has_charts, has_media |
read_powerpoint |
path (.pptx) |
JSON: slides (each with slide, text, speaker_notes, image_count, chart_count, has_media), slide_count, has_media |
get_file_overview |
path |
JSON summary for the file type: PDF page count, sizes and text previews; Excel sheets, sizes and sample rows; Word headings and counts; PowerPoint slide titles; image size; or size, line count and first and last lines for any other file |
OCR (LLMWhisperer)¶
| Tool | Key parameters | Returns |
|---|---|---|
ocr_pdf |
path (.pdf), pages="all" |
OCR text with --- Page N --- headers |
ocr_image |
path (.png, .jpg, .jpeg, .webp, .tif, .tiff, .bmp) |
OCR text |
Seeing pages and images¶
These return MCP image content, so the model sees the pixels. Every image is first brought within model-safe limits — see Image size limits below.
| Tool | Key parameters | Returns |
|---|---|---|
read_image |
path (PNG, JPEG, WEBP, GIF, BMP, TIFF) |
The image, with its format taken from the bytes rather than the extension; the file itself when it is within the limits |
get_image_metadata |
path |
JSON: format, width, height, mode, file_size, file_size_bytes — no pixels |
render_document_page |
path, page=1, scale=2.0 |
One page as a PNG |
render_document_thumbnail |
path, max_pages=5 |
The first pages as PNGs at scale 1.0 (72 dpi) |
read_document_pages_as_images |
path, pages="all", scale=2.0, max_pages=20 |
One PNG per requested page |
The renderers accept PDF, DOCX, XLSX, PPTX, DOC, XLS, PPT, ODT, ODS and ODP, and reject image files
(use read_image). scale multiplies 72 dpi, so the default 2.0 renders an A4 page at about
1190 × 1684 pixels.
Image size limits¶
New in 0.6.0. read_image, render_document_page, render_document_thumbnail and
read_document_pages_as_images scale an image down when its long edge is over
DPTTOOLS_IMAGE_MAX_EDGE_PX (default 1568 px) or its encoded size is over DPTTOOLS_IMAGE_MAX_MB
(default 3 MB). Those defaults are accepted by every provider the toolkit supports. An image within
both limits is sent unchanged, byte for byte; a scaled one may arrive as JPEG. An A4 page at the
default scale=2.0 is 1684 px tall, so it is scaled to 1568 px. Images
explains the rules.
Converting documents¶
New in 0.6.0.
| Tool | Key parameters | Returns |
|---|---|---|
convert_document |
path, to, outdir=None, page="all", overwrite=False |
JSON {"output_files": [...], "pages": ..., "engine": ...} — the files it wrote, not their content |
- Targets (
to):pdf,docx,xlsx,pptx,odt,ods,odp,csv,html,txt,png,jpg(jpegis accepted asjpg). - Sources: Office and OpenDocument files (DOCX, XLSX, PPTX, DOC, XLS, PPT, ODT, ODS, ODP, RTF and
similar). A PDF can only become
pngorjpg; to get its text, useread_pdf. pngandjpgwrite one image per page, named<name>-p<N>.png(or.jpg), rendered at 144 dpi. The document is converted to PDF first, then each page is rendered with pymupdf;pagepicks the pages ("all","1-3","2,5"). For other targetspagemust be"all".csvexports only the first sheet of a spreadsheet.txtandcsvare written as UTF-8.- Other targets write one file,
<name>.<to>. - Where: next to the source file, or into
outdir, which must already exist. An existing output file is never replaced unlessoverwrite=True; otherwise the call fails and names the file. pagesin the result is the number of images written forpng/jpg, the page count forpdf(when pymupdf is installed), andnullotherwise.engineislibreoffice,libreoffice+pymupdforpymupdf.
convert_document writes files and returns paths; it does not show anything to the model. To look
at pages, use read_document_pages_as_images, or read_image on a converted page image.
LibreOffice runs¶
convert_document and the Office-to-PDF step of the three render tools run LibreOffice headless.
Each run gets its own LibreOffice profile and output folder, which are removed afterwards, so
concurrent conversions in one container do not collide (new in 0.6.0). A run is stopped after
DPTTOOLS_CONVERT_TIMEOUT_S seconds (default 120).
Choosing a tool¶
| The file is… | Start with | Then, if needed |
|---|---|---|
| Unknown | get_file_overview |
the matching reader |
| A PDF with selectable text | read_pdf |
read_document_pages_as_images for charts and diagrams |
| A scanned PDF | ocr_pdf (needs a key; costs per page) |
or read_document_pages_as_images, which needs no key — the model reads the page images |
| A Word, Excel or PowerPoint file | read_word, read_excel, read_powerpoint |
read_document_pages_as_images when the result is near-empty or reports media (has_media, the image count) |
| A photo or screenshot of text | ocr_image |
or read_image |
| An image to inspect visually | read_image |
get_image_metadata to check its size first |
| A file to deliver in another format | convert_document |
read_document_pages_as_images to check the result |
Environment variables¶
| Variable | Default | Effect here |
|---|---|---|
LLMWHISPERER_API_KEY |
none | Required by ocr_pdf and ocr_image. Read on every call |
DPTTOOLS_OCR_TIMEOUT |
180 |
Deadline for one OCR call (upload plus waiting for the result), in seconds, clamped to 30–600. Read once per process; a value that is not a positive integer is an error naming the variable |
DPTTOOLS_MAX_FILE_SIZE_MB |
50 |
Every tool here refuses files larger than this |
DPTTOOLS_IMAGE_MAX_EDGE_PX |
1568 |
Long-edge limit for images returned to the model. New in 0.6.0 |
DPTTOOLS_IMAGE_MAX_MB |
3 |
Encoded-size limit for images returned to the model. New in 0.6.0 |
DPTTOOLS_OUTPUT_TRUNCATION_LIMIT |
50000 |
Text results are cut at this many characters. OCR output is cut on a page boundary |
DPTTOOLS_SOFFICE_BIN |
none | The LibreOffice executable (a path, or a command on PATH). When unset, libreoffice then soffice on PATH. A value that does not resolve is an error naming the variable. New in 0.6.0 |
DPTTOOLS_CONVERT_TIMEOUT_S |
120 |
Timeout for one LibreOffice conversion, in seconds. New in 0.6.0 |
Examples¶
Tool calls are written as Python calls; the model sends the same arguments as JSON.
get_file_overview(path="statements/2026-09.pdf")
read_pdf(path="statements/2026-09.pdf", pages="1-3", extract_tables=True)
ocr_pdf(path="scans/contract.pdf", pages="1-3,7")
ocr_pdf(path="scans/contract.pdf", pages="21-") # page 21 to the end
read_document_pages_as_images(path="deck.pptx", pages="1-5", max_pages=5)
convert_document(path="reports/q3.docx", to="pdf")
convert_document(path="deck.pptx", to="png", page="1-3", outdir="exports")
A convert_document result:
{
"output_files": ["/workspace/exports/deck-p1.png", "/workspace/exports/deck-p2.png",
"/workspace/exports/deck-p3.png"],
"pages": 3,
"engine": "libreoffice+pymupdf"
}
Pitfalls¶
- The
pagessyntax differs between tools.read_pdfandread_document_pages_as_imagestake"all", a page ("3"), a range ("1-5") or a comma list mixing both ("1-3,7"); a range that runs past the end is clipped, but a start page past the end is an error.ocr_pdftakes the same forms plus an open-ended range,"21-". pages="all"can flood the context.read_document_pages_as_imagesreturns one image per page, up tomax_pages(20); pages past the cap are dropped without an error. Ask for a range.- A higher
scaledoes not mean more detail for the model. Pages are scaled back to the long-edge limit, so beyond aboutscale=2.0a larger value mostly costs time. To read small print, crop or zoom with Image Tools first, thenread_imagethe result. - An image that cannot fit is an error. If an image would have to shrink below 256 px on its long
edge to fit the byte limit, the tool returns an
Error:suggesting a largerDPTTOOLS_IMAGE_MAX_MBor a crop. - Long OCR output is cut on a page boundary. The result then names the pages left out and the
pagesvalue to request them with.ocr_imagehas no pagination. - OCR prechecks the PDF. An empty file and a file without a PDF header are refused before anything is uploaded; so are a password-protected PDF and a PDF with no pages, when pymupdf is installed.
- Excel values are strings, and formulas are not returned.
read_excelreads the values saved with the workbook. A workbook generated by code and never opened in Excel may have no saved results for its formulas, which then read as empty strings. Only.xlsxworkbooks are read; render an old.xlsfile withread_document_pages_as_imagesinstead. - Old binary formats.
read_wordandread_powerpointread.docxand.pptxonly..docand.pptfiles can still be rendered as images, through LibreOffice. - Office conversion needs LibreOffice. Without it,
convert_documentand rendering a Word, Excel or PowerPoint file return an error with the install command. - Fonts come from the machine. LibreOffice lays out pages with the fonts installed where it
runs; install CJK fonts (for example
fonts-noto-cjk) for Chinese, Japanese or Korean documents. convert_documentwill not overwrite. Passoverwrite=True, or anotheroutdir, when the output already exists. Converting a file to its own format is an error.- Large documents. A conversion that takes longer than
DPTTOOLS_CONVERT_TIMEOUT_Sis stopped; raise it for very long documents. - In-process image results need toolkit 0.5.1 or later. See Compatibility.
Upgrading from 0.5.0
DPTTOOLS_OCR_TIMEOUT used to be read on every call, and a non-integer value silently fell back
to 180. It is now read once per process, and an invalid value is an error naming the variable;
the composed launcher refuses to start. Values outside 30–600 are still clamped.
Skills that run LibreOffice by hand
Skill content that tells the model to write its own soffice commands through execute_command
can be retired: convert_document handles the per-run profile, the timeout, cleanup and the
"exit 0 but no output" case. Keep the policy — when to convert, naming and folders — in the
skill, and have it call convert_document.
Recipes¶
- OCR a Scanned PDF: tell a scan from a text PDF, OCR the pages you need, and read a long document in parts.
- Office Files to Page Images: show Word, Excel and PowerPoint pages to the model, or save them as image files.