mermaid_to_excalidraw
Convert Mermaid flowchart syntax into an Excalidraw diagram. Supports graph directions, node shapes, edge types, and subgraphs with auto-detected component styling.
Instructions
Convert Mermaid flowchart syntax into an Excalidraw diagram.
Supports the mermaid flowchart subset that AI agents commonly generate:
Directions: graph TD, LR, BT, RL
Node shapes: [text], {text}, ((text)), ([text])
Edge types: -->, ---, -.-> ==> with |label|
Subgraphs: subgraph Title ... end
Component types are auto-detected from node labels (e.g., a node labeled "PostgreSQL DB" automatically gets database styling).
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| mermaid_syntax | Yes | Mermaid flowchart source code. | |
| output_path | Yes | File path to save the .excalidraw file. | |
| theme | No | Color theme - "default", "dark", "colorful". Default: "default" | default |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| result | Yes |
Implementation Reference
- src/excalidraw_mcp/server.py:140-178 (handler)The tool handler function for 'mermaid_to_excalidraw'. It calls parse_mermaid() to parse the mermaid syntax, compute_layout() for layout, build_excalidraw_file() to render, save_excalidraw() to persist, then returns a summary string.
@mcp.tool def mermaid_to_excalidraw( mermaid_syntax: str, output_path: str, theme: str = "default", ) -> str: """Convert Mermaid flowchart syntax into an Excalidraw diagram. Supports the mermaid flowchart subset that AI agents commonly generate: - Directions: graph TD, LR, BT, RL - Node shapes: [text], {text}, ((text)), ([text]) - Edge types: -->, ---, -.-> ==> with |label| - Subgraphs: subgraph Title ... end Component types are auto-detected from node labels (e.g., a node labeled "PostgreSQL DB" automatically gets database styling). Args: mermaid_syntax: Mermaid flowchart source code. output_path: File path to save the .excalidraw file. theme: Color theme - "default", "dark", "colorful". Default: "default" Returns: Summary of the converted diagram. """ graph = parse_mermaid(mermaid_syntax) layout = compute_layout(graph) doc = build_excalidraw_file(layout, theme_name=theme, direction=graph.direction) path = save_excalidraw(doc, output_path) return ( f"Converted mermaid to excalidraw at: {path}\n" f"Nodes: {len(graph.nodes)}\n" f"Connections: {len(graph.edges)}\n" f"Subgraphs: {len(graph.subgraphs)}\n" f"Direction: {graph.direction.value}\n" f"Theme: {theme}\n\n" f"Open with the VS Code Excalidraw extension or drag into excalidraw.com" ) - The main parse_mermaid() function that converts mermaid flowchart source into a DiagramGraph intermediate representation. Uses two-pass parsing: pass 1 extracts node definitions and shapes, pass 2 extracts edges.
def parse_mermaid(source: str) -> DiagramGraph: """Parse mermaid flowchart source into a DiagramGraph.""" nodes: dict[str, Node] = {} edges: list[Edge] = [] subgraphs: list[Subgraph] = [] direction = Direction.TOP_DOWN subgraph_stack: list[Subgraph] = [] for raw_line in source.strip().splitlines(): line = raw_line.strip() if not line or line.startswith("%%"): continue line = re.sub(r"%%.*$", "", line).strip() if not line: continue m = _GRAPH_DECL.match(line) if m: direction = _DIRECTION_MAP.get(m.group(1).upper(), Direction.TOP_DOWN) continue m = _SUBGRAPH_START.match(line) if m: sg_id = m.group(1) or m.group(3) or _sanitize_id(m.group(4) or "subgraph") sg_label = m.group(2) or m.group(4) or m.group(3) or sg_id sg = Subgraph(id=sg_id, label=sg_label.strip()) subgraph_stack.append(sg) continue if _SUBGRAPH_END.match(line): if subgraph_stack: subgraphs.append(subgraph_stack.pop()) continue # Pass 1: extract node definitions, get cleaned line cleaned = _extract_nodes_from_line(line, nodes, subgraph_stack) # Pass 2: extract edges from cleaned line _extract_edges_from_line(cleaned, nodes, edges, subgraph_stack) # If no edges found and no nodes extracted, try as standalone node if not edges or edges[-1].from_id not in {n.id for n in nodes.values()}: pass # Nodes already handled in pass 1 while subgraph_stack: subgraphs.append(subgraph_stack.pop()) return DiagramGraph( nodes=list(nodes.values()), edges=edges, subgraphs=subgraphs, direction=direction, ) - DiagramGraph model - the intermediate representation produced by the mermaid parser and consumed by the layout engine. Contains nodes, edges, subgraphs, and direction.
class DiagramGraph(BaseModel): """ The intermediate representation shared across all tools. Produced by: create_diagram args, mermaid parser, or diagram state manager. Consumed by: layout engine -> excalidraw builder. """ nodes: list[Node] = Field(default_factory=list) edges: list[Edge] = Field(default_factory=list) subgraphs: list[Subgraph] = Field(default_factory=list) direction: Direction = Direction.LEFT_RIGHT - EdgeStyle enum used to map mermaid arrow types (-->, ==>, -.->) to edge styles (solid, thick, dashed, dotted).
class EdgeStyle(str, Enum): """Visual style for edges/arrows.""" SOLID = "solid" DASHED = "dashed" DOTTED = "dotted" THICK = "thick" - src/excalidraw_mcp/server.py:140-140 (registration)The @mcp.tool decorator registers 'mermaid_to_excalidraw' as a FastMCP tool. No explicit name arg means the function name is used as the tool name.
@mcp.tool