Skip to main content

MCP server

Twain includes a read-only Model Context Protocol server, so an AI assistant such as Claude can render, check, and summarise your Markdown and MDX documents using the same engine as the app, without a browser or a dev server.

Not yet published

The MCP server is built but not yet published to npm. For now, wire it up by pointing at the file in a checkout, using an absolute path, as shown below. It requires Node.js 18 or later.

What it does, and does not do

The server is read-only and works offline. It will not write to your files, run any code from a document, or make network requests. In particular, unlike the CLI, it does not probe remote links: doing so on documents handed to an automated agent would be a request-forgery risk.

Wiring it up

The server confines its reads to one or more root folders. Specify them with --root, or, for a client that finds environment variables easier to set than command arguments, with the colon-separated TWAIN_MD_MCP_ROOTS variable (consulted only when no --root is given). Always set at least one: with neither, the server falls back to whatever directory the client happened to launch it in, which can be an unexpectedly wide boundary.

For Claude Code:

claude mcp add twain-md -- node /absolute/path/to/twain-md/mcp/twain-md-mcp.mjs --root /absolute/path/to/your/docs

For Claude Desktop or any client that uses an mcpServers config block:

{
"mcpServers": {
"twain-md": {
"command": "node",
"args": [
"/absolute/path/to/twain-md/mcp/twain-md-mcp.mjs",
"--root",
"/absolute/path/to/your/docs"
]
}
}
}

You can pass --root more than once. The server only opens Markdown and MDX files inside a root, and refuses to read anything outside.

There are limits. A document larger than 4 MB is refused before it is read. twain_md_project stops after 5,000 files, saying so when it does, and descends at most ten directory levels. Any tool's text output is capped at 1 MB, with a note appended that gives the limit and the full size, so a truncated result is never mistaken for a whole one.

Set TWAIN_MD_MCP_DEBUG to any value to make the server log to standard error, which helps when a client will not connect. Standard output carries the protocol and is never used for logging.

The tools

Most tools take a path (absolute, or relative to the first --root) and an optional componentMap (docusaurus, mintlify, nextra, or fumadocs). twain_md_project takes a directory instead of a file, and twain_md_status takes no path at all.

ToolWhat it returns
twain_md_checkDiagnostics with line numbers: unknown components, missing images, broken local links, and links pointing outside the root. Takes an optional strict flag.
twain_md_projectA whole directory in one call: every Markdown and MDX file with its heading, link and task counts, the orphaned files (nothing links to them), broken cross-file links and anchors, and a task rollup. The one to call first to understand a docs set. For the full link graph, with per-file out-links and backlinks, use twain-md inventory --json.
twain_md_renderThe document as sanitised HTML: a body fragment by default, or, with output set to page, a whole page with the stylesheet inlined. Local images stay as links rather than being embedded, so it is not the fully self-contained export the CLI produces.
twain_md_outlineThe heading outline with depth, text and slug, plus the title and frontmatter.
twain_md_statsWord count, reading time, and counts of headings, local references, remote references, MDX imports, expressions, and unknown components. Links and images are counted together, not separately.
twain_md_reportThe same brief as the app's review report: your review notes, re-anchored to the current document, together with any rendering issues.
twain_md_statusWhat the running app is doing: the open documents, which of them have unsaved edits, which is frontmost, and whether the state is live or stale, so an agent avoids overwriting a file you are editing.

The server runs the same rendering pipeline as the app, so a document renders the same way in both. Two differences are worth knowing. Mermaid diagrams are drawn by the app's web view, not by the pipeline, so the server returns them as fenced code blocks. And twain_md_check does not validate the anchor fragment in a cross-file link, which the app does: for that, run twain_md_project over the folder.

twain_md_status reads a small file the app writes to its Application Support folder while it runs. The switch is Twain ▸ Settings… ▸ Agents ▸ Publish workspace state for local agents, on by default. The file lists which documents are open, which is frontmost, and whether each has unsaved edits: paths, counts and timestamps only, never any document content. It is refreshed every 15 seconds, and immediately when you open or close a document, and deleted when you quit or turn the setting off; a reader treats a file that has not been refreshed for 90 seconds as stale.

Direct edition only

twain_md_status reflects the app's live session, which only the direct download edition publishes. The Mac App Store edition runs sandboxed and cannot share that state, so on that edition the tool always answers that Twain is not running, even while it is. See Editions.