Six infra skills carry `version: 1.0.0` in frontmatter: project-bootstrap, setup-context7, task-status-wiki, using-context7, using-markitdown, wiki-maintainer. Bumped manually on SKILL.md edits; semver — MAJOR breaks contract, MINOR adds, PATCH wording. project-bootstrap gets a new Step 5.5 that writes .wiki/concepts/bootstrap-manifest.md per project — skill + version + role table read live from each delegated skill's frontmatter, not hardcoded. The file is overwritten on re-bootstrap; for history, git log. Why: when canonical layout for .wiki/ or .tasks/ changes, projects bootstrapped under the old version drift silently. The per-project manifest makes that drift debuggable instead of guesswork. Communication and discovery skills (caveman family, find-skills, active-platform) aren't versioned — their content is "good copy-paste" and snapshot mismatch isn't a layout problem. Wiki: .wiki/concepts/skill-versioning.md documents the convention; index.md and log.md updated. .tasks/STATUS.md tracks (a/b/c) progress. Setup/using split for wiki and tasks (commits b and c) follows. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
82 lines
5.7 KiB
Markdown
82 lines
5.7 KiB
Markdown
---
|
|
name: using-markitdown
|
|
version: 1.0.0
|
|
description: Use when capturing external content into a markdown-based knowledge base, wiki `raw/` directory, or any pipeline that must preserve the source's full text — for web pages, PDFs, DOCX/PPTX/XLSX, EPUB, CSV/JSON/XML, ZIP archives, images (with OCR/EXIF), audio (with transcription), or YouTube URLs. Also use when WebFetch returned an LLM-summarized version but the raw content is what's needed.
|
|
---
|
|
|
|
# using-markitdown
|
|
|
|
> Convert almost any URI to plain markdown using Microsoft's `markitdown` MCP server. Returns **raw textual content**, not an LLM summary.
|
|
|
|
## Tool
|
|
|
|
```
|
|
mcp__markitdown__convert_to_markdown(uri: string) → markdown string
|
|
```
|
|
|
|
`uri` accepts: `http://`, `https://`, `file://`, `data:`.
|
|
|
|
## Local files — Docker-mount caveat (READ FIRST)
|
|
|
|
The markitdown MCP usually runs in a **Docker container** with a single host directory bind-mounted. The container does **not** see your full host filesystem. `file://` URIs must point to the **in-container path**, not the host path.
|
|
|
|
1. Open `~/.claude.json` and find `mcpServers.markitdown.args`. Look for the `-v` flag — e.g. `-v C:\Users\vitya:/workdir` means host `C:\Users\vitya` is mounted at `/workdir` inside the container.
|
|
2. Translate the host path to the container path before forming the URI.
|
|
3. Forward slashes only inside the container path.
|
|
|
|
**Example.** Host file at `C:\Users\vitya\modular\heart-and-mask\.wiki\raw\foo.html` with mount `C:\Users\vitya:/workdir`:
|
|
|
|
```
|
|
file:///workdir/modular/heart-and-mask/.wiki/raw/foo.html
|
|
```
|
|
|
|
**Symptom of getting this wrong:** `[Errno 2] No such file or directory: '/c:/Users/...'` — the container literally tried to open the host-shaped path. The fix is path translation, not URL encoding.
|
|
|
|
**If the file falls outside the mount:** either copy it into the mounted tree, or extend the mount in `~/.claude.json` (a Claude restart is required for MCP changes to take effect — MCP servers are spawned at session start).
|
|
|
|
**Filenames.** Non-ASCII filenames (Cyrillic, etc.) inside `file://` URIs are flaky across the URL-encode → urllib → Docker → host-FS chain. Rename to Latin kebab-case **before** calling markitdown.
|
|
|
|
## When to use
|
|
|
|
- Filling a wiki's `raw/` directory from a URL or local PDF/DOCX.
|
|
- Datasheets, papers, blog posts, GitHub READMEs, Obsidian Web Clipper outputs, KiCad netlist exports — anything where the source text matters and lossy summarization would break later ingest steps.
|
|
- Any time the next step is "save the source verbatim before summarizing".
|
|
|
|
## When NOT to use
|
|
|
|
- You only need a *summary* or an *answer about* a page → use **WebFetch** (cheaper, runs through a small model, returns prose).
|
|
- The URI is GitHub/PR/issue/release content → use `gh` CLI (richer metadata, structured output).
|
|
- The URI is private/authenticated (GDocs, Confluence, Jira, Slack, Notion, `share.google/*` sign-in walls) → markitdown receives the **public-facing fallback page** (sign-in screen, cookie banner) and returns *that* as markdown. Verify the result is real content before saving.
|
|
- **The URI is a browser-rendered web page the user is already viewing** → ask the user to capture it via **Obsidian Web Clipper** (browser extension, runs Readability extraction client-side) and drop the resulting `.md` into `raw/`. Web Clipper output is dramatically cleaner than markitdown's HTML pass — no nav chrome, no sidebar history, no cookie banners — plus it carries YAML frontmatter (title / source URL / date) out of the box. Reserves markitdown for things browsers can't easily save (PDF, DOCX, PPTX, XLSX, EPUB, file:// resources). Note: rename the resulting file to Latin kebab-case before ingest (Web Clipper preserves the page `<title>` verbatim, often non-ASCII).
|
|
|
|
## Pattern: ingest a remote source into a wiki
|
|
|
|
```
|
|
1. mcp__markitdown__convert_to_markdown(uri="https://example.com/foo.pdf")
|
|
2. Inspect the head of the result. If it looks like a sign-in/cookie/consent page, abort — ask the user for an alternative (manual save, paste, authenticated MCP).
|
|
3. Write the result to .wiki/raw/<slug>.md (kebab-case, Latin only).
|
|
4. Register the new file in .wiki/raw/README.md.
|
|
5. Hand off to the wiki ingest workflow (creates sources/<slug>.md summary + entity/concept updates).
|
|
```
|
|
|
|
## Common gotchas
|
|
|
|
| Symptom | Cause | Fix |
|
|
|---|---|---|
|
|
| Output is a Google/Microsoft sign-in page in some random language | URI behind auth wall | Ask user to export the content manually (Save as PDF, copy-paste) and put it in `raw/` |
|
|
| Output is mostly nav/cookie banner text | Site is JS-rendered or anti-bot | Try the cached or print URL; or ask user for HTML export |
|
|
| Output lacks images / diagrams | Markdown is text-only by design | Save the original asset separately under `raw/assets/`; reference it from the `sources/` summary |
|
|
| Tool not available in session | MCP server not loaded | Confirm `mcp__markitdown__convert_to_markdown` appears via ToolSearch; load with `select:mcp__markitdown__convert_to_markdown` |
|
|
| Huge output (book-length) | Whole document converted in one call | Save raw, then summarize *from the saved file* — do not hold the entire markdown in working context |
|
|
|
|
## Quick contrast with WebFetch and Web Clipper
|
|
|
|
| | markitdown | WebFetch | Obsidian Web Clipper |
|
|
|---|---|---|---|
|
|
| Returns | raw markdown of the source | LLM answer about the source | Readability-extracted markdown with YAML frontmatter |
|
|
| Use for | PDF / DOCX / non-browser-friendly | one-shot Q&A | any browser-viewable web page |
|
|
| Auth-aware | no | no | **yes** (uses the user's logged-in browser session) |
|
|
| Chrome / nav stripped | partial (still verbose) | n/a (model picks signal) | **yes** (clean) |
|
|
| Handles PDFs / DOCX | yes | text-only HTML extraction | no (web pages only) |
|
|
| Who triggers it | Claude | Claude | the user (manual click) |
|