MCP tools
anymd exposes four tools.
| Tool | Use it to |
|---|---|
outline | Navigate a heading tree, without a model or API key |
read | Turn a file, URL, or folder into Markdown |
search | Find text across files, folders, and URLs |
inspect | Go deeper on a PDF: render pages, crop regions, OCR, JSON structure, compare |
Only source is required for read and outline; only query is required for search; inspect requires operation and sources, with further arguments needed for the chosen operation as described below. Other options can be omitted to use their defaults. Nullable options do not need an explicit null, including read's transcript, download_asr_model, images and revisions, and search's case_sensitive and whole_word. The MCP input schemas reflect this distinction so clients can validate minimal calls before sending them.
outline
Get the document tree before reading a long document. PDF uses bookmarks when present, otherwise the headings detected by the layout engine. Word uses headings, PowerPoint uses slides, EPUB uses its EPUB 3 TOC or EPUB 2 NCX (chapters and headings when neither is present), and HTML and Markdown use headings. A document with no headings gets unit nodes. No model, vector database, or API key is needed.
| Argument | Type | Default | Description |
|---|---|---|---|
source | string | required | File path or http(s) URL |
format | "json" | "tree" | "json" | Machine-readable preorder nodes or an indented tree |
ocr | boolean or "auto" | "vlm" | "tesseract" | false | OCR image-only pages; use the same option in node reads. true inherits ANYMD_OCR; a named engine overrides it. |
images | "none" | "refs" | "none" | Embedded images; use the same option in node reads |
revisions | string | "markup" | Word revision mode; use the same option in node reads |
{ "source": "report.pdf", "format": "tree" }Each node has id, title, level, from, to, start, end, children, and path. from and to are inclusive 1-based units: pages, slides, sheets or chapters. start and end are a half-open UTF-8 byte range in the canonical Markdown body (not front matter): each unit's trimmed Markdown followed by two newlines, with <!-- unit label --> and two newlines before it for PDF or multi-unit files. The canonical body uses these extraction options: no OCR or embedded images by default, and Word revision markup. Node reads use these same defaults; regular reads without node keep automatic OCR and image refs. Pass matching ocr, images, and revisions options to outline and read when changing them. Search uses the default outline extraction options. children counts immediate children; nodes are in preorder and level gives heading depth. n1 is the document root; children are n1.1, n1.1.1, and so on. IDs are deterministic for an unchanged document and extraction options, not durable identifiers across edits. A PDF bookmark resolves to its page, so bookmarks sharing a page can overlap. TOCs may omit sections; text outside a section belongs to the nearest containing node, including the root.
Read a node with { "source": "report.pdf", "node": "n1.2" }. If it stops, repeat both source and node with the returned cursor. pages intersects the node's unit range. Search hits include a node id and title path for this same navigation.
read
Any file, URL, or directory → Markdown.
| Argument | Type | Default | Description |
|---|---|---|---|
source | string | required | File path, http(s) URL, or directory. A directory returns the list of readable files. |
node | string | – | Read the section id from outline; includes child sections. Unknown ids return an error. |
pages | string | all | Pages (PDF), slides, sheets, or chapters, e.g. "1-5,8" |
max_tokens | number ≥ 500 | 20000 | Token budget. Longer documents stop at a page/slide/chapter boundary and end with a cursor. |
cursor | string | – | Continue a previous read with the cursor from its last line |
ocr | "auto" | "vlm" | "tesseract" | boolean | automatic | Local OCR for images and scanned PDF pages. Auto uses explicitly installed models, otherwise tesseract. No automatic downloads. false disables; true enables the default runtime (ANYMD_OCR when set). See local OCR. |
revisions | "markup" | "accept" | "reject" | "markup" | Word tracked changes and comments. markup writes them as CriticMarkup with each change's author and date; accept or reject gives the text with every change accepted or rejected, without comments (see Word). A document with no tracked changes and no comments reads the same either way. |
images | "refs" | "none" | "refs" | Images embedded in PDFs, DOCX, PPTX and EPUB files. refs saves each meaningful raster image to the anymd cache and marks it in the Markdown (see Embedded images); none leaves images out. |
transcript | boolean | false | Transcribe audio/video with bundled Qwen3-ASR |
download_asr_model | boolean | false | Implies transcript; downloads Qwen3-ASR-1.7B Q8 weights (2.19 GB, SHA-256 verified) into the anymd cache when none is installed |
{ "source": "papers/attention.pdf" }---
source: papers/attention.pdf
title: Attention Is All You Need
pages: 15
showing: pages 1-9
---
<!-- page 1 -->
# Attention Is All You Need
…
<!-- page 8 -->
|Model|BLEU EN-DE|BLEU EN-FR|
|-|-|-|
|Transformer (big)|28.4|41.8|
…
<!-- Stopped at the 20000-token budget. Continue with cursor: "10", or pick pages, or raise max_tokens. -->Scanned pages
A PDF page with no text layer that images cover is a scan. When OCR does not read it (not configured, or ocr: false), read says so instead of returning an empty page. The page marker explains how to enable local OCR: run anymd setup ocr to opt into downloading the OCR engine and ~2 GB of model weights, then retry with ocr: true. Documents stay on your machine; setting ocr: true alone does not download models. The front matter lists scanned_pages: [3, 5] (page numbers shown in this response), and when every page shown is a scan the body opens with the same guidance. Pages with text are unchanged, and a page that OCR reads gets no marker.
Cursor and pagination
When a document is larger than max_tokens, read stops at a unit boundary (a page, slide, sheet, or chapter) and its last line names the cursor to continue from. Pass it back unchanged:
{ "source": "papers/attention.pdf", "cursor": "10" }A cursor is "<page>" or, when a single page was larger than the whole budget and had to be split, "<page>:<offset>". You can also skip the cursor and ask for exactly what you need with pages, or raise max_tokens.
Folders and URLs
read on a directory lists the readable files in it, so the agent can pick one or search them all. read on a web URL returns the main article only; see Formats.
search
Find text across files, directories, and URLs, one line per hit.
| Argument | Type | Default | Description |
|---|---|---|---|
query | string | required | Text to find |
sources | string[] | current directory | Files, directories (searched recursively, .gitignore respected), or URLs. Up to 256. |
mode | string | auto | auto: exact phrase, falling back to ranked passages when nothing matches. literal: exact phrase only. ranked: BM25 over the query words. |
glob | string | – | Only files matching this glob inside directories, e.g. "*.pdf" or "reports/**" |
case_sensitive | boolean | false | Match case |
whole_word | boolean | false | Match whole words |
max_results | number 1–500 | 20 | Maximum hits |
context_chars | number 0–1000 | 80 | Snippet context on each side |
{ "query": "masked language model", "sources": ["papers/"] }5 matches for "masked language model" (2 files, 31 sections searched)
### papers/bert.pdf (5)
- p.1: …by using a “**masked language model**” (MLM) pre-training objective, inspired by the Cloze task…
- p.2: …In addition to the **masked language model**, we also use a “next sentence prediction” task…In auto mode, a question like "how does bidirectional pretraining work" that matches nothing exactly still finds the right page through BM25-ranked passages.
inspect
Go deeper on a PDF. inspect returns JSON, for the cases where an agent needs geometry, images, or a diff rather than prose.
operation | What it does |
|---|---|
cite_check | (anymd Pro) Check a quoted passage at a page and bounding box, without a model or truth claim |
inspect | Page count, metadata, and per-page facts |
render_page | Render pages to PNG images |
extract_regions | Crop regions (bounding boxes) out of rendered pages |
ocr_pages | OCR pages with the local OCR provider |
analyze_regions | Send regions to a configured vision/region provider |
structure | Structured JSON read: document map, elements, geometry, tables, and reports |
compare | Page-level text diff between two local PDFs (sources[0] = before, sources[1] = after) |
| Argument | Type | Description |
|---|---|---|
operation | string | One of the operations above (required) |
sources | object[] | { path | url, pages?, regions? } per PDF. A region is { page, bounding_box: { left, bottom, right, top }, padding? }. |
profile | string | structure only: fast (default), quality, or research (adds safety, trust, and accessibility reports) |
scale | number 0.25–4 | Render scale for render_page / extract_regions |
max_pages | number 1–20 | Page cap for rendering and OCR |
max_regions | number 1–100 | Region cap |
max_pixels_per_page | number | Pixel cap per rendered page |
include_image | boolean | Include the rendered PNG in the response |
ocr | "auto" | "vlm" | "tesseract" | Engine for ocr_pages; omit to use the configured command provider. |
languages | string[] | Tesseract OCR languages, e.g. ["eng", "chi_tra"]; doc-VLM detects the language. |
timeout_ms | number | Time limit for external tools (1,000–300,000) |
max_output_chars | number | Output cap (1,000–1,000,000) |
Render page 3 at 2×:
{ "operation": "render_page", "sources": [{ "path": "report.pdf", "pages": [3] }], "scale": 2 }Get the structured JSON (elements with bounding boxes, tables, outline):
{ "operation": "structure", "sources": [{ "path": "report.pdf" }], "profile": "quality" }Diff two versions:
{ "operation": "compare", "sources": [{ "path": "contract-v1.pdf" }, { "path": "contract-v2.pdf" }] }