Convert Yuque Lakeboard (.lakeboard) and XMind (.xmind) mind maps into Markdown or a fresh .xmind. Comes as a CLI, a guided TUI, an MCP server and a drag-and-drop web UI (convert.ledring.dev). English | 简体中文
Open convert.ledring.dev to convert a file in your browser.
Or use the CLI without installing it globally (requires Node 20.12+):
npx -y lakeboard-converter convert ./map.xmind --format md --out-dir ./outRead Markdown to stdout without writing files:
npx -y lakeboard-converter read ./map.xmind --format mdStart the MCP server:
npx -y lakeboard-converter mcpgit clone https://github.com/FelixFangX/lakeboard-converter.git
cd lakeboard-converter && npm ci
npm run convert -- ./test-fixtures/test.lakeboard --format md --out-dir ./outExisting output files are never overwritten unless you pass --overwrite.
Live demo: https://convert.ledring.dev
The web UI runs entirely in your browser: files never leave your machine. It is self-hosted with no third-party requests, including fonts. Run npm run dev:web locally, or try the bundled Lakeboard and XMind samples.
With CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID set in your environment:
npm ci && npm run deploy:webwrangler.jsonc serves dist-web/ as static assets with single-page application fallback.
To deploy a preview build to lakeboard-convert-preview.<subdomain>.workers.dev instead (it has no custom domain), run npm run build:web && npx wrangler@3 deploy --env preview.
Requires Node 20.12+. The MCP server provides four tools:
convert(path, format?, sheet?, maxNodes?, maxDepth?): read one mind map asmd(default),json(topic tree) oroutline(compact indented text).from_markdown(markdown, output?, overwrite?, title?, maxNodes?): build an XMind file from a Markdown outline.convert_many(paths, format?, sheet?, maxNodes?, maxTotalNodes?, maxDepth?): read several mind maps with a shared node budget.inspect(path, sheet?): return file size and topic counts without content.
convert, convert_many and inspect are read-only. from_markdown writes only to the output path you pass.
Start the MCP server:
npx -y lakeboard-converter mcpClaude Desktop (claude_desktop_config.json):
{
"mcpServers": {
"lakeboard-converter": {
"command": "npx",
"args": ["-y", "lakeboard-converter", "mcp"]
}
}
}Cursor (.cursor/mcp.json or ~/.cursor/mcp.json):
{
"mcpServers": {
"lakeboard-converter": {
"command": "npx",
"args": ["-y", "lakeboard-converter", "mcp"]
}
}
}Codex CLI (~/.codex/config.toml):
[mcp_servers.lakeboard-converter]
command = "npx"
args = ["-y", "lakeboard-converter", "mcp"]Read a file from the CLI, or install the CLI globally:
npx -y lakeboard-converter read ./map.xmind --format md
npm i -g lakeboard-converterfrom_markdown accepts headings, nested lists, numbered lists, links, trailing code labels and > notes. Multiple sheets use repeated # Sheet / ## Root sections, each sheet heading containing exactly one root heading. Text before the first heading or list item is ignored with a warning.
To write a file, pass an absolute .xmind output path in an existing folder. No folders are created, and an existing file requires overwrite: true. Without output, the tool returns the file in structuredContent.base64. Markdown input is capped at 2 MB (UTF-8). maxNodes defaults to 2000 (1–50000); omitted topics are reported with truncated and warnings.
CLI build requires -o, resolves it to an absolute path, and uses --overwrite to allow replacement:
npx -y lakeboard-converter build plan.md -o plan.xmindconvert_many accepts 1–50 absolute paths. maxNodes applies per file; maxTotalNodes defaults to 10000 (1–200000) across the batch. Text contains the converted content; structuredContent contains per-file metadata and errors without content. Per-file errors do not fail the MCP call. CLI multi-file read returns per-file results and errors too, and exits 1 if any file fails. Use --max-total-nodes to change its total budget.
inspect returns bytes, node counts, depth and sheet metadata without content.
npx -y lakeboard-converter read a.xmind b.lakeboard --json
npx -y lakeboard-converter inspect a.xmind --jsonnpm run build
node /abs/path/lakeboard-converter/dist/cli.js mcp
node dist/cli.js read ./test-fixtures/test.lakeboard --format json --json
node dist/cli.js convert ./test-fixtures/test.xmind -f md --out-dir out --jsonEvery single-file CLI read JSON result has schemaVersion: 1, source, format, nodeCount, maxDepth and content. Errors with --json print {"error": "..."} and exit 1. See AGENTS.md for contributors.
All XMind sheets are included. A Lakeboard document has one sheet named after its root. Untitled XMind sheets use Sheet N. With multiple sheets, generic Markdown uses # <sheet title> followed by ## <root title> and the topic list. A single sheet keeps # <root title>. First-level list items start at column 0; deeper items use two more spaces. Notes align with the item's content column. Linked topics use [Title](url) directly, including headings, with brackets in titles escaped. Generic Markdown labels follow the title as code spans, such as - Split vendor chunk `P1` `tech-debt` . Outlines use - Title [P1, tech-debt] and a sheet heading before each outline when there are several sheets.
XMind-import Markdown uses one root list per sheet separated by a blank line, without headings. It omits labels so they do not become part of imported topic titles.
CLI read, convert and inspect accept --sheet <index|name> (1-based index or exact case-insensitive title). MCP accepts sheet as a string or integer. Selection is recorded in selectedSheet; unknown selections list available sheets.
lakeboard-converter read /absolute/path/map.xmind --sheet Roadmap --max-nodes 5000 --max-depth 3 --json
lakeboard-converter convert ./map.xmind --sheet 2 --format mdreadMindMap(file, format, options) and CLI read / MCP default to maxNodes: 2000; valid values are integers from 1 to 50000. Optional maxDepth is a nonnegative integer. The root is depth 0, so a root with children only has maxDepth: 1. Limits prune topics in pre-order across sheets. truncated and warnings report omitted topics. Increase the limits or select a sheet to read more. File conversion has no size limit. CLI read without --json and MCP text append warnings as > Note: ....
Use absolute paths for MCP: for convert, relative paths resolve against the server's working directory, which may differ from your terminal's. CLI read and MCP convert expand leading ~ or ~/ (also ~\ on Windows) using the home directory. Missing relative paths report the resolved path and server working directory.
CLI read --json keeps schemaVersion: 1 and the existing fields, adding sheets: [{ index, title, nodeCount, maxDepth }], optional selectedSheet: { index, title }, truncated, and warnings. Counts describe the selected input before truncation; maxDepth always counts the root as depth 0.
For format: "json", content is a topic tree for one sheet. Starting in 0.4.0, multiple sheets produce { sheets: [{ index, title, root: AgentTopic }] }. Limits apply to these trees as well as Markdown and outlines.
MCP convert returns one plain text block containing Markdown, outline text, or pretty-printed JSON trees. It also returns structuredContent with { schemaVersion, file, source, format, nodeCount, maxDepth, sheets, selectedSheet?, truncated, warnings }, validated against the tool's registered outputSchema. The text is no longer a JSON-stringified result envelope. Warnings are appended as a final > Note: ... line. Errors use isError: true with a clear message; the tool remains read-only.
Cursor CLI in headless mode (cursor-agent -p) needs --force (plus --approve-mcps) or the tool call is rejected.
.lakeboard ─┐ ┌─ renderGenericMarkdown → # root + nested list
├─ parse → MindMapDocument ─┼─ renderXmindMarkdown → root list per sheet for XMind import
.xmind ─────┘ (TopicNode tree) └─ renderXmind → minimal .xmind package
The seam is convertBuffer / convertFile in src/index.ts. Every input format parses into one MindMapDocument, so a new format needs one parser and no renderer changes. The CLI and TUI use that seam. The web UI uses its browser converter with shared fallback ID allocation; agents use readMindMap, readMindMaps, inspectMindMap and buildMindMap in src/agent.ts, exported from src/index.ts. Only buildMindMap writes, when given an explicit output path.
Keeps text, hierarchy, order, notes and links. All XMind sheets are read. Labels appear inline in generic Markdown and outlines. Drops styling, colour and layout. XMind 8 (legacy XML) isn't supported.
npm test # vitest specs at the convert, readMindMap and MCP seams, using test-fixtures/
npm run typecheck