# Draw.io MCP Server A [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server for programmatic diagram generation using [Draw.io](https://www.drawio.com/) (Diagrams.net). This server generates Draw.io XML directly — no browser extension or Draw.io instance required. [![Build project](https://github.com/simonkurtz-MSFT/drawio-mcp-server/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/simonkurtz-MSFT/drawio-mcp-server/actions/workflows/ci.yml) [![Docker Hub](https://img.shields.io/docker/v/simonkurtzmsft/drawio-mcp-server?label=Docker%20Hub&logo=docker&sort=semver)](https://hub.docker.com/r/simonkurtzmsft/drawio-mcp-server) [![AgentSeal MCP](https://agentseal.org/api/v1/mcp/https-githubcom-simonkurtz-msft-drawio-mcp-server/badge)](https://agentseal.org/mcp/https-githubcom-simonkurtz-msft-drawio-mcp-server) ## Demo Video [![Draw.io MCP Server Demo](https://img.youtube.com/vi/YAz-qjDPVZI/0.jpg)](https://youtu.be/YAz-qjDPVZI) ## Acknowledgements This project would not exist in this manner if it weren't for the following repositories and their authors. Thank you! - **Original drawio-mcp-server** by **Ladislav (lgazo)**: [lgazo/drawio-mcp-server](https://github.com/lgazo/drawio-mcp-server) - **Azure icons source** (`dwarfered`): [dwarfered/azure-architecture-icons-for-drawio](https://github.com/dwarfered/azure-architecture-icons-for-drawio) - **VS Code Drawio extension** by **hediet**: [hediet/vscode-drawio](https://github.com/hediet/vscode-drawio) ## Features - **700+ Azure Architecture Icons** — Official Microsoft icons with embedded SVG data, organized into ~20 categories (Compute, Networking, Storage, Databases, AI + ML, Security, and more) - **Basic Shapes** — Rectangles, ellipses, diamonds, parallelograms, and other flowchart primitives - **Fuzzy Search** — Find shapes by partial name across the entire icon library - **Batch Operations** — Create and update multiple cells in a single call for better performance - **Layer Management** — Create, list, and organize cells across layers - **Style Presets** — Built-in Azure, flowchart, and general color presets - **Multiple Transports** — stdio (default) and streamable HTTP - **XML Export** — Standard Draw.io XML format compatible with Draw.io desktop and web For PNG/SVG/PDF conversion, use jgraph's Draw.io `skill-cli` workflow: `https://github.com/jgraph/drawio-mcp/blob/main/skill-cli/README.md`. ## Documentation - Transactional mode design: [docs/transactional_mode_design.md](docs/transactional_mode_design.md) ## Requirements - **[Deno](https://deno.com/)** v2.3 or higher ## Quick Start ### From Source ```sh deno run --allow-net --allow-read --allow-env src/index.ts ``` ### MCP Client Configuration Configure your MCP client (Claude Desktop, VS Code, Codex, etc.) to use the server: #### Claude Desktop Edit `claude_desktop_config.json`: - **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json` - **Windows**: `%APPDATA%\Claude\claude_desktop_config.json` ```json { "mcpServers": { "drawio": { "command": "deno", "args": ["run", "--allow-net", "--allow-read", "--allow-env", "/path/to/drawio-mcp-server/src/index.ts"] } } } ``` #### VS Code Add to your VS Code settings or `.vscode/mcp.json`: ```json { "mcpServers": { "drawio": { "command": "deno", "args": ["run", "--allow-net", "--allow-read", "--allow-env", "/path/to/drawio-mcp-server/src/index.ts"] } } } ``` #### Zed In the Assistant settings, add a Context Server: ```json { "drawio": { "command": "deno", "args": ["run", "--allow-net", "--allow-read", "--allow-env", "/path/to/drawio-mcp-server/src/index.ts"], "env": {} } } ``` #### Codex Edit `~/.codex/config.toml`: ```toml [mcp_servers.drawio] command = "deno" args = ["run", "--allow-net", "--allow-read", "--allow-env", "/path/to/drawio-mcp-server/src/index.ts"] ``` For a locally running HTTP transport: ```toml [mcp_servers.drawio] url = "http://localhost:8080/mcp" ``` #### oterm (Ollama) Edit `~/.local/share/oterm/config.json`: ```json { "mcpServers": { "drawio": { "command": "deno", "args": ["run", "--allow-net", "--allow-read", "--allow-env", "/path/to/drawio-mcp-server/src/index.ts"] } } } ``` ## Configuration ### Transport Selection The `--transport` flag controls which transports to start. Default is `stdio`. | Flag | Description | | ------------------------ | -------------------- | | `--transport stdio` | stdio only (default) | | `--transport http` | HTTP only | | `--transport stdio,http` | Both transports | ### Environment Variables | Variable | Description | Default | | ------------------------- | ------------------------------------------------------------------------------------- | ---------- | | `AZURE_ICON_LIBRARY_PATH` | Path to Azure icon library XML file (auto-detected from `assets/` if unset) | (detected) | | `LOGGER_TYPE` | Logger implementation: `console` or `mcp_server` | `console` | | `HTTP_PORT` | HTTP server port (CLI `--http-port` takes precedence) | `8080` | | `TRANSPORT` | Transport type: `stdio`, `http`, or `stdio,http` (CLI `--transport` takes precedence) | `stdio` | | **`SAVE_DIAGRAMS`** | **⚠️ DEV MODE ONLY** — Auto-save diagram XML to `./diagrams/` on export/finish | (disabled) | > **Tip**: You can create a `.env` file from `.env.example` to configure environment variables locally: > > ```sh > cp .env.example .env > # Edit .env and uncomment/set SAVE_DIAGRAMS=true or other variables > ``` > > The server automatically loads `.env` files at startup. The `.env` file is gitignored and won't be committed to the repository. ### Development Mode — Auto-save Diagrams > **⚠️ WARNING: DEVELOPMENT MODE ONLY — NOT FOR PRODUCTION USE** For local debugging and development, you can enable automatic saving of diagram XML to a local `diagrams/` folder. This is useful for inspecting generated diagrams without manually copying XML output. **To enable:** ```sh export SAVE_DIAGRAMS=true deno task start ``` or ```sh SAVE_DIAGRAMS=true deno task start ``` **Behavior when enabled:** - Every call to `export-diagram` or `finish-diagram` automatically saves the XML to `./diagrams/_.drawio` - Timestamp format: `YYYYMMDD_HHMMSS` (e.g., `20260219_143052_export-diagram.drawio`) - The `diagrams/` folder is created automatically if it doesn't exist - Errors during file saving are logged but do not fail the tool operation **To disable (default):** Simply unset the environment variable or set it to any value other than `true` or `1`: ```sh unset SAVE_DIAGRAMS ``` or ```sh export SAVE_DIAGRAMS=false ``` **Security note**: This feature is **disabled by default** and should **never be enabled in production** or containerized deployments. It is intended solely for local development and debugging. ### HTTP Transport The HTTP transport exposes a streamable HTTP endpoint at `/mcp` (default port 8080). ```sh deno task start:http # or with a custom port: deno run --allow-net --allow-read --allow-env src/index.ts --transport http --http-port 4000 ``` MCP client configuration for HTTP: ```json { "mcpServers": { "drawio": { "command": "deno", "args": [ "run", "--allow-net", "--allow-read", "--allow-env", "/path/to/drawio-mcp-server/src/index.ts", "--transport", "http", "--http-port", "4000" ] } } } ``` Health check: `curl http://localhost:8080/health` ### Docker The Docker image uses `deno compile` to produce a self-contained native binary, then runs it on a minimal [distroless](https://github.com/GoogleContainerTools/distroless) base image (~20MB) with no shell, no package manager, and a non-root user. #### Pulling from Docker Hub A pre-built image is available on [Docker Hub](https://hub.docker.com/r/simonkurtzmsft/drawio-mcp-server). This is the fastest way to get started — no cloning or building required. **1. Pull the latest image:** ```sh docker pull simonkurtzmsft/drawio-mcp-server:latest ``` **2. Start the container:** ```sh docker run -d --name drawio-mcp-server -p 8080:8080 simonkurtzmsft/drawio-mcp-server:latest ``` This starts the server in the background, exposing the HTTP transport on port 8080. **3. Verify the server is running:** ```sh curl http://localhost:8080/health ``` You should receive an `OK` response, confirming the server is healthy and ready to accept connections. **4. Point your MCP client to the running container.** For example, in VS Code (`.vscode/mcp.json`): ```json { "mcpServers": { "drawio": { "url": "http://localhost:8080/mcp" } } } ``` Or in Claude Desktop (`claude_desktop_config.json`): ```json { "mcpServers": { "drawio": { "url": "http://localhost:8080/mcp" } } } ``` **5. To stop and remove the container:** ```sh docker stop drawio-mcp-server docker rm drawio-mcp-server ``` #### Building Locally To build the image from source instead of pulling from Docker Hub: ```sh # Build docker build -t drawio-mcp-server . # Run (exposes HTTP on port 8080) docker run -d --name drawio-mcp-server -p 8080:8080 drawio-mcp-server ``` #### Docker Compose ```sh cp .env.example .env # Configure REGISTRY and IMAGE_VERSION docker compose up -d ``` The `.env` file supports: - `REGISTRY` — Docker registry URL (e.g., `docker.io/myusername`) - `IMAGE_VERSION` — Semantic version for image tags (e.g., `1.0.0`) > **Note**: The distroless image has no shell, so in-container health checks (wget, curl) are not available. Use external health checks (e.g., Kubernetes liveness probes, load balancer health checks) to monitor the `/health` endpoint. ## Tools > **Performance tip**: All cell-manipulation tools accept arrays — pass ALL items in a single call rather than calling a tool repeatedly. > > **Stateless contract**: Diagram tools are stateless per call. Pass the full prior `diagram_xml` into each diagram-related tool call, and carry forward the returned `diagram_xml` from the response for the next call. ### Shape Discovery | Tool | Description | | ------------------------ | -------------------------------------------------------------------------------------------- | | `search-shapes` | Fuzzy search for shapes including 700+ Azure icons. Pass all queries in the `queries` array. | | `get-shape-categories` | List all shape categories (General, Flowchart, Azure categories). | | `get-shapes-in-category` | List all shapes in a category by `category_id`. | | `get-style-presets` | Get built-in style presets (Azure colors, flowchart shapes, edge styles). | ### Diagram Modification | Tool | Description | | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | | `add-cells` | Add vertices and/or edges. Supports `shape_name` for icon resolution, `temp_id` for within-batch references, and `dry_run` validation. | | `edit-cells` | Update vertex cell properties (position, size, text, style). | | `edit-edges` | Update edge properties (text, source, target, style). | | `set-cell-shape` | Apply library shape styles to existing cells. | | `delete-cell-by-id` | Remove a cell (vertex or edge) by ID. Cascade-deletes connected edges for vertices. | ### Diagram Inspection | Tool | Description | | ------------------- | ------------------------------------------------------------- | | `list-paged-model` | Paginated view of all cells with filtering by type. | | `get-diagram-stats` | Statistics about cell counts, bounds, and layer distribution. | | `export-diagram` | Export the diagram as Draw.io XML. | | `import-diagram` | Import a Draw.io XML string, replacing the current diagram. | | `clear-diagram` | Clear all cells and reset the diagram. | ### Layer Management | Tool | Description | | -------------------- | -------------------------------------- | | `list-layers` | List all layers with IDs and names. | | `set-active-layer` | Set the active layer for new elements. | | `create-layer` | Create a new layer. | | `move-cell-to-layer` | Move a cell to a different layer. | ### Page Management | Tool | Description | | ----------------- | ---------------------------------------------------------------- | | `create-page` | Create a new page (tab) in the diagram. | | `list-pages` | List all pages with IDs and names. | | `get-active-page` | Get the currently active page. | | `set-active-page` | Switch to a different page. | | `rename-page` | Rename an existing page. | | `delete-page` | Delete a page and all its contents. Cannot delete the last page. | ### Group / Container Management | Tool | Description | | ------------------------ | ---------------------------------------------------------------------- | | `create-groups` | Create group/container cells for VNets, subnets, resource groups, etc. | | `add-cells-to-group` | Assign cells to groups. | | `remove-cell-from-group` | Remove a cell from its group, returning it to the active layer. | | `list-group-children` | List all cells contained in a group. | ### Add Cells Example Use `add-cells` with `temp_id` references to create vertices and edges in a single call: ```json { "cells": [ { "type": "vertex", "temp_id": "web", "x": 100, "y": 100, "width": 60, "height": 60, "text": "Web", "style": "aspect=fixed;html=1;image;image=img/lib/azure2/compute/Container_Instances.svg;" }, { "type": "vertex", "temp_id": "api", "x": 220, "y": 100, "width": 60, "height": 60, "text": "API", "style": "aspect=fixed;html=1;image;image=img/lib/azure2/compute/Container_Instances.svg;" }, { "type": "edge", "source_id": "web", "target_id": "api", "text": "HTTPS" } ] } ``` ## Azure Icon Library The server includes **700+ official Azure architecture icons** from [dwarfered/azure-architecture-icons-for-drawio](https://github.com/dwarfered/azure-architecture-icons-for-drawio), organized into categories: | Category | Examples | | ----------------------- | --------------------------------------------------------------------- | | AI + Machine Learning | Cognitive Services, Azure OpenAI, Bot Service, Machine Learning | | Analytics | Synapse Analytics, Databricks, Data Factory, Event Hubs | | App Services | App Service, Static Web Apps | | Compute | Virtual Machines, Functions, AKS, Container Instances, Batch | | Containers | Container Registry, Container Instances, AKS | | Databases | SQL Database, Cosmos DB, Cache for Redis, PostgreSQL | | DevOps | Azure DevOps, Pipelines, Repos | | Identity | Azure AD, Key Vault | | Integration | Service Bus, Logic Apps, API Management, Event Grid | | Management + Governance | Monitor, Automation, Policy, Log Analytics | | Networking | Front Door, Load Balancer, Application Gateway, VPN Gateway, Firewall | | Security | Sentinel, Security Center | | Storage | Storage Account, Blob Storage, File Storage, Disk Storage | Icons use **embedded base64 SVG data** — no external dependencies, works fully offline with correct Azure branding and colors. The library loads lazily on first access (singleton pattern). Search operations are <5ms after initial load. ## Development ### Setup ```sh git clone https://github.com/simonkurtz-MSFT/drawio-mcp-server.git cd drawio-mcp-server ``` No install step needed — Deno resolves dependencies on first run. ### Common Commands | Command | Description | | ------------------------- | ------------------------------------ | | `deno task start` | Start with stdio + HTTP transports | | `deno task start:http` | Start with HTTP transport only | | `deno task dev` | Watch mode — auto-restart on changes | | `deno task test` | Run tests | | `deno task test:watch` | Run tests in watch mode | | `deno task test:coverage` | Run tests with coverage | | `deno task bench` | Run focused performance benchmarks | | `deno task lint` | Lint and type-check | | `deno task fmt` | Format code | | `deno task fmt:check` | Check formatting without writing | | `deno task compile` | Compile to a self-contained binary | | `deno task update` | Update dependencies and Docker Deno | `deno task update` refreshes `deno.json` dependency requirements and `deno.lock` via `deno outdated --update --latest`, then updates the Docker builder image's `DENO_VERSION` argument to the latest stable Deno GitHub release. ### MCP Inspector Use the [MCP Inspector](https://modelcontextprotocol.io/docs/tools/inspector) to debug the server: ```sh deno task inspect ``` After making changes, **Restart** the Inspector. After changing tool definitions, **Clear** and **List** the tools again. ## Related Approaches > **Note**: The comparisons below are all **as of February 2026**. Both projects and the agent skill continue to evolve — check their repositories for the latest state. This project is a fork of [lgazo/drawio-mcp-server](https://github.com/lgazo/drawio-mcp-server) by Ladislav Gazo. The original acts as a **bridge to a live Draw.io instance** via a WebSocket browser extension for interactive, real-time diagram control. This fork is a **standalone XML generator** — it builds diagrams in memory and outputs Draw.io XML without needing a browser or Draw.io instance. [thomast1906/github-copilot-agent-skills](https://github.com/thomast1906/github-copilot-agent-skills/tree/main/.github/skills/drawio-mcp-diagramming) takes yet another approach: a **Copilot Agent Skill** that constructs raw Draw.io XML and sends it to the hosted `mcp.draw.io` service, guided by prompt instructions and a static Azure icon catalog. | Aspect | simonkurtz-MSFT | Original (lgazo) | Agent Skill (thomast1906) | | -------------------------------- | ------------------------------------------------------ | ------------------------------------------------------ | --------------------------------------------------- | | **Architecture** | Standalone MCP server — generates XML in memory | Bridge to live Draw.io via WebSocket browser extension | Copilot Agent Skill + hosted `mcp.draw.io` endpoint | | **Runtime** | Deno (TypeScript) | Node.js + pnpm (TypeScript + JavaScript) | None (prompt-driven) | | **Draw.io instance required** | ❌ | ✅ Browser + MCP extension | ❌ (uses hosted endpoint) | | **Setup effort** | Clone + Deno, or `docker pull` | `npx` + browser extension + open Draw.io | Drop `SKILL.md` + catalog into repo | | **Batch operations** | ✅ Arrays in `add-cells`, `edit-cells`, etc. | ❌ One tool call per cell | ✅ Full XML in one shot | | **Azure icons** | ✅ 700+ embedded base64 SVG | ✅ From live Draw.io libraries | ✅ Static catalog (`img/lib/azure2/…`) | | **Fuzzy shape search** | ✅ `search-shapes` | ❌ Exact name lookup only | ❌ | | **Page management** | ✅ | ❌ | ❌ | | **Group / container management** | ✅ | ❌ | ❌ | | **Iterative editing** | ✅ Stateful model, incremental calls | ✅ Live edits in Draw.io | ❌ Regenerate full XML each time | | **Interactive features** | ❌ Stateless XML generation | ✅ `get-selected-cell`, `set-cell-data` | ❌ | | **Docker / cloud deployment** | ✅ Distroless image (~20 MB) | ❌ npm package only | ❌ Relies on hosted endpoint | | **Offline support** | ✅ Fully offline | ⚠️ Needs browser with Draw.io | ❌ Requires internet | | **Best for** | CI/CD, containers, headless / offline batch generation | Interactive diagramming with real-time visual feedback | Quick one-shot diagrams with zero install | All three approaches are valid — the right choice depends on whether you need interactive visual feedback (original), headless batch generation (this fork), or a zero-install agent skill. ## License [MIT](LICENSE.md)