Skip to content

Office documents

Office documents is a built-in worker that reads, writes, and converts Word, Excel, PowerPoint, and PDF files, and renders charts. It needs no account or API key, and it works only on files already in your project. This page covers the worker behind the feature described in Office documents: what it consists of, the formats it handles, and how a file moves through it.

The worker is a single container, mcp-office, a thin TypeScript layer over established tools:

  • markitdown and SheetJS for reading
  • pandoc for Markdown conversions
  • WeasyPrint for HTML and Markdown to PDF
  • LibreOffice headless for Office-to-PDF and Office-to-Office conversion
  • python-docx, openpyxl, and python-pptx for creating and editing files
  • pypdf for PDF operations
  • matplotlib for chart images

It mounts one thing from the host, your project workspace, read-write, at /workspace. There’s no /tokens mount, same as the credential-less web automation worker.

Claude calls a tool through the hub, the worker acts on a file under your project workspace, and the result comes back as a file plus a short preview, not the whole document in context.

Reading a document. The worker picks its engine by file type: SheetJS for spreadsheets, markitdown for Word, PowerPoint, and PDF, with fallbacks for harder files. None of this runs OCR, so a scanned or image-only PDF has no text layer to extract, and there is no full-fidelity “editable Word doc from a PDF” path.

Writing or converting. For a PDF, the worker picks the shortest path from what you start with: Markdown, HTML, or an existing .docx, .xlsx, or .pptx. An editable Office file works the same way, from three starting points: Markdown, a structured spec, or an existing file to edit in place (as a new copy).

convertOffice handles format conversion through a fixed matrix, .docx to pdf, odt, txt, html, or rtf for example. A pair outside that matrix, such as .xlsx to .docx, gets rejected.

Charts split the same way: a standalone PNG or SVG comes from renderChart, while a native, editable chart in a spreadsheet or deck only comes from createXlsx or createPptx, since a chart embedded in a .docx is always an image.

Every input and output path is canonicalized and checked before use: a path outside the workspace, or with a symlinked component, is rejected. Generated files land under .speedwave/office/ in your project, written atomically, and an existing file is never overwritten unless you pass overwrite: true.

None of these tools delete or overwrite your source file: edits and conversions always write a new file, and an existing output is only replaced when you pass overwrite: true.

ToolWhat it does
readDocumentExtracts a Word, Excel, PowerPoint, PDF, or HTML file to Markdown.
readPdfTextReturns a PDF’s raw text layer, no structure.
pdfMetadataReturns a PDF’s page count, title, author, and encryption status.
markdownToPdfRenders Markdown to PDF through pandoc and WeasyPrint.
htmlToPdfRenders local HTML to PDF through WeasyPrint.
markdownToDocxConverts Markdown to a Word file through pandoc.
markdownToPptxConverts Markdown to a slide deck, one slide per heading.
renderChartDraws a bar, line, pie, scatter, or area chart to PNG or SVG.
createDocxBuilds a Word file from a spec of headings, paragraphs, tables, and images.
editDocxAppends content, replaces text, or deletes a paragraph in a Word file, writing a new copy.
createXlsxBuilds a workbook from sheet data, with optional native Excel charts.
editXlsxSets cells or formulas, adds a sheet, or adds a chart, writing a new copy.
createPptxBuilds a deck from slides with titles, bullets, images, or native charts.
editPptxAdds a slide, retitles one, or deletes one, writing a new copy.
officeToPdfRenders an existing Office or ODF file to PDF through LibreOffice.
convertOfficeConverts between Office and ODF formats through a fixed matrix, such as .xlsx to .csv.
mergePdfConcatenates two or more PDFs into one.
splitPdfSplits a PDF into separate files by page range.
rotatePdfRotates chosen pages by 90, 180, or 270 degrees.
watermarkPdfStamps a one-page watermark PDF onto every page of a document.
fillPdfFormFills an AcroForm PDF’s fields from a name to value map and flattens it by default.
  • Directoryyour-project/
    • Directory.speedwave/
      • Directoryoffice/
        • report.pdf
        • slides.pptx
flowchart LR
  Claude -->|"tool call"| Hub["Hub"]
  Hub -->|"HTTP"| Worker["mcp-office worker<br/>no tokens, no egress"]
  Worker -->|"reads"| WS["project workspace<br/>/workspace:rw"]
  Worker -->|"writes"| Out[".speedwave/office/"]

LibreOffice headless runs one job at a time, so parallel officeToPdf and convertOffice calls queue. Inline Markdown, HTML, or spec content is accepted up to 200 KB, and PDF tools read up to 2000 pages by default.

Turn on Beta features in the Speedwave tray-icon menu, then enable Office documents for your project from the integrations list. The first enable builds the worker image on demand, pulling in LibreOffice and a Python environment, which extends the usual restart wait. Later toggles are near-instant, since the image is cached. See Connect an integration for the general steps.

The worker can reach only the files inside your project workspace. It has no network egress: it runs on a dedicated internal network with no route out, so it cannot fetch a URL or call any external service, and htmlToPdf and markdownToPdf load only local resources under the workspace, never remote ones. A compromised parser is confined to your project’s files, since the container holds nothing else to reach. Macros and other active content never run: LibreOffice runs with no script provider, and the Python parsers read XML without executing it. This mirrors the isolation model in Isolation, where a worker only ever holds the one credential its job requires, or here, none at all.