all2md
all2md
Read, convert, search, and chunk PDFs, Office files, e-books, emails, and 40+ other formats, as Markdown and back again. From Python, from your terminal, or from your AI assistant.
Try it in ten seconds
With uv there is nothing to install first:
uvx --from "all2md[all]" rcat report.pdf # read any document in the terminal
uvx --from "all2md[all]" all2md report.docx # print it as MarkdownKeep it around as a tool, with all2md, rcat and the all2md-mcp server on your PATH:
uv tool install "all2md[all]"Or use it as a library:
uv add "all2md[pdf,docx]" # or: pip install "all2md[pdf,docx]"from all2md import to_markdown
markdown = to_markdown("report.pdf")Related MCP server: document-converter-mcp
Pick your path
I want to… | Start with | Read |
Read documents without leaving the terminal |
| |
Convert files, one or a thousand, in either direction |
| |
Parse documents in my Python code |
| |
Find text inside PDFs, Word files and slide decks |
| |
Feed documents to a RAG pipeline |
| |
Let Claude or another assistant work with my files | the one-click Claude Desktop extension | |
Know how far to trust the output |
|
Read documents in your terminal
rcat is cat for documents. It renders PDFs, Word and PowerPoint files (the 97-2003 .doc and .ppt too), spreadsheets, e-books, emails, notebooks, man pages and every other format all2md reads, with headings, tables, syntax-highlighted code, links with their targets, footnotes, math and admonitions. No browser, no office suite, and it works over SSH. If you reach for glow to read Markdown or doxx to read Word files, rcat is the same idea for every format.
rcat report.docx # read a Word document
rcat deck.pptx --outline # just the slide titles
rcat handbook.pdf --extract "Installation" # one section, by heading
rcat contract.pdf --pager # page through it
curl -sL https://example.com/spec.pdf | rcat -For anything longer, all2md read (or rcat -i) opens the interactive viewer shown above: an outline beside the text, jumps between headings, the links on screen, and, given a folder, a tree of the documents in it.
all2md read handbook.pdf
all2md read docs/ # choose from the documents in a folderWhen you would rather have a browser, all2md view report.docx opens a styled HTML preview, all2md view ./docs -r browses a whole folder with on-demand conversion, and all2md edit notes.md opens a browser editor that saves back to the file.
Styling needs the cli_extras extra and the viewer needs tui; all2md[all] includes both. More in the viewer documentation.
Convert documents from the command line
Any supported format to Markdown, and Markdown back to DOCX, PDF, PPTX, HTML, EPUB and more:
all2md report.pdf > report.md # to Markdown on stdout
all2md answer.md --out answer.docx # Markdown (an LLM's output, say) to Word
all2md ./inbox -r --output-dir ./markdown -p 4 # a whole tree, four at a time
all2md ./inbox -r --output-dir ./markdown --watch # keep converting as files arrive
all2md scan.pdf --pdf-ocr-enabled # scanned pages, through OCREvery option of every converter is a CLI flag (all2md --help) or a key in a config file (all2md config generate). Every file command reads stdin and writes stdout with -, so all2md slots into pipelines. Word documents come out as Word shows them: tracked changes resolved by policy, comments with their anchors, footnotes, field results, merged cells, and the list numbers Word actually prints.
See the CLI reference and the cheat sheet.
Python API
to_markdown() handles the common case; convert() goes between any two formats; to_ast() gives you the parsed document to work with.
from all2md import to_markdown, convert, to_ast, from_ast
markdown = to_markdown("report.pdf", pages="1-3", flavor="gfm")
convert("notes.md", "notes.docx", target_format="docx")
doc = to_ast("report.docx") # a typed document tree
html = from_ast(doc, target_format="html")The core has no dependencies; each format's extra pulls in only what that format needs. Options are typed dataclasses (PdfOptions, DocxOptions, …) or plain keyword arguments, and AST transforms (remove-images, heading-offset, your own) slot in between parsing and rendering. New formats and transforms plug in through entry points.
If you are an LLM with a coding environment, all2md llm-help prints usage guidance written for you, and all2md install-skills installs it as a skill for Claude Code, Cursor and others.
See the Python API guide, the AST guide, and examples/python.
Search inside any document
grep doesn't look inside a PDF or a .docx. all2md grep does, across any mix of formats, with the usual flags:
all2md grep -i "termination" contracts/ -r # every format in the tree
all2md grep -C 2 "deadline" contracts/ -r --rich # with context, highlighted
all2md search "renewal terms" ./contracts --keyword # ranked BM25 search
all2md search "who approved the budget" ./minutes --hybrid
all2md diff draft-v1.docx draft-v2.pdf # a colored diff, across formatsVector and hybrid search need the search extra. Add --cache (or ALL2MD_CACHE=1) to reuse parsed documents across repeated runs.
RAG and chunking
all2md chunk converts and splits in one step. Each chunk carries its section heading and source page span, so answers can cite where they came from.
all2md chunk handbook.pdf --strategy semantic --max-tokens 512 --overlap 64 > chunks.jsonlimport all2md
for c in all2md.chunk("handbook.pdf", strategy="semantic", max_tokens=512, overlap=64):
print(c.chunk_id, c.section_heading, c.page, c.token_count)There are 11 strategies (semantic, heading, section, token, sentence, paragraph, code, …). Tables and code blocks are kept whole, and the output is JSONL ready for any vector store. Real token counts use tiktoken from the chunk extra. See the chunk command.
Give your AI assistant your documents
all2md ships a Model Context Protocol server, so an assistant like Claude can read your PDFs and Office files, write Word documents, edit them in place, search a folder, and compare two versions. You don't need to write any code.
In Claude Desktop (no Python or terminal needed):
Download
all2md.mcpbfrom the latest release.Open Claude Desktop → Settings → Extensions and drag the file onto the page.
Choose the folder all2md may work in, and whether it may write files.
Ask Claude about the documents in that folder.
The server is in the MCP Registry as io.github.thomas-villani/all2md. To run it yourself, use uvx (nothing to install):
{
"mcpServers": {
"all2md": {
"command": "uvx",
"args": ["--from", "all2md[all]", "all2md-mcp", "--temp", "--enable-from-md"]
}
}
}or install it with uv tool install "all2md[mcp]" and use "command": "all2md-mcp". The [mcp] extra covers PDF, Word, PowerPoint, Excel, HTML, EPUB, ODF and reStructuredText; use [all] for everything.
Tools: read_document_as_markdown, save_document_from_markdown, edit_document, plus the read-only search_documents, diff_documents and get_document_outline.
See the MCP documentation for the options and the security model.
Measured fidelity
all2md's conversion quality is measured against independent ground truth, not asserted. Each benchmark lane is published with a control that shows what the measurement looks like when it should fail:
Born-digital PDFs: publisher PDFs from PubMed Central, scored against the JATS XML deposited beside them.
Scanned pages: 981 OmniDocBench pages against human annotation, for the OCR path.
Round trips: Markdown → format → Markdown must hold fidelity 100 for this repository's own docs, on every pull request.
Against other converters, on a sealed holdout of 103 PubMed Central articles scored with the same instruments (reading of 2026-08-29):
all2md | pymupdf4llm 1.28.2 | Docling 2.120.3 | |
Recall of attainable text | 97.3% | 97.1% | 96.2% |
Invented text (lower is better) | 0.55% | 6.26% | 2.05% |
Table text preserved | 73.1% | 60.7% | 79.3% |
Docling's learned table model still leads on tables. The comparison lane has the full results, the ground rules, and the caveats that bound them. Conversion Fidelity has the rest.
You can measure your own documents the same way:
all2md report scan.pdf # a reference-free "quality card"
all2md roundtrip notes.md --via docx # convert, parse back, score what survived
all2md optimize hard.pdf --sample-pages 5 # auto-tune the settings for a difficult fileCI quality gate
The same scores run as a GitHub Action, which fails the build when your documents stop converting cleanly:
- uses: thomas-villani/all2md@v1.19.0
with:
paths: docs/**/*.md
roundtrip-fail-under: 97It fails rather than passing quietly when no files match, no threshold is set, or a document cannot be converted at all, and it warns when a threshold sits so far below your real floor that it could never fire. See the action's documentation.
Supported formats
Documents: PDF, DOCX, DOC, PPTX, PPT, ODT, ODP, RTF, EPUB, FB2, CHM
Web & markup: HTML, MHTML, Markdown, reStructuredText, AsciiDoc, Org-Mode, LaTeX, MediaWiki, Textile, DokuWiki, BBCode, man pages
Data & spreadsheets: XLSX, ODS, CSV/TSV, JSON, YAML, TOML, INI, OpenAPI/Swagger
Email: EML, MBOX, Outlook (MSG/PST/OST), Evernote (ENEX)
Notebooks & code: Jupyter, plus nearly 200 source-code and config file types
Archives: ZIP, TAR, 7Z, RAR and more;
.gz,.bz2and.xzconvert as the file they holdCustom output: any text format through Jinja2 templates
Format | File Extensions | Input (Parse) | Output (Render) | Dependencies Extra |
| ✅ | ✅ |
| |
Word Document |
| ✅ | ✅ |
|
Word 97-2003 Document |
| ✅ | (N/A) | (built-in) |
PowerPoint Presentation |
| ✅ | ✅ |
|
PowerPoint 97-2003 |
| ✅ | (N/A) | (built-in) |
HTML |
| ✅ | ✅ |
|
MHTML Web Archive |
| ✅ | (N/A) |
|
Email Message |
| ✅ | (N/A) | (built-in) |
MBOX Mailbox Archive |
| ✅ | (N/A) | (built-in) |
Outlook Message/Archive |
| ✅ | (N/A) |
|
Jupyter Notebook |
| ✅ | ✅ | (built-in) |
EPUB E-book |
| ✅ | ✅ |
|
FictionBook 2.0 (FB2) |
| ✅ | (N/A) |
|
CHM (Compiled HTML Help) |
| ✅ | (N/A) |
|
OpenDocument Text |
| ✅ | ✅ |
|
OpenDocument Presentation |
| ✅ | ✅ |
|
OpenDocument Spreadsheet |
| ✅ | (N/A) |
|
Excel Spreadsheet |
| ✅ | (N/A) |
|
CSV / TSV |
| ✅ | ✅ | (built-in) |
Rich Text Format |
| ✅ | ✅ |
|
LaTeX |
| ✅ | ✅ |
|
AsciiDoc |
| ✅ | ✅ | (built-in) |
reStructuredText |
| ✅ | ✅ |
|
Org-Mode |
| ✅ | ✅ |
|
MediaWiki |
| ✅ | ✅ |
|
Textile |
| ✅ | ✅ | (built-in) |
BBCode |
| ✅ | (N/A) | (built-in) |
DokuWiki |
| ✅ | ✅ | (built-in) |
Man Page (man(7)) |
| ✅ | ✅ | (built-in) |
Evernote Export |
| ✅ | (N/A) |
|
Safari Web Archive |
| ✅ | (N/A) |
|
JSON |
| ✅ | ✅ | (built-in) |
YAML |
| ✅ | ✅ | (built-in) |
TOML |
| ✅ | ✅ | (built-in) |
INI / Config |
| ✅ | ✅ | (built-in) |
OpenAPI/Swagger |
| ✅ | (N/A) |
|
Plain Text |
| ✅ | ✅ | (built-in) |
Source Code | nearly 200 extensions ( | ✅ | (N/A) | (built-in) |
Archive Formats |
| ✅ | (N/A) | (built-in) |
Single Compressed File |
| ✅ | (N/A) | (built-in) |
ZIP Archive |
| ✅ | (N/A) | (built-in) |
Jinja2 Templates (Custom) | User-defined ( | ❌ | ✅ |
|
Run all2md list-formats to see what your install supports, or browse the formats documentation.
Installation
You are… | Install |
Using the CLI and viewer |
|
Trying it once |
|
Building with the library |
|
Running the MCP server | the Claude Desktop extension above, or |
all2md check-deps shows which formats your install can handle.
Install scripts. These set up uv (installing it if needed) and install the CLI globally with the all extra.
# macOS / Linux
curl -LsSf https://raw.githubusercontent.com/thomas-villani/all2md/main/scripts/install.sh | sh# Windows (PowerShell)
powershell -ExecutionPolicy Bypass -c "irm https://raw.githubusercontent.com/thomas-villani/all2md/main/scripts/install.ps1 | iex"To slim it down, download the script and pass the extras you want: sh install.sh pdf,docx,html or .\install.ps1 -Extras pdf,docx,html.
Extras for specific needs:
uv add "all2md[cli_extras]" # terminal styling for --rich / rcat, progress bars, watch mode
uv add "all2md[tui]" # the interactive viewer, all2md read
uv add "all2md[pdf,ocr]" # OCR for scanned PDFs (Tesseract; needs the system binary)
uv add "all2md[pdf,ocr-easyocr]" # ...or binary-free EasyOCR (downloads models on first use)
uv add "all2md[pdf_layout]" # ML layout analysis for difficult PDFs
uv add "all2md[search]" # vector and hybrid search
uv add "all2md[chunk]" # real token counts for chunking
uv add "all2md[outlook]" # Outlook MSG (PST/OST also need: pip install libpff-python)See the installation guide for the full list.
FAQ
How is all2md different from Pandoc? all2md is Python-native and built for programmatic use, LLM pipelines and reading documents in the terminal. Pandoc has more publishing breadth and scholarly features such as citations. They complement each other well.
Does it work with scanned PDFs?
Yes. Install all2md[pdf,ocr] (or ocr-easyocr for no system binary) and pass --pdf-ocr-enabled. all2md report tells you when a PDF has no text layer.
Can I output something other than Markdown? Yes: DOCX, PDF, PPTX, HTML, EPUB, ODT, RST, LaTeX and more, or any text format through Jinja2 templates.
How do I add a format?
Write a parser, describe it with ConverterMetadata, and register it under the all2md.converters entry point. See examples/plugins.
Contributing
Bug reports, feature requests, docs and code are all welcome. See CONTRIBUTING.md for the development setup. Parser changes are judged against the benchmark lanes; see Conversion Fidelity.
Questions and bugs go to GitHub Issues. Full documentation is on Read the Docs.
License
MIT. See LICENSE.
Available Tools
5 toolsdiff_documentsA
Compare two documents and return their differences.
Each input is auto-detected (file path, data URI, base64, or inline content), so documents in any supported format can be compared — even across formats (e.g. a DOCX against its PDF export).
Returns a dictionary with:
diff: the rendered diff (unified text or JSON string)
has_changes: whether any differences were found
| Name | Required | Description | Default |
|---|---|---|---|
| new | Yes | Updated document: file path (within read allowlist), data URI, base64, or inline content. REQUIRED. | |
| old | Yes | Original document: file path (within read allowlist), data URI, base64, or inline content. REQUIRED. | |
| format | No | Output format: 'unified' (default, plain text) or 'json' (structured). | unified |
| granularity | No | Comparison granularity: 'block' (default), 'sentence', or 'word'. | block |
| context_lines | No | Context lines around changes in unified output (default: 3). | |
| ignore_whitespace | No | Normalize whitespace before comparing. Default: false. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are supplied, so the description carries the disclosure burden. It does add real context — inputs are auto-detected from path, data URI, base64, or inline content, and the comparison works across formats — but it says nothing about error behavior for unsupported formats, read-allowlist failures, size limits, or cost of large comparisons.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action in one sentence, then a compact bullet list for the return value. The 'Returns a dictionary with' block partly duplicates the existing output schema, which costs some space, but nothing is padded or verbose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given a six-parameter tool with an output schema, the description covers input flexibility, cross-format support, and the shape of the result. Remaining gaps (failure modes for unsupported or oversized documents) are modest for a read-only comparison operation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so every parameter is already documented in the schema; baseline 3 applies. The description adds only the input auto-detection idea and does not elaborate on format, granularity, context_lines, or ignore_whitespace beyond what the schema states.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Compare two documents and return their differences') plus a notable capability: cross-format comparison such as DOCX vs its PDF export. It is clearly distinct from the siblings (read_document_as_markdown, search_documents, get_document_outline, list_workspace_files), though it never explicitly names an alternative.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied by the purpose — an agent infers that this is the tool for 'are these two documents different' questions. There is no explicit when-to-use/when-not guidance, no statement about prerequisites, and no routing advice versus the read/search/outline siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_document_outlineA
Return the heading structure (table of contents) of a document.
Use this to navigate a large document before extracting specific sections: the returned indices line up with edit_document's '#N' target notation.
Returns a dictionary with:
sections: list of {index, level, heading}
total: number of headings returned
| Name | Required | Description | Default |
|---|---|---|---|
| doc | Yes | Document to outline: file path (within read allowlist), data URI, base64, or inline content. REQUIRED. | |
| max_level | No | Deepest heading level to include, 1-6 (default: 6 = all levels). | |
| format_hint | No | Optional format hint for ambiguous/extensionless sources (e.g. 'pdf', 'docx', 'html'). |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are supplied, so the description carries the burden and does disclose one non-obvious behavioral trait: returned indices line up with edit_document's '#N' addressing, which is not inferable from the schema. It is silent on failure behavior for unsupported formats or size limits, and the return-value section partly duplicates the existing output schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action, then usage, then return shape in a scannable list; no filler sentences. The 'Returns a dictionary with' block is somewhat redundant against the declared output schema, costing a point on tightness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 3-parameter read tool with full schema coverage and an output schema, the description covers purpose, navigation use case, and cross-tool index semantics. Remaining gaps are minor: no note on unsupported formats or how errors surface.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so doc, max_level, and format_hint are already well documented in the input schema. The description adds no parameter-level meaning (e.g., when to set format_hint or how max_level affects indices), so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a concrete verb and resource: 'Return the heading structure (table of contents) of a document.' The parenthetical clarifies the concept and the follow-up sentence scopes it to navigation of large documents, which separates it from read_document_as_markdown (full content) and search_documents (query match) without needing the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit when-to-use: 'navigate a large document before extracting specific sections,' and it points at a downstream consumer (edit_document's '#N' notation). It stops short of naming an alternative sibling or a case where this tool is the wrong choice, so it is clear context without explicit exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_workspace_filesA
List files the server is allowed to read.
Use this to discover what is available before reading or editing. Results are confined to the read allowlist (the workspace folder plus any additional read-only folders). Paths returned here can be passed directly to the other tools.
Returns a dictionary with:
files: list of {path, size_bytes} (absolute paths, sorted)
total: number of files returned
truncated: true if more files exist than were returned (capped)
read_dirs: the read folders that were searched
| Name | Required | Description | Default |
|---|---|---|---|
| pattern | No | Optional glob filter on file names, e.g. '*.pdf' or '*.docx'. Default: all files. | |
| recursive | No | Recurse into subdirectories. Default: true. | |
| subdirectory | No | Optional workspace-relative subdirectory to list. If omitted, all read folders are listed. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does well: it discloses the read-allowlist confinement, that results are absolute and sorted, and that output can be capped via a truncation flag. It omits whether hidden files are included and says nothing about permissions or performance on large trees, so it is strong but not exhaustive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the scope constraint, then a usage sentence, then a bulleted return shape — clean and skimmable with no filler. The return-value block is duplicated by the existing output schema, so a chunk of the text is redundant rather than earning its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-required-parameter listing tool this covers the essentials: scope, purpose, allowed follow-up use, and truncation behavior. Since an output schema already exists, the enumerated return fields are surplus, and the description never explains how narrowing by subdirectory or pattern changes the result set.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so pattern, recursive, and subdirectory are already fully documented with defaults and examples. The description adds no meaning beyond the schema for any of the three parameters, which is the baseline case rather than a value-add.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence states a specific verb and resource (list files) plus the governing scope (the read allowlist), and the follow-up frames it as the discovery step preceding reading/editing. That framing makes it immediately distinguishable from read_document_as_markdown and search_documents without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
"Use this to discover what is available before reading or editing" gives clear sequencing guidance, and "Paths returned here can be passed directly to the other tools" tells the agent how output feeds siblings. It does not explicitly say when to prefer search_documents over listing (e.g., known filename vs known content), so a small gap remains.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_document_as_markdownA
Read a document and convert it to Markdown format (simplified API).
Supports PDF, Word (DOCX), PowerPoint (PPTX), HTML, email (EML), EPUB, Jupyter Notebooks (IPYNB), Excel (XLSX/CSV), ODF formats, and 200+ text formats.
The source parameter is auto-detected as:
File path (if file exists in read allowlist)
Data URI (data:image/...)
Base64-encoded content (auto-detected)
Plain text content (HTML, Markdown, etc.)
Optionally extract a specific section by providing the section parameter with a heading name (case-insensitive match).
Image inclusion and markdown flavor are configured at server startup and cannot be changed per-call.
Returns the Markdown as a text content block, followed by an image content block for each image found (when include_images=true), so vision models can see the images alongside the text. When include_images=false, only the text, with image alt text in place of the images.
| Name | Required | Description | Default |
|---|---|---|---|
| source | Yes | Unified source parameter. Auto-detected as: file path (if exists in read allowlist), data URI (data:...), base64 string, or plain text content. REQUIRED. | |
| section | No | Optional section name to extract (case-insensitive heading match). If provided, only that section is returned. | |
| pdf_pages | No | Page specification for PDF sources only. Examples: '1-3' (pages 1-3), '1,3,5' (specific pages), '1-3,5,10-' (ranges and individual pages), '1-' (from page 1 to end). | |
| format_hint | No | Optional format hint for ambiguous cases (e.g., extensionless files). Options: auto (default), pdf, docx, pptx, html, eml, epub, ipynb, odt, odp, ods, xlsx, csv, rst, markdown, txt. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations supplied, the description carries the full burden and does well: it discloses the read-allowlist constraint on file paths, that image inclusion and markdown flavor are fixed at server startup and cannot be changed per call, and that section matching is case-insensitive. It also describes the response shape (a text content block followed by one image block per image, or alt-text placeholders when include_images=false), which no output schema covers. Only error behavior and size/rate limits are unaddressed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the purpose, then formats, then source detection, then optional behaviors, then return shape — a sensible ordering for an agent scanning it. The long format enumeration and the repeated source auto-detection list (already in the schema) are the main slack, but they remain short and skimmable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a four-parameter read tool with no annotations and no output schema, the definition covers input handling, configuration constraints, and return structure, which is enough to invoke it correctly. The only meaningful omission is what happens on failure (unreadable file, unsupported format, no matching section).
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all four parameters are already documented, and the description largely restates the source auto-detection rules and the section heading match. It adds no meaning for pdf_pages or format_hint, which live entirely in the schema, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Read a document and convert it to Markdown format') plus the full set of supported input formats, so the agent knows exactly what the tool produces. It does not explicitly contrast itself with the closest sibling, get_document_outline, which returns structure rather than full content, so an agent must infer that boundary.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied rather than stated: the description says you may 'optionally extract a specific section' and explains how the source is auto-detected, which guides parameter choice. It never says when to prefer this over search_documents, diff_documents, or get_document_outline, and gives no exclusions or prerequisites beyond the read-allowlist note.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_documentsA
Search a corpus of documents and return ranked snippets.
Instead of returning whole files, this tool returns the most relevant passages (with hit spans wrapped in << >> markers), so an agent can locate information across many documents cheaply.
Modes:
keyword: BM25 relevance ranking (requires the optional rank-bm25 dependency). Best for "find the most relevant passages" queries.
grep: literal/regex line matching. Best for "find every occurrence of X". Stateless, no extra dependencies.
Supports all formats the read tool supports (PDF, DOCX, HTML, etc.); files are converted to text before searching.
Returns a dictionary with:
results: list of {snippet, score, document_path, section_heading, chunk_id}
mode: the search mode used
total: number of results returned
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | Search mode: 'keyword' (default, BM25 relevance ranking) or 'grep' (literal/regex line matching). | keyword |
| paths | No | Files, directories, or globs to search (each must be within the read allowlist). If omitted, the server's read allowlist is searched. | |
| query | Yes | Search query. Natural language for keyword mode; a literal string (or regex) for grep mode. REQUIRED. | |
| regex | No | Treat the query as a regular expression (grep mode only). Default: false. | |
| top_k | No | Maximum number of results to return (default: 10). | |
| recursive | No | Recurse into directories when collecting input files. Default: true. | |
| ignore_case | No | Case-insensitive matching (grep mode only). Default: false. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does well: it discloses that keyword mode needs the optional rank-bm25 dependency, that grep is stateless, that files are converted to text first, and that hit spans are marked with << >>. It omits permission/allowlist behavior (only in the schema) and any performance or size limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose then structured into modes and return shape; every section is scannable. The return dictionary listing is partly redundant given an output schema exists, which costs a bit of tightness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers purpose, mode tradeoffs, format support, and conversion behavior for a 7-parameter search tool. Because an output schema exists, the return-value enumeration is unnecessary, and allowlist scoping is left entirely to the schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description corroborates mode semantics and the format support, but adds little parameter meaning beyond what the schema already documents for paths, regex, top_k, and recursive.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('search a corpus of documents and return ranked snippets') and immediately contrasts it with the sibling read tool by explaining it returns passages rather than whole files. An agent can distinguish it from read_document_as_markdown without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use guidance for each mode: keyword for 'find the most relevant passages', grep for 'find every occurrence of X'. It does not explicitly say when to prefer this over list_workspace_files or when a direct read is better, but the mode routing is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
5 tool updates
v1.19.0- First observed
diff_documents - First observed
get_document_outline - First observed
list_workspace_files - First observed
read_document_as_markdown - First observed
search_documents
TDQS
Scored across 5 tools
Each tool has a clearly distinct purpose: full/section conversion, corpus search, document diffing, heading outline extraction, and workspace listing. Overlap between read_document_as_markdown and get_document_outline is limited to section navigation, but their outputs and use cases are clearly differentiated.
All tool names use snake_case and begin with a verb-like action, e.g. read_document_as_markdown, search_documents, diff_documents, get_document_outline, and list_workspace_files. The phrasing is predictable and easy to scan.
Five tools is well-scoped for a document reading/search/diff/outline surface. Each tool covers a meaningful operation without excessive fragmentation.
The set covers reading, searching, diffing, outlining, and file discovery, but get_document_outline explicitly references an edit_document tool that is not present. This creates a notable dead end for editing/navigation workflows, and there is no write/save or edit operation on the surface.
Maintenance
Related MCP Connectors
Documents to Markdown: PDF, DOCX, PPTX, XLSX, HTML. Scanned PDF pages read by AI.
Convert PDFs, Office docs, websites and audio into AI-ready Markdown, then search and ask your docs.
Convert PDF, Word, Excel and scanned documents to Markdown, tables and RAG chunks. OCR.
PDF, Word, PowerPoint, Excel, HTML, EPUB to clean Markdown for LLMs/RAG; OCR for scans; chunks.
Related MCP Servers
- AlicenseAqualityCmaintenanceMCP server for seamless document format conversion using Pandoc, supporting Markdown, HTML, PDF, DOCX (.docx), csv and more.1586MIT
- AlicenseAqualityCmaintenanceConverts documents between Markdown, PDF, DOCX, and HTML locally with AI-friendly Markdown output and secure file access.611 npmMIT
- AlicenseNot gradedqualityCmaintenanceProvides AI agents with comprehensive document parsing capabilities including PDF text extraction, OCR, HTML-to-markdown conversion, table extraction, and summarization, optimized for agent workflows.57 npmMIT
- AlicenseAqualityDmaintenanceConverts PDF, DOCX, PPTX, XLSX, CSV, and JSON into clean, compact, AI-ready Markdown, reducing tokens up to 65%.135 npmMIT