mohganji/mindmapio-mcp · Archived

mindmapio

Drive Mindmap.io maps directly over its HTTP node API: list and read maps, build node subtrees with client-minted ids, and run the generative node operations (submit, auto-expand, retry, interrupt). Use when the user wants to create or grow a mindmap.io map, run prompts on nodes, fan a node out into follow-ups, or read a map/branch programmatically without the MCP server.

First seen Jun 28, 2026

Installation

$ npx skills add mohganji/mindmapio-mcp --skill mindmapio

Stronger alternatives

This repository is archived — consider an actively maintained alternative.

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

License LICENSE
Default branch main
Open issues 0
Status Archived

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 10,957 B
  • docs SUMMARY.md 391 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 6 installs

SKILL.md

Drive Mindmap.io maps via the node API

This skill teaches you to drive Mindmap.io maps by calling its HTTP node API directly. It is the alternative to the mindmapio-mcp server: same primitives, no MCP client required, just authenticated HTTP calls.

The API is the authoritative contract — match the shapes in the examples exactly. A map's data is a tree of nodes, the same shape every read returns, with camelCase fields like nodeType and parentId. The single-node write endpoints take their own snakecase fields like nodetype.

Setup

Every call sends a personal access token as a bearer header. Generate the token once in Mindmap.io: settings → API access. It acts as its user; regenerating it immediately revokes the old one.

export MINDMAP_API_TOKEN="<your personal access token>"
export MINDMAP_API_BASE_URL="https://mindmap.io"   # optional, this is the default

Never print, echo, or commit the token. Send it on every request:

Authorization: Bearer $MINDMAP_API_TOKEN

A reusable curl alias for the examples below:

mm() { curl -sS -H "Authorization: Bearer $MINDMAP_API_TOKEN" \
  -H "Content-Type: application/json" "$MINDMAP_API_BASE_URL$@"; }

Primitives

IDs are unprefixed everywhere. You mint node ids client-side, so you can reference a node id you chose before it is persisted.

Node content is sent as messages: a UIMessage array (Vercel AI SDK shape). Each message is {role, parts} and each part is {type: "text", text}. A node's body — a prompt, a data node, a note's source turn — is a single user message with one or more text parts.

Read

List maps — GET /api/mindmaps → array of {id, title, kind, createdat, updatedat}, newest first.

mm /api/mindmaps

Read a full map — GET /api/mindmaps/{id} → {id, title, kind, user_id, data} where data is {rootId, selectedId, nodes} and nodes maps id → node.

mm /api/mindmaps/MAP_ID

Read one node — GET /api/mindmaps/{mapId}/nodes/{nodeId} → a SubtreeNode {node, children} with children: []. The node's own children array still lists child ids for navigation.

mm /api/mindmaps/MAP_ID/nodes/NODE_ID

Read a subtree — GET /api/mindmaps/{mapId}/nodes/{nodeId}/subtree?depth=N → nested SubtreeNode. Omit depth for the full subtree; 0 returns just the node, 1 the node and its immediate children.

mm "/api/mindmaps/MAP_ID/nodes/NODE_ID/subtree?depth=2"

Structural write

Create a map — POST /api/mindmaps with {title?, kind?, data?}. Pass an initial data tree with a root node so later node primitives have a parent to hang from. → 201 {id, title?, kind?}.

Each node has a type. A data node holds content you keep — a topic, reference text, a note. A prompt node is a question you run against a model with submit. The root usually holds the map's subject, so make it a data node:

mm /api/mindmaps -X POST -d '{
  "title": "My research map",
  "data": {
    "rootId": "root",
    "nodes": {
      "root": {
        "id": "root",
        "nodeType": "data",
        "messages": [{ "role": "user", "parts": [{ "type": "text", "text": "Topic" }] }],
        "children": []
      }
    }
  }
}'

Create a node — POST /api/mindmaps/{mapId}/nodes with {nodeId, parentId, position?, data?}. nodeId must be unique within the map; mint a uuid yourself. data may carry {messages, note, node_type}, where messages is the node's content as a UIMessage array. The node is born structural (a draft); running it is a separate generative call. → 201 full node.

mm /api/mindmaps/MAP_ID/nodes -X POST -d '{
  "nodeId": "q1",
  "parentId": "root",
  "data": {
    "messages": [{ "role": "user", "parts": [{ "type": "text", "text": "What is X?" }] }],
    "node_type": "prompt"
  }
}'

A data or note node carries its body the same way — a user message in messages:

mm /api/mindmaps/MAP_ID/nodes -X POST -d '{
  "nodeId": "d1",
  "parentId": "root",
  "data": {
    "messages": [{ "role": "user", "parts": [{ "type": "text", "text": "Reference notes for the branch." }] }],
    "node_type": "data"
  }
}'

Update a node — PATCH /api/mindmaps/{mapId}/nodes/{nodeId} with any subset of {messages, note, nodetype, iscollapsed, modelprovider, modelid}. Send messages to replace the node's content. Pure tree mutation, no LLM call, no metering. → 200 {success}.

mm /api/mindmaps/MAP_ID/nodes/q1 -X PATCH -d '{
  "messages": [{ "role": "user", "parts": [{ "type": "text", "text": "What is X, precisely?" }] }]
}'

Delete a node — DELETE /api/mindmaps/{mapId}/nodes/{nodeId}. Cascades to descendants and reindexes siblings. The root cannot be deleted. → 200 {success}.

mm /api/mindmaps/MAP_ID/nodes/q1 -X DELETE

Delete a map — DELETE /api/mindmaps/{id} → 200 {success}.

mm /api/mindmaps/MAP_ID -X DELETE

Generative

Submit a node — POST /api/mindmaps/{mapId}/nodes/{nodeId}/submit with optional {prompt?, modelId?}. Runs the LLM and blocks until no ancestor is still generating, then returns the completed node {nodeId, status, messages}. prompt supplies the user text when the node has none yet; omit it to run the stored text. modelId overrides the house model. Metered; over budget returns 429.

mm /api/mindmaps/MAP_ID/nodes/q1/submit -X POST -d '{}'

Auto-expand a node — POST /api/mindmaps/{mapId}/nodes/{nodeId}/auto-expand with optional {count?, direction?} (count 1–4, default 2). Generates follow-up prompts as queued child nodes and returns {nodeId, childIds}. One level only — it does NOT run the children. Metered; over budget 429.

mm /api/mindmaps/MAP_ID/nodes/q1/auto-expand -X POST -d '{"count": 3}'

Retry a node — POST /api/mindmaps/{mapId}/nodes/{nodeId}/retry?force=true with optional {prompt?, modelId?}. Clears the prior error and re-runs, returning {status, messages}. Retrying an expand node that already has children returns 409 unless force=true (which deletes those children first). Metered; over budget 429.

mm "/api/mindmaps/MAP_ID/nodes/q1/retry?force=true" -X POST -d '{}'

Interrupt a node — POST /api/mindmaps/{mapId}/nodes/{nodeId}/interrupt. A generating or queued node flips to interrupted with partial output preserved. Idempotent; not metered. → 200 final node.

mm /api/mindmaps/MAP_ID/nodes/q1/interrupt -X POST

Publish

Publishing flips a map from private to public and mints a non-guessable public id (slug). Owner-only; not metered. This is how you turn a map you built into a shareable link or an iframe embed.

Publish a map — POST /api/mindmaps/{mapId}/publish. Mints a public id if the map has none (re-publishing reuses the existing one) and flips visibility to public. → {publicId}.

mm /api/mindmaps/MAP_ID/publish -X POST
# → {"publicId":"G_N4wWD2TiUIoHuO"}

Unpublish a map — DELETE /api/mindmaps/{mapId}/publish. Flips back to private, which immediately 404s every public/embed link (the revoke mechanism). The public id is retained for re-publishing. → {success:true}.

Build the shareable links from the publicId. The query frames the map on first paint: node=root, the semantic zoom level (full default; keyword/phrase open a large reference map zoomed-out so its whole shape shows at a glance), and cz, the canvas-zoom percent.

Viewer link:  https://mindmap.io/app/<publicId>?node=root&zoom=<level>&cz=<percent>
Iframe embed: https://mindmap.io/app/embed/<publicId>?node=root&zoom=<level>&cz=<percent>

So a zoomed-out reference map embeds as https://mindmap.io/app/embed/G_N4wWD2TiUIoHuO?node=root&zoom=keyword&cz=90, and a normal example/template map as …?node=root&zoom=full&cz=100.

Via the MCP server, publish_map does both steps in one call — it publishes
and returns {publicId, viewerUrl, embedUrl} already framed by the zoom/cz
you pass. unpublish_map reverses it.

Pattern: agent-drives-recursion for auto-expand

Auto-expand does NOT recurse and does NOT run the children it creates — it only queues one level of follow-up prompts. You drive the recursion: call auto-expand, then submit each returned child yourself, and recurse if you want to go deeper.

# 1. Fan a completed node out into queued follow-up children.
resp=$(mm /api/mindmaps/MAP_ID/nodes/q1/auto-expand -X POST -d '{"count": 3}')

# 2. Submit each returned child to run it (each blocks on its ancestors).
echo "$resp" | jq -r '.childIds[]' | while read -r child; do
  mm "/api/mindmaps/MAP_ID/nodes/$child/submit" -X POST -d '{}'
done

# 3. To go deeper, auto-expand a child and repeat. Choose your own depth/breadth
#    budget — there is no server-side recursion or fan-out cap beyond count 1-4.

Submit blocks until ancestors finish, so it is safe to submit children in sequence; the generation gate guarantees each child sees complete parent context.

Errors

Responses carry {error} on failure. Common statuses: 401 (no/revoked token), 403 (not the token user's map), 404 (missing map/parent/node), 400 (malformed, or deleting the root), 409 (duplicate node id, or re-expanding without force), 429 (over budget — body carries an upgrade/buy-credits CTA). On 429, stop generating and surface the CTA rather than retrying blindly.

Hello world

# create a map whose root is a data node holding the topic
MAP=$(mm /api/mindmaps -X POST -d '{"title":"Hello","data":{"rootId":"root","nodes":{"root":{"id":"root","nodeType":"data","messages":[{"role":"user","parts":[{"type":"text","text":"Hello"}]}],"children":[]}}}}' | jq -r '.id')
# add a prompt node under the root, then run it
mm /api/mindmaps/$MAP/nodes -X POST -d '{"nodeId":"q1","parentId":"root","data":{"messages":[{"role":"user","parts":[{"type":"text","text":"Say hi in one word."}]}],"node_type":"prompt"}}'
# run it and read the answer back
mm /api/mindmaps/$MAP/nodes/q1/submit -X POST -d '{}'

For the MCP-server route instead, see the project README.