The diagram library agents can reliably create, edit, validate, and explain.
@aigentive/wire is an LLM-first diagram library with native MCP support. It pairs a canonical JSON schema for agent-friendly diagrams with a shared reducer, a reusable Wire-native React editor/viewer, static SVG/PNG/Mermaid renderers, and an MCP server so any MCP-compatible agent can author and edit diagrams as structured graphs, not pixels.
LLMs and agents struggle with diagrams: they emit Mermaid blobs that almost render, JSX trees that go fragile on edit, or PNGs they cannot revise. Wire solves this by giving agents a structured graph they can read, mutate, validate, and re-render — with the same canonical model behind a JSX developer surface and an MCP tool surface.
- Canonical JSON —
from,branch,attachedTo,tone,handles, style, routing, and metadata semantics designed to be unambiguous to LLMs. - Shared actions — every human, hosted editor, CLI, and MCP edit flows through the
WireActionreducer inwire-core. - React library —
WireEditor,WireViewer,WireCanvas, palette, toolbar, inspector, validation panel, and JSX authoring. - LLM-friendly React extensibility — option catalogs, custom node cards, custom edge renderers, and custom group renderers without requiring app code to import a graph-canvas package.
- Static renderers — SVG, PNG, Mermaid, and optional React Flow conversion without pulling React into server-only consumers.
- MCP server — diagram CRUD, direct action tools, atomic
apply_actions, resources, prompts, render tools, andv1_get_agent_guideover stdio or HTTP. - Hosted parity — the playground/editor uses
@aigentive/wire-react, stores canonical JSON, and renders from the same model as MCP.
| Package | Description |
|---|---|
@aigentive/wire-core |
Schema, validation, IDs, graph normalization, layout, pure WireAction reducer |
@aigentive/wire-renderers |
Static renderers and adapters: SVG, PNG helpers, Mermaid, optional React Flow conversion |
@aigentive/wire-react |
Reusable React editor/viewer components and JSX authoring facade |
@aigentive/wire-mcp |
MCP server (stdio + streamable-HTTP) |
@aigentive/wire-cli |
wire CLI (init, add, validate, export, ls) |
apps/playground |
Self-hostable Next.js playground, JSON share API, React editor, preview/render service |
# clone + install
git clone https://github.com/aigentive/wirediagram.git
cd wirediagram
npm install
npm run build
npm test# npm package, stdio transport
npx -y @aigentive/wire-mcp@latest
# or HTTP transport (default port 3860)
npx -y @aigentive/wire-mcp@latest --http{
"mcpServers": {
"wire": {
"command": "npx",
"args": ["-y", "@aigentive/wire-mcp@latest"],
"env": {
"WIRE_STORAGE_DIR": "/absolute/path/to/diagrams"
}
}
}
}npm install -g @aigentive/wire-cli
wire init my-flow --template=approval-flow
wire add ai --diagram=my-flow --title="Classify" --from=incoming --model=gpt-5.4-mini
wire validate my-flow
wire export my-flow --format=svg --out=my-flow.svg
wire lsControlled editor:
import type { WireDiagram } from "@aigentive/wire-core";
import { WireEditor, WireViewer } from "@aigentive/wire-react";
export function WorkflowEditor({
diagram,
onChange
}: {
diagram: WireDiagram;
onChange: (diagram: WireDiagram) => void;
}) {
return <WireEditor diagram={diagram} onChange={onChange} fitView showMiniMap />;
}
export function WorkflowPreview({ diagram }: { diagram: WireDiagram }) {
return <WireViewer diagram={diagram} fitView />;
}Custom editor surface:
import {
WireCanvas,
WireInspector,
WirePalette,
WireProvider,
WireToolbar,
WireValidationPanel
} from "@aigentive/wire-react";
export function ProductEditor({ diagram, onChange }) {
return (
<WireProvider diagram={diagram} onChange={onChange}>
<WireToolbar />
<WirePalette />
<WireCanvas mode="edit" fitView />
<WireInspector />
<WireValidationPanel />
</WireProvider>
);
}LLM-friendly custom cards and options:
import {
WireWorkspace,
type WireOptionCatalog
} from "@aigentive/wire-react";
const options: WireOptionCatalog = {
ai: [
{ key: "model", storage: "node", type: "select", options: ["gpt-4.1", "gpt-4.1-mini"] },
{ key: "temperature", type: "number", min: 0, max: 2, step: 0.1 }
]
};
export function AgentEditor({ diagram, onChange }) {
return (
<WireWorkspace
diagram={diagram}
onChange={onChange}
optionCatalog={options}
title="Agent workflow"
subtitle={`${diagram.nodes.length} nodes`}
/>
);
}WireWorkspace uses a decoupled event model: card/list clicks emit
node.inspect and update selection; option panels can follow selection by
default or receive an explicit inspectNodeId for fully controlled sidebars.
See docs/REACT_COMPONENTS.md, the playground
route /docs, and the playground route /samples/agent-chain.
JSX authoring remains supported:
import { Flow, TriggerNode, AINode, ConditionNode, ActionNode, Note } from "@aigentive/wire-react";
export function Example() {
return (
<Flow layout="LR">
<TriggerNode id="webhook" title="Webhook fires" />
<AINode id="classify" title="Classify intent" from="webhook" model="gpt-4.1" />
<ConditionNode id="route" title="Route request" from="classify" branches={["sales", "support", "other"]} />
<ActionNode id="notify-sales" title="Notify sales" from="route.sales" tone="success" />
<ActionNode id="open-ticket" title="Open ticket" from="route.support" tone="warning" />
<Note id="risk" title="Routing risk" attachedTo="classify">
Check confidence before routing.
</Note>
</Flow>
);
}┌──────────────────────┐ ┌──────────────────────┐ ┌──────────────────────┐
│ wire-react editor/UI │───▶│ wire-core │◀───│ wire-mcp (server) │
│ WireEditor, Canvas │ │ schema · validate │ │ actions, render… │
└──────────────────────┘ │ normalize · layout │ └──────────────────────┘
│ actions · reducer │
└─────────┬────────────┘ ▲
│ │
▼ │
┌──────────────────────┐ │
│ wire-renderers │ │
│ SVG · PNG · Mermaid │ │
└──────────┬───────────┘ │
│ │
▼ │
┌──────────────────────┐ │
│ apps/playground │────────────────┘
│ Next.js · Share JSON │ preview/edit/render
└──────────────────────┘
Wire JSON is the source of truth. The React canvas in @aigentive/wire-react
renders directly from that model and emits WireAction updates back into it.
Minimum shape:
{
"version": 1,
"id": "agent-router",
"title": "Agent router",
"layout": "LR",
"nodes": [],
"edges": []
}Use node from for ordinary connections. Use explicit edges when a connection
needs a stable id, label, branch, fromHandle, toHandle, style, label style,
routing, markers, or future edge edits.
All user-visible edits should become WireAction values. Direct MCP tools and
React gestures both map to the same reducer:
node.add, node.patch, node.remove, node.move, node.resize
edge.connect, edge.patch, edge.disconnect, edge.remove
diagram.patch, metadata.patch, layout.apply, group.add, group.ungroup, note.add
For multi-step changes, use apply_actions so the batch is atomic and validated
once.
Wire MCP exposes direct tools for common actions, plus apply_actions for any
full reducer action:
v1_get_agent_guide, v1_get_docs_shape
create_diagram, load_diagram, save_diagram, patch_diagram, list_diagrams
add_node, update_node, remove_node, move_node, resize_node
connect, disconnect, update_edge, remove_edge
add_note, set_layout, add_group, ungroup, patch_metadata, apply_actions
validate, get_diagram_json, render_svg, render_png, render_preview
summarize_diagram, export_mermaid
Edge handles and styling are first-class:
{
"diagramId": "agent-router",
"id": "route-sales",
"from": "route.sales",
"to": "notify-sales",
"label": "sales",
"fromHandle": "right",
"toHandle": "left",
"routing": "smoothstep",
"style": { "markerEnd": "arrow", "strokeWidth": 2 },
"labelStyle": { "background": "#ffffff", "fontSize": 12 }
}Use update_edge to patch explicit edges by id. Use disconnect for node
from references and remove_edge for explicit edge ids.
Resources:
wire://diagrams/{id}.json
wire://diagrams/{id}.svg
wire://diagrams/{id}.png
wire://diagrams/{id}.mermaid
wire://diagrams/{id}/preview
wire://templates/
wire://templates/{name}
wire://schemas/wire-diagram
Prompts:
diagram_from_codebase
diagram_from_logs
diagram_from_workflow_description
review_diagram_for_clarity
simplify_diagram
The playground is intentionally simple and deployment-safe:
WireProvider/WireEditorreceives a canonicalWireDiagram.- React edits dispatch core actions and emit the next diagram through
onChange. POST /api/sharevalidates and canonicalizes the JSON.- The JSON is stored at
wires/{token}.json, wheretokenis a content hash. Hosted playground storage uses Turso/libSQL whenTURSO_DATABASE_URLis configured and local SQLite during development. Vercel Blob is used only when explicitly selected withWIRE_CLOUD_BACKEND=blob. - Authenticated shares mint separate random view/edit tokens.
/s/{viewToken}renders public read-only HTML, and/s/{viewToken}.svg,.png,.json, and.mmdreturn raw embeddable assets./e/{editToken}opens public edit only when an edit-scope share exists.
For a production multi-user hosted app, keep JSON blobs revisioned behind stable ids:
diagrams(id, workspace_id, title, current_revision_id, updated_at)
diagram_revisions(id, diagram_id, blob_key, content_hash, parent_revision_id, created_by, created_at)
Saves should take expectedRevision, write a new JSON blob, insert a revision,
update current_revision_id, and return a conflict instead of overwriting stale
work.
- Local (stdio) — bundled MCP server runs alongside Claude Desktop, Cursor, Claude Code, or another local MCP client.
- Local (HTTP) —
wire-mcp --httpfor network clients on:3860. - Local (Docker Compose) — MCP at
http://localhost:3860/mcpplus playground/editor athttp://localhost:3870, with local volumes for diagrams and share tokens. - Cloud (Docker) — multi-stage
Dockerfiledeploys MCP to Fly, Render, Cloud Run, or Kubernetes; persistent volume at/data/diagrams. - Cloud (Vercel) —
apps/playgroundis a Next.js React editor, JSON share API, and renderer/preview surface deployable as a Vercel app with Turso/libSQL storage.
Run the full local Docker stack:
docker compose up -d --build
# MCP: http://localhost:3860/mcp
# Playground: http://localhost:3870See DEPLOY.md for local Docker, HTTP, and self-hosted Vercel deployment instructions.
Wire works with any MCP-compatible client. The usual local setup is a stdio
server named wire:
mcpServers:
wire:
command: npx
args:
- -y
- @aigentive/wire-mcp@latest
env:
WIRE_STORAGE_DIR: ${HOME}/Documents/wire-diagrams
WIRE_PREVIEW_BASE: http://localhost:3870For authenticated cloud sync, generate an API key from Wires -> Connect local MCP and add:
env:
WIRE_CLOUD_URL: https://wire.example.com
WIRE_CLOUD_API_KEY: PASTE_WIRE_CLOUD_API_KEYWith cloud sync configured, render_preview returns hosted Wire Cloud URLs:
public view, optional edit, SVG, PNG, JSON, Mermaid, and workspace links.
Customers do not need a local playground. render_svg and render_png still
return inline assets directly from the MCP server.
Some clients expose tools as bare MCP names such as create_diagram; others
prefix tools with the server name, such as wire__create_diagram or
mcp__wire__create_diagram. Full setup examples for stdio, HTTP, tool prefixes,
resources, and prompts are in MCP_CLIENTS.md.
examples/agent-router.json— webhook → classify → routeexamples/refund-approval.json— threshold-gated refund with human-in-the-loopexamples/rag-pipeline.json— RAG with self-critique + retry loop
Apache-2.0 — see LICENSE.