excalidraw-export-mcp
by johnymontana
README.md
# Excalidraw Export MCP Server
[](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