Every change Wellknown observed on this MCP server, newest first, with what it was before and what it became. Tool-surface changes carry the definition diff. Nothing here is edited after the fact.
Authorization not required, issuer https://datadef.io
Authorization not required, issuer https://datadef.io
Authorization not required, issuer https://datadef.io
Authorization not required, issuer https://datadef.io
Authorization not required, issuer https://datadef.io
Authorization not required, issuer https://datadef.io
Authorization not required, issuer https://datadef.io
Authorization not required, issuer https://datadef.io
Authorization not required, issuer https://datadef.io
Authorization not required, issuer https://datadef.io
Added "canvas_batch", "canvas_remove_lineage" and "canvas_view"; changed the definition of "canvas_add_flow_arrow", "canvas_add_lineage", "canvas_add_nodes" and 31 more (36 tools before, 39 now)
addAdd a flow arrow
When: Use after the final layout, where one arrow should stand for a bundle of identical flows (zone to zone). Draw one large labelled arrowrepresentingSHAPEabetweenwholetwoflowareas of the diagram
Changed the definition of "create_blank_diagram" and "create_diagram"
⟨14 unchanged words⟩ with the canvas_* tools. No AI generation runsand no credit is spent: you draw it. Use this when you ⟨51 unchanged words⟩
⟨352 unchanged words⟩ one is still generating; you would create aduplicate and spend another credit.duplicate. Do not use image generation for these. This ⟨5 unchanged words⟩
Authorization not required, issuer https://datadef.io
Authorization not required, issuer https://datadef.io
Authorization not required, issuer https://datadef.io
Changed the definition of "create_diagram"
⟨27 unchanged words⟩ ETL/ELT pipelines, streaming topologies, data mesh,warehousestar anddimensionalsnowflakemodelsschemas, ER diagrams, lineage maps, cloud architectures, and data platform designs. EXISTING SCHEMAS: if the conversation or the repository has the schema itself (SQL DDL, a MySQL or pg_dump export, migrations, schema.prisma), pass the file contents as the prompt, unedited. Datadef parses it instead of asking a model: every table, column, type, primary key and foreign key comes out exactly as written, in seconds. Warehouse DDL with no declared foreign keys (fact_sales.customer_key → dim_customer.customer_key) gets its links from key names, drawn dashed. Add a sentence only if you want something other than a picture of that schema; "turn these tables into a star schema" or "design the pipeline that loads them" goes to the model instead. Write a specific prompt. Name the actual technologies ⟨218 unchanged words⟩
Authorization not required, issuer https://datadef.io
Authorization not required, issuer https://datadef.io
Authorization not required, issuer https://datadef.io
Authorization not required, issuer https://datadef.io
Authorization not required, issuer https://datadef.io
Certificate recorded, valid to 2026-11-19
Authorization not required, issuer https://datadef.io
First tool surface recorded: 36 tools (server version 1.0.0)
Showing the latest 24 events. The API returns up to 500 and filters by kind: ?kind=tool_surface_changed
⟨10 unchanged words⟩ ,"properties":{"color":{"description":"HexColourfill.name or hex. Default a soft grey-blue.","type":"string" ⟨95 unchanged words⟩ :"array"},"diagram_id":{"description":"CanvasDiagram id, from list_diagrams, create_diagram,or create_blank_diagram.","type":"string"}}, ⟨5 unchanged words⟩
{"destructiveHint":truefalse,"idempotentHint":false,"openWorldHint":false,"readOnlyHint":false}
addRecord column lineage
When: Use to record which source columns produce which target columns. No line is drawn. Record column-level lineage: which source column produces which ⟨13 unchanged words⟩ analysis, so add it for every real transformation. canvas_remove_lineage undoes it. Batch: `links` (up to 100) takes a list; put every item in one call rather than one call per item. Operates on one Datadef diagram, named by diagram_id. Returns compact JSON: the ids it created, changed or removed, the diagram revision, a one-line summary and the next step. A viewer-role account is refused. Next: canvas_validate_canvas before you finish.
⟨5 unchanged words⟩ ,"properties":{"diagram_id":{"description":"CanvasDiagram id, from list_diagrams, create_diagram,or create_blank_diagram.","type":"string"}," ⟨81 unchanged words⟩
{"destructiveHint":truefalse,"idempotentHint":false,"openWorldHint":false,"readOnlyHint":false}
addAdd nodes
When: Use to add components (tables, pipelines, sources, consumers, service icons), each placed in its zone with `group`. Add one or more nodes to the canvas. ⟨12 unchanged words⟩ by canvas_layout_canvas afterwards — never set them yourself. Batch: `nodes` (up to 40) takes a list; put every item in one call rather than one call per item. Operates on one Datadef diagram, named by diagram_id. Returns compact JSON: the ids it created, changed or removed, the diagram revision, a one-line summary and the next step. A viewer-role account is refused. If you have not already, call get_design_guide first: it carries Datadef's size, edge,and zone standard, and diagrams built without it read poorly. Next: canvas_connect_nodes for the real flows, then canvas_layout_canvas once when the structure is complete.
⟨5 unchanged words⟩ ,"properties":{"diagram_id":{"description":"CanvasDiagram id, from list_diagrams, create_diagram,or create_blank_diagram.","type":"string"}," ⟨50 unchanged words⟩ bigint\", \"timestamp\". Default \"unknown\".for a new column; an existing column keeps its type.","type":"string"}},"required": ⟨26 unchanged words⟩ {"description":"Accent hue for the nodetile: source=teal, ingest=blue, bronze/silver/gold=medallion layers, consume=magenta, dbt=coral.tile. Tables infer their layer from names; set this ⟨15 unchanged words⟩ :"string"},"group":{"description":"GroupZone id or label to place this node in. Thegroupzone must already exist.","type":"string"} ⟨3 unchanged words⟩ id from search_icons, e.g. \"snowflake\".OmitA product name is resolved ifunsure.unambiguous; an unknown one is left out.","type":"string"},"kpiFormula":{ ⟨107 unchanged words⟩ business metric; serviceIcon = a plain labelled servicelogo.logo (needs an icon).","enum":["table","kpi"," ⟨22 unchanged words⟩
{"destructiveHint":truefalse,"idempotentHint":false,"openWorldHint":false,"readOnlyHint":false}
addAdd a region
When: Use after the final layout to mark nodes that belong together without moving them into a zone. Regions do not move with layout. Draw a labelled translucent area behind existing nodes ⟨59 unchanged words⟩ enclose the nodes with roughly 24px of margin. Batch: `regions` (up to 12) takes a list; put every item in one call rather than one call per item. Operates on one Datadef diagram, named by diagram_id. Returns compact JSON: the ids it created, changed or removed, the diagram revision, a one-line summary and the next step. A viewer-role account is refused. Next: canvas_view to check the result.
⟨5 unchanged words⟩ ,"properties":{"diagram_id":{"description":"CanvasDiagram id, from list_diagrams, create_diagram,or create_blank_diagram.","type":"string"}," ⟨4 unchanged words⟩ ,"properties":{"color":{"description":"HexColourfillname or hex, drawn translucent. Default a neutral slate."," ⟨53 unchanged words⟩
{"destructiveHint":truefalse,"idempotentHint":false,"openWorldHint":false,"readOnlyHint":false}
addAdd a shape
When: Use rarely: a pointer or highlight the user asked for. Never as a backdrop; zones are the containers. Place a rectangle, circle, arrow, or line as a visual annotation — abackdrop highlightingdivider, aregion,highlight.anShapesarrowarepointingdrawings:somethingtheyout,connectanothingdivider.(useShapescanvas_connect_nodessitforbehindarrowsdatabetween nodes) and they are notpart ofzonesthe(usedatacanvas_group_nodes). Batch:flow.`shapes`To(upgrouptonodes20)intotakes alabelledlist;zoneputuseeverycanvas_group_nodesiteminstead.in one call rather than one call per item. Operates on one Datadef diagram, named by diagram_id. Returns compact JSON: the ids it created, changed or removed, the diagram revision, a one-line summary and the next step. A viewer-role account is refused. Next: canvas_view to check the result.
⟨5 unchanged words⟩ ,"properties":{"diagram_id":{"description":"CanvasDiagram id, from list_diagrams, create_diagram,or create_blank_diagram.","type":"string"}," ⟨4 unchanged words⟩ ,"properties":{"fillColor":{"description":"HexColourcolour.name or hex.","type":"string"},"height":{ ⟨22 unchanged words⟩ :"string"},"strokeColor":{"description":"HexColourcolour.name or hex.","type":"string"},"width":{ ⟨29 unchanged words⟩
{"destructiveHint":truefalse,"idempotentHint":false,"openWorldHint":false,"readOnlyHint":false}
addAddstandaloneone node at a fixed spot
When: Use only when the user wants a node at a specific position, outside the automatic layout. Otherwise use canvas_add_nodes. Add a single data node at an exact ⟨41 unchanged words⟩ Operates on one Datadef diagram, named by diagram_id. Returns compact JSON: the ids it created, changed or removed, the diagram revision, a one-line summary and the next step. A viewer-role account is refused. Next: canvas_view to check the result.
⟨8 unchanged words⟩ :"string"},"diagram_id":{"description":"CanvasDiagram id, from list_diagrams, create_diagram,or create_blank_diagram.","type":"string"}," ⟨50 unchanged words⟩
{"destructiveHint":truefalse,"idempotentHint":false,"openWorldHint":false,"readOnlyHint":false}
addAddtexta note
PlaceWhen:aUsefree-floatingfortextaboxnoteonthat tells thecanvasdiagram's—reader acaptiondecision,aconstraintcalloutor gotcha. Pass `anchor` (the node or zone it explains) and it is placed beside it, no coordinates needed. To edit asectionnote'sheadingtext use canvas_update_nodes. Add a text note: a caption, a callout, a note explaining a decision.PositionGive `anchor` (the node or zone itwithexplains)explicitandcoordinatesthefromnotecanvas_measure_canvas.isTextplacedboxesbeside it, clear of other content, without coordinates. Use x/y only for a note that belongs to no particular element. Notes are annotations: theyaretakenotnopartedges.ofTothechangedataanflowexistingandnote'staketextnouseedges.canvas_update_nodes. Batch: `texts` (up to 20) takes a list; put every item in one call rather than one call per item. Operates on one Datadef diagram, named by diagram_id. Returns compact JSON: the ids it created, changed or removed, the diagram revision, a one-line summary and the next step. A viewer-role account is refused. Next: canvas_view to check the result.
⟨5 unchanged words⟩ ,"properties":{"diagram_id":{"description":"CanvasDiagram id, from list_diagrams, create_diagram,or create_blank_diagram.","type":"string"},"texts":{"items":{"additionalProperties":false,"properties":{"anchor":{"description":"Node or zone id or label this note explains; the note is placed next to it.","type":"string"},"bold":{"type":"boolean"},"fontSize" ⟨15 unchanged words⟩ "minimum":20,"type":"number"},"style":{"description":"note = quiet grey text (default), callout = highlighted amber box, caption = small bold label.","enum":["note","callout","caption"],"type":"string"},"text":{"description":"The text content. Newlines are ⟨4 unchanged words⟩ :"string"},"textColor":{"description":"HexColourcolourname or hex, e.g. \"#111827\".","type":" ⟨17 unchanged words⟩ boolean"},"width":{"description":"Default220.220 (240 for anchored notes).","maximum":1200,"minimum":40,"type ⟨2 unchanged words⟩ {"description":"Absolute x of the top-leftcorner.corner, when there is no anchor.","type":"number"},"y":{"description":"Absolute y of the top-left
{"destructiveHint":truefalse,"idempotentHint":false,"openWorldHint":false,"readOnlyHint":false}
alignAlign nodes by hand
When: Use only when the user asked for alignment that layout does not give. Align nodes to a shared edge or centre ⟨7 unchanged words⟩ far more reliable than computing coordinates by hand. Batch: `nodes` (up to 40) takes a list; put every item in one call rather than one call per item. Operates on one Datadef diagram, named by diagram_id. Returns compact JSON: the ids it created, changed or removed, the diagram revision, a one-line summary and the next step. A viewer-role account is refused. Next: canvas_view to check.
⟨5 unchanged words⟩ ,"properties":{"diagram_id":{"description":"CanvasDiagram id, from list_diagrams, create_diagram,or create_blank_diagram.","type":"string"}," ⟨48 unchanged words⟩
{"destructiveHint":true,"idempotentHint":false,"openWorldHint":false,"readOnlyHint":false}
collapseCollapse nodes into one
When: Use to merge several similar nodes into one while keeping their connections, usually after canvas_suggest_simplifications. Merge several nodes into one summary node, keeping ⟨32 unchanged words⟩ individual objects are what the reader came for. Batch: `nodes` (up to 40) takes a list; put every item in one call rather than one call per item. Operates on one Datadef diagram, named by diagram_id. Returns compact JSON: the ids it created, changed or removed, the diagram revision, a one-line summary and the next step. A viewer-role account is refused. Next: canvas_layout_canvas once, then canvas_view.
⟨21 unchanged words⟩ :"string"},"diagram_id":{"description":"CanvasDiagram id, from list_diagrams, create_diagram,or create_blank_diagram.","type":"string"}," ⟨47 unchanged words⟩
{"destructiveHint":true,"idempotentHint":false,"openWorldHint":false,"readOnlyHint":false}
connectConnect nodes
When: Use to draw the flows that genuinely move data between two nodes. Never connect a zone: connect a node inside it. Draw edges (arrows) between nodes to show how data flows.AlwaysLabellabelan edge only when theedgereaderwithcould not guess whatactuallyithappensdoes ("ingest", "dbt transformCDC", "hourlysyncbatch");—obviousunlabelledflowsedgesandmakedimensional joins read better unlabelled. Edges always render with an arrowhead at the target; bidirectional adds one at the source. Batch: `edges` (up to 60) takes adiagramlist;useless.put every item in one call rather than one call per item. Operates on one Datadef diagram, named by diagram_id. Returns compact JSON: the ids it created, changed or removed, the diagram revision, a one-line summary and the next step. A viewer-role account is refused. Next: canvas_layout_canvas once, when the structure is complete.
⟨5 unchanged words⟩ ,"properties":{"diagram_id":{"description":"CanvasDiagram id, from list_diagrams, create_diagram,or create_blank_diagram.","type":"string"},"edges":{"items":{"additionalProperties":false,"properties":{"bidirectional":{"description":"Arrowheads on both ends, for a genuinely two-way link. Not a replacement for existing edges in each direction.","type":"boolean"},"color":{"description":"Override the edge colour (default: the source node's hue).","type":"string"},"label":{"description":"What this connectiondoes.does,Required.when not obvious.","type":"string"},"source":{ ⟨47 unchanged words⟩ string"}},"required":["source","target","label"],"type":"object"},"maxItems": ⟨10 unchanged words⟩
{"destructiveHint":truefalse,"idempotentHint":false,"openWorldHint":false,"readOnlyHint":false}
describeListcanvasevery node (flat)
When: Use when you want a flat list of every node, edge and zone. canvas_view shows the same ids as a zone tree with positions and defects, and is usually the better first read. Get an overview of the current canvas: zones as a nested tree in reading order, every node with its id, type,labelicon andgroupfamily,plusall connections with labels, andgroups.every note in full. Call this first, before any edit, so ⟨23 unchanged words⟩ get_design_guide first: it carries Datadef's size, edge,and zone standard, and diagrams built without it read poorly. Next: canvas_inspect_nodes for a node's full fields, or the write tool you need.
⟨5 unchanged words⟩ ,"properties":{"diagram_id":{"description":"CanvasDiagram id, from list_diagrams, create_diagram,or create_blank_diagram.","type":"string"}," ⟨19 unchanged words⟩
{"destructiveHint":false,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":true}
disconnectRemovenodesedges
RemoveWhen:theUseedgeto delete specific edges between two nodes. Remove edges, given as source and target, or as an edge id / "Source -> Target" string in `edge`. Batch: `edges` takes a list; put every item in one call rather than one call per item. Operates on one Datadef diagram, named by diagram_id. Returns compact JSON: the ids it created, changed or removed, the diagram revision, a one-line summary and the next step. A viewer-role account is refused. Next: canvas_view to check the result.
⟨5 unchanged words⟩ ,"properties":{"diagram_id":{"description":"CanvasDiagram id, from list_diagrams, create_diagram,or create_blank_diagram.","type":"string"},"edges":{"items":{"additionalProperties":false,"properties":{"sourceedge":{"description":"Edge id, or \"Source -> Target\".","type":"string"},"targetsource":{"description":"Source node id or label.","type":"string"}},"requiredtarget":[{"sourcedescription":"Target node id or label.","targettype"]:"string"}},"type":"object"},"minItems":1, ⟨7 unchanged words⟩
{"destructiveHint":true,"idempotentHint":false,"openWorldHint":false,"readOnlyHint":false}
groupCreatenodesa zone
When: Use to create a zone (a layer, domain, stage or boundary), nested with `parentGroup`, optionally moving existing nodes into it: the zone is drawn around them where they are, inside the zone they already share. Create a labelled zone (e.g. "Bronze Layer", "Ingestion") and optionally move nodes into it. The zone is drawn around the nodes where they already are, so nothing moves on screen; it nests inside their shared zone unless parentGroup says otherwise. Zones are what turn a tangle of boxes ⟨5 unchanged words⟩ use them for layers, domains, or environments. Batch: One zone per call. Create all zones in a single canvas_batch call, outermost first, instead of one call per zone. Operates on one Datadef diagram, named by diagram_id. Returns compact JSON: the ids it created, changed or removed, the diagram revision, a one-line summary and the next step. A viewer-role account is refused. If you have not already, call get_design_guide first: it carries Datadef's size, edge,and zone standard, and diagrams built without it read poorly. Next: canvas_add_nodes with `group` set to the zone.
{"$schema":"http://json-schema.org/draft-07/schema#","additionalProperties":false,"properties":{"color":{"description":"A colour instead of a family, e.g. \"green\".","type":"string"},"description":{"type":"string"},"diagram_id":{"description":"CanvasDiagram id, from list_diagrams, create_diagram,or create_blank_diagram.","type":"string"},"family":{"description":"Accent hue encoding the zonerole: source=teal (inputs/producers), ingest=blue (movement/processing), bronze/silver/gold=medallion layers, consume=magenta (outputs/consumers), dbt=coral (transformation projects), neutral=grey (platform).role. Zones with different roles get different families.", ⟨21 unchanged words⟩ string"},"nodes":{"description":"Node or zone ids or labels to place inside.","items" ⟨3 unchanged words⟩ array"},"parentGroup":{"description":"Existinggroupzone to nest this one inside, e.g. \"Databricks Workspace\".Zones nest freely — aDefault:platformtheboundaryzonecontainingtheBronze/Silver/Gold
{"destructiveHint":truefalse,"idempotentHint":false,"openWorldHint":false,"readOnlyHint":false}
inspectInspect nodes in full
When: Use before changing a node's fields or columns, to see everything it carries: columns, metadata, owners, neighbours. Get full detail for specific nodes: all columns ⟨13 unchanged words⟩ so you preserve fields you are not changing. Batch: `nodes` (up to 10) takes a list; put every item in one call rather than one call per item. Operates on one Datadef diagram, named by diagram_id. Next: canvas_update_nodes, canvas_set_columns or canvas_replace_node.
⟨5 unchanged words⟩ ,"properties":{"diagram_id":{"description":"CanvasDiagram id, from list_diagrams, create_diagram,or create_blank_diagram.","type":"string"}," ⟨27 unchanged words⟩
{"destructiveHint":false,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":true}
layoutLaycanvasout the diagram
ArrangeWhen:theUsecanvas.once,Callafterthistheoncestructureat(zones,thenodes,endedges) is complete, not afteralleachstructuralchange.editsWitharenodonearguments—itnotonlybetweenplaceseachwhatedit.wasByaddeddefaultor changed; nothing else moves. Set mode "full", direction (LR/TB/RL), spacing (compact/normal/airy), fit (page-portrait/page-landscape/slide-16:9/square) or zone only when thepartsuser asked for a different layout. Position what youtouchedaddedareorre-arrangedmoved, or re-arrange the diagram. Default (no arguments): places new andeverythingmoved nodes next to what they connect to, in the reading direction, and grows their zone if needed; nothing elsekeepsmoves.itsCallposition.it once after structural edits. Re-arranging (mode "full", or any of direction / spacing / fit / zone) redraws the layout the way a generated diagram is drawn, so only do it when the user asks for a different layout: "make it vertical" → direction TB; "more breathing room" / "less cramped" → spacing airy; "fit a Word doc / paper / A4" → fit page-portrait; "for a slide" → fit slide-16:9; "tidy this zone" → zone. Notes and flow arrows follow what they annotate. Operates on one Datadef diagram, named by diagram_id. Returns compact JSON: the ids it created, changed or removed, the diagram revision, a one-line summary and the next step. A viewer-role account is refused. Next: canvas_view to check the result, then notes and flow arrows, then canvas_validate_canvas.
⟨5 unchanged words⟩ ,"properties":{"diagram_id":{"description":"CanvasDiagram id, from list_diagrams, create_diagram,or create_blank_diagram.","type":"string"},"fulldirection":{"description":"Re-arrangeReading direction for a re-arrange: LR left-to-right, TB top-to-bottom, RL right-to-left. Default: theentiredirectioncanvasthefromdiagramscratchreads in now.","enum":["LR","TB","RL"],"type":"string"},"fit":{"description":"Shapediscardingtheexistingdiagrampositions.forOnlyause
{"destructiveHint":true,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":false}
measureMeasurecanvasexact geometry
When: Use only for a precise manual placement the user asked for: exact x/y/width/height per node. To check a layout, canvas_view is faster and already reports overlaps. Get exact geometry: every node's position and size ⟨21 unchanged words⟩ anything precisely — positions are meaningless without it. Batch: `nodes` takes a list; put every item in one call rather than one call per item. Operates on one Datadef diagram, named by diagram_id. Next: canvas_move_nodes, canvas_resize_nodes or canvas_align_nodes.
⟨5 unchanged words⟩ ,"properties":{"diagram_id":{"description":"CanvasDiagram id, from list_diagrams, create_diagram,or create_blank_diagram.","type":"string"}," ⟨22 unchanged words⟩
{"destructiveHint":false,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":true}
moveMove nodes by hand
When: Use only when the user asked for a specific placement. Moving a zone moves its children; never move the children as well. Set node positions precisely. Use absolute x/y to ⟨32 unchanged words⟩ children in the same call. Call canvas_measure_canvas first. Batch: `moves` (up to 60) takes a list; put every item in one call rather than one call per item. Operates on one Datadef diagram, named by diagram_id. Returns compact JSON: the ids it created, changed or removed, the diagram revision, a one-line summary and the next step. A viewer-role account is refused. Next: canvas_view to check. Do not run canvas_layout_canvas afterwards: it would undo the placement.
⟨5 unchanged words⟩ ,"properties":{"diagram_id":{"description":"CanvasDiagram id, from list_diagrams, create_diagram,or create_blank_diagram.","type":"string"}," ⟨75 unchanged words⟩
{"destructiveHint":true,"idempotentHint":false,"openWorldHint":false,"readOnlyHint":false}
moveMovetonodesgroupinto a zone
When: Use to move existing nodes or zones into another zone (they are placed inside it and the zone grows to fit), or out of every zone with group null. A zone cannot move into its own sub-zone. Move existing nodes or zones into an existinggroupzone, or out ofanyeverygroup.zone (group: null). They keep their place on screen when they already sit inside the zone; otherwise they are placed inside it and the zone grows to fit. A zone cannot move into its own sub-zone. Batch: `nodes` takes a list; put every item in one call rather than one call per item. Operates on one Datadef diagram, named by diagram_id. Returns compact JSON: the ids it created, changed or removed, the diagram revision, a one-line summary and the next step. A viewer-role account is refused. Next: canvas_view to check the result.
⟨5 unchanged words⟩ ,"properties":{"diagram_id":{"description":"CanvasDiagram id, from list_diagrams, create_diagram,or create_blank_diagram.","type":"string"},"group":{"description":"Targetgroupzone id or label. Pass null toremovetake the nodesfromout of theirgroup.zones.","type":["string","null"]},"nodes":{"description":"Node or zone ids or labels to move.","items": ⟨12 unchanged words⟩
{"destructiveHint":true,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":false}
removeRemove nodes
DeleteWhen: Use to delete nodes and their edges. Removing a zone keeps its contents (they move up to the parent, same place on screen): that is how to ungroup. Pass keepChildren:false only to delete the zone with everything inside it. Delete nodes, notes or zones, with every edge and lineage row touching them.DeletingRemoving agroupzonealsokeepsdeletesits contents by default: they move up to thenodeszone's parent and stay where they are on screen (this is how to ungroup a zone). Pass keepChildren:false only when the user wants the zone AND everything inside it—deleted. Batch:check`nodes`withtakescanvas_describe_canvasafirstlist;ifputthateveryisitemnotinwhatoneyoucallwant.rather than one call per item. Operates on one Datadef diagram, named by diagram_id. Returns compact JSON: the ids it created, changed or removed, the diagram revision, a one-line summary and the next step. A viewer-role account is refused. Next: canvas_view to check the result.
⟨5 unchanged words⟩ ,"properties":{"diagram_id":{"description":"CanvasDiagram id, from list_diagrams, create_diagram,or create_blank_diagram.","type":"string"},"keepChildren":{"description":"For zones: true (default) moves the contents up to the parent; false deletes everything inside too.","type":"boolean"},"nodes":{"description":"Node or zone ids or exact labels.","items":{" ⟨11 unchanged words⟩
{"destructiveHint":true,"idempotentHint":false,"openWorldHint":false,"readOnlyHint":false}
replaceReplace a node in place
SwapWhen: Use when one component changes identity or type (Redshift becomes Snowflake, anodecardforbecomes adifferentserviceoneicon).whileThekeepingnodeeverykeepsconnectionits id,itsconnections,positionlineage,andzone,itspositiongroup.andUsefields. Turnthisawhennode into a different componentchangesin place — Redshift becomes Snowflake, a batch job becomesstreamingstreaming.—Itinsteadkeepsofitsdeletingid, every connection andrebuildinglineage row,whichitswouldzone,loseposition,allowners, schedule, colours and columns; only what you pass changes (a new label with no icon picks theedges.new product's icon). canvas_update_nodes does the same for many nodes at once. Batch: One node per call. To convert many nodes, use canvas_update_nodes with `type` (and `label`, `icon`) for each, in one call. Operates on one Datadef diagram, named by diagram_id. Returns compact JSON: the ids it created, changed or removed, the diagram revision, a one-line summary and the next step. A viewer-role account is refused. Next: canvas_view to check the result.
⟨8 unchanged words⟩ :"string"},"diagram_id":{"description":"CanvasDiagram id, from list_diagrams, create_diagram,or create_blank_diagram.","type":"string"}," ⟨7 unchanged words⟩ :"string"},"keepColumns":{"description":"CarryKeep the existing columnsover(table tothe replacement.table). Defaulttrue.true; false clears them.","type":"boolean"},"label":{ ⟨44 unchanged words⟩
{"destructiveHint":true,"idempotentHint":false,"openWorldHint":false,"readOnlyHint":false}
resizeResize nodes by hand
When: Use only when the user asked for a specific size. Set the width and height of nodes. Mostly ⟨15 unchanged words⟩ and resizing one can clip what it displays. Batch: `resizes` (up to 40) takes a list; put every item in one call rather than one call per item. Operates on one Datadef diagram, named by diagram_id. Returns compact JSON: the ids it created, changed or removed, the diagram revision, a one-line summary and the next step. A viewer-role account is refused. Next: canvas_view to check.
⟨5 unchanged words⟩ ,"properties":{"diagram_id":{"description":"CanvasDiagram id, from list_diagrams, create_diagram,or create_blank_diagram.","type":"string"}," ⟨43 unchanged words⟩
{"destructiveHint":true,"idempotentHint":false,"openWorldHint":false,"readOnlyHint":false}
searchFindiconsvendor icon ids
SearchWhen:Datadef'sUse before adding nodes that should show a vendor logo (Snowflake, Kafka, Power BI) and you are unsure of the icon id. Find icon ids in Datadef's library (2000+ cloud and data-tool logos)forbyaproductvalidname,icone.g.id."AmazonUseAuroraitPostgreSQL",when"k8s",you"AzurewantEventaHubs".specificPassvendor`queries`logotoandlookareupunsuremanyofnamesitsinexactone call (best id—perpassingname);anpassinvalid`query`idforsilentlythefallstopbackmatchestoofaonegenericname.icon.Scores: 90+ sure, 75+ good. A name with no match has no icon; leave the icon field out rather than guessing.OperatesBatch:onPassone`queries`Datadefwithdiagramevery vendor at once (up to 40,namedbestbyiddiagram_id.per name) instead of one call per vendor. Next: canvas_add_nodes (or canvas_update_nodes) with icon set to a returned id; omit icon when nothing matched.
⟨5 unchanged words⟩ ,"properties":{"diagram_id":{"description":"CanvasNotid,neededfromforlist_diagrams,iconcreate_diagram,search;oracceptedcreate_blank_diagram.for compatibility.","type":"string"},"limit":{"description":"MaxMatchesresultsper name. Default 5 for `query`,default18.for `queries`.","maximum":2010,"minimum":1,"type":"integer"},"queryqueries":{"description":"Tool
{"destructiveHint":false,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":true}
setChange a table's columns
SetWhen: Use `mode: "merge"` to add or update (renameTo) a few columns, `mode: "remove"` to drop some, or the default replace for the fullcolumnlist.listColumnsofthat stay keep their ids and lineage. Change atabletable'snode,columns.replacingmodewhatever"merge"itaddshad.newPasscolumnseveryandcolumnupdates (or renames, with renameTo) the ones youwantname,toleavingkeepthe rest alone —thisuseisitato add one column. mode "remove" deletes the named columns only. mode "replace" (default) makes the list exactly what you pass. Columns are matched by name,notso amerge.column that stays keeps its id, its lineage and the edges anchored to it; lineage and anchors of removed columns are cleaned up. Mark primary and foreignkeys;keys. Batch:theyOnearetablewhatpermakecall.aFordataseveraldiagramtables,worthsendreading.one set_columns operation per table in a single canvas_batch call. Operates on one Datadef diagram, named by diagram_id. Returns compact JSON: the ids it created, changed or removed, the diagram revision, a one-line summary and the next step. A viewer-role account is refused. Next: canvas_add_lineage for column-level mappings, if there are any.
⟨34 unchanged words⟩ "customer_id\".","type":"string"},"renameTo":{"description":"merge mode: new name for the column called `name`.","type":"string"},"type":{"description":"SQL type, e.g. \"varchar\", \"bigint\", \"timestamp\". Default \"unknown\".for a new column; an existing column keeps its type.","type":"string"}},"required":["name"],"type":"object"},"maxItems":6080,"type":"array"},"diagram_id":{"description":"CanvasDiagram id, from list_diagrams, create_diagram,or create_blank_diagram.","type":"string"},"mode":{"description":"Default \"replace\".","enum":["replace","merge","remove"],"type":"string"},"node":{" ⟨15 unchanged words⟩
{"destructiveHint":true,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":false}
suggestSuggest simplifications
When: Use when the diagram feels dense or the user asks to simplify. It changes nothing; it reports what could collapse. Report where this canvas could be collapsed — ⟨43 unchanged words⟩ Operates on one Datadef diagram, named by diagram_id. Next: canvas_collapse_nodes to apply a suggestion the user wants.
⟨5 unchanged words⟩ ,"properties":{"diagram_id":{"description":"CanvasDiagram id, from list_diagrams, create_diagram,or create_blank_diagram.","type":"string"}," ⟨18 unchanged words⟩
{"destructiveHint":false,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":true}
updateUpdate edges
When: Use to relabel, retype, restyle (dashed, colour), reverse, put arrowheads on both ends, or re-point an existing edge, instead of disconnecting and reconnecting it. Change existing connectionswithout deletinginthemplace:fixrelabel,aretype,labelrestyle (solid/dashed/dotted,changecolour), reverse thetypedirection, put arrowheads on both ends, orrestyle.re-pointUseonethisend tocorrectanother node. Identify each edge by source and target, or by `edge` (an id or "Source -> Target"). Change only the edges the user asked about: awrongrequest and its response are two edges on purpose, never merge them into one two-headed edgelabelto tidy the drawing. Batch: `updates` (up to 60) takes a list; put every item in one call rather thandisconnectingoneandcallreconnecting.per item. Operates on one Datadef diagram, named by diagram_id. Returns compact JSON: the ids it created, changed or removed, the diagram revision, a one-line summary and the next step. A viewer-role account is refused. Next: canvas_view to check the result.
⟨5 unchanged words⟩ ,"properties":{"diagram_id":{"description":"CanvasDiagram id, from list_diagrams, create_diagram,or create_blank_diagram.","type":"string"},"updates":{"items":{"additionalProperties":false,"properties":{"bidirectional":{"description":"true = arrowheads on both ends of this one edge (a genuinely two-way link); false = only at the target.","type":"boolean"},"color":{"description":"Colour name or hex; \"default\" returns to the source node's hue.","type":"string"},"edge":{"description":"Edge id, or \"Source -> Target\".","type":"string"},"label":{"description":"New label.","type":"string"},"newSource":{"description":"Re-point the edge to start at this node.","type":"string"},"newTarget":{"description":"Re-point the edge to end at this node.","type":"string"},"removeLabel":{"description":"Remove the label.","type":"boolean"},"reverse":{"description":"Swap source and target: the arrow points the other way.","type":"boolean"},"source":{"description":"SourceCurrent source node id or label.","type":"string" ⟨6 unchanged words⟩ :"string"},"target":{"description":"TargetCurrent target node id or label.","type":"string" ⟨6 unchanged words⟩ "join"],"type":"string"}},"required":["source","target"],"type":"object"},"maxItems":
{"destructiveHint":true,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":false}
updateUpdate nodes, zones and notes
ChangeWhen:propertiesUseoffor any in-place change: rename a node or zone (it keeps its size and contents), edit a note's text, recolour (`color: "green"`, `fill`, `family`), change a zone's style, swap an icon, or change a data node's type; fields you do not pass stay as they are. Many nodes in one call. Change existingnodes.nodes, zones or notes in place: rename (a zone keeps its size and contents), edit a note's text, recolour ("color": "green" or "#16a34a"; "fill" for the background; "family" for a layer hue), change a zone's style, swap an icon, change a data node's type. Only the fields you passarechange;touched;id, position, size, edges and everything elseisarepreserved.kept.ToBatchreplacemanyanodestable'sin one call. For columns usecanvas_set_columnscanvas_set_columns. Batch:instead.`updates` (up to 60) takes a list; put every item in one call rather than one call per item. Operates on one Datadef diagram, named by diagram_id. Returns compact JSON: the ids it created, changed or removed, the diagram revision, a one-line summary and the next step. A viewer-role account is refused. Next: canvas_view to check the result.
⟨5 unchanged words⟩ ,"properties":{"diagram_id":{"description":"CanvasDiagram id, from list_diagrams, create_diagram,or create_blank_diagram.","type":"string"},"updates":{"items":{"additionalProperties":false,"properties":{"borderStyle":{"description":"Border line of a zone or card; line style of an arrow or line shape.","enum":["solid","dashed","dotted"],"type":"string"},"color":{"description":"Main colour: a zone's border and header, a card's tile and border, a note's border, a shape's stroke. Name, hex, or family.","type":"string"},"container":{"description":"Zones only: layer = tinted band with a header; boundary = dashed perimeter (account, VPC, workspace).","enum":["layer","boundary"],"type":"string"},"dataOwner":{"type":"string"},"dataSteward" ⟨2 unchanged words⟩ ,"description":{"type":"string"},"family":{"description":"Colour family for a node or zone. Clears custom colours.","enum":["source","ingest","bronze","silver","gold","consume","dbt","neutral"],"type":"string"},"fill":{"$ref":"#/properties/updates/items/properties/color","description":"Background / wash colour. Name or hex."},"icon":{"description":"Icon id fromsearch_icons.search_icons, or \"none\" to remove it. An unknown icon is not applied.","type":"string"},"kpiFormula":{" ⟨6 unchanged words⟩ {"type":"string"},"label":{"description":"New name. For a zone this renames its caption; for a note it replaces the note text.","type":"string"},"node":{"description":"Node or zone id, or exact label.","type":"string"},"pipelineType":{"type":"string"},"resetStyle":{"description":"Drop custom colours and family, back to the default look. Applied before any colour in the same update.","type":"boolean"},"
{"destructiveHint":true,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":false}
validateValidatecanvasthe diagram
CheckWhen:theUsecanvasbeforeforyoustructuralfinish:problemsbroken(disconnectedreferencesnodesand icons,circularnodesdataoutsideflowtheir zone, overlapping zones or nodes. Loops are reported as information only. Check your work: broken references),andbrokenqualityicons,problemsnodes(unlabelledstickingedgesout of their zone,tablesoverlappingwithoutzonescolumns).orCallnodes,thisunconnectedbeforeor unfed nodes. By default it reports only issues in what youfinish,changedandinfixthisanysessionerrors(scopeit"changed");reports.scope "all" checks the whole canvas. Fix errors; judge warnings; info needs no action. Operates on one Datadef diagram, named by diagram_id. Next: Fix errors. Warnings are observations; ignore the ones that do not apply.
⟨5 unchanged words⟩ ,"properties":{"diagram_id":{"description":"CanvasDiagram id, from list_diagrams, create_diagram,or create_blank_diagram.","type":"string"},"scope":{"description":"\"changed\" (default when you have changed something) or \"all\".","enum":["changed","all"],"type":"string"}},"required":[ ⟨3 unchanged words⟩
{"destructiveHint":false,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":true}
Create an empty diagram and return itsWhen:diagram_id,usesowhen youcanwill builditthe diagram yourself with the canvas_*tools. No AI generation runs: you draw it. Use thistools,whenbecause you want control over the result,or already know the architecture from the conversation. Use create_diagram instead whenyou wantDatadef's modeltoshould design the whole thing from a prompt. Creates an empty diagram and returns its diagram_id. No AI generation runs: you draw it. Call get_design_guide first: it is the standard Datadef's own generator follows, and building without it produces the diagrams this tool exists to avoid. Next: canvas_search_icons (all vendors in one call), then one canvas_batch with every zone (group_nodes) and node (add_nodes), canvas_connect_nodes, canvas_layout_canvas once, canvas_view.
GenerateWhen: use when Datadef's own model should design a whole new diagram from a description or a pasted schema. To build it yourself step by step, use create_blank_diagram; to change an existing diagram, canvas_view and the canvas_* tools, or edit_diagram. Generates a professional data architecture diagram from a description andsavesaves it to the user's Datadef account.Usethisit for any data-shaped diagram: medallion and lakehouse ⟨340 unchanged words⟩ for these. This produces a real, editable diagram. Next: show the user the preview line it returns; to adjust the result, canvas_view then the targeted canvas_* tools.
Editan existinga diagram with Datadef's agent
ChangeWhen:anuseexistingfordiagramawithlarge change you can describe in words better than you can make it tool by tool: "reorganise this into bronze, silver and gold", "rebuild the consumption side from this spec", "add owners and schedules everywhere". For anatural-languagepreciseinstructionchange (rename, add a node, rewire an edge), the canvas_* tools are faster and exact. Datadef's own editing agent carries out the instruction: add nodes, rewire connections, add columns, reorganise into layers, fill in owners and schedules.Be specific about what to change andwhere.where: "Add a Kafka topic between the API ⟨5 unchanged words⟩ 'events'" works; "make it better" does not. Timing:Returnsan edit takes 30-120 s. This waits about 35 s; aPNGfinished edit comes back with its summary, the ids it changed and a PNG. A slower one answers "in progress" and keeps running on the server: do NOT call edit_diagram again. Sending the same instruction again joins the running edit (or returns the result of theupdatedonediagram.that finished less than a minute ago); a different instruction is refused until it finishes. canvas_view and get_diagram report when it has finished. Next: canvas_view to check the result.
⟨5 unchanged words⟩ ,"properties":{"diagram_id":{"description":"CanvasDiagram id to modify.","type":"string"},"include_image":{"description":"Return a PNG of the updateddiagram.diagram when the edit finishes in time. Default true.","type":"boolean"}," ⟨17 unchanged words⟩
RenderWhen: use to give the user an image of a diagram, or a link to download, attach or embed one. Not to check your own edits: a render starts a browser (6-10 s), while canvas_view answers in milliseconds and reports overlaps. Renders a diagram to PNG orJPEG image.JPEG. Returns the image inline AND a short-lived signed ⟨28 unchanged words⟩ the file directly and needs no API key. Next: nothing; show the image or the link to the user.
When: read once before your first canvas_* call, to build or to edit. Datadef's standard forwhat makesadiagramreadable,diagram (size, edge discipline, nested zones,annotations,notes) and the toolorderworkflow:forwhichbuildingcanvas_*ortoolediting.toReadusethiswhen,BEFOREbatching,yourlayingfirstoutcanvas_*once,call.checking with canvas_view. It is the same standard Datadef's own generator ⟨7 unchanged words⟩ hand comes out indistinguishable from a generated one. Works without a subscription. Next: create_blank_diagram to build, or canvas_view to edit an existing diagram.
{"idempotentHint":true,"openWorldHint":false,"readOnlyHint":true}
Read a diagram, with a pictureReadWhen: use to show thefulluserstructureaofdiagram (it attaches a rendered PNG and a markdown image line, 6-10 s), or to poll a diagram:that create_diagram or edit_diagram is still working on. To check your own edits, canvas_view is faster and reports overlaps. Returns every node with its type and columns, every connection,and thegroups. Usezones,thisplusbeforewhethereditingasogenerationyouorknowedit_diagramwhatrun isactuallystillthere.in progress. Next: canvas_view and the canvas_* tools to edit.
ListWhen: use to find the id of an existing diagram before viewing, editing or exporting it. Lists the diagrams in the user's Datadef account, most recently updated first.Use thisNext:tocanvas_viewfindwith theid of a diagram before editingdiagram_idortoexportingsee it.
Apply several canvas changes at once — When: use whenever you would otherwise make several canvas_* write calls in a row, above all with tools that take one item per call: create every zone (group_nodes), convert many nodes (replace_node), set several tables' columns (set_columns). Eighteen zone creations or thirty-five replacements become one call and one save. Each operation is {"tool": "<canvas tool, with or without the canvas_ prefix>", "args": {<that tool's arguments, without diagram_id>}}. Operations run in order on the same diagram, so a later one can use what an earlier one created by its exact label (create a zone in ope…
Remove column lineage — When: Use to delete lineage rows between two nodes (one column pair, or all rows between them). Lineage pointing at deleted nodes or columns is cleaned automatically. Delete lineage rows between two nodes: one column pair, or every row between the two nodes when no column is given. Lineage pointing at deleted nodes or columns is cleaned automatically and never needs this. Batch: `links` (up to 100) takes a list; put every item in one call rather than one call per item. Operates on one Datadef diagram, named by diagram_id. Returns compact JSON: the ids it created, changed or removed, the d…
View the diagram (fast) — When: use to see a diagram before you edit it and after each round of changes; this is how you check your work. It answers in milliseconds from the saved diagram, where export_diagram starts a browser for 6-10 s. Returns a text map: the zones as a tree, each with its place on a coarse grid (r1 = top row, c1 = left column) and its nodes (label, type, icon, #id), then the edges, then the checks a render would reveal: overlapping nodes, overlapping sibling zones, nodes sticking out of their zone, nodes not laid out yet, empty zones, and the validator's error and warning counts. Every #id works …