mcp-drawio-server

mcp-drawio-server

Turns relational schemas into editable entity-relationship diagrams in draw.io, supporting live databases, SQL DDL, YAML/JSON specs, and existing .drawio files, with tools for managing tables, columns, and relations.

Category
Visit Server

README

MCP draw.io server

mcp-drawio-server is a local MCP server that turns a relational schema into an editable entity-relationship diagram in draw.io. It can reflect a live database, parse SQL DDL, read a YAML or JSON schema specification, or reopen an existing uncompressed .drawio file. It also exposes granular tools for changing tables, columns, relations, and layout before saving the diagram.

The schema model is the source of truth. Every save regenerates the complete mxGraph document instead of patching XML cells in place.

Relations use deterministic, obstacle-aware orthogonal routing. Each endpoint gets a private port, crowded hubs fan out into separate lanes, recursive relations loop outside their table, and persistent waypoints keep the route stable when the file is reopened. Adjacent hub ports keep a visible pitch, terminal stubs cannot backtrack over themselves, and arc jumps make the remaining crossings explicit. Crow's-foot markers include nullable-FK optionality (0..1, 0..N, 1, and N).

Requirements and installation

  • Python 3.14 or newer
  • uv
  • draw.io Desktop is optional for generation, but required for interactive viewing and the final compatibility check

Install the locked environment:

git clone https://github.com/marcelovillanuevam-code/MCP-Draw.IO.git
cd MCP-Draw.IO
uv sync --locked

Run the stdio server directly while developing:

uv run --locked --no-sync mcp-drawio-server

The server communicates over standard input and output, so it normally appears to wait silently when started by hand.

Register with Claude Code

Register it as a user-scoped utility so it is available in every project. Use absolute paths because Claude starts the command directly rather than through an interactive shell.

claude mcp add --transport stdio --scope user drawio -- \
  /absolute/path/to/uv run \
  --project /absolute/path/to/MCP-Draw.IO \
  --locked --no-sync \
  mcp-drawio-server

uv run --project selects this project's environment without changing the server process's working directory. This matters because relative output paths normally resolve from the Claude project that launched the server. Do not replace it with uv --directory, which changes the working directory to this repository.

Confirm the registration, then start a new Claude Code session:

claude mcp get drawio
claude mcp list

Use --scope local instead if the server should be available only in the current Claude project.

Configuration and output paths

The only server setting is optional:

MCP_DRAWIO_OUTPUT_DIR=/absolute/path/to/diagrams

It is the base directory for relative .drawio save and open paths. If it is unset, the process working directory is used. Absolute paths always take precedence, and a missing .drawio extension is added automatically. The server creates missing parent directories when it saves.

The project does not load .env files itself; .env.example documents the variable for shells, process managers, or MCP client configuration. To pin a single output directory in Claude Code, add the environment setting when registering the server:

claude mcp add --transport stdio \
  -e MCP_DRAWIO_OUTPUT_DIR=/absolute/path/to/diagrams \
  --scope user drawio -- \
  /absolute/path/to/uv run \
  --project /absolute/path/to/MCP-Draw.IO \
  --locked --no-sync \
  mcp-drawio-server

Named diagrams live only in the server process. Save important work before the session ends, and use open_diagram to restore it in a later session.

Input formats

Live database

load_database_schema uses SQLAlchemy reflection. It supports a named schema and include/exclude table filters. SQLite works without an extra package; other engines require a DBAPI driver.

Database Example URL Driver command
SQLite sqlite:////absolute/path/store.db Built in
PostgreSQL postgresql+psycopg://user:password@host/database uv add "psycopg[binary]"
MySQL/MariaDB mysql+pymysql://user:password@host/database uv add pymysql

Other SQLAlchemy dialects may work after their driver is installed, but are not part of the base environment. Run driver installation commands from the project root so pyproject.toml and uv.lock stay in sync.

SQL DDL

load_ddl_schema accepts SQL text or a file path. Pass a sqlglot dialect such as postgres, mysql, sqlite, or tsql when the syntax is dialect-specific. Only CREATE TABLE statements contribute to the diagram; unrelated statements are skipped. Foreign keys to tables outside a partial DDL input are omitted. Constraints must appear inside CREATE TABLE; dump-style ALTER TABLE ... ADD CONSTRAINT statements and standalone CREATE UNIQUE INDEX statements are not currently imported by the DDL parser.

YAML or JSON specification

load_spec_schema accepts text or a file path. JSON is parsed as a subset of YAML. Both expanded objects and concise column/relation forms are supported:

name: shop
tables:
  customer:
    columns:
      - "customer_id: INTEGER pk"
      - "email: VARCHAR(255) not null unique"
  orders:
    columns:
      - "order_id: INTEGER pk"
      - "customer_id: INTEGER required"
relations:
  - orders.customer_id -> customer.customer_id

Column shorthand recognizes pk/primary key, unique/uq, not null/ not_null/notnull/required, and null/nullable. A <table>_id column may infer a relation to a matching table with a single-column primary key when no explicit relation exists.

Composite unique keys use the expanded table form and participate in cardinality inference:

tables:
  enrollment:
    columns:
      - "student_id: INTEGER"
      - "course_id: INTEGER"
    unique_keys:
      - [student_id, course_id]

draw.io XML

open_diagram reads uncompressed .drawio or .xml mxGraph documents. Generated files use draw.io's native table, table-row, and ERD edge shapes.

MCP tools

The server exposes 16 tools. A loader creates a named diagram or replaces the schema of an existing diagram with that name.

Tool Purpose
load_database_schema(url, diagram, schema=None, include_tables=None, exclude_tables=None) Reflect selected tables from a live database.
load_ddl_schema(diagram, ddl=None, path=None, dialect=None) Load CREATE TABLE statements from inline DDL or one file.
load_spec_schema(diagram, spec=None, path=None) Load an inline YAML/JSON specification or one file.
open_diagram(path, diagram=None) Open an existing uncompressed draw.io document.
list_diagrams() List the diagrams currently held in memory.
describe_diagram(diagram) Summarize tables, primary keys, and relations.
add_table(diagram, table, columns) Add a table; columns is a list of column shorthand strings.
remove_table(diagram, table) Remove a table and relations that touch it.
add_column(diagram, table, column) Add one column from shorthand.
remove_column(diagram, table, column) Remove a column and invalidated relations.
add_relation(diagram, source, target, cardinality=None, name=None) Add a relation between endpoints such as orders.customer_id and customer.customer_id.
remove_relation(diagram, source, target) Remove the relation matching the two endpoints.
move_table(diagram, table, x, y) Set a table's draw.io coordinates.
relayout_diagram(diagram) Recompute the complete automatic layout.
save_diagram(diagram, path=None) Regenerate and save .drawio XML; omit path after the first save.
export_spec(diagram, format="yaml") Return the current schema as YAML or JSON.

Composite endpoints use parentheses, for example order_line.(order_id,line_no). Explicit cardinalities are one-to-one, one-to-many, and many-to-many; when omitted, the server infers cardinality from keys where possible.

The MCP server produces .drawio/.xml and YAML/JSON text. It does not export PNG, SVG, or PDF itself; use draw.io Desktop or its CLI for those formats.

Security

  • Treat a database URL as a secret. Do not commit it, paste it into issue reports, or store it in .env.example; MCP tool calls and client logs may retain arguments.
  • Percent-encode reserved characters in usernames and passwords, and quote a URL when passing it through a shell. Prefer short-lived credentials so an accidentally retained URL has limited value.
  • Use a dedicated, least-privilege, read-only database account and encrypted transport for remote databases. Reflection reads metadata, but the database still receives a real connection from this process.
  • Schema names, table names, column names, and comments returned by reflection become available to the MCP client and model. Do not introspect sensitive production metadata unless that disclosure is acceptable.
  • File tools can read or write any path permitted to the server process. There is no built-in path allowlist, so use a restricted OS account or container when processing untrusted requests.
  • DDL and YAML/JSON inputs are parsed locally and are not executed against a database.

Round-trip limitations

  • Compressed draw.io documents cannot be opened. In draw.io Desktop, use File > Properties, clear Compressed, and save again.
  • Multi-page files are rejected rather than silently dropping pages. Save the ERD page as a separate uncompressed file before calling open_diagram.
  • Generated files contain a hidden mcp-schema-metadata JSON cell. The server prefers its canonical schema on reopen, while current visible table geometry wins over stale coordinates in the hidden payload.
  • Manual edits to visible table shapes do not update the hidden metadata. Moves and resizes are recovered from visible geometry, but manually renamed columns, added rows, or new relations can be ignored the next time the MCP server opens the file. Make structural changes through the MCP tools.
  • Manually edited edge ports and waypoints are intentionally regenerated from the schema and current table positions on the next save. Table geometry is preserved; route geometry is deterministic rather than a round-trip input.
  • A foreign or metadata-free draw.io document is parsed from its visible native table shapes on a best-effort basis. Names, types, common key markers, and row-anchored relations can be recovered. A table-to-table edge without MCP endpoint attributes is skipped because its columns cannot be inferred safely. Comments, arbitrary styling, some constraint details, and complex edge semantics may be lost. The next save regenerates the document in the server's standard style.
  • The router separates shared lanes and avoids table interiors, but a dense ERD can still contain line crossings. Crossings use arc jumps, and relation labels have opaque backgrounds. Labels can be dragged in draw.io when final presentation polish matters.

Tests

Run the full suite from any directory:

uv run --project /absolute/path/to/MCP-Draw.IO \
  --locked --no-sync pytest

The suite should cover all input sources, composite-primary-key cardinality, granular tools, save/open behavior, and draw.io round-trips both with and without embedded metadata.

The real stdio subprocess test is opt-in because restricted sandboxes can block AnyIO worker threads used by the SDK transport:

MCP_STDIO_INTEGRATION=1 uv run --locked --no-sync \
  pytest tests/test_stdio.py

Desktop validation

XML parsing and server round-trip tests do not prove that draw.io Desktop lays out and edits every native shape correctly. Before a release, generate a representative ERD containing PK, FK, combined PF, unique, nullable, one-to-one, one-to-many, and composite-key cases.

First exercise the real Desktop renderer non-interactively:

drawio --export --format png --border 20 \
  --output validation.png validation.drawio

On Windows PowerShell, replace drawio with the full path to draw.io.exe. Then open validation.drawio in the desktop application and confirm:

  • table headers and rows render without clipping or overlap;
  • PK, FK, PF, and U markers are visible;
  • ERD endpoints and cardinality markers are correct;
  • single-column relations attach to their column rows;
  • every relationship can be traced independently from endpoint to endpoint;
  • parallel relationships use separate ports and lanes rather than sharing a segment;
  • recursive relationships loop outside the table;
  • crossings have visible arc jumps and no route crosses a table interior;
  • tables can be selected, moved, resized, collapsed, and expanded;
  • the hidden metadata cell is not visible; and
  • saving with compression disabled produces a file open_diagram can reopen.

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured