mindnode-mcp
Enables reading and writing MindNode mind maps directly by parsing their on-disk format, without AppleScript or Shortcuts.
README
mindnode-mcp
English | 日本語
An MCP server that lets an AI assistant
(Claude, etc.) read and write your MindNode mind maps
directly — by parsing the .mindnode file format itself. No AppleScript, no
Shortcuts, no export/import dance.
Ask your assistant to "read my project map", "add these three ideas under Marketing", "connect the API node to the Auth node", or "turn this outline into a new mind map" — and it operates on the real files MindNode syncs.
Why this exists: MindNode dropped its AppleScript dictionary, and its Shortcuts/URL-scheme automation is thin. But a
.mindnodedocument is just a package whosecontents.xmlis an Apple binary plist — a clean recursive node tree. Read/write that, and you get full programmatic control.
Requirements
- macOS with MindNode installed (format version 9 — current MindNode releases)
- Python 3.11+ and uv
- An MCP client (e.g. Claude Code)
Install
git clone https://github.com/masamitsu-konya/mindnode-mcp.git
cd mindnode-mcp
uv sync
Register it with Claude Code (user scope = available everywhere):
claude mcp add --scope user mindnode -- uv --directory "$PWD" run mindnode-mcp
Then start a new session and run /mcp (or claude mcp list) to confirm it
shows mindnode ✔ Connected.
By default it finds your MindNode documents in the iCloud container
automatically. Point it elsewhere with the MINDNODE_DOCS_DIR environment
variable (a local library, or a fixture folder for testing).
Usage
Talk to your assistant in plain language — it picks the right tool. Examples:
| You say | What happens |
|---|---|
| "List my mind maps" | list_documents → names + dates, newest first |
| "Read my Project Plan map" | read_document → the full node tree as JSON |
| "Search all my maps for 'pricing'" | search_nodes → every matching node + its document |
| "Add 'Hire a designer' under the Team node in Roadmap" | add_node |
| "Connect 'Frontend' to 'API' with the label 'calls'" | add_connection |
| "Tag the 'Launch' node as #urgent" | add_tag (creates the tag if new) |
| "Mark 'Ship v1' as done" | set_task |
| "Attach ~/Desktop/wireframe.png to the Design node" | attach_image |
| "Make a new map 'Q3 Goals' with branches Sales, Product, Hiring" | create_map |
Nodes can be referenced by their text (a case-insensitive substring is enough)
or by their exact id (ids come back from read_document).
Tools
| Tool | Kind | What it does |
|---|---|---|
list_documents |
read | All .mindnode files, newest first |
read_document |
read | Mind maps as {id, text, note?, task?, tags?, attachment?, children?} trees, plus connections and the document's tag list |
search_nodes |
read | Substring search over node text + notes, in one document or all |
add_node |
write | Add a node under a parent (by id or text), with optional note |
add_connection |
write | Cross-link two existing nodes with an optional label and arrow direction |
add_tag / remove_tag |
write | Tag / untag a node (tags are document-wide and auto-created) |
set_task |
write | Turn a node into a checkbox task and set done / todo |
attach_image |
write | Attach a local image to a node (copied into the package's resources/) |
create_map |
write | Create a new .mindnode from a title + (optionally nested) outline |
Connections (cross-links)
Free links between any two nodes, independent of the parent/child tree (stored
at canvas.crossConnections[]). add_connection(document, start, end, label?, direction?) — direction ∈ forward (default) / backward / both / none.
read_document returns each as {id, start_id, end_id, start_text, end_text, direction, label?}.
Tags, tasks, attachments
read_document surfaces these per node (and lists all tag names at the top):
- Tags — normalized:
canvas.tags[]defines{tagID, name, color},node.tags[]references tagIDs.add_tagauto-defines a tag of that name if it doesn't exist, then attaches it (idempotent). - Tasks —
node.task = {state, uuids}, wherestate1 = todo, 2 = done.set_task(document, node, done)toggles it. - Attachments (images) —
node.attachment = {fileName, size, tintKind, type}; image bytes live inresources/<fileName>.attach_imagecopies the file in and links it, clamping display width to 300px (matching MindNode).
How it works
A .mindnode document is a package directory. Its contents.xml — despite
the extension — is an Apple binary plist holding the mind map (format
version 9):
canvas.mindMaps[].mainNode # root node of each map
├─ nodeID # UUID
├─ title.text # the node's text, stored as small HTML
├─ note / task / tags / attachment
└─ subnodes[] # children (same shape, recursive)
canvas.crossConnections[] # free links between nodes
canvas.tags[] # tag definitions
The server reads and writes this with Python's standard plistlib, so it needs
no third-party plist libraries. Node text round-trips through a minimal
HTML encode/decode (with proper escaping).
Write safety
These tools mutate your real files, so every write:
- backs up
contents.xmlto a timestamped.bak-*first, - writes to a temp file then atomically replaces it (no partial writes),
- preserves keys it didn't author (styling, layout, print info), and
- drops the stale QuickLook preview so it regenerates.
create_map clones an existing document as a structural skeleton (keeping all
opaque auxiliary files valid) and overwrites only the node tree.
Caveat — document open in MindNode. Writes go straight to disk. If MindNode (or another device via iCloud) has the same document open, its next autosave can clobber the change, or you may get an iCloud conflict copy. Close the document in MindNode before writing, or reopen it afterwards to pick up the edit. Backups make this recoverable, but it's cleaner to avoid.
Development
uv run python tests/smoke.py
The smoke test exercises reads against your real documents (read-only) and all writes against throwaway temp copies — it never modifies your actual maps. It also asserts that generated structures (nodes, connections, tags, tasks, image attachments) match the schema of real MindNode files key-for-key.
Status & roadmap
- [x] Read — list / read / search
- [x] Write — add_node / create_map
- [x] Connections / cross-links — read + add_connection
- [x] Tags, tasks, image attachments — read + write
- [ ] Non-image attachments (links, stickers)
- [ ] Tag color palette / rename, task removal
- [ ] Connection waypoint editing
License
MIT © 2026 Masamitsu Konya
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。