Update a document
update_documentEdit an existing tab. mode "replace" swaps the whole tab’s elements (validated + auto-laid-out) and paints every element in the tab’s theme, its own colours replaced (a sticky keeps its own); mode "ops" keeps the colours it is given, and applies an ordered list of add/update/remove against existing elements (by id, or the ref read_document prints) and PRESERVES positions (no auto-layout), or takes "edits": edit operations as text (insert between, wrap in a frame, connect, layout a selection, place beside another element), the form each lint finding’s fix is written in. On an event-storming tab, event-storming notes you add or move land on the board’s horizontal lanes (240px apart, lane 0 centred at y=100). Returns an inline PNG.
Tool call template
Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.
{
"id": 1,
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"arguments": {
"documentId": "<documentId>",
"mode": "<mode>"
},
"name": "update_document"
}
}Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| ops | No | ops mode: ordered add / update / remove against existing elements, by id or ref. | |
| rev | No | ops mode: the tab revision read_document returned. An element a person changed since is then a conflict, never silently overwritten; read again and redo the edit. | |
| mode | Yes | "replace" the whole tab, or change it in place: "ops" (an ops list, or "edits" text); "edits" names the same mode by its text form. | |
| edits | No | ops mode, instead of "ops": edit operations, one a line, applied all or nothing. The language the lint fixes are written in. Operations: add <kind> [id=<id>] key=value… [placement]; set <sel> key=value… [all]; rm <sel> [all] [keep-arrows]; move <sel> <placement>|by=dx,dy; connect <a> -> <b> [label=…] [line=straight|angled|curved]; rewire <arrow> from=<x> to=<y>; insert <kind> key=value… between <a> <b> (puts a node on the a→b arrow and makes room); wrap <sel…> in frame|lane [label=…] [tidy]; unwrap <frame>; order <sel> front|back; layout <sel> [style=flow|tree|mindmap] [direction=down|right]. Selectors: a ref or id, "Label text", type:sticky, shape:diamond, in:<frame>, a->b, from:<x>, to:<x>, downstream:<x>. Placement: right-of:<x> left-of:<x> above:<x> below:<x> [gap:<n>], after:<x>, inside:<frame>, align:<x>, at:x,y; inside:<frame> right-of:<x> places beside x in that frame. A box placed beside one inside a frame or lane joins it (the container grows); to stay outside, place it against the frame itself (below:<frame>), with align:<x> to line it up with a member (below:<frame> align:<x>). Keys: label= note= shape= fill=theme|red|orange|yellow|green|blue|violet (a sticky: classic|lemon|peach|rose|lilac|sky|mint|teal|slate) text=sm|md|lg border=solid|dashed|dotted line=…, or any stored field by name. Values with spaces are quoted: label="Sign in". Coordinates are relative to the content origin, as the layout view prints them. | |
| graph | No | A node/edge graph the server turns into laid-out boxes + arrows — the easiest way to author. Provide one of graph, mermaid, elements or template. | |
| tabId | No | Which tab to edit; defaults to the first. | |
| layout | No | How to position elements. "preserve" keeps the exact x/y you give — use it for a deliberate shape (a cycle as a ring, a tree, a grid). "auto" arranges a clean directed graph for you. Omit to auto-detect: a real arrangement is kept; nodes left piled at one point get laid out. Supporting text is always kept in place either way. | |
| mermaid | No | The diagram as Mermaid text: a flowchart (graph / flowchart, with subgraphs), a state diagram (stateDiagram), an ER diagram (erDiagram: crow's-foot ends from the cardinality tokens, an entity alias in brackets is its title, BOOK_AUTHOR[Book author]) or a sequence diagram (sequenceDiagram: participant / actor, ->> calls, -) async, -->> replies, +/- activations, Note over, alt/else, loop, opt, par, autonumber, title). Parsed into the same graph as the "graph" input: subgraphs become groups, the direction is kept, and the same label limit applies; a sequence diagram is drawn with lifelines, activation bars, notes and fragments. Front matter (---, title: Text, ---) titles any of them. Provide one of graph, mermaid, elements or template. | |
| elements | No | Replace mode: the full new element list. An array of element objects. This is the COMPLETE format, documented inline here: the tool definition is the full reference for it. Each element: { "id": a unique string, "type", "x", "y", "width", "height", and optional "label" }. type "shape" is a NODE (a labelled box) and also needs "shape", one of square, circle, diamond, cylinder, parallelogram, hexagon, document, page, mind-node, lane, entity, banner, callout, card, badge, step, pointer-note, diagram-key, stack, sequence, boundary, layer-stack, pyramid, cycle, hub, onion, chevrons, stat-row, process, site-header, mode-button, portal, session-button, reveal, picker, reaction-pad, comment-pin, action-card, done-check, estimate, temperature, idea-box, qa-board, agenda, decision, roll-call, quiz, stadium, actor, final-state, cloud, triangle, trapezoid, star, speech-bubble, frame, browser, monitor, laptop, phone, tablet, foldable, smartwatch, progress-bar, progress-ring, timeline-rail, rating, pie-chart, bar-chart, line-chart, code-block, checklist, legend, sankey, focus-button, icon, sticker. The default box is "square" (there is NO "rectangle"); use "diamond" for a decision, "cylinder" for a datastore, "stadium" for start/end. type "text" is BARE text with no box; use it only for a title, caption, or legend, never for a node; it is centred in its box, so a left-aligned heading or caption sets "textAlignX": "left". type "freehand" is a HAND-DRAWN stroke: give "points" as canvas coordinates, [[x, y], ...] in drawing order (the box is taken from them), with "closed" true to close and fill the shape, and "penColour" (ink, grey, blue, red, orange, yellow, green, teal, violet, pink). A hand-drawn board starts from the "whiteboard" template, a tab in Draw mode: underline a heading, ring a word or draw a doodle with a few strokes, a point every 10 to 20 px along a curve; an arrow between boxes stays a pinned "arrow", which a "sketch" finish draws by hand and which stays attached. Any box may carry "rotation" in degrees, a small tilt (-4 to 4) reading as placed by hand. type "arrow" needs "from" and "to" endpoints, each either { "kind": "pinned", "elementId", "anchor" } (anchors: n, nne, ne, ene, e, ese, se, sse, s, ssw, sw, wsw, w, wnw, nw, nnw; preferred, so arrows track their shapes) or { "kind": "free", "x", "y" }; an arrow may carry a "label". The theme owns fill, stroke, and text colour on every element except a sticky. Any element may carry "finish" ("flexible", "professional", "sketch" or "marker") to be drawn differently from its tab. Style fields: "textSize" (sm, md, lg, scale), "textAlignX" (left, center, right), "textAlignY" (top, middle, bottom), "iconPosition" (left, right, above, below), "arrowStyle" (straight, angled, curved), "arrowEnds" (to, from, both, none), "arrowheadShape" (triangle, triangle-hollow, line, circle, circle-hollow, diamond, diamond-hollow, one, zero-or-one, many, zero-or-many, one-or-many), "arrowheadStartShape" (triangle, triangle-hollow, line, circle, circle-hollow, diamond, diamond-hollow, one, zero-or-one, many, zero-or-many, one-or-many), "strokeStyle" (solid, dashed, dotted, long-dash, dash-dot, dash-dot-dot), "borderRadius" (none, sm, md, lg, full), "accentEdge" (left, top, bottom), "cardMedia" (badge, tile, initial), "chipLook" (solid, ink, outline, tinted, quiet), "attachAt" (top-left, top, top-right, right, bottom-right, bottom, bottom-left, left), "boundaryStyle" (tab, inset, c4), "pyramidVariant" (pyramid, inverted, funnel), "stackDirection" (row, column, grid), "stackAlign" (start, center, end), "mindLook" (person), "sequenceAnim" (play), "iconWeight" (thin, regular, bold), "font" (inter, poppins, nunito, oswald, space-grotesk, lora, abril-fatface, roboto-slab, roboto-mono, caveat, permanent-marker); "textBold", "textItalic" (true/false); "colorPreset" (a shape’s look from the theme, its border’s width and style included, so it outranks a "strokeStyle" given with it; ghost and outline are dashed, dotted and dash-dot as named: theme, soft, tinted, solid, bold, ghost, paper, muted, slate, inked, hairline, outline, dotted, dash-dot, frame, info, success, warning, danger, highlight); "iconId" (an id from search_icons) with "iconPosition"; "note" (detail shown on the element); on text, wordmark type: "letterSpacing" (em between letters, -0.2 to 1), "fontWeight" (400, 500, 700), "textCase" (upper, lower), "textArc" (bends one line along a circle, -360 to 360 degrees, positive bowing up: a badge’s top line 180, its bottom -180); on an arrow "label", "strokeStyle", "arrowEnds", "arrowheadShape" (an ER line’s ends: one, zero-or-one, many, zero-or-many, one-or-many), "arrowheadStartShape" (the start’s, when it differs: a one at one table, a many at the other). A Mermaid erDiagram draws these ends itself. A field a type does not have, or a value off its list, is refused naming what it takes. Facilitation kinds and what they hold: "session-button" a "session" ({"tool": "timer" with "minutes", "stopwatch", "vote" with "dots", or "poll" with "question" and "options"}), drawn as what pressing it does unless it has a label; "agenda" its "agendaItems" ([{"label", "minutes"}]); "checklist" its "checklistItems" ([{"text", "done"}]); a stat row its "stats" ([{"value", "caption"}]); a callout its "pageTitle" over its "label" (the body); a banner its "pageTitle" and "pageSubtitle"; "sticker" a "stickerId" (an emoji- id from search_icons). The entries of a "qa-board", "idea-box" and "temperature" are the people’s, never an edit’s: starter questions or ideas go on stickies beside them. Content-carrying kinds: type "sticky": a note whose "label" is its text; the theme never recolours it, so its own "fillColor" + "textColor" are kept (palette pairs, fill/text: classic #fde68a/#451a03, lemon #fef08a/#422006, peach #fed7aa/#431407, rose #fecdd3/#4c0519, lilac #e9d5ff/#3b0764, sky #bae6fd/#082f49, mint #bbf7d0/#052e16, teal #99f6e4/#042f2e, slate #e2e8f0/#0f172a, paper #ffffff/#0f172a, charcoal #334155/#f1f5f9, ink #0f172a/#e2e8f0); unset it is the classic amber note. A sticky with "esKind" (domain-event, command, actor, policy, read-model, external-system, aggregate, hotspot) is an event-storming note of that kind (its paper, size and lane on a storm board): add one to a board with the edit `add sticky label="Courier" esKind=actor`. type "image": a picture from the user's gallery: "imageId" is an id from list_images (one not in the gallery is refused); without it the element is a placeholder the user fills in the editor. "objectFit" contain (default, the whole picture) or cover (fills the box, cropping); "alt" describes it. A box in the picture's own proportions (its width and height from list_images, scaled) shows it uncropped. type "table": "cells" is rows of strings (ragged rows are padded), "headerRow" / "headerColumn" style the first row / column, "zebra" tints alternate rows. shape "code-block": "code" (up to 4000 chars), "codeLanguage" (plain, ts, js, python, json, bash, sql, html, css, yaml), "codeTheme" (midnight, graphite, ocean, forest, plum, contrast, paper, parchment; default midnight, dark), "codeWrap"; the block draws itself and shows no label. shape "entity": "label" is the title, "entityFields" is [{ "name", "type"?, "key"? }] rows (up to 40; "key" is "pk", "fk", "pk-fk" or "uk"); the box grows to fit its rows. A pinned arrow end on an entity may add "field": a row index, with anchor "w" or "e", to join that field. shape "lane": a swimlane whose "label" is the title in its left strip; elements fully inside its box belong to it, lanes are placed one under another, and they paint behind everything. shape "bar-chart" / "pie-chart": "pieSlices" is [{ "label", "value" }]; categories show in the legend. shape "line-chart": "lineCategories" is the x labels, "lineSeries" is [{ "name", "values" }] with one value per category. "chartVariant" picks the chart type: on "bar-chart" "horizontal" draws a Bar chart (absent: upright columns); on "line-chart" "area" fills each series down to zero and "scatter" draws points only, at x = each category read as a number; on "pie-chart" "doughnut" opens the middle. "chartValues": true prints each mark's number on the chart (a pie's as percentages when its values add up to 100; a column chart also names each column under it, so "chartLegend": false can drop the key). "chartAxis": true draws the value axis, round tick values and gridlines (not on a pie). A "lineSeries" entry with "axis": "right" is drawn against a scale of its own, labelled on the right, so a series in the thousands and one in the tens both read. A chart draws no title (a caption is a separate "text" element) and draws sample data when its data is empty. shape "sankey": a Sankey diagram, bands as wide as the amount they carry, laid out in columns by itself. "sankeyFlows" is [{ "from", "to", "value" }] with node NAMES (the nodes are the names; up to 200 flows, names up to 60 chars, values above zero; a flow back to an earlier node is hidden, as is one into itself). Options: "sankeyLinkColor" (gradient, source, target, neutral; default gradient), "sankeyAlign" (justify: end nodes in the last column, the default; left: each at its own step), "sankeyValueLabel" (value, percent, none), "sankeyUnit" (e.g. "£", "kWh"; up to 8 chars), "sankeyNodes" [{ "name", "color", "leftover": false }] to colour a node or switch off its own leftover, "sankeyLeftover" (show, the default: a middle node that sends on less than it receives draws the difference to a "Leftover" end node; hide: it does not), "sankeyLeftoverName" (that node's name; do not write leftover flows yourself). Make it wide (about 2:1); it draws no title. shape "card": a node with a title, meta line and body; "pageTitle" is the title, "pageSubtitle" the meta (a product or runtime), "label" the body, "cardMedia" + "iconId" the glyph (a badge disc, a tile or an initial), "cardHeader" true for a coloured header band, "tags" up to 6 short facts. Use cards for service and component nodes. "callout" is accepted and stored as a card. "accentEdge" on a square, stadium or card draws a coloured strip on that side. shape "badge": a small label pill (up to 24 chars); shape "step": a numbered disc ("label" the number, up to 3 chars). Both take "chipLook"; with "attachedTo" (a node id) and "attachAt" they sit on that point of the node and move, copy and delete with it; no x / y needed. shape "boundary": a titled container ("label" the title, "pageSubtitle" a meta line such as a CIDR, "iconId" in its tab); elements whose centre is inside it belong to it; nest them for edge, region, VPC and subnet, "boundaryStyle" inset for a nested one, c4 for a C4 diagram. shape "layer-stack" / "pyramid" / "cycle": "conceptRows" is [{ "label", "note"? }]: a stack 2 to 8 (note = a side note), a pyramid 2 to 6 (first row the apex; "pyramidVariant" funnel makes it a funnel and its note the row's value), a cycle 3 to 8 clockwise from the top (its "label" is the centre); "hub" 3 to 8 satellites round its "label" ("hubSpokes" false hides the lines), "onion" 2 to 6 rings from the core out, "chevrons" 2 to 8 stages left to right, "timeline-rail" 2 to 8 milestones left to right (label = what, note = when: a date, a quarter). They draw their own rows in the colour ramp; do not draw them from separate shapes. shape "pointer-note": a note ("label") with a leader to a tip; "pointerTip" { x, y } is relative to its top-left, or "attachedTo" + "attachAt" pins the tip to that point of a node. shape "diagram-key": a legend of the tab's arrow line styles and tag colours; its rows fill in by themselves, "keyMeanings" maps a row id ("line:dashed", "tag:<tag>") to what it means. shape "stack": a container that lines up the elements whose centre is inside it; "stackDirection", "stackColumns" (2 to 6, grid), "stackGap" and "stackPadding" (0 to 64), "stackAlign"; place children anywhere inside and the editor lays them out. An org chart is quickest as a graph with style "tree" and a "role" on each node (see the graph tool). shape "sequence": a UML sequence diagram in one element; "sequenceParticipants" is [{ "id", "label", "actor"? }] (2 to 12, left to right), "sequenceMessages" [{ "from", "to", "label", "kind": call | async | reply }] (up to 60, top to bottom, from === to a self-call), "sequenceNumbered" true numbers them. It lays itself out; prefer it over loose shapes and arrows for a sequence diagram you will edit. | |
| documentId | Yes | The document to edit (from find_documents / read_document). |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | The document id. | |
| rev | Yes | The tab revision now, to pass as rev on the next update_document. | |
| url | Yes | Link that opens the document in the livediagram editor. | |
| lint | Yes | The diagram lint summary line of the tab as written. | |
| text | Yes | What the changeset did, one line per element, and how to revert it. | |
| notes | No | What the graph or Mermaid could not keep of what it asked (a nested subgraph folded). | |
| tabId | Yes | The tab that was edited. | |
| documentId | Yes | The document id again, under the name the other tools take it by. | |
| changesetId | Yes | The changeset written; null when nothing changed. |