Skip to main content
Glama

Principle

The MCP lives on the consumer side, not on the Axomind server. It contains no business logic — it makes HTTP POST requests to bot_api.php and returns the JSON. All security (auth, rate limiting, IP bans, bots @> checks) stays on the PHP side.

AI (any MCP client — Hermes, Claude, Cursor, etc.)
  → MCP server Python (FastMCP)
    → HTTP POST → bot_api.php
      → PHP does the work (auth, DB, WS notify)
    ← JSON response
  ← MCP tool result → AI

Related MCP server: telegram-api-mcp

What this MCP does

This server exposes 26 bot tools that let an AI interact with Axomind resources where a bot is assigned:

  • Mindmap (10 tools) — read, create, update, delete nodes; manage styles

  • Messenger (4 tools) — send, read, update, delete bot messages

  • Planning (9 tools) — list activities, manage assignments, read time slots

  • Tree (3 tools) — scan local directories and inject them as mindmap structures

Installation

uv pip install -e .

Dependencies: mcp (official SDK), httpx (HTTP client).

Configuration

Copy .env.example to .env and fill in your bot credentials:

cp .env.example .env

Required variables

Variable

Description

AXOMIND_BASE_URL

URL to bot_api.php on the Axomind server (e.g. https://quantive-studio.fr/app/bot_api.php)

AXOMIND_BOT_ID

Bot ID (from Axomind UI → bot management)

AXOMIND_BOT_KEY

Bot access key (generated when creating the bot in the UI)

Optional

Variable

Default

Description

AXOMIND_TIMEOUT

30

HTTP timeout in seconds

AXOMIND_ENV_FILE

—

Explicit path to .env file (recommended for production)

How to get bot credentials

  1. Open Axomind desktop app

  2. Go to bot management

  3. Create a new bot → you get a Bot ID and a Bot access key

  4. Assign the bot to the resources you want it to access (mindmaps, activities, conversations)

  5. Put the credentials in your .env file

The bot can only access resources where its ID is listed in the bots JSONB column — this is enforced server-side by Axomind.

Available tools (26)

Mindmap (10) — bot API

Tool

Description

Destructive?

list_mindmaps

List mindmaps where the bot is assigned (metadata only)

No

get_mindmap

Read a mindmap (metadata + all nodes). ⚠️ Response can exceed 2 MB for 60+ nodes with descriptions

No

get_mindmap_summary

Compact summary — node count, titles, structure, has_description. Context-safe, no descriptions or styles

No

get_node_description

Read a single node's description by order_index (capped at ~4 KB). Use after get_mindmap_summary

No

sync_nodes

Replace ALL nodes (full JSON, ~25 fields per node). ⚠️ DESTRUCTIVE — sends 1 node → deletes the other 98

⚠️ Yes

add_nodes

Append nodes to an existing mindmap (simplified format). Reads existing, appends, syncs

No

replace_mindmap

Replace all nodes (simplified format). Validates hierarchy before sending

⚠️ Yes (validated)

update_node

Update a single node — all fields supported (title, descriptions, parent, style, positions, free_links). Reads full mindmap, patches one node, syncs back. The algorithm handles the JSON, not the AI

No (safe)

delete_node

Delete a node + its subtree. Cleans free_links pointing to deleted nodes. Root node (parent=0) cannot be deleted. The algorithm handles the JSON, not the AI

No (safe)

update_nodes_style

Update style fields on multiple nodes (color, bold, size_box, etc.). Reads, patches, syncs back

No (safe)

Safe node modification — the algorithm handles the JSON

update_node and delete_node are the safe way to modify a mindmap. They read the full mindmap, apply targeted changes to specific nodes, and sync everything back. Other nodes (including their descriptions) are preserved untouched.

The AI never builds the full node JSON — it passes only the fields to modify, and the algorithm does the rest:

// update_node: rename node 33
{"title": "messenger.md test"}

// update_node: change description (markdown → Quill Delta conversion is automatic)
{"descriptions": "# Module Messenger\n\nThis module handles..."}

// update_node: re-parent with cycle detection
{"parent": 2}

// update_node: change style + propagate to children
{"color": "0xFFFF6F91", "bold": true, "is_write_children": true}

// delete_node: just the order_index, no JSON at all
// delete_node(id_mindmap=100, order_index=33)

Validations enforced by the algorithm (not by the AI):

  • Self-reference: parent == order_index → rejected

  • Cycle detection: new_parent is a descendant of order_index → rejected

  • Parent must exist in the mindmap

  • Root node (parent=0) cannot be deleted

  • free_links cannot target self, all targets must exist

  • size_box must be 0–11

Simplified format for replace_mindmap / add_nodes

The AI provides a compact JSON — the MCP auto-expands ~25 default fields:

[
  {"title": "Root", "parent": 0, "color": "0xFFF0BA6D", "size_box": 2, "bold": true},
  {"title": "Category A", "parent": 1, "color": "0xFF7A8FF5", "size_box": 1, "line_style": 1},
  {"title": "Item 1", "parent": 2},
  {"title": "Item 2", "parent": 2, "color": "0xFFFF6F91", "free_links": [3]}
]

Fields:

  • title (required) — node title

  • parent (required) — order_index of the parent node (0 = root, 1 = first node)

  • color (optional) — hex color (default: 0xFF7A8FF5)

  • pos_x, pos_y (optional) — canvas position (default: 0)

  • size_box (optional) — 0=normal, 1=category, 2=root (default: 0)

  • bold, italic, underline (optional) — text style

  • line_type (optional) — 0=curve, 1=rounded, 2=square

  • line_style (optional) — 0=solid, 1=dashed

  • stroke_width, dot_radius, radius, border_size, label_size (optional)

  • icon_id (optional) — icon ID

  • active_bg_colors (optional) — active background colors

  • descriptions (optional) — descriptive text (markdown → Quill Delta)

  • free_links (optional) — list of order_index for free links between nodes

  • spacing_h, spacing_v (optional) — spacing multipliers (0-10)

  • is_write_children (optional) — propagate style to children (one-shot)

UID and order_index are assigned automatically. add_nodes reads the existing mindmap and appends after existing nodes.

Tree / Directory scanning (3) — local + bot API

These tools scan the local filesystem to build mindmap structures from directory trees.

Tool

Description

HTTP?

tree_scope

Compact telemetry of a directory (title, type, size, hierarchy). Does NOT read file content. Use before injection to get a reference node count

No (local)

inject_directory_to_mindmap

One-shot scan + read + inject — scans the directory, reads .md/.markdown/.txt files, converts to Quill Delta, and syncs everything into the mindmap. Returns a compact summary for validation

Yes (sync_nodes)

tree_to_mindmap

Scan → JSON nodes (simplified format, no file content). Ready for replace_mindmap or add_nodes

No (local)

Workflow: inject a directory into a mindmap

1. tree_scope(root_path, root_title) → reference count (1 root + N dirs + M files)
2. inject_directory_to_mindmap(root_path, root_title, id_mindmap) → scan + read + Quill Delta + sync
3. Compare the returned summary (total_nodes, descriptions_filled, errors) with tree_scope count
4. If they match and errors is empty → injection validated. DONE.
  • Only .md, .markdown, .txt files are read and converted to Quill Delta

  • Files > 500 KB and non-text formats (.docx, .pdf, images) get nodes with empty descriptions

  • Hidden files and VCS directories (.git, node_modules, __pycache__) are skipped automatically

  • Never call get_mindmap to verify an injection — the summary + tree_scope count are sufficient

Messenger (4) — bot API

Tool

Description

send_message

Send a message (targeted or broadcast to all conversations)

get_messages

Read bot messages in a conversation

update_message

Update a bot message

delete_message

Delete a bot message

Activity / Planning (9) — bot API

All planning tools use the bot API (bot_api.php → api_activity route). The bot operates as the bot owner's user_id — the same authentication chain as add_assignment / update_assignment / delete_assignment.

High-level tools (prefer these)

Tool

Description

create_assignment

Create an assignment (single-day or recursive) with human-friendly params (dates, hours, weekday names). Builds the JSON internally

modify_assignment

Modify an existing assignment group. Server marks tombstone, removes old slots, creates new ones

verify_assignment

Read an activity and return a telemetry report (groups, slots, consistency checks)

read_planning

Read all planning slots for a given year via the bot API. Returns actual time slot data (start/end times, day of year, user assignments) and group controls. Uses PlanningsUsers::getList() + GstGroupControlPlanning::getList() with the bot owner's user_id

Low-level tools (raw JSON)

Tool

Description

list_activities

List activities where the bot is assigned

get_activity

Read a specific activity (full metadata)

add_assignment

Assign time slots (raw planning_list + recursive_group JSON)

update_assignment

Update an assignment group (raw JSON)

delete_assignment

Delete an assignment group

Token-efficient reading strategy

The MCP provides a 3-tier reading strategy to keep AI context small:

  1. list_mindmaps() — metadata only (id, title, participants). No nodes.

  2. get_mindmap_summary(id_mindmap) — compact summary: node count, titles, structure, has_description flag. No descriptions, no positions, no styles.

  3. get_node_description(id_mindmap, order_index) — read a single node's description (capped at ~4 KB).

The AI should never call get_mindmap (full) unless it needs to inspect individual node fields before a modification. For understanding structure, use get_mindmap_summary. For reading content, use get_node_description on specific nodes.

Integration with Hermes

To consume the Axomind Bot API from Hermes, add the MCP server to ~/.hermes/config.yaml:

mcp_servers:
  axomind:
    command: "python3"
    args: ["-m", "axomind_mcp.serveur.server"]
    env:
      # Bot API — URL to bot_api.php on the Axomind server
      AXOMIND_BASE_URL: "https://quantive-studio.fr/app/bot_api.php"
      # Bot credentials (from Axomind UI → bot management)
      AXOMIND_BOT_ID: "<your_bot_id>"
      AXOMIND_BOT_KEY: "<your_key_access>"
      # Python import path (required — workdir sets cwd but not the import path)
      PYTHONPATH: "/path/to/axomind-mcp/src"
    workdir: "/path/to/axomind-mcp"

⚠️ All env values must be strings (YAML parses 72 as int → pydantic rejects it). ⚠️ PYTHONPATH is required — workdir sets the cwd but not the Python import path.

After editing the config, restart Hermes or run /reload-mcp — the 26 tools are discovered automatically with the mcp_axomind_ prefix (e.g. mcp_axomind_list_mindmaps, mcp_axomind_send_message, mcp_axomind_read_planning).

Other MCP clients (Claude Desktop, Cursor, etc.)

Use the same env vars and command. The MCP server uses standard stdio transport.

Tests

PYTHONPATH=src python -m pytest tests/ -v

149 tests — mock httpx, no network calls to the Axomind server.

Architecture

src/axomind_mcp/
├── __init__.py
├── _common.py              — FastMCP instance, env config, _post() helper, node defaults
├── _planning.py            — 9 tools planning/activity (bot API)
├── imports.py              — Single import hub (registers all @mcp.tool() decorators)
├── messaging/              — Messaging tools
│   ├── __init__.py
│   └── _messenger.py       — 4 tools messenger (bot API)
├── serveur/
│   ├── __init__.py
│   └── server.py           — Entry point stdio, mcp.run()
├── mindmap/
│   ├── __init__.py
│   ├── _mindmap.py         — 10 tools mindmap (bot API)
│   ├── node_operations.py  — Shared algo: update/delete/patch nodes, cycle detection, style propagation
│   └── config_layout_mindmap.py — Node expansion, validation, auto-positioning
└── tools/
    ├── __init__.py
    ├── _file_reader.py     — File reading by extension → Quill Delta
    ├── md_to_quill_delta.py — Markdown → Quill Delta converter
    └── _tree.py            — 3 tools tree (local + bot API)

Security

  • The MCP does not touch the database or contain any business logic

  • Credentials come from environment variables (never hardcoded)

  • The Axomind server cannot tell it's a MCP — it sees normal bot_api requests

  • Tree tools (local filesystem scan) only scan the local machine where the MCP runs

  • The .env file path is set via AXOMIND_ENV_FILE — not discoverable from the public repo

License

Proprietary — see LICENSE. Copyright © 2025 VEZZANI Sébastien. All rights reserved.


Available Tools

26 tools
add_assignmentA

Assign time slots to an activity by creating a new recursive group.

A recursive group defines a date range and recurrence pattern. The planning list defines the time slots within each day of that range. Together they form a complete assignment that appears on the activity timeline.

Args: id_activity: Activity ID planning_list: JSON string — array of day slots. Each element: { "id": "0", # 0 for new slots "slot_year": 2026, # year of the slot "index_position_jour": 1, # day-of-year (1-365/366) "rel_id_user": 2, # user ID the slot belongs to "taches": [ # time slots within the day { "id": "0", "rel_id_planning_day": "0", # 0 for new "rel_id_activity": <id_activity>, "group_control_id": "0", # 0 for new (assigned server-side) "start_time": "08:00:00", # HH:mm:ss "end_time": "12:00:00", # HH:mm:ss "maj_datetime": "2026-06-23T10:00:00.000Z" # ISO 8601 UTC } ], "maj_datetime": "2026-06-23T10:00:00.000Z" } recursive_group: JSON string — the group definition: { "id": "0", # 0 for new group "id_activity": <id_activity>, "titre": "Weekly morning", # group title "notes": "", # optional notes "start_date": "2026-06-01T00:00:00.000Z", # ISO 8601 UTC "end_date": "2026-06-30T00:00:00.000Z", # ISO 8601 UTC "active_days": 127, # bitmask: bit 0=Mon, 1=Tue, ... 6=Sun "created_by": 2, # user ID of the creator "created_datetime": "2026-06-23T10:00:00.000Z", "maj_datetime": "2026-06-23T10:00:00.000Z" }

Returns: JSON string — server response with created slot IDs and group ID.

Inputs: id_activity (required), planning_list (required), recursive_group (required). Returns: result

add_nodesA

Append nodes to an existing mindmap (simplified format).

Unlike sync_nodes which replaces everything, add_nodes reads the existing mindmap, appends the new nodes, and syncs the full set.

Simplified node format (JSON string): [ {"title": "Node 1", "parent": 0, "color": "0xFF7A8FF5"}, {"title": "Node 2", "parent": 1, "color": "0xFFFF6F91"}, {"title": "Node 3", "parent": 1} ]

Fields:

  • title (required): node title

  • parent (required): order_index of the parent node (0 = root)

  • color (optional): hex color (default: 0xFF7A8FF5)

  • pos_x, pos_y (optional): canvas position (default: 0)

  • size_box (optional): 0=normal, 1=category, 2=root

  • bold, italic, underline (optional): text style

  • line_type (optional): 0=curve, 1=rounded, 2=square

  • line_style (optional): 0=solid, 1=dashed

  • stroke_width, dot_radius, radius, border_size, label_size (optional)

  • icon_id (optional): icon ID

  • active_bg_colors (optional): active background colors

  • descriptions (optional): descriptive text

  • free_links (optional): list of order_index for free links. ONLY use to close a cycle (e.g. topology A→B→C→A). Do NOT use in pure tree structures (file trees, doc trees, org charts). One free_link per cycle max.

  • spacing_h (optional): horizontal spacing multiplier 0-10 (default: 1). 0=1 cell gap (60px), 1=2 cells (120px), etc.

  • spacing_v (optional): vertical spacing multiplier 0-10 (default: 0)

  • is_write_children (optional): propagate style to children (default: false)

Auto-positioning: when free_links are present, new nodes are auto-positioned using a hierarchical tree layout (retrospective mode). When no free_links, positions stay at default (0,0) and the Flutter client handles layout.

UID and order_index are assigned automatically after existing nodes. All other fields are filled with application defaults.

Args: id_mindmap: Mindmap ID nodes: JSON string — array of simplified nodes

Inputs: nodes (required), id_mindmap (required). Returns: result

create_assignmentA

Create a planning assignment with human-friendly parameters.

This tool builds the JSON payloads internally — you only need to provide dates (YYYY-MM-DD), times (hour/minute integers), and weekday names. It mirrors the Flutter setSingleOutForm / setMultiOutForm logic.

Two modes:

  • Single-day: start_date == end_date, weekdays omitted or empty. Creates one slot per user on that date.

  • Recursive: start_date < end_date, weekdays specifies which days of the week are active. Creates one slot per user per active weekday.

Args: id_activity: Activity ID (from list_activities) user_ids: List of user IDs to assign (from activity participants) titre: Assignment title (e.g. "Morning shift") start_date: Start date in YYYY-MM-DD format (e.g. "2026-06-23") end_date: End date in YYYY-MM-DD format. For single-day, use same as start_date. start_hour: Start hour 0-23 (e.g. 8 for 08:00) start_minute: Start minute 0-59 (e.g. 0) end_hour: End hour 0-23 (e.g. 14 for 14:00) end_minute: End minute 0-59 (e.g. 0) weekdays: Active weekday names for recursive mode. Case-insensitive. Full names or 3-letter abbreviations: monday/mon, tuesday/tue, etc. Omit or leave empty for single-day assignment. notes: Optional notes text

Returns: JSON string — human-readable summary with group ID, slot count, and per-slot details (slot_id, day_of_year, user_id, times).

Inputs: titre (required), end_date (required), end_hour (required), user_ids (required), +7 more. Returns: result

delete_assignmentA

Delete an assignment group and all its time slots.

Removes the recursive group and every slot that references it. Use get_activity first to find the group ID.

Args: id_activity: Activity ID delete_recursive_group_slot: Group ID to delete

Returns: JSON string — server confirmation.

Inputs: id_activity (required), delete_recursive_group_slot (required). Returns: result

delete_messageA

Delete a bot message.

Removes a message sent by the bot. Only bot messages can be deleted with this tool (use the user API for user messages).

Args: delete_message_id: Message ID to delete

Returns: JSON string — server confirmation.

Inputs: delete_message_id (required). Returns: result

delete_nodeA

Delete a single node and its entire subtree from a mindmap.

This is the SAFE way to delete a node. It reads the full mindmap, removes the target node and all its descendants, cleans free_links pointing to deleted nodes, and syncs the remaining nodes back.

The root node (parent=0) cannot be deleted — returns an error.

The algorithm mirrors the Flutter client's MindMapManager._deleteNodeRecursive:

  1. Recursively collect all descendant order_indexes

  2. Clean free_links in remaining nodes that point to deleted nodes

  3. Remove all deleted nodes in one pass

  4. Sync the remaining nodes back

Args: id_mindmap: Mindmap ID order_index: Order index of the node to delete (1-based)

Inputs: id_mindmap (required), order_index (required). Returns: result

get_activityA

Read a specific activity (full metadata).

Returns the full activity object including participants, planning groups, and assignment details. Use list_activities first to find the IDs.

Args: id_activity: Activity ID

Returns: JSON string — full activity metadata object.

Inputs: id_activity (required). Returns: result

get_messagesA

Read bot messages in a conversation.

Returns messages sent by the bot in the specified conversation. Each message object contains: id, content_message, id_conversation, rel_id_bot, created_datetime, maj_datetime.

Args: id_conversation: Conversation ID

Returns: JSON string — array of bot message objects.

Inputs: id_conversation (required). Returns: result

get_mindmapA

Read a mindmap (full metadata + all nodes).

Returns the complete mindmap object with metadata and a 'nodes' array. Each node has ~25 fields (position, style, title, descriptions, etc.).

⚠️ LARGE RESPONSE: for a mindmap with 60+ nodes and Quill Delta descriptions, the response can exceed 2 MB. Only call this when you actually need to inspect individual nodes. Do NOT use it to verify a previous inject_directory_to_mindmap or replace_mindmap operation — those tools return a summary that is sufficient for validation.

Typical use cases:

  • Reading node structure before add_nodes or update_nodes_style

  • Debugging missing/misplaced nodes

  • Extracting specific node data

Args: id_mindmap: Mindmap ID

Returns: JSON string — {meta: {...}, nodes: [{...}, ...]}.

Inputs: id_mindmap (required). Returns: result

get_mindmap_summaryA

Read a compact summary of a mindmap — node count, titles, structure, and whether each node has a description.

Does NOT return full node data, descriptions, positions, or styles. Use this when you need to know how many nodes exist or what the structure looks like, without loading the full (potentially huge) mindmap data.

Args: id_mindmap: ID of the mindmap to summarize.

Returns: JSON string — compact summary with total_nodes, max_depth, estimated_size_kb, and a list of nodes (order_index, title, parent, size_box, has_description).

Inputs: id_mindmap (required). Returns: result

get_node_descriptionA

Read the description of a single node in a mindmap by its order_index.

Returns the description text (Quill Delta JSON) for that specific node. Use this after get_mindmap_summary to read the content of a specific node without loading the entire mindmap. The description is capped at ~4 KB.

Args: id_mindmap: ID of the mindmap. order_index: Order index of the node to read (1-based).

Returns: JSON string — {id_mindmap, order_index, title, description} or {error: "Node with order_index=X not found in mindmap Y"}.

Inputs: id_mindmap (required), order_index (required). Returns: result

inject_directory_to_mindmapA

Scan a directory, read file contents, and inject everything into a mindmap.

This is a one-shot tool: it scans the directory tree, reads each file's content, converts it to Quill Delta JSON (for .md/.markdown/.txt files), builds the full node hierarchy, and syncs it to the mindmap via sync_nodes.

The AI does NOT need to manipulate JSON — everything happens internally.

RECOMMENDED WORKFLOW:

  1. Call tree_scope on the same path to get a reference count.

  2. Call inject_directory_to_mindmap with the same path + id_mindmap.

  3. Compare the returned summary (total_nodes, descriptions_filled) with the tree_scope count. If they match and errors is empty, the injection is validated — do NOT call get_mindmap to re-verify.

File handling by extension:

  • .md / .markdown → content converted via markdown_to_quill_delta()

  • .txt → content wrapped as plain text Quill Delta

  • .docx, .pdf, .xlsx, images, binaries, etc. → node created, description empty

  • Unknown extensions → node created, description empty

  • Files > 500 KB → node created, description empty (too large)

The 'descriptions' field on each node is a Quill Delta JSON string. Directory nodes (categories) never get descriptions — only file leaves do.

Args: root_path: absolute path to the directory to scan root_title: title for the root node (empty = use directory name) id_mindmap: target mindmap ID to inject the nodes into

Returns: JSON string with a summary: {"status": "success", "total_nodes": N, "descriptions_filled": N, "files_ignored": N, "total_desc_size_kb": N, "errors": [], "ignored_formats": [".docx", ".pdf", ...]}

Inputs: root_path (required), id_mindmap, root_title. Returns: result

list_activitiesA

List activities where the bot is assigned (metadata only).

Returns a JSON string. The response contains an array of activity objects with at least: id, titre, participants (list of user IDs), and scheduling metadata. Use get_activity to read the full detail of a single activity.

Returns: JSON string — array of activity metadata objects.

Inputs: no named parameters. Returns: result

list_mindmapsA

List mindmaps where the bot is assigned (metadata only).

Returns a JSON string with an array of mindmap metadata: id, titre, rel_id_user, participants, bots, canvas dimensions, type_mindmap, created_datetime, maj_datetime. Does NOT include nodes — use get_mindmap to read the full node tree of a specific mindmap.

Returns: JSON string — array of mindmap metadata objects.

Inputs: no named parameters. Returns: result

modify_assignmentA

Modify an existing assignment group with human-friendly parameters.

Replaces the group definition and all its time slots. The server marks a tombstone for the old group, removes old slots, and creates new ones. Uses the same parameter format as create_assignment but requires group_id.

Args: id_activity: Activity ID group_id: Existing group ID to update (from get_activity or create_assignment result) user_ids: List of user IDs to assign titre: Assignment title start_date: Start date in YYYY-MM-DD format end_date: End date in YYYY-MM-DD format (same as start_date for single-day) start_hour: Start hour 0-23 start_minute: Start minute 0-59 end_hour: End hour 0-23 end_minute: End minute 0-59 weekdays: Active weekday names for recursive mode. Omit for single-day. notes: Optional notes text

Returns: JSON string — human-readable summary with updated slot details.

Inputs: titre (required), end_date (required), end_hour (required), group_id (required), +8 more. Returns: result

read_planningA

Read all planning slots for a given year via the bot API.

Returns actual time slot data (start_time, end_time, day of year, user assignments) and group controls (recursive assignment groups).

Args: year: Year to read (e.g. 2026). Returns all slots for that year. id_activity: Optional — filter to a specific activity. 0 = all activities.

Returns: JSON string — a readable report with: - Per-activity summary: activity_id, group_title, date_range, active_weekdays, slots: [{day_of_year, user_id, start_time, end_time}] - If id_activity is 0, all activities are included. - If id_activity is set, only that activity's slots are returned.

Workflow: 1. Call list_activities to get activity IDs 2. Call read_planning(year=2026) to get all slots 3. Filter by activity or user as needed

Inputs: year (required), id_activity. Returns: result

replace_mindmapA

Replace all nodes in a mindmap (simplified format).

Removes existing nodes and replaces them with the new set. The first node must have parent=0 (it becomes the root).

Simplified format (JSON string): [ {"title": "Root", "parent": 0, "color": "0xFFF0BA6D", "size_box": 2}, {"title": "Category A", "parent": 1, "color": "0xFF7A8FF5", "size_box": 1}, {"title": "Item 1", "parent": 2, "color": "0xFF7A8FF5"}, {"title": "Item 2", "parent": 2} ]

Fields:

  • title (required): node title

  • parent (required): order_index of the parent (0 = root, 1 = first node)

  • color (optional): hex color (default: 0xFF7A8FF5)

  • pos_x, pos_y (optional): canvas position (default: 0)

  • size_box (optional): 0=normal, 1=category, 2=root (default: 0)

  • bold, italic, underline (optional): text style

  • line_type (optional): 0=curve, 1=rounded, 2=square

  • line_style (optional): 0=solid, 1=dashed

  • stroke_width, dot_radius, radius, border_size, label_size (optional)

  • icon_id (optional): icon ID

  • active_bg_colors (optional): active background colors

  • descriptions (optional): descriptive text

  • free_links (optional): list of order_index for free links. ONLY use to close a cycle (e.g. topology A→B→C→A). Do NOT use in pure tree structures (file trees, doc trees, org charts). One free_link per cycle max.

  • spacing_h (optional): horizontal spacing multiplier 0-10 (default: 1). 0=1 cell gap (60px), 1=2 cells (120px), etc.

  • spacing_v (optional): vertical spacing multiplier 0-10 (default: 0)

  • is_write_children (optional): propagate style to children (default: false)

Auto-positioning: when free_links are present, nodes are auto-positioned using a hierarchical tree layout (retrospective mode). When no free_links, positions stay at default (0,0) and the Flutter client handles layout.

UID and order_index are assigned automatically (1, 2, 3...). All other fields are filled with default values.

Args: id_mindmap: Mindmap ID nodes: JSON string — array of simplified nodes

Inputs: nodes (required), id_mindmap (required). Returns: result

send_messageA

Send a message to a conversation as the bot.

The message is sent on behalf of the bot assigned to the conversation. Content is plaintext — the server encrypts it before storage.

Args: content_message: Message content (plaintext, encrypted server-side) id_conversation: Conversation ID (0 = broadcast to all assigned conversations)

Returns: JSON string — server confirmation with message ID.

Inputs: content_message (required), id_conversation. Returns: result

sync_nodesA

Sync mindmap nodes (Redis only + dirty flag).

⚠️ DESTRUCTIVE: replaces ALL nodes. If you send 1 node out of 99, the other 98 are deleted. Always send the COMPLETE node list.

The cron flushDirtyMindmaps handles database persistence. This is the same flow used by the Flutter client.

Args: id_mindmap: Mindmap ID nodes: JSON string — array of full node objects (advanced use)

Inputs: nodes (required), id_mindmap (required). Returns: result

tree_scopeA

Scan a directory and return compact telemetry (no file content).

Returns a JSON array where each entry is: {title, type, size, oi, parent, depth}

  • type: "dir", "file", or "root"

  • size: human-readable for files (e.g. "2.3KB"), item count for dirs

  • oi: 1-based order_index (matches what tree_to_mindmap would produce)

  • parent: order_index of the parent node

  • depth: nesting level (0 = root's direct children)

Use this BEFORE inject_directory_to_mindmap to get a reference count of expected nodes (1 root + N dirs + M files). After injection, compare the summary's total_nodes with this count to validate — no need to call get_mindmap afterwards.

Does NOT read file content — just names, sizes, and structure. Hidden files and VCS dirs are skipped automatically.

Args: root_path: absolute path to the directory to scan root_title: title for the root entry (empty = use directory name) max_depth: maximum nesting depth to scan (default 10)

Returns: JSON string — array of compact scope entries.

Inputs: root_path (required), max_depth, root_title. Returns: result

tree_to_mindmapA

Scan a directory tree and return a JSON array of simplified mindmap nodes.

The returned JSON is ready to use with replace_mindmap or add_nodes. Order_index is implicit (1-based position in the array). Parent values are pre-computed — no manual index tracking needed.

Directories become category nodes (size_box=1), files become leaf nodes. Hidden files, VCS dirs (.git, .github, pycache, node_modules, etc.) are skipped automatically.

Args: root_path: absolute path to the directory to scan root_title: title for the root node (empty = use directory name)

Returns: JSON string — array of simplified nodes ready for replace_mindmap.

Inputs: root_path (required), root_title. Returns: result

update_assignmentB

Update an existing assignment group and its time slots.

Replaces the group definition and all its slots. Use get_activity first to find the group ID (update_assignement_id). The planning_list and recursive_group formats are identical to add_assignment, but the group id and slot ids should be set to the existing values (non-zero).

Args: id_activity: Activity ID update_assignement_id: Existing group ID to update planning_list: JSON string — full slot list (same format as add_assignment) recursive_group: JSON string — updated group definition (same format, id = group ID)

Returns: JSON string — server response with updated slot IDs.

Inputs: id_activity (required), planning_list (required), recursive_group (required), update_assignement_id (required). Returns: result

update_messageA

Update a bot message.

Replaces the content of an existing bot message. Only messages sent by the bot can be updated (use user_send_message for user messages).

Args: update_message_id: Message ID to update content_message: New content (plaintext)

Returns: JSON string — server confirmation.

Inputs: content_message (required), update_message_id (required). Returns: result

update_nodeA

Update a single node in a mindmap — all fields supported, no data loss.

This is the SAFE way to modify any field of a single node. It reads the full mindmap, applies targeted changes to one node, and syncs everything back. Other nodes (including their descriptions) are preserved untouched.

Unlike sync_nodes (which replaces ALL nodes and can destroy data), this tool only touches the specified node. Use it for:

  • Renaming a node (title)

  • Updating a node's description (markdown → Quill Delta conversion)

  • Changing the parent (re-parenting, with cycle detection)

  • Moving a node (pos_x, pos_y)

  • Changing any style field (color, bold, size_box, etc.)

  • Updating free_links

node_updates is a JSON string with any combination of fields: { "title": "New title", // string — new node title "descriptions": "markdown text", // string — markdown converted to Quill Delta "parent": 2, // int — new parent order_index (0 = root) "color": "0xFFFF6F91", // hex color string "pos_x": 240, // canvas X position "pos_y": 480, // canvas Y position "is_manual_position": true, // bool — preserve position "size_box": 1, // 0=normal, 1=category, 2=root, 3-11=larger "bold": true, // bool "italic": false, // bool "underline": false, // bool "line_type": 1, // 0=curve, 1=rounded, 2=square "line_style": 0, // 0=solid, 1=dashed "stroke_width": 2.5, // float "dot_radius": 6, // float "radius": 5, // int "border_size": 2, // int "label_size": 12, // float "icon_id": 0, // int "active_bg_colors": false, // bool "spacing_h": 2, // 0-10 "spacing_v": 0, // 0-10 "is_write_children": true, // propagate style to children (one-shot) "free_links": [3, 5] // list of order_indexes }

Only provided fields are updated — others remain untouched. Setting pos_x or pos_y automatically sets is_manual_position=true. Descriptions are converted from markdown to Quill Delta by the algorithm.

Args: id_mindmap: Mindmap ID order_index: Order index of the node to update (1-based) node_updates: JSON string with fields to update

Inputs: id_mindmap (required), order_index (required), node_updates (required). Returns: result

update_nodes_styleA

Update style fields on specific nodes without losing existing data.

This is the SAFE way to modify node style — it reads the full mindmap, applies targeted changes, and syncs everything back. Never use sync_nodes with a partial node list (it deletes everything not sent).

style_updates is a JSON string: { "node_indices": [1, 2, 3], // order_index of nodes to update (empty = all) "size_box": 0, // optional: 0=normal(180×60), 1=category(180×120), 2=root(180×180), 3-11=larger paliers "line_type": 1, // optional: 0=curve, 1=rounded, 2=square "line_style": 0, // optional: 0=solid, 1=dashed "spacing_h": 2, // optional: horizontal spacing multiplier (0-10) "spacing_v": 0, // optional: vertical spacing multiplier (0-10) "color": "0xFF7A8FF5", // optional: hex color "bold": true, // optional "italic": false, // optional "underline": false, // optional "stroke_width": 2.5, // optional "dot_radius": 6, // optional "radius": 5, // optional "border_size": 2, // optional "label_size": 12, // optional "icon_id": 0, // optional "active_bg_colors": false, // optional "is_write_children": true, // optional: propagate style to children }

Only provided fields are updated — others remain untouched. If node_indices is empty, the update applies to ALL nodes.

Args: id_mindmap: Mindmap ID style_updates: JSON string with node_indices + fields to update

Inputs: id_mindmap (required), style_updates (required). Returns: result

verify_assignmentA

Verify and inspect all assignments for an activity.

Reads the activity metadata and validates that all assignment groups have consistent time slots. Returns a telemetry report with:

  • Activity info (id, title, participants)

  • Per-group details (group_id, titre, type, date range, active weekdays)

  • Per-slot details (slot_id, day_of_year, user_id, start/end times)

  • Consistency checks (group references, date ranges, weekday matching)

Use this after create_assignment or modify_assignment to confirm the server accepted and stored the assignment correctly.

Args: id_activity: Activity ID to verify

Returns: JSON string — telemetry report with activity, groups, slots, and validation results.

Inputs: id_activity (required). Returns: result

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4/5.0

    Scored across 26 tools

    Disambiguation4/5

    Tools are clearly grouped by domain (mindmap, planning, messaging) with distinct purposes. However, there is potential confusion between add_assignment and create_assignment (both create assignments with different parameter styles) and similarly update_assignment vs modify_assignment. The descriptions help differentiate but the overlap reduces clarity.

    Naming Consistency4/5

    Most tools follow a consistent snake_case verb_noun pattern. However, there are multiple verbs for similar operations (add/create, update/modify) which introduces minor inconsistency. Overall, the naming is predictable and readable.

    Tool Count4/5

    With 26 tools covering two main domains plus messaging, the count is slightly high but still reasonable. Some redundancy exists (duplicate raw and human-friendly versions), but each tool serves a specific use case. The scope fits the server's purpose.

    Completeness5/5

    The tool set provides full CRUD coverage for mindmaps, planning assignments, and bot messages. Mindmap tools include bulk import and scanning helpers; planning tools offer both raw and human-friendly operations; messaging covers send, read, update, delete. No obvious gaps in the featured workflows.

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      D
      maintenance
      MCP server that connects AI assistants to your real Telegram account via User API (MTProto). Features default-deny ACL with per-chat permissions, message search, file sending, forwarding, media downloads, and rate limiting.
      3
      MIT
    • A
      license
      C
      quality
      C
      maintenance
      Ultimate MCP server for Telegram Bot API — 169 methods, full v9.6 coverage, meta-mode, rate limiting, and circuit breaker, enabling AI to control Telegram bots with natural language.
      100
      34
      MIT