Skip to main content
Glama
johnymontana

excalidraw-export-mcp

by johnymontana
README.md
# Excalidraw Export MCP Server

[![Test](https://github.com/neo4j-labs/agent-memory/actions/workflows/test.yml/badge.svg)](https://github.com/neo4j-labs/agent-memory/actions/workflows/test.yml)

An MCP (Model Context Protocol) server for exporting Excalidraw diagrams to PNG or SVG format.

## Features

- Export `.excalidraw` files to PNG or SVG
- Batch export multiple files at once
- Get diagram metadata (element count, types, bounds, etc.)
- Pixel-perfect rendering using headless Chromium browser
- Configurable export options (scale, dark mode, background)

## Prerequisites

- Node.js 18 or later
- Playwright (Chromium is downloaded automatically on install)

## Installation

```bash
npm install
npm run build
```

On first install, Playwright will download Chromium automatically.

## Usage

### As an MCP Server

Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json`):

```json
{
  "mcpServers": {
    "excalidraw-export": {
      "command": "node",
      "args": ["/path/to/excalidraw-export-mcp/dist/index.js"]
    }
  }
}
```

### Tools

#### `export_excalidraw`

Export a single Excalidraw diagram.

**Parameters:**
- `inputPath` (required): Absolute path to the `.excalidraw` file
- `outputPath`: Output file path (defaults to input path with new extension)
- `format`: `"png"` or `"svg"` (default: `"png"`)
- `background`: Include background color (default: `true`)
- `darkMode`: Export in dark mode (default: `false`)
- `scale`: Scale factor 1, 2, or 3 (default: `2` for high DPI)

#### `export_excalidraw_batch`

Export multiple diagrams at once.

**Parameters:**
- `inputPaths` (required): Array of absolute paths to `.excalidraw` files
- `outputDir`: Output directory (defaults to same directory as each input)
- `format`: `"png"` or `"svg"` (default: `"png"`)
- `background`, `darkMode`, `scale`: Same as above

#### `get_excalidraw_info`

Get metadata about an Excalidraw file without exporting.

**Parameters:**
- `inputPath` (required): Absolute path to the `.excalidraw` file

**Returns:**
- `elementCount`: Number of elements in the diagram
- `elementTypes`: Count of each element type (rectangle, arrow, text, etc.)
- `hasBackground`: Whether background is exported
- `backgroundColor`: Background color
- `version`: Excalidraw schema version
- `fileSize`: File size in bytes
- `bounds`: Diagram dimensions (width, height)

## Examples

### Example 1: Export a Single Diagram to PNG

```json
{
  "tool": "export_excalidraw",
  "arguments": {
    "inputPath": "/Users/me/diagrams/architecture.excalidraw",
    "format": "png",
    "scale": 2
  }
}
```

**Result:**
```json
{
  "success": true,
  "outputPath": "/Users/me/diagrams/architecture.png",
  "format": "png",
  "message": "Successfully exported to /Users/me/diagrams/architecture.png"
}
```

### Example 2: Export with Custom Output Path

```json
{
  "tool": "export_excalidraw",
  "arguments": {
    "inputPath": "/Users/me/docs/flowchart.excalidraw",
    "outputPath": "/Users/me/images/flowchart-hires.png",
    "scale": 3
  }
}
```

### Example 3: Export in Dark Mode

```json
{
  "tool": "export_excalidraw",
  "arguments": {
    "inputPath": "/Users/me/diagrams/network.excalidraw",
    "darkMode": true,
    "background": true
  }
}
```

### Example 4: Export to SVG

```json
{
  "tool": "export_excalidraw",
  "arguments": {
    "inputPath": "/Users/me/diagrams/logo.excalidraw",
    "format": "svg"
  }
}
```

### Example 5: Batch Export Multiple Diagrams

```json
{
  "tool": "export_excalidraw_batch",
  "arguments": {
    "inputPaths": [
      "/Users/me/docs/diagram1.excalidraw",
      "/Users/me/docs/diagram2.excalidraw",
      "/Users/me/docs/diagram3.excalidraw"
    ],
    "outputDir": "/Users/me/exports",
    "format": "png",
    "scale": 2
  }
}
```

**Result:**
```json
{
  "success": true,
  "results": [
    {
      "inputPath": "/Users/me/docs/diagram1.excalidraw",
      "outputPath": "/Users/me/exports/diagram1.png",
      "success": true
    },
    {
      "inputPath": "/Users/me/docs/diagram2.excalidraw",
      "outputPath": "/Users/me/exports/diagram2.png",
      "success": true
    },
    {
      "inputPath": "/Users/me/docs/diagram3.excalidraw",
      "outputPath": "/Users/me/exports/diagram3.png",
      "success": true
    }
  ],
  "totalProcessed": 3,
  "successful": 3,
  "failed": 0
}
```

### Example 6: Get Diagram Information

```json
{
  "tool": "get_excalidraw_info",
  "arguments": {
    "inputPath": "/Users/me/diagrams/architecture.excalidraw"
  }
}
```

**Result:**
```json
{
  "elementCount": 15,
  "elementTypes": {
    "rectangle": 5,
    "arrow": 6,
    "text": 4
  },
  "hasBackground": true,
  "backgroundColor": "#ffffff",
  "version": 2,
  "source": "https://excalidraw.com",
  "fileSize": 12453,
  "bounds": {
    "width": 800,
    "height": 600
  }
}
```

### Example 7: Export Without Background (Transparent)

```json
{
  "tool": "export_excalidraw",
  "arguments": {
    "inputPath": "/Users/me/diagrams/icon.excalidraw",
    "format": "png",
    "background": false
  }
}
```

## Claude Code Usage Examples

When using with Claude Code, you can ask:

**Export a diagram:**
> "Export the architecture diagram at /path/to/architecture.excalidraw to PNG"

**Export all diagrams in a folder:**
> "Export all .excalidraw files in the docs folder to PNG format"

**Get diagram info before exporting:**
> "What's in the diagram at /path/to/diagram.excalidraw? How many elements does it have?"

**Create high-resolution exports:**
> "Export diagram.excalidraw at 3x scale for printing"

**Dark mode exports:**
> "Export the network diagram in dark mode"

## Development

```bash
# Install dependencies
npm install

# Build
npm run build

# Watch mode
npm run dev

# Run all tests
npm test

# Run unit tests only (faster, no browser)
npm run test:unit

# Run integration tests (requires Playwright/Chromium)
npm run test:integration
```

## Test Suite

The project includes a comprehensive test suite:

### Unit Tests (`tests/get-info.test.ts`)
- Element counting and categorization
- Bounds calculation
- AppState property extraction
- Edge cases (empty elements, missing properties)

### Schema Validation Tests (`tests/mcp-server.test.ts`)
- Zod schema validation for all tool inputs
- Default value handling
- Required field validation
- Boundary conditions (scale min/max)
- Tool definition structure validation

### Integration Tests (`tests/export.test.ts`)
- Full export pipeline with Playwright
- PNG file validation (magic bytes check)
- Page reload handling
- Canvas capture
- Batch processing
- Error recovery

To skip integration tests (if Chromium is not installed):
```bash
SKIP_INTEGRATION=true npm test
```

## How It Works

This server uses Playwright to run a headless Chromium browser that:
1. Navigates to excalidraw.com
2. Loads your diagram data via localStorage
3. Captures a screenshot of the rendered canvas

This approach ensures pixel-perfect rendering identical to the Excalidraw web app.

## Troubleshooting

### Chromium not installed
If you see "Executable doesn't exist" errors, run:
```bash
npx playwright install chromium
```

### Timeout errors
For large diagrams, the export may take longer. The server includes automatic retries and page reload handling.

### Memory issues with batch exports
For very large batches, consider breaking them into smaller chunks or increasing Node.js memory:
```bash
NODE_OPTIONS="--max-old-space-size=4096" node dist/index.js
```

## Publishing to npm

### Prerequisites

1. Create an npm account at https://www.npmjs.com/
2. Generate an access token with publish permissions
3. Add the token as `NPM_TOKEN` secret in GitHub repository settings

### Automated Publishing (Recommended)

Publishing is automated via GitHub Actions. To publish a new version:

1. Update the version in `package.json`:
   ```bash
   npm version patch  # or minor, major
   ```

2. Push the changes and create a GitHub release:
   ```bash
   git push && git push --tags
   ```

3. Create a release on GitHub from the tag - this triggers the publish workflow

### Manual Publishing

To publish manually:

```bash
# Login to npm
npm login

# Build and test
npm run build
npm run test:unit

# Publish
npm publish --access public
```

### Version Guidelines

- **Patch** (0.1.x): Bug fixes, documentation updates
- **Minor** (0.x.0): New features, non-breaking changes
- **Major** (x.0.0): Breaking changes

### Using from npm

Once published, users can install directly:

```bash
npm install -g excalidraw-export-mcp
```

Or use with npx:

```bash
npx excalidraw-export-mcp
```

## License

MIT

TDQS

A3.7/5.0

Scored across 3 tools

Disambiguation5/5

Each tool has a clearly distinct purpose: single export, batch export, and metadata retrieval. There is no overlap or ambiguity.

Naming Consistency4/5

Two tools use the 'export_excalidraw' prefix consistently, but 'get_excalidraw_info' deviates by using 'get_' instead of 'export_'. Minor inconsistency.

Tool Count4/5

Three tools is a reasonable, focused set for the server's purpose of exporting and inspecting Excalidraw diagrams. Not overly thin.

Completeness4/5

The tool surface covers the core functionality (single/batch export and metadata). Missing features like format conversion or diagram editing are outside the stated scope.

Maintenance

ActivityInactive
ResponsivenessNo issues