ToolMint

Catalog / PDF / DOCX Extract

MCP package · coming soon Developer & security

PDF / DOCX Extract

"Give me the text of this PDF, Word, PowerPoint or Excel file as clean Markdown, plus pages, headings, tables and counts as JSON."

This is a local MCP / CLI package today. Hosted pay-per-call access is not live yet; the text below describes the current code.

The question it answers

"Give me the text of this PDF, Word, PowerPoint or Excel file as clean Markdown, plus pages, headings, tables and counts as JSON."

Use it when

  • An agent has a text-based PDF or an Office file and needs readable text and a rough structure.
  • You want the same input to give the same output every time (no LLM involved).

Do not use it when

  • The PDF is a scan. There is no OCR for PDFs. You get little or no text. (extract_image_ocr works on a single PNG/JPEG you provide, if the optional OCR package is installed.)
  • You need exact table structure or layout. Tables are guessed from whitespace (PDF) or read from the document XML (DOCX, XLSX).
  • The file is over 40 MB.

Example call

There is no public HTTP route yet, so no curl example. Locally:

npx tsx src/cli.ts extract --url https://www.irs.gov/pub/irs-pdf/f1040.pdf

MCP: extract_document {"url":"https://www.irs.gov/pub/irs-pdf/f1040.pdf","kind":"pdf","maxPages":5}. You can instead pass base64 (with an optional filename). Local path input works only for files in the server's sandbox folder.

Params: path, url, base64 (one required), filename, kind (pdf, docx, pptx, xlsx; detected from the name or file header if left out), maxPages (1-200, default 50), ocr, useCache. extract_batch takes up to 50 items.

Example response (trimmed; shape follows the code)

{
  "ok": true,
  "kind": "pdf",
  "source": { "type": "url", "name": "f1040.pdf", "bytes": 220237 },
  "markdown": "## Page 1\n\nForm\n1040 2025U.S. Individual Income Tax Return\n...",
  "structured": {
    "meta": { "title": null, "author": null, "totalPages": 2, "contentSha256": "3d31c226..." },
    "parts": [ { "index": 1, "label": "Page 1", "text": "Form\n1040 2025 ..." } ],
    "sections": [ { "heading": "Page 1", "level": 2, "text": "..." } ],
    "tables": [],
    "wordCount": 2225,
    "charCount": 10151
  },
  "limits": [ "Deterministic local extraction — no LLM rewriting.", "PDF text layer only — scanned/image PDFs need OCR (optional tesseract.js)." ],
  "ocrUsed": false,
  "cacheHit": false,
  "billing": { "sku": "pdf-docx-extract.extract", "plannedPriceUsd": 0.02, "x402Enabled": false },
  "toolVersion": "0.1.0"
}

On failure you get "ok": false and an error string instead of content.

Data sources and licence

Only the document you send or link. We do not claim any licence over the content. The URL fetch refuses private and internal addresses.

Freshness and caching

Extractions are cached by file content, page limit and OCR flag, with no expiry, and the cache holds the full extracted text. Send useCache:false to skip reading the cache (the result is still saved).

Honest limits

  • PDF: text layer only (unpdf / pdfjs). Reading order and table detection are heuristic.
  • DOCX: via mammoth; SmartArt, charts and complex layout lose detail; headers, footers and comments may be incomplete.
  • PPTX: slide text only. XLSX: cell values only (cached formula results, no charts or macros).
  • ocr:true on a PDF does not run OCR; it only adds a note.
  • Limits: 40 MB per file, 50 pages by default, 30 s URL fetch timeout, 5,000 entries / 200 MB inflated for zip-based files.

Errors are not charged

Payment settles only on a successful answer. Any response with status 400 or higher (bad input, not found, upstream failure) is never settled.