MCP server that lets Claude draw in your Excalidraw canvas in real-time via the collaboration protocol
Server has 6 tools with explicit registrations and schemas. Naming is clear and verb-based (connect, draw_elements, get_scene, delete_elements, undo, clear_canvas). Descriptions are present but vary in quality. The draw_elements tool has an exceptionally long description (1800+ chars) with embedded layout rules that should be in documentation, not the tool description itself. Input schemas are visible for all tools, but several parameters lack descriptions. Error handling is basic, responses indicate success/failure but lack recovery guidance. No tool annotations (readOnlyHint, destructiveHint) despite clear risk levels.
Delete all elements on the canvas. This is irreversible — use with caution.
Connect to an Excalidraw collaboration room. If already connected to another room, the existing connection is closed first. Get the link by clicking 'Live collaboration' in Excalidraw. Must be called before any other tool.
Delete elements by ID. Provide a list of element IDs to remove from the canvas.
Draw elements on the connected Excalidraw canvas. Supports rectangle, ellipse, diamond, text, arrow, line, frame, image. CRITICAL — ALWAYS USE RECTANGLES: - Every card, section, or group MUST be a rectangle element with width and height — NEVER use standalone text as a container. - To make a labeled box: draw a rectangle, then use the "label" property to put text inside it, OR draw a separate text element positioned inside. - Standalone text (without a surrounding rectangle) should only be used for titles and annotations, not for cards or content blocks. - Use frames to group related sections of a layout. LAYOUT RULES (CRITICAL — follow these every time): 1. PLAN BEFORE DRAWING: Before calling this tool, mentally map out the full layout. Calculate positions for every element, annotation, and arrow FIRST. Never place elements without considering the full picture. 2. SPACING: Leave at least 80px horizontal gap between shapes for arrows + labels. Leave at least 120px vertical gap between rows for annotations. Annotations go BELOW their screen in a dedicated zone — never in the arrow corridor. 3. ARROWS MUST NEVER OVERLAP CONTENT: Before drawing any arrow, check what elements exist between the start and end points. If anything is in the path, route the arrow around it using multi-point paths with 90-degree turns: points: [[0,0], [dx,0], [dx,dy]] for L-shapes, or [[0,0], [dx,0], [dx,dy], [dx2,dy]] for Z-shapes. Use as many segments as needed. 4. LABELS ON ARROWS: Arrow labels are standalone text (not bound). Place them adjacent to the arrow in empty space — above for horizontal arrows, beside for vertical arrows. Never on top of the arrow line or other content. 5. TEXT IN DARK CONTAINERS: The server auto-detects dark backgrounds and sets white text. But verify visually — if backgroundColor is dark and fillStyle is "solid", the label will be white. 6. USE get_scene FIRST: When adding to an existing canvas, ALWAYS call get_scene first to see current element positions. Then calculate new positions that avoid all existing content. 7. RESPONSIVE ROUTING: If the best path for an arrow would overlap content, consider: (a) routing the arrow with extra waypoints, (b) repositioning the annotation text, or (c) adding more spacing. Choose whichever produces the cleanest result. 8. TEXT DIMENSIONS: Text elements need width/height for proper rendering. The server estimates these, but keep text concise. Multi-line text uses \n. 9. STANDALONE TEXT NEAR ARROWS: When placing text elements near arrows manually (not using the label property), position them at least 10px ABOVE horizontal arrows or 12px to the RIGHT of vertical arrows. Never at the same y-coordinate as a horizontal arrow or the same x-coordinate as a vertical arrow — the text will visually overlap the arrow line. 10. NO ELEMENT OVERLAP EVER: Before placing ANY element, verify its bounding box (x, y, width, height) does not intersect with any existing element. If it would overlap, move it to clear space. This applies to text, shapes, arrows — everything. 11. CENTER TEXT PROPERLY: For annotation text below shapes (titles, descriptions), ALWAYS use textAlign: "center" and set width equal to the shape's width and x equal to the shape's x. This ensures Excalidraw centers the text visually regardless of width estimation. For standalone text inside phone mockups or UI elements, also use textAlign: "center". Never rely on manual x-offset calculations for centering — use textAlign instead. ARROW BINDINGS (optional — for connecting arrows to shapes): - Set "id" on shapes, then reference that id in arrow startBinding/endBinding within the same call. - fixedPoint: [0.5, 0]=top, [0.5, 1]=bottom, [0, 0.5]=left, [1, 0.5]=right. - Set elbowed: true for auto-routed right-angle arrows (requires at least one binding).
draw_elements description is 1800+ characters with embedded layout rules, layout examples, and implementation guidance. Tool descriptions should be 10 - 1024 chars and focus on WHAT the tool does, not HOW to use it or detailed layout algorithms. Move layout rules to a separate CLAUDE.md or documentation file.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint) despite clear risk levels. delete_elements and clear_canvas are destructive; get_scene is read-only; undo is reversible. Annotations help LLMs reason about safety and retry logic.
Error responses lack recovery guidance. When connect fails, the response is 'Connection failed: <message>' with no hint about what to try next (e.g., 'Check the URL format or verify the room ID'). Errors should guide the LLM toward resolution.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 61 | <=2025-11-25 | v2 |
Get the current scene state — all elements on the canvas. Use this before drawing to see what's already there and avoid overlaps.
Undo the last draw_elements call. Removes all elements that were added in that call.
draw_elements input schema has complex nested objects (elements array with many optional properties) but lacks clear documentation of which properties are required vs optional, and what combinations are valid. E.g., can you draw an arrow without startBinding/endBinding? What happens if you specify both label and text on the same element?
No confirmation or dry-run pattern for destructive operations (delete_elements, clear_canvas). An LLM could accidentally delete the entire canvas. Consider adding a 'dry_run' parameter or a separate 'preview_delete' tool.