dgv
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@dgvlint the architecture diagram"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Thirty seconds
git clone https://github.com/ShAInyXYZ/Dia-GramV.git && cd Dia-GramV
npm install && npm run build
node packages/mcp/bin/dgv.mjs doctor # checks Node + the build, prints the lines below with your path
claude mcp add dgv -s user -- node "$PWD/packages/mcp/bin/dgv.mjs" mcp
ln -s "$PWD/skill" ~/.claude/skills/dgv # optional: teaches the agent the workflowThen, in any project, tell the agent:
Map this system in DGV before we start.
It reads the catalog, writes dgv/<name>.dgv.json, gets a lint report back on every write, repairs what it broke, lays the diagram out and opens it at http://127.0.0.1:7710. From then on the file is the map: every later session reads it before it reads code.
Needs Node 20.19+ or 22.12+. npm install fetches everything (~100 MB, nothing global); npm run build compiles the viewer once. Skip the build if you only want the MCP tools — everything works without it except dgv_open.
Related MCP server: mermaid-mcp-server
What's new · v0.2 — flags and history
The agent can now flag an architecture problem on the exact node, wire or frame it is about — a ⚑ bubble on the canvas with what is wrong, why, and the fix — and every change to the diagram, by the agent or by you, lands in a history you open from the bottom of the canvas. Three new MCP tools: dgv_flag, dgv_resolve, dgv_history.
Lint says whether the graph is valid. It cannot say whether the design is right. Reviewing a real project through its diagram, the agent found six things no rule would ever fire on — a process that was a dead end for settings (every change was a restart), plugins loaded three times across the map, a spawned child with no death-pact — and had nowhere to put them but a chat message that scrolls away. Now it has two places: a flag on the element, and a record of what changed.
How you use it. After the map exists, ask for a review rather than a fix:
Read the diagram, then audit the architecture for incoherences lint can't see. Verify each against the code. Pin every real one on its element with what's wrong, why, and the fix. Don't fix anything yet.
Open the viewer: every flag is a ⚑ on its card, filled and ringing until read. Click one to read the note; resolve the ones you disagree with (the history keeps the fact that it was raised), leave the rest. Then: "fix the open flags on chainx, resolve each as you go" — and the history pill turns 3 new when the agent's writes land, with a mark on every card it touched. Layout moves are not recorded; architecture is.
Where it lives. Flags sit on the element in the file ("flags": [ { "id", "kind", "title", "note", "fix", "by", "at" } ]) and lint reports each one — flag/issue counts as a warning, flag/idea and flag/question as info — so the problems panel, the rail counter and the report dgv_apply returns all carry them. ack never silences a flag; only resolving does. History is computed by the server on every save, by diffing the file on disk against the one being written, and kept in the file as history (the last 300 changes). Nobody has to remember to log anything, and a save from the browser records the same way as one from the agent. Existing diagrams need nothing — the fields are optional and appear on the first save.
Every new command.
where | command | does |
MCP |
|
|
MCP |
|
|
MCP |
|
|
MCP |
| unchanged, plus: accepts |
MCP |
| unchanged, plus: |
CLI |
| the history in the terminal |
viewer |
| open / close the history |
viewer | click a ⚑ | read the note; resolve removes the flag |
viewer | inspector → | raise a flag by hand on the selected element |
What it is
One file. dgv/<name>.dgv.json holds frames (boundaries), nodes (components) and edges (connections). Every node has a kind from a fixed catalog — ui, service, api, db, queue, bridge, external… — and can declare ports. Every edge names the port it lands on and the protocol it speaks. Plain JSON, in your repository, next to the code it describes.
Two ways in. The MCP server is the agent's: it creates, changes and reads the file, and on every write gets a lint report — a stable code, the element, and concrete fixes. The viewer is yours: a Svelte Flow canvas where kinds have shapes and wires carry their protocol, with an inspector for every field and the same lint live in a side panel. When the agent changes the file, the page reloads.
Why it matters when an AI writes the code
The drawing is the least important part. What matters is that the model of the system is a file a program can read, check and change.
If you vibecode, the system grows faster than you can keep it in your head, and the shape you think it has drifts from the shape it has. DGV gives that shape a place to live, and a linter that objects when it stops making sense.
If you develop with an AI beside you, the diagram is where you state intent the code cannot express yet — the worker consumes the queue; the API never writes to the bucket directly — once, in a form every later session inherits.
If you are the agent, this is the difference between grepping and knowing. In an unfamiliar repository you rebuild the picture by opening files. dgv_read hands you the picture. Its complete output for the notes app below, verbatim:
# Notes app
frames 3 · nodes 6 · edges 5 · updated 2026-08-27
## frame browser: Browser
- web [ui] Notes UI — SvelteKit
## frame server: Server · one process
- api [api] HTTP API — /api/notes ports: rest:http/in
- jobs [worker] Job runner — thumbnails, exports
## frame data: Data
- pg [db] Postgres — notes, users ports: sql:sql/in
- redis [queue] Job queue — Redis lists ports: jobs:redis/in
- s3 [storage] Object store — uploads ports: put:s3/in
## edges
- web-api: web → api [sync http] fetch ports ·→rest
- api-pg: api → pg [data sql] ports ·→sql
- api-redis: api → redis [async redis] enqueue ports ·→jobs
- jobs-redis: jobs → redis [async redis] consume ports ·→jobs
- jobs-s3: jobs → s3 [data s3] ports ·→putAn agent that can read api → pg [data sql] ·→sql does not invent a REST endpoint on the database. Two hundred tokens replace a tour of the tree.
What it does — four cases
1 · Plan before you build, and be told when the plan cannot work
The agent describes a small notes app in one dgv_apply. Two ordinary mistakes are in it: the object store's port is called put on the node and upload on the edge, and a database is calling back into the API.
dgv_apply({ name: "notes-app",
nodes: [ { id: "s3", kind: "storage", label: "Object store", frame: "data",
ports: [ { id: "put", protocol: "s3", dir: "in" } ] }, … ],
edges: [ { id: "jobs-s3", source: "jobs", target: "s3", kind: "data", protocol: "s3", targetPort: "upload" },
{ id: "pg-api", source: "pg", target: "api", kind: "sync", protocol: "http", label: "notify on change" }, … ] })The write goes through, and the report comes back in the same turn:
{ "ok": false, "lint": { "error": 1, "warning": 2, "info": 0 },
"diagnostics": [
{ "code": "port/undeclared", "severity": "error",
"message": "edge \"jobs-s3\" uses target port \"upload\" but node \"s3\" does not declare it",
"subject": { "type": "edge", "id": "jobs-s3", "field": "targetPort" },
"fixes": [ "add port {id:\"upload\"} to node \"s3\"", "point the edge at one of: put" ] },
{ "code": "kind/store-initiates", "severity": "warning",
"message": "\"pg\" is a db; stores do not initiate sync calls to \"api\"",
"subject": { "type": "edge", "id": "pg-api" },
"fixes": [ "reverse the edge and mark it kind:\"data\"",
"if it is a trigger/CDC stream, add a worker or queue between them" ] }, … ] }The same report in the viewer — the failing wire is red, and every entry jumps to its element:
The first mistake is a typo that would have become a bug. The second is an architecture an agent would have implemented without a second thought. Both come back as an id, a code and a fix, so the plan is repaired before any code exists:
dgv_apply({ name: "notes-app",
edges: [ { id: "jobs-s3", targetPort: "put" } ], // partial: id + the field that changes
remove: { edges: [ "pg-api" ] } })
→ { "ok": true, "lint": { "error": 0, "warning": 0, "info": 0 } }2 · Map a system you already have
Point the agent at a repository — map Cerveau's architecture in DGV, from the code — and it reads entrypoints, listeners, clients and config, then writes what it found. The local AI harness below is 13 components in four boundaries: a panel and a phone driving a Go core, a llama.cpp server, Typesense for memory, a Python embedding sidecar.
At full size — Cerveau itself, 35 components across 7 boundaries, every call bound to a declared port:
Press S and every frame folds into one node, with the wires that crossed it merged into a single labelled link. Same file; there is no second overview diagram to keep in step with the first:
3 · Track the build on the same diagram
A node can carry a status — todo wip done blocked failed update. Press 2 and the canvas colours by status instead of kind; the file is now the build board. An agent picks up where the last session stopped by reading what is still todo, and a note on a blocked node says why:
4 · Know when it stops being true
Lint says the plan is coherent. It cannot say the plan is true — that the code on disk is still the code the diagram describes. Give a node a path (a file, a directory, a glob, a list) and dgv_drift walks the project — git ls-files, so .gitignore is respected — and reports a path that matches nothing (drift/missing), a directory of code that belongs to no node (drift/unclaimed), and two nodes claiming the same file (drift/shared).
This repository keeps its own architecture that way, every node with a path:
The first time drift ran on it, it found something:
$ node packages/mcp/bin/dgv.mjs drift dia-gramv
warning drift/unclaimed packages/mcp/ — 1 of 5 files belong to no node
fix: add a node with this path | widen an existing node's path to cover it | add it to meta.driftIgnore if it is not part of the systempackages/mcp/package.json, claimed by nobody, because the MCP node's path was one file. Widened, and clean.
Two optional Claude Code hooks close the loop (hooks/; doctor prints the settings block with your path):
SessionStart prints the outline of every diagram in
./dgvinto context, with its drift summary — the first thing the agent knows is the shape of the system and whether the map is stale.Stop runs drift after each turn and, only when there is something to say, leaves one line:
DGV · app: 1 node path no longer exists (old). It never blocks.
The viewer
node packages/mcp/bin/dgv.mjs serve → http://127.0.0.1:7710 — or dgv_open from the agent.
Flags. Lint catches what a rule can catch. The agent (or you) catches the rest — a process that is a dead end for settings, plugins loaded three times across the map, a child process with no death-pact — and pins it on the element with dgv_flag. On the canvas it is a ⚑ bubble on the card, the frame label or the wire, filled and ringing until you open it; the note says what is wrong, why, and the concrete fix, with a resolve button. Open flags sit in the problems list too (flag/issue counts as a warning), and in the outline every session starts with.
History. The pill at the bottom centre — history · 3 new — opens upward into what changed: per element (chainx · 4 changes · 2m ago, click to see them and jump to the card) or as a timeline. Every save that changes the architecture lands there, whether it came from dgv_apply (agent) or from this page (you): a status flipped, a port added, a node renamed, a flag raised or resolved. Dragging cards around does not count. It is computed on the server by diffing the file on every write, kept in the file (capped), and readable from the agent with dgv_history. Cards changed since you last looked carry a small green mark.
Drag a node into a frame and it joins it; frames grow to fit. Ctrl+Z undoes. Ctrl+S saves — and if the agent changed the file while you had unsaved edits, the page says so and lets you choose. L cycles the wire style: floating bezier, routed around cards, straight. Shift+S saves what is on screen as a self-contained SVG, which is how every diagram in this README was made.
| add a node, choosing its kind |
drag from a node's right handle | connect; drop on a port chip to bind the edge to that port |
| wrap the selection in a new frame |
| colour by kind / by status |
| wire style: floating, routed, straight |
| fold every frame into one node; again to unfold. Hover a single frame to fold just that one |
| save what is on screen as SVG |
| the change history |
|
The folded view keeps its own arrangement per diagram in your browser, never in the file.
Reference
tool | does |
| the node kinds (shape and meaning), edge kinds, protocols and statuses — read once per session |
| the diagrams in the directory, with counts |
| one diagram: |
| a new, empty diagram |
| upsert frames, nodes and edges by id; remove by id; places new nodes; returns the lint report. Partial: to change one field on an existing element, send its id and that field |
| the diagnostics: |
| does the diagram still describe the code? every |
| pin an architecture judgement on a node, edge or frame — |
| remove a flag once it is fixed; the history keeps both ends |
| who changed what: every architecture change per element, |
| dagre layout, |
| starts the viewer if it is not running and opens the diagram |
|
|
Diagrams go to ./dgv under the directory the agent was started in; DGV_DIR puts them elsewhere.
Shape first (schema/invalid), then references (ref/missing-node, ref/missing-frame, ref/duplicate-id), then the rules below. Errors block ok; warnings and info are advice.
Errors — fix before moving on.
code | fires when |
| an edge names a port the node does not declare |
| the edge's protocol is not the port's protocol |
| an edge enters an |
| modules import each other in a loop |
| a frame has a |
Warnings — the plan probably has a hole.
code | fires when |
| the target declares ports and a call edge names none |
| an edge between different kinds has neither a protocol nor a label |
| a database, cache or bucket is the source of a call |
| an import crosses a frame boundary — two processes cannot share one |
| an API that nothing calls |
| a bridge touching fewer than two other nodes |
| a node with no edges |
| cards overlap, or sit outside their frame — |
Info — worth a look, silent in the counts: kind/store-access, kind/module-loose, kind/external-inside, graph/shared-store, layout/unplaced.
Flags — not rules but judgements, raised with dgv_flag: flag/issue is a warning, flag/idea and flag/question are info. They are never acknowledged away; they are resolved.
A warning that is intentional gets ack: "<reason>" on its element: it becomes info with the reason attached, and the reason travels with the file. Errors cannot be acknowledged.
{ "dgv": 1,
"meta": { "title": "Notes app", "description": "…", "colorBy": "kind", "edgeStyle": "routed" },
"frames": [ { "id": "server", "label": "Server · one process", "tone": "amber",
"position": { "x": 480, "y": 60 }, "size": { "width": 380, "height": 300 } } ],
"nodes": [ { "id": "api", "kind": "api", "label": "HTTP API", "sublabel": "/api/notes",
"frame": "server", "status": "done", "path": "src/api", "position": { "x": 520, "y": 120 },
"ports": [ { "id": "rest", "protocol": "http", "dir": "in" } ] } ],
"edges": [ { "id": "web-api", "source": "web", "target": "api",
"kind": "sync", "protocol": "http", "targetPort": "rest", "label": "fetch",
"flags": [ { "id": "f1", "kind": "issue", "title": "no death-pact on the child", "fix": "PR_SET_PDEATHSIG", "by": "agent", "at": "2026-08-28T12:15:00Z" } ] } ],
"history": [ { "at": "2026-08-28T12:15:00Z", "by": "agent", "type": "edge", "id": "web-api", "op": "flag", "flag": { "id": "f1", "kind": "issue", "title": "no death-pact on the child" } } ] }flags may sit on any frame, node or edge; history is written by the store on every save (never by hand) and holds the last 300 architecture changes.
kind is required on a node. On an edge it is inferred from the protocol when omitted — data for sql redis s3 fs smb, async for kafka nats amqp mqtt sse ws, otherwise sync. Positions are saved, so an arrangement you made stays made. The full catalog — every kind, protocol and lint code — is in skill/references/format.md.
node packages/mcp/bin/dgv.mjs serve [--dir d] [--port p] [--no-open] # viewer, default http://127.0.0.1:7710
node packages/mcp/bin/dgv.mjs lint <name|file> [--json]
node packages/mcp/bin/dgv.mjs layout <name|file> [--direction TB|LR]
node packages/mcp/bin/dgv.mjs export <name|file> [--format markdown|mermaid|summary|svg]
node packages/mcp/bin/dgv.mjs drift <name|file> [--root dir] [--json]
node packages/mcp/bin/dgv.mjs history <name|file> [--on id] [--limit n]
node packages/mcp/bin/dgv.mjs list | catalog | doctor | open <name>path | what |
| plain ESM, no DOM: catalog, schema, lint, dagre layout, orthogonal wire router, fold, exports, drift, history, file store |
| the |
| Svelte 5 + Svelte Flow: shaped nodes, frames, folding, inspector, live problems, flag bubbles, change history |
| a Claude Code skill ( |
| SessionStart and Stop hooks for Claude Code |
| this repository's own diagram, drift-checked |
|
|
npm test — core: schema, lint rules, patch semantics, layout containment, folding, exports, SVG, drift.
Limits
DGV does not parse your source. Lint can tell you the plan is coherent; drift can tell you every node still points at code that exists and every directory of code has a node. Neither can tell you that the calls the diagram draws are the calls the code makes — that is still read by a person, or by the agent, and the file living in the repo is what makes that reading reviewable.
Not here: collaboration or hosting, sequence and lifecycle diagrams, discovery of a repository's structure. The format is versioned (dgv: 1) so those can be added without breaking existing files.
Where it came from
Cerveau is a local-first agentic coding harness. Its docs folder held a private draft called arch-viewer: a Svelte Flow canvas reading a Diagram.json of its architecture — 99 nodes, 127 edges, nodes with a kind, edges with a label. Nothing but a browser could read it, so the agent doing the building never saw it. DGV keeps the canvas, the frames and the layout, and puts a contract underneath: a catalog, ports and protocols, declared membership, a linter, and an MCP so the agent reads and writes the same file. archify supplied the idea of a typed intermediate representation with repairable diagnostics.
MIT © Mounir Belahbib
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Render, verify, describe, and safely edit Mermaid diagrams through MCP.
Generate org charts, MCD/ERD data models, and C4 architecture diagrams — pilot OrgGen AI via MCP.
Create and edit architecture diagrams from your AI agent; get an SVG and a live editable canvas.
Create and manage Mermaid.js flowcharts and diagrams with AI agents via MCP.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables programmatic creation and management of draw.io diagrams through MCP tools. Supports building architecture diagrams, flowcharts, and visualizations with stateless operations that generate VSCode-compatible .drawio.svg files.91Apache 2.0
- AlicenseNot gradedqualityDmaintenanceProvides MCP tools to validate Mermaid diagram syntax, render diagrams to SVG, and get documentation links.7516MIT
- AlicenseAqualityDmaintenanceGenerates Excalidraw architecture diagrams with support for 60+ components including GCP, Kafka, and AI/Agentic shapes. Provides MCP tools for creating, modifying, and converting diagrams from structured input or Mermaid syntax.41MIT
- FlicenseAqualityDmaintenanceEnables local Draw.io diagram creation, editing, and export via MCP tools, using the desktop app.52
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/ShAInyXYZ/Dia-GramV'
If you have feedback or need assistance with the MCP directory API, please join our Discord server