--- name: drawio-mcp description: "Create, edit, and export draw.io diagrams via the draw.io MCP server with real-time browser preview." metadata: version: 1.0.0 mcp-server: drawio --- # Draw.io MCP — Diagram Creation & Editing You are an expert at creating and editing draw.io diagrams via the draw.io MCP server. Diagrams appear in real-time in the user's browser. ## Critical: These Are Direct Tool Calls MCP tools are **direct tool calls** — NOT CLI commands. All draw.io MCP tools use the `mcp__drawio__` prefix. ## Mandatory Workflow ``` 1. start_session ← always first (opens browser) 2. create_new_diagram ← for new diagrams (replaces entire diagram) OR get_diagram ← REQUIRED before edit_diagram edit_diagram ← for modifications (preserves user's manual edits) 3. export_diagram ← optional, saves to .drawio / .png / .svg ``` **Rules:** - `start_session` must be called before any other tool in a new session - `get_diagram` MUST be called before `edit_diagram` — skipping it will silently overwrite the user's manual changes. The server enforces a 30-second window; after 30s you must call `get_diagram` again. - `create_new_diagram` replaces the ENTIRE diagram — only use for new diagrams or complete redraws - `edit_diagram` is for targeted adds/updates/deletes to an existing diagram ## XML Format Every diagram is a complete `mxGraphModel`: ```xml ``` **Layout rules:** - Keep everything within x=0–800, y=0–600 for single-page viewport - IDs start at "2" (0 and 1 are reserved) - Space shapes 150–200px apart for clean edge routing ## Semantic Design System **Default for workflow, pipeline, and architecture diagrams.** Ported from the hand-crafted SVG design system — consistent visual language across all diagrams. Use this unless the user asks for a different theme. ### Node Styles | Role | Full draw.io style | |------|--------------------| | Action — planning (blue) | `rounded=1;fillColor=#ffffff;strokeColor=#3b82f6;fontColor=#2563eb;fontSize=13;fontStyle=1;shadow=1;` | | Action — builder (purple) | `rounded=1;fillColor=#ffffff;strokeColor=#8b5cf6;fontColor=#7c3aed;fontSize=13;fontStyle=1;shadow=1;` | | Action — validator (green) | `rounded=1;fillColor=#ffffff;strokeColor=#22c55e;fontColor=#166534;fontSize=13;fontStyle=1;shadow=1;` | | Action — neutral (gray) | `rounded=1;fillColor=#ffffff;strokeColor=#6b7280;fontColor=#374151;fontSize=13;fontStyle=1;shadow=1;` | | Decision diamond | `rhombus;fillColor=#ffffff;strokeColor=#6b7280;fontColor=#374151;fontSize=11;` | | Done pill (terminal success) | `rounded=1;arcSize=50;fillColor=#dcfce7;strokeColor=#16a34a;fontColor=#15803d;fontSize=13;fontStyle=1;shadow=1;` | | Phase done | `rounded=1;fillColor=#f0fdf4;strokeColor=#22c55e;fontColor=#166534;fontSize=13;shadow=1;` | | Annotation callout | `rounded=1;fillColor=#fefce8;strokeColor=#eab308;fontColor=#a16207;fontSize=11;dashed=1;` | ### Group / Container Styles Use as swim-lane or container shapes (set `vertex=1` with large geometry to act as a background region): | Role | Full draw.io style | |------|--------------------| | Planning group (blue) | `rounded=1;fillColor=#eff6ff;gradientColor=#dbeafe;gradientDirection=south;strokeColor=#93c5fd;strokeWidth=1.5;fontSize=11;fontStyle=1;fontColor=#1d4ed8;verticalAlign=top;shadow=1;` | | Builder group (purple, dashed) | `rounded=1;fillColor=#faf5ff;gradientColor=#f3e8ff;gradientDirection=south;strokeColor=#a78bfa;strokeWidth=1.5;fontSize=11;fontStyle=1;fontColor=#7c3aed;verticalAlign=top;dashed=1;` | | Validator group (green, dashed) | `rounded=1;fillColor=#f0fdf4;gradientColor=#dcfce7;gradientDirection=south;strokeColor=#4ade80;strokeWidth=1.5;fontSize=11;fontStyle=1;fontColor=#15803d;verticalAlign=top;dashed=1;` | | Outer container (gray) | `rounded=1;fillColor=#fafafa;strokeColor=#d1d5db;strokeWidth=1.5;fontSize=11;fontStyle=1;fontColor=#374151;verticalAlign=top;shadow=1;` | ### Edge Styles (Semantic) | Meaning | Full draw.io style | |---------|--------------------| | Neutral flow | `endArrow=block;endFill=1;strokeColor=#6b7280;strokeWidth=1.5;edgeStyle=orthogonalEdgeStyle;` | | Pass / success | `endArrow=block;endFill=1;strokeColor=#22c55e;strokeWidth=1.5;edgeStyle=orthogonalEdgeStyle;` | | Fail / error | `endArrow=block;endFill=1;strokeColor=#ef4444;strokeWidth=1.5;edgeStyle=orthogonalEdgeStyle;` | | Fix / retry | `endArrow=block;endFill=1;strokeColor=#d97706;strokeWidth=1.5;edgeStyle=orthogonalEdgeStyle;` | | Annotation link (dashed, no arrow) | `endArrow=none;strokeColor=#eab308;strokeWidth=1;dashed=1;dashPattern=4 3;` | ### Typography (fontStyle bitmask: 1=bold, 2=italic, 4=underline) | Role | fontSize | fontStyle | fontColor | |------|----------|-----------|-----------| | Group title | 11 | 1 (bold) | Phase color | | Primary node text | 13 | 1 (bold) | Phase color | | Subtitle / secondary | 11 | 0 | #6b7280 | | Edge label | 11 | 1 (bold) | Semantic color | ### Semantic Color Reference | Role | Fill | Stroke | Text | |------|------|--------|------| | Blue (planning) | `#ffffff` | `#3b82f6` | `#2563eb` | | Purple (builder) | `#ffffff` | `#8b5cf6` | `#7c3aed` | | Green (validator/pass) | `#ffffff` | `#22c55e` | `#166534` | | Gray (neutral) | `#ffffff` | `#6b7280` | `#374151` | | Red (fail) | — | `#ef4444` | `#dc2626` | | Amber (fix/retry) | — | `#d97706` | `#d97706` | | Yellow (annotation) | `#fefce8` | `#eab308` | `#a16207` | | Done pill | `#dcfce7` | `#16a34a` | `#15803d` | --- ## Alternative Palettes Use when the user explicitly requests a different visual style. ### Dark / Tech ``` nodes: fillColor=#1e1e2e;strokeColor=#89b4fa;fontColor=#cdd6f4 accents: strokeColor=#a6e3a1 (green), #f38ba8 (red), #cba6f7 (purple) ``` ### Pastel / Soft ``` nodes: fillColor=#dae8fc;strokeColor=#6c8ebf;fontColor=#333333 ``` ### Minimal / Mono ``` nodes: fillColor=#ffffff;strokeColor=#333333;fontColor=#333333 edges: endArrow=open;endSize=8;strokeColor=#333333 ``` ### Bold / AWS ``` header: fillColor=#232F3E;strokeColor=#FF9900;fontColor=#ffffff compute: fillColor=#FF9900;strokeColor=#FF9900;fontColor=#ffffff ``` ### Vibrant / UI ``` primary: fillColor=#6366f1;strokeColor=#4f46e5;fontColor=#ffffff;shadow=1 secondary: fillColor=#8b5cf6;strokeColor=#7c3aed;fontColor=#ffffff;shadow=1 ``` ## Common Shape Styles | Shape | Style fragment | |-------|----------------| | Rounded rectangle | `rounded=1;` | | Diamond (decision) | `rhombus;` | | Pill (terminal) | `rounded=1;arcSize=50;` | | Cylinder (database) | `shape=cylinder3;` | | Circle | `ellipse;` | | User/person | `shape=mxgraph.aws4.user;` | | Cloud | `shape=mxgraph.aws4.cloud;` | | Title text | `text;fontSize=16;fontStyle=1;align=center;` | ## Layout Rules (Critical — violations cause misaligned diagrams) ### 1. Center-align all nodes in a flow column Every node in a vertical flow column **must share the same `center_x`**. Mixed center_x values cause orthogonal edges to jog horizontally, routing through text. **Formula:** `node_x = center_x - node_width / 2` For a container at `x=C_x, width=C_w`: `center_x = C_x + C_w / 2` If subgroups inside the container have a fixed center (e.g. builder nodes at center_x=533), align ALL orchestrator nodes above/below them to that same center_x. Do not place orchestrator nodes at a different x and rely on routing to bridge the gap. ### 2. Edges between vertically-stacked nodes must be straight vertical If source and target share the same `center_x`, use `exitX=0.5;exitY=1;entryX=0.5;entryY=0;` — the edge routes as a clean vertical line with no horizontal jog. If they have different center_x values (unavoidable), add an explicit waypoint that steps horizontally **above** the entry node (at `y = target_top - 15`) so the jog happens in empty space, not through text: ```xml ``` ### 3. Annotation boxes: vertical center must match the connector exit point For horizontal dashed connectors to annotation boxes, the annotation's vertical center **must equal** the source element's exit y. **Formula:** `annotation_y = source_center_y - annotation_height / 2` Example: source diamond center_y=234, annotation height=72 → `annotation_y = 234 - 36 = 198`. If the annotation y is wrong the connector angles — it will not be horizontal. Calculate this explicitly before placing annotations. ### 4. Loopback labels: use edge `value`, not rotated text cells **Do NOT** use standalone `mxCell` text cells with `rotation=-90` as sidebar labels for loopback edges. They render as floating horizontal blocks, not clean sidebar annotations. **Do:** Put the label as the edge `value` — it will appear near the midpoint of the edge in horizontal text, which is readable and unambiguous: ```xml ``` For loopbacks with two semantic labels (e.g. "FAIL" on horizontal segment, "Fresh builder" on vertical), use the more important label as `value` and omit the secondary label. ## Edge Routing Rules - Always specify `exitX`, `exitY`, `entryX`, `entryY` explicitly — never rely on auto-routing to pick correct connection points - For bidirectional connections (A↔B), use **opposite sides** (exitY=0.3 / entryY=0.7) - Never let multiple edges share the same path — offset using different exit/entry points - Add `curved=1;` for smoother bends on complex routes ```xml ``` ## edit_diagram Operations ```json { "operations": [ { "operation": "add", "cell_id": "new-1", "new_xml": "" }, { "operation": "update", "cell_id": "2", "new_xml": "" }, { "operation": "delete", "cell_id": "old-1" } ]} ``` Always use descriptive `cell_id` values (e.g. `"lambda-fn"`, `"api-gw"`) — not numeric IDs — for new cells to avoid collisions. ## Export ``` export_diagram({ path: "./diagram.drawio" }) ← XML (default) export_diagram({ path: "./diagram.png" }) ← PNG (requires open browser tab) export_diagram({ path: "./diagram.svg" }) ← SVG (requires open browser tab) ``` PNG/SVG export requires the browser tab to be open and the diagram loaded. ## Port & Session Notes - MCP server uses port **6002** by default; auto-increments to 6003–6020 if occupied - The next-ai-draw-io **desktop app** uses port **61337** in production — no conflict - In dev mode (`npm run dev`) the desktop app also uses 6002 — conflict likely; set `PORT=6003` in MCP env - The MCP server and the desktop app are **separate** — the MCP controls a browser-based draw.io embed, not the Electron window ## Configuration | Env var | Default | Purpose | |---------|---------|---------| | `PORT` | `6002` | MCP embedded server port | | `DRAWIO_BASE_URL` | `https://embed.diagrams.net` | draw.io embed source (for self-hosted) | ## Decision Tree | User says | Action | |-----------|--------| | "Create a diagram" | `start_session` → `create_new_diagram` | | "Add X to the diagram" | `get_diagram` → `edit_diagram` (add) | | "Change / update X" | `get_diagram` → `edit_diagram` (update) | | "Remove X" | `get_diagram` → `edit_diagram` (delete) | | "Save / export" | `export_diagram` | | Asks about style | Apply named palette from this skill; show options if unsure | ## Troubleshooting ### "No active session" Call `start_session` first — the session resets on MCP server restart. ### Browser not updating Check the browser URL contains `?mcp=`. If the tab was closed, call `start_session` again to get a new URL. ### Port already in use Set `PORT=6003` in the MCP server env config (`.mcp.json` or Claude Desktop config). ### edit_diagram rejected ("must call get_diagram first") The 30-second window expired. Call `get_diagram` then retry `edit_diagram` immediately. ### PNG/SVG export returns "timed out" The browser tab must be open with the diagram loaded. Navigate to the session URL, wait for the diagram to render, then retry.