mcpField
T
to-markdown

to-markdown

github.com/mathews-tomDocuments337102 installsUpdated 2d ago
Repository

About to-markdown

to-markdown is a skill for converting files, URLs, and HTML into Markdown with MarkItDown. It guides URL fetching and conversion, with checks for extraction quality and known limitations.

Key features

  1. 01Convert files and HTML to Markdown
  2. 02Fetch static pages with trafilatura
  3. 03Fetch rendered or authenticated pages with Playwright
  4. 04Handle YouTube transcript extraction
  5. 05Check output structure and extraction quality

Use cases

  1. 01Turn a PDF into Markdown
  2. 02Extract article content from a URL
  3. 03Convert multiple files into separate Markdown outputs

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/mathews-tom/armory --skill to-markdown

After installing, type/to-markdownin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

evals/
cases.yaml
references/
fetch.md
formats.md
install.md

Details

From the project README

To Markdown

Convert any file or URL to clean Markdown using MarkItDown as the conversion engine, with a lightweight fetch layer for URLs.

Reference Files

FilePurpose
references/formats.mdPer-format handling notes, internal engines, known gaps
references/fetch.mdURL fetch layer: trafilatura + Playwright strategies
references/install.mdDependency install guide for all variants

Decision Tree

Determine the input type before touching any tool:

Input type?
  Local file path        -> markitdown directly
  URL
    YouTube URL          -> markitdown directly (transcript extraction built-in)
    Static page          -> trafilatura fetch -> markitdown on HTML result
    JS-rendered / auth   -> Playwright fetch -> markitdown on result
  Pasted HTML string     -> markitdown directly on string

Do not use web_fetch or WebFetch for URLs — route through the fetch layer described in references/fetch.md to preserve the conversion pipeline.

Core Conversion Workflow

Step 1: Ensure dependencies
uv pip show markitdown || uv pip install 'markitdown[all]' trafilatura

See references/install.md for selective installs and full dependency table.

Step 2: Convert
from markitdown import MarkItDown

md = MarkItDown(enable_plugins=False)
result = md.convert("path/to/file.pdf")
print(result.text_content)
Step 3: Workflow
  1. Detect input type (file path, URL, raw HTML).
  2. If URL, run fetch layer first (see references/fetch.md).
  3. Run markitdown conversion on the local file or fetched content.
  4. Post-process if needed (strip boilerplate, trim to main content).
  5. Write output or return inline per output conventions below.

Output Conventions

ContextOutput behaviour
Single file, user wants fileWrite <input_stem>.md to same directory
Single file, inline requestReturn Markdown in conversation
Batch (multiple files)Write each to <stem>.md, summarise what was produced
URLWrite <slug>.md to current directory or return inline
Piped into another workflowReturn result.text_content string only

Default: "convert this file" -> write a file. "Read this" or "what does this say" -> return inline.

Output Example

Source (two-column PDF with a table):

Annual Report 2024                    Financial Highlights
Revenue grew 12% year-over-year...    | Metric   | 2023  | 2024  |
                                      | Revenue  | $4.2B | $4.7B |
                                      | EBITDA   | $1.1B | $1.3B |

Converted Markdown:

# Annual Report 2024

Revenue grew 12% year-over-year...

## Financial Highlights

| Metric  | 2023  | 2024  |
| ------- | ----- | ----- |
| Revenue | $4.2B | $4.7B |
| EBITDA  | $1.1B | $1.3B |

Multi-column layouts merge into linear flow. Tables are preserved as Markdown tables. Headings are inferred from font size/weight.

LLM Image Description (opt-in)

Markitdown supports an llm_client for image description in PPTX and image files. Never enable by default — it incurs cost, latency, and unexpected API calls. Prompt the user first: "This file contains images. Do you want me to use Claude to describe them? This will make additional API calls."

import anthropic
from markitdown import MarkItDown

client = anthropic.Anthropic()
md = MarkItDown(llm_client=client, llm_model="claude-sonnet-4-6")
result = md.convert("presentation.pptx")

Opus 4.7 vision ceiling: Opus 4.7 accepts images up to 2,576 pixels on the long edge (~3.75 MP), roughly 3× prior Claude models. When routing image-heavy documents through llm_model="claude-opus-4-7", retain higher-resolution source images rather than pre-downsampling — text in screenshots and diagrams that previously required OCR may now be readable directly.

Error Handling

SeverityConditionAction
TerminalUnsupported format (no converter exists)Report to user immediately; do not retry
TerminalPassword-protected Office fileReport to user; no programmatic workaround
TerminalFile not found / path invalidReport exact path; ask user to verify
RecoverEmpty output from PDFLikely scanned — escalate to OCR path in references/formats.md
RecoverMissing optional dependency (e.g. playwright)Install the dependency, then retry the conversion
RecoverURL fetch returns paywall pageReport fetch limitation; do not retry or attempt bypass
Recovertrafilatura returns emptyEscalate to Playwright fetch strategy per references/fetch.md
result = md.convert(path)
if not result.text_content.strip():
    raise ValueError(f"No text extracted from {path}. See references/formats.md for OCR options.")

Never silently return empty Markdown. Surface the failure with the severity and a pointer to the relevant reference file.

Known Gaps and Escalation

  • HTML fidelity: markitdown uses html2text internally — complex layouts lose structure. For high-fidelity HTML conversion where DOM structure matters, suggest Turndown via Node subprocess.
  • Hard paywalls: The fetch layer returns the regwall page, not the content. This is a fetch limitation, not a conversion problem.
  • Scanned PDFs (image-only, no text layer): markitdown returns near-empty output. Escalate to OCR workflow (Azure Document Intelligence or Tesseract). See references/formats.md.
  • Protected Office files: Password-protected DOCX/XLSX will fail. Inform the user.

Calibration Rules

  1. Converted output must contain at least 10 words per page of source document. Below this threshold, treat as empty extraction and escalate per the error handling table.
  2. Tables in the source must appear as Markdown tables in the output — if a table is present in the original but missing in the conversion, flag it to the user.
  3. Heading hierarchy from the source document must be preserved (H1 > H2 > H3). Flat output with no headings from a structured document indicates a conversion quality issue.
  4. For URL conversions, output must not contain navigation elements, cookie banners, or footer boilerplate. If present, re-run through trafilatura with include_tables=True to strip boilerplate.
  5. Multi-sheet XLSX must produce one clearly labeled section per sheet. Missing sheets indicate a partial conversion — report which sheets were extracted.

Limitations

  • No paywall bypass. Document it, don't attempt it.
  • No Turndown integration built-in. Different runtime (Node.js).
  • No scheduled/batch crawling. One conversion per invocation.
  • No output format other than Markdown.
  • Auto-generated YouTube captions may contain errors for technical terms.
  • Scanned PDFs require external OCR — markitdown alone returns empty output.

Comments

Markdown supported