LabscoMCP early access ↗
h0rvMCP SERVER

D2 MCP

Validate and render D2 diagrams from your assistant — PNG, SVG, or ASCII a model can read back.

by h0rv ↗Diagrams & ChartsCommunity

LABSCO SUMMARY

The diagram is checked before it is drawn.

Compiling first is what makes this usable in a loop: the model gets told exactly where the syntax broke, fixes it, and only then renders — and in ASCII mode it can read its own output and iterate without a human looking at the picture.

What it is

A Go server for D2, the declarative diagramming language. It compiles D2 source to catch syntax errors before anything renders, produces the diagram in the format you asked for, and carries a built-in cheat sheet so the model has the syntax to hand rather than guessing at it.

What you get

  • compile-d2 — validates D2 source and surfaces syntax errors, taking either code or a file_path
  • render-d2 — renders to png, svg or ascii, with ascii_mode choosing extended Unicode box drawing or standard basic characters; ASCII is the one an LLM can read back
  • fetch_d2_cheat_sheet — a Markdown reference covering shapes, styling and layout, useful as support material in a prompt
  • Optional file output with --write-files, so rendered diagrams land in a mounted directory rather than only in the response

Requirements

Install with go install github.com/h0rv/d2-mcp@latest, build from source, or run the container image ghcr.io/h0rv/d2-mcp:main. PNG output needs rsvg-convert from librsvg present — install it with brew, apt or apk — and without it the server removes png from the format enum and falls back to SVG rather than failing; the Docker image ships librsvg and fallback fonts, so PNG works there out of the box. Defaults to stdio; --transport http serves the streamable endpoint at /mcp and --transport sse the legacy one, with MCP_TRANSPORT and PORT as environment overrides. Writing files requires a bind mount, since the container has no view of your working tree otherwise.

Setup effort

One command — go install github.com/h0rv/d2-mcp@latest