@stablebaseline/sdk 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -74,7 +74,7 @@ interface paths {
74
74
  put?: never;
75
75
  /**
76
76
  * listArchitectureIcons
77
- * @description List icons for systemsarchitecture diagrams. Use returned iconPath as-is in D2 code (e.g. icon: dev/docker.svg).
77
+ * @description List curated software-architecture icons (AWS, Azure, GCP, Docker, Kubernetes, databases, message queues, etc.). Each result has an `iconPath` (e.g. 'dev/docker.svg'). TWO ways to use it: (1) on a WHITEBOARD, drop it via addWhiteboardElements({ type:'image', iconPath:'dev/docker.svg', x, y, width:96, height:96, text:'Docker' }); (2) in a D2 systems-architecture diagram, use the iconPath as-is in D2 code (e.g. icon: dev/docker.svg).
78
78
  */
79
79
  post: operations["listArchitectureIcons"];
80
80
  delete?: never;
@@ -674,7 +674,7 @@ interface paths {
674
674
  put?: never;
675
675
  /**
676
676
  * updateWhiteboardScene
677
- * @description Edit elements on a whiteboard's canvas WITHOUT dropping the rest of the scene. A board may hold many diagrams/elements, so prefer surgical edits: mode='patch' (DEFAULT) shallow-merges each incoming object into the existing element with the same `id` (send just {id, backgroundColor:'blue'} to recolour one box, or {id, x, y} to move one) and appends any elements whose id is new/absent — everything else is left untouched. `deleteIds` removes specific elements by id. mode='append' only adds. mode='replace' overwrites the ENTIRE scene (use ONLY when intentionally rewriting the whole board). To author NEW shapes/connectors from a high-level spec, prefer addWhiteboardElements. Optional appState/files are merged in. PROCESS: for a non-trivial edit call getWhiteboardGuide FIRST; after editing, ALWAYS call getWhiteboardImage to confirm the board still looks right (layout, labels, overlaps), and patch again if it doesn't.
677
+ * @description Edit elements on a whiteboard's canvas WITHOUT dropping the rest of the scene. A board may hold many diagrams/elements, so prefer surgical edits: mode='patch' (DEFAULT) shallow-merges each incoming object into the existing element with the same `id` (send just {id, backgroundColor:'blue'} to recolour one box, or {id, x, y} to move one) and appends any elements whose id is new/absent — everything else is left untouched. `deleteIds` removes specific elements by id. mode='append' only adds. mode='replace' overwrites the ENTIRE scene — to rebuild or edit only PART of a board, still use 'patch', because replace DELETES every element you don't resend (of ANY type). As a safeguard, a replace that would drop ANY existing element not in your payload is REJECTED unless you pass confirmReplace:true (or include those ids); diagrams/images/frames are flagged specially since they're inserted separately and costliest to lose. To author NEW shapes/connectors from a high-level spec, prefer addWhiteboardElements — and prefer library stencils / sticky notes / architecture icons over plain rectangles wherever a standard form fits (sticky notes, kanban/scrum, flowcharts, UML/ER, BPMN, org charts, wireframes). Optional appState/files are merged in. PROCESS: for a non-trivial edit call getWhiteboardGuide FIRST; after editing, ALWAYS call getWhiteboardImage to confirm the board still looks right (layout, labels, overlaps), and patch again if it doesn't.
678
678
  */
679
679
  post: operations["updateWhiteboardScene"];
680
680
  delete?: never;
@@ -694,7 +694,7 @@ interface paths {
694
694
  put?: never;
695
695
  /**
696
696
  * addWhiteboardElements
697
- * @description Author shapes onto a whiteboard from high-level specs (you do NOT need the full Excalidraw element schema). Appends to the canvas. Expressive enough to reproduce real Excalidraw templates (sticky-note brainstorm grids, sketchy mind maps, flowcharts). Each spec: { type: 'rectangle'|'ellipse'|'diamond'|'sticky'|'text'|'arrow'|'line'|'frame'|'image'|'stencil', id?, x, y, width, height, text? (STRONGLY PREFER setting a shape's label via its own `text` — it becomes a centered, auto-WRAPPED bound label fitted to the shape; do NOT drop a separate type:'text' element on top of a shape as its label. Standalone type:'text' is for free-floating titles/notes and now also wraps to its width; Yes/No label on an arrow — emojis are fine, e.g. 'Risks ⚠️'), fontSize?, fontFamily? (1=hand-drawn default, 2=normal, 3=code), textAlign?, backgroundColor? (name 'blue'/'green'/'yellow'/'pink'/'violet'/'orange'/'teal'/… or hex), strokeColor?, fillStyle? ('solid'|'hachure'|'cross-hatch'), strokeStyle? ('solid'|'dashed'|'dotted' — use 'dashed' for grid/category borders), strokeWidth? (1 thin/2 bold/4 extra), roughness? (0 clean, 1 default, 2 very sketchy/hand-drawn — use 2 for organic mind maps), roundness? (number type or null for sharp), opacity?, name? (frame title), frameId? (put a shape inside a frame), start?:{id}, end?:{id} (connect arrows/lines to shapes by id — connectors AUTO-CLIP to the shape edges, never overrun to the centre, AUTO-ROUTE around any shapes in between so a decision's No/loop-back branch never cuts straight through the boxes between source and target, and bound text auto-wraps + centres), routing? ('straight' default | 'elbow' for clean right-angle flowchart/org-chart connectors | 'curved'), startArrowhead?/endArrowhead? (arrowheads are SOLID filled triangles by default — just OMIT them. Pass null for a plain mind-map spoke with no head. Do NOT pass 'arrow': that is Excalidraw's open 'V' and is auto-upgraded to a solid triangle anyway), points? ([[0,0],[dx,dy]] relative, only for manual geometry — almost never needed; binding by id is better), props? (escape hatch: any other Excalidraw field) }. ARCHITECTURE ICONS: to place a software-architecture icon (AWS/Azure/GCP/Docker/Kubernetes/databases/etc.), first call listArchitectureIcons to find one, then add a spec { type:'image', iconPath:'<relative_url e.g. dev/docker.svg>', x, y, width:96, height:96, text?:'<caption shown below>' } — the icon is stored as a URL reference (never base64). Use imageUrl instead of iconPath for any other public image. Combine icons with labelled boxes + elbow arrows for clean architecture diagrams. LIBRARY STENCILS: for hand-drawn, on-brand elements (sticky notes, scrum/kanban columns, flowchart symbols, UML/ER, BPMN, org-chart nodes, wireframe widgets, stick figures), FIRST call listWhiteboardStencils to find one, then add { type:'stencil', stencilKey:'<key from listWhiteboardStencils>', x, y } (or { type:'stencil', stencil:'<name e.g. yellow sticky note>', pack?:'<pack>', x, y } to fuzzy-match by name). STRONGLY prefer these over plain rectangles whenever the user asks for sticky notes, kanban/scrum/story boards, flowcharts, wireframes/mockups, org charts, etc. FRAMES: a frame is a NON-DESTRUCTIVE, ANY-SIZE container. To enclose shapes that ALREADY exist, add ONE type:'frame' sized to cover them (Excalidraw auto-captures elements inside a frame's bounds) or set those shapes' frameId — never recreate or delete-and-redraw content just to frame it. If a frame doesn't fully cover its content, just RESIZE the frame (patch its width/height). Deleting a frame (deleteIds:[frameId]) leaves all its contents intact on the canvas — it only removes the frame border + title. PRESENTATION/SLIDES: when the user wants a presentation or slide deck, create type:'frame' slides sized width:1280,height:720 (16:9), laid out LEFT-TO-RIGHT at the same y (x: 0, then 1440, 2880, 4320, …), each with a `name` (the slide title). Put every slide's shapes/text/images INSIDE its frame by setting their frameId to that frame's id (give the frame an id and reference it). Slides play in order (left-to-right, then top-to-bottom) in the board's Present mode and export to PPTX, so one frame = one slide. FLOWCHART recipe: rectangles (roundness null for sharp process boxes), diamonds for decisions, arrows with routing:'elbow' and Yes/No as the arrow's text. Use type 'sticky' for solid-fill notes; type 'line' with no arrowheads + roughness:2 for sketchy mind-map spokes. Give shapes ids and reference them from connectors. Connectors may also bind to shapes ALREADY on the board by their id (get them via getWhiteboard includeElements:true) — you do NOT need to resend existing shapes; the server reads the live scene to bind the arrow and route it around the other boxes. Great for brainstorms, mind maps, flowcharts, org charts, SWOT, retros. PROCESS: for any non-trivial board call getWhiteboardGuide FIRST to plan it; then after adding, ALWAYS call getWhiteboardImage to SEE the result and check layout, labels, spacing, overlaps and how shapes connect — if anything looks off, fix it with updateWhiteboardScene (patch by id) and render again, iterating until it looks right.
697
+ * @description Author shapes onto a whiteboard from high-level specs (you do NOT need the full Excalidraw element schema). Appends to the canvas. PREFER THE RICHEST FORM THAT FITS, not plain rectangles: for a sticky/post-it note use { type:'sticky', text, backgroundColor } (a first-class note with an auto-fitting bound label — there is NO sticky-note stencil; OMIT x/y and it is auto-placed in clear space below existing content, so it doesn't land on top of the current drawing); for kanban/scrum/story boards, flowcharts, UML/ER, BPMN, org charts, wireframes/mockups, charts or people use a LIBRARY STENCIL in ONE call — { type:'stencil', stencil:'<name e.g. decision>', x, y } fuzzy-matches by name with no prior listWhiteboardStencils call (pass width/height to SCALE the whole stencil and text to fill its single label); for cloud/software-architecture use ICONS — { type:'image', iconPath:'dev/docker.svg', x, y } (paths from listArchitectureIcons); reserve raw rectangles/ellipses for when no standard form fits. Expressive enough to reproduce real Excalidraw templates (sticky-note brainstorm grids, sketchy mind maps, flowcharts). Each spec: { type: 'rectangle'|'ellipse'|'diamond'|'sticky'|'text'|'arrow'|'line'|'frame'|'image'|'stencil', id?, x, y, width, height, text? (STRONGLY PREFER setting a shape's label via its own `text` — it becomes a centered, auto-WRAPPED bound label fitted to the shape; do NOT drop a separate type:'text' element on top of a shape as its label. Standalone type:'text' is for free-floating titles/notes and now also wraps to its width; Yes/No label on an arrow — emojis are fine, e.g. 'Risks ⚠️'), fontSize?, fontFamily? (1=hand-drawn default, 2=normal, 3=code), textAlign?, backgroundColor? (name 'blue'/'green'/'yellow'/'pink'/'violet'/'orange'/'teal'/… or hex), strokeColor?, fillStyle? ('solid'|'hachure'|'cross-hatch'), strokeStyle? ('solid'|'dashed'|'dotted' — use 'dashed' for grid/category borders), strokeWidth? (1 thin/2 bold/4 extra), roughness? (0 clean, 1 default, 2 very sketchy/hand-drawn — use 2 for organic mind maps), roundness? (number type or null for sharp), opacity?, name? (frame title), frameId? (put a shape inside a frame), start?:{id}, end?:{id} (connect arrows/lines to shapes by id — connectors AUTO-CLIP to the shape edges, never overrun to the centre, AUTO-ROUTE around any shapes in between so a decision's No/loop-back branch never cuts straight through the boxes between source and target, and bound text auto-wraps + centres), routing? ('straight' default | 'elbow' for clean right-angle flowchart/org-chart connectors | 'curved'), startArrowhead?/endArrowhead? (arrowheads are SOLID filled triangles by default — just OMIT them. Pass null for a plain mind-map spoke with no head. Do NOT pass 'arrow': that is Excalidraw's open 'V' and is auto-upgraded to a solid triangle anyway), points? ([[0,0],[dx,dy]] relative, only for manual geometry — almost never needed; binding by id is better), props? (escape hatch: any other Excalidraw field) }. ARCHITECTURE ICONS: to place a software-architecture icon (AWS/Azure/GCP/Docker/Kubernetes/databases/etc.), first call listArchitectureIcons to find one, then add a spec { type:'image', iconPath:'<relative_url e.g. dev/docker.svg>', x, y, width:96, height:96, text?:'<caption shown below>' } — the icon is stored as a URL reference (never base64). Use imageUrl instead of iconPath for any other public image. Combine icons with labelled boxes + elbow arrows for clean architecture diagrams. LIBRARY STENCILS: for hand-drawn, on-brand elements (scrum/kanban columns, flowchart symbols, UML/ER, BPMN, org-chart nodes, wireframe widgets, stick figures), FIRST call listWhiteboardStencils to find one, then add { type:'stencil', stencilKey:'<key from listWhiteboardStencils>', x, y } (or { type:'stencil', stencil:'<name e.g. decision>', pack?:'<pack>', x, y } to fuzzy-match by name). A stencil is a mini-whiteboard (a collection of elements) of kind 'symbol' or 'template' (listWhiteboardStencils returns the kind + its embedded `labels`). For a SYMBOL (one atomic labelled node — flowchart box, BPMN task, org node), pass id + text + width/height: the label auto-fits its single slot and arrows bind to it via start/end {id}. For a TEMPLATE (a multi-component layout — Alerts, Forms, Tables, Charts), place it WHOLE (no single text); the result returns its `children` (id + text + colour + position) so you retext, recolour, or DELETE specific parts by id via updateWhiteboardScene (cluster children by y to act on a whole row/variant). STRONGLY prefer stencils over plain rectangles for wireframes/mockups, kanban/scrum boards, UML/BPMN, org charts; for dense flowcharts, plain shapes with bound text + elbow arrows are equally reliable. (For a plain sticky/post-it note use type:'sticky', NOT a stencil — there is no sticky-note stencil.) FRAMES: a frame is a NON-DESTRUCTIVE, ANY-SIZE container. To enclose shapes that ALREADY exist, add ONE type:'frame' sized to cover them (Excalidraw auto-captures elements inside a frame's bounds) or set those shapes' frameId — never recreate or delete-and-redraw content just to frame it. If a frame doesn't fully cover its content, just RESIZE the frame (patch its width/height). Deleting a frame (deleteIds:[frameId]) leaves all its contents intact on the canvas — it only removes the frame border + title. PRESENTATION/SLIDES: when the user wants a presentation or slide deck, create type:'frame' slides sized width:1280,height:720 (16:9), laid out LEFT-TO-RIGHT at the same y (x: 0, then 1440, 2880, 4320, …), each with a `name` (the slide title). Put every slide's shapes/text/images INSIDE its frame by setting their frameId to that frame's id (give the frame an id and reference it). Slides play in order (left-to-right, then top-to-bottom) in the board's Present mode and export to PPTX, so one frame = one slide. FLOWCHART recipe: rectangles (roundness null for sharp process boxes), diamonds for decisions, arrows with routing:'elbow' and Yes/No as the arrow's text. Use type 'sticky' for sticky/post-it notes (a solid-fill note with an auto-fitting bound label — set text + backgroundColor); type 'line' with no arrowheads + roughness:2 for sketchy mind-map spokes. Give shapes ids and reference them from connectors. Connectors may also bind to shapes ALREADY on the board by their id (get them via getWhiteboard includeElements:true) — you do NOT need to resend existing shapes; the server reads the live scene to bind the arrow and route it around the other boxes. Great for brainstorms, mind maps, flowcharts, org charts, SWOT, retros. PROCESS: for any non-trivial board call getWhiteboardGuide FIRST to plan it; then after adding, ALWAYS call getWhiteboardImage to SEE the result and check layout, labels, spacing, overlaps and how shapes connect — if anything looks off, fix it with updateWhiteboardScene (patch by id) and render again, iterating until it looks right. RESULT: returns `added` (count), `placement` (bounding box {x,y,width,height} of what you just added) and `autoPlaced` (true when you omitted x/y so it was placed in clear space below existing content) — use placement/autoPlaced to tell the user WHERE the new elements landed, never invent a location.
698
698
  */
699
699
  post: operations["addWhiteboardElements"];
700
700
  delete?: never;
@@ -703,6 +703,26 @@ interface paths {
703
703
  patch?: never;
704
704
  trace?: never;
705
705
  };
706
+ "/tools/duplicateWhiteboardElements": {
707
+ parameters: {
708
+ query?: never;
709
+ header?: never;
710
+ path?: never;
711
+ cookie?: never;
712
+ };
713
+ get?: never;
714
+ put?: never;
715
+ /**
716
+ * duplicateWhiteboardElements
717
+ * @description Copy-paste existing whiteboard elements — the MCP equivalent of selecting a group and pressing Ctrl/Cmd+D. Clones the given elements (plus their group peers + bound text/labels) with FRESH ids, offsets the copy by dx/dy, and by default groups it into ONE new unit so it moves together. Use it to build something once (a labelled stencil frame, a kanban card, a UML class) then stamp out consistent repeats fast — then retext/recolour each copy by its new id (via the returned idMap) with updateWhiteboardScene. Pass `groupId` to copy a whole group as a unit (e.g. a placed stencil's groupId from its placement result) and/or `ids` for specific elements. Internal references (group membership, bound text containerId, arrow start/end bindings) are remapped within the copied set; a binding to an element you did NOT copy is dropped. Returns { duplicated, idMap (old id → new id), groupId (the copy's new unit group), elementCount }. Render with getWhiteboardImage afterwards to verify.
718
+ */
719
+ post: operations["duplicateWhiteboardElements"];
720
+ delete?: never;
721
+ options?: never;
722
+ head?: never;
723
+ patch?: never;
724
+ trace?: never;
725
+ };
706
726
  "/tools/insertWhiteboardImage": {
707
727
  parameters: {
708
728
  query?: never;
@@ -754,7 +774,7 @@ interface paths {
754
774
  put?: never;
755
775
  /**
756
776
  * listWhiteboardStencils
757
- * @description Search the built-in library of STRUCTURAL whiteboard stencils — ready-made, hand-drawn multi-element graphics: sticky notes (post-it), scrum-board columns, flowchart symbols, UML/ER, BPMN, org-chart nodes, gantt, lo-fi/UX wireframe widgets, charts, and stick figures. Returns matching stencils each with a `key`, name, pack and category, plus the full pack/category lists. Place one via addWhiteboardElements({type:'stencil', stencilKey:'<key>', x, y}). These look far richer and more on-brand than plain rectangles use them when the user asks for sticky notes, kanban/scrum boards, flowcharts, wireframes, mockups, etc. SEARCH TIPS: prefer BROAD single words ('sticky', 'decision', 'actor', 'phone', 'process') multi-word exact phrases often miss. If an exact query matches nothing the result is auto-broadened to close candidates (broadened:true is set); you can also pass pack/category to browse. When ANY returned stencil reasonably fits, PLACE it instead of drawing a plain rectangledo not abandon stencils just because your first phrase returned 0. The library does NOT contain free-form 'cloud' / 'hat' / 'thought-bubble' shapes; approximate those with the closest stencil (e.g. a sticky note or a simple shape) or fall back to a plain shape only when nothing fits. For cloud/architecture ICONS (AWS/Azure/GCP/Docker/Kubernetes/databases) use listArchitectureIcons instead.
777
+ * @description Search the built-in library of structural whiteboard stencils — ready-made hand-drawn graphics: flowchart/UML/ER/BPMN symbols, scrum columns, org-chart nodes, gantt, lo-fi/UX wireframe widgets (buttons, forms, tables, alerts, navs), charts, device frames, stick figures. A stencil is a MINI-WHITEBOARD (a collection of elements), NOT a single shape. Each result returns: `key`, `title` (a real human name e.g. 'Alerts', not an index), `kind` ('symbol' | 'template'), `labels` (the TEXT it actually contains — its real content, e.g. an Alerts template's variant messages), `size` ({w,h} px), `summary`, `pack`, `category`; plus the full pack/category lists. The two kinds are used DIFFERENTLY: • SYMBOL = one atomic labelled node (flowchart Process/Decision, BPMN task, org node). Place + label + connect: addWhiteboardElements({type:'stencil', stencilKey, id:'n1', text:'Review', width, height}) the text auto-fits its single slot and an arrow's start/end {id:'n1'} binds to it like any shape. A few symbols are text-less FRAMES (e.g. a UML class box = rectangle + divider line): place create-only, then use the placement result's `children` (shapes + x/y/w/h) and `groupId` to add type:'text' specs INTO the regions — pass that groupId so the text is one unit with the frame. • TEMPLATE = a multi-component layout (Alerts, Forms, Tables, Charts, device frames). Place the WHOLE thing: addWhiteboardElements({type:'stencil', stencilKey, x, y, width?, height?}); the placement RESULT returns `stencils[].children` (each child's id + text + colour + position x/y/w/h, so you can group children into rows/sections) so you then keep / retext / recolour / DELETE specific parts via updateWhiteboardScene (e.g. delete the info + error rows to keep only the green success alert). Do NOT pass a single `text` to a template read its `labels` to see its parts, then edit them by id. To make several similar items, build one then duplicateWhiteboardElements({groupId, dx}) to stamp consistent copies (like copy-paste in the UI). SEARCH TIPS: prefer BROAD single words ('decision','alert','form','phone','process'); content words match the embedded `labels` too (searching 'success' finds the Alerts template). If nothing exact matches, results auto-broaden (broadened:true); pass pack/category to browse. For cloud/architecture ICONS (AWS/Azure/GCP/Docker/Kubernetes/databases) use listArchitectureIcons; for a sticky/post-it use addWhiteboardElements({type:'sticky'}), not a stencil.
758
778
  */
759
779
  post: operations["listWhiteboardStencils"];
760
780
  delete?: never;
@@ -6591,7 +6611,7 @@ interface operations {
6591
6611
  /** @description Elements to write. For mode 'patch', each may be a partial { id, ...changedFields } merged into the matching element by id; full Excalidraw elements for 'replace'/'append' (or new ids in 'patch'). */
6592
6612
  elements?: Record<string, never>[];
6593
6613
  /**
6594
- * @description patch (DEFAULT — merge by id, keep the rest), append (add only), or replace (overwrite the whole scene).
6614
+ * @description How to apply your `elements`. patch (DEFAULT — use this for ANY partial edit): merges each item into the element with the same id and leaves everything else untouched, like find-and-replace by id; new ids are added. append: only adds your items, changes nothing else. replace: OVERWRITES THE WHOLE CANVAS — every existing element you don't resend is DELETED — so use it ONLY to set an entire board at once. To change or rebuild just a SECTION, use patch (+ deleteIds to remove specific ids), NEVER replace. A replace that would drop any existing element is rejected unless confirmReplace:true.
6595
6615
  * @enum {string}
6596
6616
  */
6597
6617
  mode?: "patch" | "append" | "replace";
@@ -6601,6 +6621,10 @@ interface operations {
6601
6621
  appState?: Record<string, never>;
6602
6622
  /** @description Optional Excalidraw BinaryFiles map (for embedded images), merged in. */
6603
6623
  files?: Record<string, never>;
6624
+ /** @description Optional optimistic-locking token from getWhiteboard. Only used for mode 'replace': if the board changed since you read it, the replace is rejected so you don't overwrite a collaborator's newer edits — re-read with getWhiteboard and retry. Not needed for patch/append, which automatically merge onto the latest scene. */
6625
+ versionTimestamp?: number;
6626
+ /** @description Safety acknowledgement for mode 'replace' ONLY. A replace that would DELETE ANY existing element not present in your `elements` is rejected unless this is true. Leave it unset and use mode:'patch' to edit part of a board (it merges by id and keeps the rest); set true only when you truly intend to overwrite the WHOLE scene. */
6627
+ confirmReplace?: boolean;
6604
6628
  };
6605
6629
  };
6606
6630
  };
@@ -6683,8 +6707,143 @@ interface operations {
6683
6707
  content: {
6684
6708
  "application/json": {
6685
6709
  documentId: string;
6686
- /** @description Non-empty array of shape specs to append. */
6687
- shapes: Record<string, never>[];
6710
+ /** @description Non-empty array of shape specs to append. Prefer stencils / sticky notes / architecture icons over raw rectangles wherever a standard form fits (see the `type` enum below and the tool description). */
6711
+ shapes: ({
6712
+ /**
6713
+ * @description Element kind. 'sticky' = a first-class sticky/post-it note (solid fill + auto-fitting bound label; set text + backgroundColor) — use this for sticky notes, NOT a stencil. 'stencil' = a hand-drawn library graphic from listWhiteboardStencils, of kind 'symbol' (one atomic labelled node — flowchart box, BPMN task, org node: set `id` + `text` + width/height, text auto-fits, connect arrows via start/end {id}) or 'template' (a multi-element layout — Alerts, Forms, Tables, Charts: place whole, then customise its returned children by id; do NOT set a single `text`). Set `stencil` (fuzzy name, one call) or `stencilKey` (exact). 'image' with `iconPath` = a software-architecture icon from listArchitectureIcons. Reserve rectangle/ellipse/diamond for when no standard form fits.
6714
+ * @enum {string}
6715
+ */
6716
+ type: "rectangle" | "ellipse" | "diamond" | "sticky" | "text" | "arrow" | "line" | "frame" | "image" | "stencil";
6717
+ /** @description For type:'stencil' — fuzzy-match a library stencil by name in ONE call, no prior listWhiteboardStencils needed (e.g. 'decision', 'actor', 'phone frame', 'kanban column'). NOTE: there is no sticky-note stencil — use type:'sticky' for sticky/post-it notes. */
6718
+ stencil?: string;
6719
+ /** @description For type:'stencil' — exact stencil key from listWhiteboardStencils (takes precedence over `stencil`). */
6720
+ stencilKey?: string;
6721
+ /** @description For type:'stencil' — optional pack to disambiguate a fuzzy `stencil` match (e.g. 'Flowchart', 'BPMN', 'UML & ER', 'Scrum Board'). */
6722
+ pack?: string;
6723
+ /** @description For type:'image' — a software-architecture icon path from listArchitectureIcons (e.g. 'dev/docker.svg'). */
6724
+ iconPath?: string;
6725
+ /** @description For type:'image' — any other public image URL (use iconPath for curated architecture icons). */
6726
+ imageUrl?: string;
6727
+ /** @description Optional id so connectors (arrows/lines) can reference this shape via start/end. On a type:'stencil' it adds a transparent bindable anchor covering the stencil, so an arrow's start/end {id} connects to the whole stencil as a unit. */
6728
+ id?: string;
6729
+ /** @description Join an existing group. Pass a placed stencil's `groupId` (returned in the placement result) on a type:'text' or shape spec to FILL that frame as part of the same unit — the text then moves, duplicates and renders together with the frame (e.g. a title in a UML class box's top band, members in its body). */
6730
+ groupId?: string;
6731
+ /** @description Top-left x on the canvas. OMIT both x and y to auto-place this element in clear empty space below the board's existing content. Strongly preferred when adding a note/shape to a board that already has content: a guessed coordinate usually lands ON TOP of existing shapes (the 'added a sticky but can't see it' bug). Set x/y only for deliberate layout among shapes you add in this same call. */
6732
+ x?: number;
6733
+ /** @description Top-left y on the canvas. Omit together with x to auto-place (see x). */
6734
+ y?: number;
6735
+ /** @description Shape width; for type:'stencil' it scales the whole stencil to fit this width. */
6736
+ width?: number;
6737
+ /** @description Shape height; for type:'stencil' it scales the whole stencil to fit this height. */
6738
+ height?: number;
6739
+ /** @description For type:'stencil' — uniform scale factor for the whole stencil (alternative to width/height). */
6740
+ scale?: number;
6741
+ /** @description Label/caption. On a shape it's a centered auto-wrapped bound label (prefer over a separate type:'text'); on a type:'sticky' it's the note text; on a type:'stencil' of kind 'symbol' it fills + re-fits its single label (IGNORED for 'template' stencils — customise their children by id instead). */
6742
+ text?: string;
6743
+ /** @description Fill colour: a name ('blue'/'green'/'yellow'/'pink'/'violet'/'orange'/'teal'/…) or a hex value. */
6744
+ backgroundColor?: string;
6745
+ /** @description For arrows/lines: { id } of the source shape (auto-clips to the edge + auto-routes around shapes in between). */
6746
+ start?: Record<string, never>;
6747
+ /** @description For arrows/lines: { id } of the target shape. */
6748
+ end?: Record<string, never>;
6749
+ } & {
6750
+ [key: string]: unknown;
6751
+ })[];
6752
+ };
6753
+ };
6754
+ };
6755
+ responses: {
6756
+ /** @description Tool result (shape varies per tool — refer to the tool's docs for the exact return value). */
6757
+ 200: {
6758
+ headers: {
6759
+ [name: string]: unknown;
6760
+ };
6761
+ content: {
6762
+ "application/json": {
6763
+ [key: string]: unknown;
6764
+ };
6765
+ };
6766
+ };
6767
+ /** @description Validation error. */
6768
+ 400: {
6769
+ headers: {
6770
+ [name: string]: unknown;
6771
+ };
6772
+ content: {
6773
+ "application/json": components["schemas"]["ErrorResponse"];
6774
+ };
6775
+ };
6776
+ /** @description Missing or invalid credentials. */
6777
+ 401: {
6778
+ headers: {
6779
+ [name: string]: unknown;
6780
+ };
6781
+ content: {
6782
+ "application/json": components["schemas"]["ErrorResponse"];
6783
+ };
6784
+ };
6785
+ /** @description Authenticated but lacking the required permission or feature flag. */
6786
+ 403: {
6787
+ headers: {
6788
+ [name: string]: unknown;
6789
+ };
6790
+ content: {
6791
+ "application/json": components["schemas"]["ErrorResponse"];
6792
+ };
6793
+ };
6794
+ /** @description Resource not found. */
6795
+ 404: {
6796
+ headers: {
6797
+ [name: string]: unknown;
6798
+ };
6799
+ content: {
6800
+ "application/json": components["schemas"]["ErrorResponse"];
6801
+ };
6802
+ };
6803
+ /** @description Body did not match the tool's input schema. */
6804
+ 422: {
6805
+ headers: {
6806
+ [name: string]: unknown;
6807
+ };
6808
+ content: {
6809
+ "application/json": components["schemas"]["ErrorResponse"];
6810
+ };
6811
+ };
6812
+ /** @description Server error. */
6813
+ 500: {
6814
+ headers: {
6815
+ [name: string]: unknown;
6816
+ };
6817
+ content: {
6818
+ "application/json": components["schemas"]["ErrorResponse"];
6819
+ };
6820
+ };
6821
+ };
6822
+ };
6823
+ duplicateWhiteboardElements: {
6824
+ parameters: {
6825
+ query?: never;
6826
+ header?: never;
6827
+ path?: never;
6828
+ cookie?: never;
6829
+ };
6830
+ requestBody?: {
6831
+ content: {
6832
+ "application/json": {
6833
+ /** @description The whiteboard's documentId. */
6834
+ documentId: string;
6835
+ /** @description Element ids to copy. Each id's full group + any bound text are auto-included. Use this and/or groupId. */
6836
+ ids?: string[];
6837
+ /** @description Copy EVERY element in this group as one unit — e.g. a placed stencil's `groupId` returned by addWhiteboardElements. */
6838
+ groupId?: string;
6839
+ /** @description Horizontal offset for the copy (default 40). Use the element width + a gap to place copies side by side. */
6840
+ dx?: number;
6841
+ /** @description Vertical offset for the copy (default 40). */
6842
+ dy?: number;
6843
+ /** @description Group the copy into one new unit so it moves/duplicates together (default true). */
6844
+ group?: boolean;
6845
+ /** @description Auto-include the full group of any id you pass (default true). */
6846
+ includeGroupPeers?: boolean;
6688
6847
  };
6689
6848
  };
6690
6849
  };
@@ -6974,9 +7133,9 @@ interface operations {
6974
7133
  requestBody?: {
6975
7134
  content: {
6976
7135
  "application/json": {
6977
- /** @description Free-text search across name + pack + category (e.g. 'sticky note', 'decision', 'database table', 'phone frame', 'actor'). */
7136
+ /** @description Free-text search across name + pack + category (e.g. 'decision', 'database table', 'phone frame', 'actor', 'kanban column'). */
6978
7137
  query?: string;
6979
- /** @description Restrict to one pack, e.g. 'Sticky Notes', 'Flowchart', 'BPMN', 'UML & ER', 'Scrum Board', 'Lo-Fi Wireframes', 'Org Chart'. */
7138
+ /** @description Restrict to one pack, e.g. 'Flowchart', 'BPMN', 'UML & ER', 'Scrum Board', 'Lo-Fi Wireframes', 'Org Chart'. */
6980
7139
  pack?: string;
6981
7140
  /** @description Filter by category: 'Notes & Planning', 'Diagramming', 'UI & Wireframing', 'Data & Charts', 'People & Fun'. */
6982
7141
  category?: string;
package/dist/index.d.ts CHANGED
@@ -74,7 +74,7 @@ interface paths {
74
74
  put?: never;
75
75
  /**
76
76
  * listArchitectureIcons
77
- * @description List icons for systemsarchitecture diagrams. Use returned iconPath as-is in D2 code (e.g. icon: dev/docker.svg).
77
+ * @description List curated software-architecture icons (AWS, Azure, GCP, Docker, Kubernetes, databases, message queues, etc.). Each result has an `iconPath` (e.g. 'dev/docker.svg'). TWO ways to use it: (1) on a WHITEBOARD, drop it via addWhiteboardElements({ type:'image', iconPath:'dev/docker.svg', x, y, width:96, height:96, text:'Docker' }); (2) in a D2 systems-architecture diagram, use the iconPath as-is in D2 code (e.g. icon: dev/docker.svg).
78
78
  */
79
79
  post: operations["listArchitectureIcons"];
80
80
  delete?: never;
@@ -674,7 +674,7 @@ interface paths {
674
674
  put?: never;
675
675
  /**
676
676
  * updateWhiteboardScene
677
- * @description Edit elements on a whiteboard's canvas WITHOUT dropping the rest of the scene. A board may hold many diagrams/elements, so prefer surgical edits: mode='patch' (DEFAULT) shallow-merges each incoming object into the existing element with the same `id` (send just {id, backgroundColor:'blue'} to recolour one box, or {id, x, y} to move one) and appends any elements whose id is new/absent — everything else is left untouched. `deleteIds` removes specific elements by id. mode='append' only adds. mode='replace' overwrites the ENTIRE scene (use ONLY when intentionally rewriting the whole board). To author NEW shapes/connectors from a high-level spec, prefer addWhiteboardElements. Optional appState/files are merged in. PROCESS: for a non-trivial edit call getWhiteboardGuide FIRST; after editing, ALWAYS call getWhiteboardImage to confirm the board still looks right (layout, labels, overlaps), and patch again if it doesn't.
677
+ * @description Edit elements on a whiteboard's canvas WITHOUT dropping the rest of the scene. A board may hold many diagrams/elements, so prefer surgical edits: mode='patch' (DEFAULT) shallow-merges each incoming object into the existing element with the same `id` (send just {id, backgroundColor:'blue'} to recolour one box, or {id, x, y} to move one) and appends any elements whose id is new/absent — everything else is left untouched. `deleteIds` removes specific elements by id. mode='append' only adds. mode='replace' overwrites the ENTIRE scene — to rebuild or edit only PART of a board, still use 'patch', because replace DELETES every element you don't resend (of ANY type). As a safeguard, a replace that would drop ANY existing element not in your payload is REJECTED unless you pass confirmReplace:true (or include those ids); diagrams/images/frames are flagged specially since they're inserted separately and costliest to lose. To author NEW shapes/connectors from a high-level spec, prefer addWhiteboardElements — and prefer library stencils / sticky notes / architecture icons over plain rectangles wherever a standard form fits (sticky notes, kanban/scrum, flowcharts, UML/ER, BPMN, org charts, wireframes). Optional appState/files are merged in. PROCESS: for a non-trivial edit call getWhiteboardGuide FIRST; after editing, ALWAYS call getWhiteboardImage to confirm the board still looks right (layout, labels, overlaps), and patch again if it doesn't.
678
678
  */
679
679
  post: operations["updateWhiteboardScene"];
680
680
  delete?: never;
@@ -694,7 +694,7 @@ interface paths {
694
694
  put?: never;
695
695
  /**
696
696
  * addWhiteboardElements
697
- * @description Author shapes onto a whiteboard from high-level specs (you do NOT need the full Excalidraw element schema). Appends to the canvas. Expressive enough to reproduce real Excalidraw templates (sticky-note brainstorm grids, sketchy mind maps, flowcharts). Each spec: { type: 'rectangle'|'ellipse'|'diamond'|'sticky'|'text'|'arrow'|'line'|'frame'|'image'|'stencil', id?, x, y, width, height, text? (STRONGLY PREFER setting a shape's label via its own `text` — it becomes a centered, auto-WRAPPED bound label fitted to the shape; do NOT drop a separate type:'text' element on top of a shape as its label. Standalone type:'text' is for free-floating titles/notes and now also wraps to its width; Yes/No label on an arrow — emojis are fine, e.g. 'Risks ⚠️'), fontSize?, fontFamily? (1=hand-drawn default, 2=normal, 3=code), textAlign?, backgroundColor? (name 'blue'/'green'/'yellow'/'pink'/'violet'/'orange'/'teal'/… or hex), strokeColor?, fillStyle? ('solid'|'hachure'|'cross-hatch'), strokeStyle? ('solid'|'dashed'|'dotted' — use 'dashed' for grid/category borders), strokeWidth? (1 thin/2 bold/4 extra), roughness? (0 clean, 1 default, 2 very sketchy/hand-drawn — use 2 for organic mind maps), roundness? (number type or null for sharp), opacity?, name? (frame title), frameId? (put a shape inside a frame), start?:{id}, end?:{id} (connect arrows/lines to shapes by id — connectors AUTO-CLIP to the shape edges, never overrun to the centre, AUTO-ROUTE around any shapes in between so a decision's No/loop-back branch never cuts straight through the boxes between source and target, and bound text auto-wraps + centres), routing? ('straight' default | 'elbow' for clean right-angle flowchart/org-chart connectors | 'curved'), startArrowhead?/endArrowhead? (arrowheads are SOLID filled triangles by default — just OMIT them. Pass null for a plain mind-map spoke with no head. Do NOT pass 'arrow': that is Excalidraw's open 'V' and is auto-upgraded to a solid triangle anyway), points? ([[0,0],[dx,dy]] relative, only for manual geometry — almost never needed; binding by id is better), props? (escape hatch: any other Excalidraw field) }. ARCHITECTURE ICONS: to place a software-architecture icon (AWS/Azure/GCP/Docker/Kubernetes/databases/etc.), first call listArchitectureIcons to find one, then add a spec { type:'image', iconPath:'<relative_url e.g. dev/docker.svg>', x, y, width:96, height:96, text?:'<caption shown below>' } — the icon is stored as a URL reference (never base64). Use imageUrl instead of iconPath for any other public image. Combine icons with labelled boxes + elbow arrows for clean architecture diagrams. LIBRARY STENCILS: for hand-drawn, on-brand elements (sticky notes, scrum/kanban columns, flowchart symbols, UML/ER, BPMN, org-chart nodes, wireframe widgets, stick figures), FIRST call listWhiteboardStencils to find one, then add { type:'stencil', stencilKey:'<key from listWhiteboardStencils>', x, y } (or { type:'stencil', stencil:'<name e.g. yellow sticky note>', pack?:'<pack>', x, y } to fuzzy-match by name). STRONGLY prefer these over plain rectangles whenever the user asks for sticky notes, kanban/scrum/story boards, flowcharts, wireframes/mockups, org charts, etc. FRAMES: a frame is a NON-DESTRUCTIVE, ANY-SIZE container. To enclose shapes that ALREADY exist, add ONE type:'frame' sized to cover them (Excalidraw auto-captures elements inside a frame's bounds) or set those shapes' frameId — never recreate or delete-and-redraw content just to frame it. If a frame doesn't fully cover its content, just RESIZE the frame (patch its width/height). Deleting a frame (deleteIds:[frameId]) leaves all its contents intact on the canvas — it only removes the frame border + title. PRESENTATION/SLIDES: when the user wants a presentation or slide deck, create type:'frame' slides sized width:1280,height:720 (16:9), laid out LEFT-TO-RIGHT at the same y (x: 0, then 1440, 2880, 4320, …), each with a `name` (the slide title). Put every slide's shapes/text/images INSIDE its frame by setting their frameId to that frame's id (give the frame an id and reference it). Slides play in order (left-to-right, then top-to-bottom) in the board's Present mode and export to PPTX, so one frame = one slide. FLOWCHART recipe: rectangles (roundness null for sharp process boxes), diamonds for decisions, arrows with routing:'elbow' and Yes/No as the arrow's text. Use type 'sticky' for solid-fill notes; type 'line' with no arrowheads + roughness:2 for sketchy mind-map spokes. Give shapes ids and reference them from connectors. Connectors may also bind to shapes ALREADY on the board by their id (get them via getWhiteboard includeElements:true) — you do NOT need to resend existing shapes; the server reads the live scene to bind the arrow and route it around the other boxes. Great for brainstorms, mind maps, flowcharts, org charts, SWOT, retros. PROCESS: for any non-trivial board call getWhiteboardGuide FIRST to plan it; then after adding, ALWAYS call getWhiteboardImage to SEE the result and check layout, labels, spacing, overlaps and how shapes connect — if anything looks off, fix it with updateWhiteboardScene (patch by id) and render again, iterating until it looks right.
697
+ * @description Author shapes onto a whiteboard from high-level specs (you do NOT need the full Excalidraw element schema). Appends to the canvas. PREFER THE RICHEST FORM THAT FITS, not plain rectangles: for a sticky/post-it note use { type:'sticky', text, backgroundColor } (a first-class note with an auto-fitting bound label — there is NO sticky-note stencil; OMIT x/y and it is auto-placed in clear space below existing content, so it doesn't land on top of the current drawing); for kanban/scrum/story boards, flowcharts, UML/ER, BPMN, org charts, wireframes/mockups, charts or people use a LIBRARY STENCIL in ONE call — { type:'stencil', stencil:'<name e.g. decision>', x, y } fuzzy-matches by name with no prior listWhiteboardStencils call (pass width/height to SCALE the whole stencil and text to fill its single label); for cloud/software-architecture use ICONS — { type:'image', iconPath:'dev/docker.svg', x, y } (paths from listArchitectureIcons); reserve raw rectangles/ellipses for when no standard form fits. Expressive enough to reproduce real Excalidraw templates (sticky-note brainstorm grids, sketchy mind maps, flowcharts). Each spec: { type: 'rectangle'|'ellipse'|'diamond'|'sticky'|'text'|'arrow'|'line'|'frame'|'image'|'stencil', id?, x, y, width, height, text? (STRONGLY PREFER setting a shape's label via its own `text` — it becomes a centered, auto-WRAPPED bound label fitted to the shape; do NOT drop a separate type:'text' element on top of a shape as its label. Standalone type:'text' is for free-floating titles/notes and now also wraps to its width; Yes/No label on an arrow — emojis are fine, e.g. 'Risks ⚠️'), fontSize?, fontFamily? (1=hand-drawn default, 2=normal, 3=code), textAlign?, backgroundColor? (name 'blue'/'green'/'yellow'/'pink'/'violet'/'orange'/'teal'/… or hex), strokeColor?, fillStyle? ('solid'|'hachure'|'cross-hatch'), strokeStyle? ('solid'|'dashed'|'dotted' — use 'dashed' for grid/category borders), strokeWidth? (1 thin/2 bold/4 extra), roughness? (0 clean, 1 default, 2 very sketchy/hand-drawn — use 2 for organic mind maps), roundness? (number type or null for sharp), opacity?, name? (frame title), frameId? (put a shape inside a frame), start?:{id}, end?:{id} (connect arrows/lines to shapes by id — connectors AUTO-CLIP to the shape edges, never overrun to the centre, AUTO-ROUTE around any shapes in between so a decision's No/loop-back branch never cuts straight through the boxes between source and target, and bound text auto-wraps + centres), routing? ('straight' default | 'elbow' for clean right-angle flowchart/org-chart connectors | 'curved'), startArrowhead?/endArrowhead? (arrowheads are SOLID filled triangles by default — just OMIT them. Pass null for a plain mind-map spoke with no head. Do NOT pass 'arrow': that is Excalidraw's open 'V' and is auto-upgraded to a solid triangle anyway), points? ([[0,0],[dx,dy]] relative, only for manual geometry — almost never needed; binding by id is better), props? (escape hatch: any other Excalidraw field) }. ARCHITECTURE ICONS: to place a software-architecture icon (AWS/Azure/GCP/Docker/Kubernetes/databases/etc.), first call listArchitectureIcons to find one, then add a spec { type:'image', iconPath:'<relative_url e.g. dev/docker.svg>', x, y, width:96, height:96, text?:'<caption shown below>' } — the icon is stored as a URL reference (never base64). Use imageUrl instead of iconPath for any other public image. Combine icons with labelled boxes + elbow arrows for clean architecture diagrams. LIBRARY STENCILS: for hand-drawn, on-brand elements (scrum/kanban columns, flowchart symbols, UML/ER, BPMN, org-chart nodes, wireframe widgets, stick figures), FIRST call listWhiteboardStencils to find one, then add { type:'stencil', stencilKey:'<key from listWhiteboardStencils>', x, y } (or { type:'stencil', stencil:'<name e.g. decision>', pack?:'<pack>', x, y } to fuzzy-match by name). A stencil is a mini-whiteboard (a collection of elements) of kind 'symbol' or 'template' (listWhiteboardStencils returns the kind + its embedded `labels`). For a SYMBOL (one atomic labelled node — flowchart box, BPMN task, org node), pass id + text + width/height: the label auto-fits its single slot and arrows bind to it via start/end {id}. For a TEMPLATE (a multi-component layout — Alerts, Forms, Tables, Charts), place it WHOLE (no single text); the result returns its `children` (id + text + colour + position) so you retext, recolour, or DELETE specific parts by id via updateWhiteboardScene (cluster children by y to act on a whole row/variant). STRONGLY prefer stencils over plain rectangles for wireframes/mockups, kanban/scrum boards, UML/BPMN, org charts; for dense flowcharts, plain shapes with bound text + elbow arrows are equally reliable. (For a plain sticky/post-it note use type:'sticky', NOT a stencil — there is no sticky-note stencil.) FRAMES: a frame is a NON-DESTRUCTIVE, ANY-SIZE container. To enclose shapes that ALREADY exist, add ONE type:'frame' sized to cover them (Excalidraw auto-captures elements inside a frame's bounds) or set those shapes' frameId — never recreate or delete-and-redraw content just to frame it. If a frame doesn't fully cover its content, just RESIZE the frame (patch its width/height). Deleting a frame (deleteIds:[frameId]) leaves all its contents intact on the canvas — it only removes the frame border + title. PRESENTATION/SLIDES: when the user wants a presentation or slide deck, create type:'frame' slides sized width:1280,height:720 (16:9), laid out LEFT-TO-RIGHT at the same y (x: 0, then 1440, 2880, 4320, …), each with a `name` (the slide title). Put every slide's shapes/text/images INSIDE its frame by setting their frameId to that frame's id (give the frame an id and reference it). Slides play in order (left-to-right, then top-to-bottom) in the board's Present mode and export to PPTX, so one frame = one slide. FLOWCHART recipe: rectangles (roundness null for sharp process boxes), diamonds for decisions, arrows with routing:'elbow' and Yes/No as the arrow's text. Use type 'sticky' for sticky/post-it notes (a solid-fill note with an auto-fitting bound label — set text + backgroundColor); type 'line' with no arrowheads + roughness:2 for sketchy mind-map spokes. Give shapes ids and reference them from connectors. Connectors may also bind to shapes ALREADY on the board by their id (get them via getWhiteboard includeElements:true) — you do NOT need to resend existing shapes; the server reads the live scene to bind the arrow and route it around the other boxes. Great for brainstorms, mind maps, flowcharts, org charts, SWOT, retros. PROCESS: for any non-trivial board call getWhiteboardGuide FIRST to plan it; then after adding, ALWAYS call getWhiteboardImage to SEE the result and check layout, labels, spacing, overlaps and how shapes connect — if anything looks off, fix it with updateWhiteboardScene (patch by id) and render again, iterating until it looks right. RESULT: returns `added` (count), `placement` (bounding box {x,y,width,height} of what you just added) and `autoPlaced` (true when you omitted x/y so it was placed in clear space below existing content) — use placement/autoPlaced to tell the user WHERE the new elements landed, never invent a location.
698
698
  */
699
699
  post: operations["addWhiteboardElements"];
700
700
  delete?: never;
@@ -703,6 +703,26 @@ interface paths {
703
703
  patch?: never;
704
704
  trace?: never;
705
705
  };
706
+ "/tools/duplicateWhiteboardElements": {
707
+ parameters: {
708
+ query?: never;
709
+ header?: never;
710
+ path?: never;
711
+ cookie?: never;
712
+ };
713
+ get?: never;
714
+ put?: never;
715
+ /**
716
+ * duplicateWhiteboardElements
717
+ * @description Copy-paste existing whiteboard elements — the MCP equivalent of selecting a group and pressing Ctrl/Cmd+D. Clones the given elements (plus their group peers + bound text/labels) with FRESH ids, offsets the copy by dx/dy, and by default groups it into ONE new unit so it moves together. Use it to build something once (a labelled stencil frame, a kanban card, a UML class) then stamp out consistent repeats fast — then retext/recolour each copy by its new id (via the returned idMap) with updateWhiteboardScene. Pass `groupId` to copy a whole group as a unit (e.g. a placed stencil's groupId from its placement result) and/or `ids` for specific elements. Internal references (group membership, bound text containerId, arrow start/end bindings) are remapped within the copied set; a binding to an element you did NOT copy is dropped. Returns { duplicated, idMap (old id → new id), groupId (the copy's new unit group), elementCount }. Render with getWhiteboardImage afterwards to verify.
718
+ */
719
+ post: operations["duplicateWhiteboardElements"];
720
+ delete?: never;
721
+ options?: never;
722
+ head?: never;
723
+ patch?: never;
724
+ trace?: never;
725
+ };
706
726
  "/tools/insertWhiteboardImage": {
707
727
  parameters: {
708
728
  query?: never;
@@ -754,7 +774,7 @@ interface paths {
754
774
  put?: never;
755
775
  /**
756
776
  * listWhiteboardStencils
757
- * @description Search the built-in library of STRUCTURAL whiteboard stencils — ready-made, hand-drawn multi-element graphics: sticky notes (post-it), scrum-board columns, flowchart symbols, UML/ER, BPMN, org-chart nodes, gantt, lo-fi/UX wireframe widgets, charts, and stick figures. Returns matching stencils each with a `key`, name, pack and category, plus the full pack/category lists. Place one via addWhiteboardElements({type:'stencil', stencilKey:'<key>', x, y}). These look far richer and more on-brand than plain rectangles use them when the user asks for sticky notes, kanban/scrum boards, flowcharts, wireframes, mockups, etc. SEARCH TIPS: prefer BROAD single words ('sticky', 'decision', 'actor', 'phone', 'process') multi-word exact phrases often miss. If an exact query matches nothing the result is auto-broadened to close candidates (broadened:true is set); you can also pass pack/category to browse. When ANY returned stencil reasonably fits, PLACE it instead of drawing a plain rectangledo not abandon stencils just because your first phrase returned 0. The library does NOT contain free-form 'cloud' / 'hat' / 'thought-bubble' shapes; approximate those with the closest stencil (e.g. a sticky note or a simple shape) or fall back to a plain shape only when nothing fits. For cloud/architecture ICONS (AWS/Azure/GCP/Docker/Kubernetes/databases) use listArchitectureIcons instead.
777
+ * @description Search the built-in library of structural whiteboard stencils — ready-made hand-drawn graphics: flowchart/UML/ER/BPMN symbols, scrum columns, org-chart nodes, gantt, lo-fi/UX wireframe widgets (buttons, forms, tables, alerts, navs), charts, device frames, stick figures. A stencil is a MINI-WHITEBOARD (a collection of elements), NOT a single shape. Each result returns: `key`, `title` (a real human name e.g. 'Alerts', not an index), `kind` ('symbol' | 'template'), `labels` (the TEXT it actually contains — its real content, e.g. an Alerts template's variant messages), `size` ({w,h} px), `summary`, `pack`, `category`; plus the full pack/category lists. The two kinds are used DIFFERENTLY: • SYMBOL = one atomic labelled node (flowchart Process/Decision, BPMN task, org node). Place + label + connect: addWhiteboardElements({type:'stencil', stencilKey, id:'n1', text:'Review', width, height}) the text auto-fits its single slot and an arrow's start/end {id:'n1'} binds to it like any shape. A few symbols are text-less FRAMES (e.g. a UML class box = rectangle + divider line): place create-only, then use the placement result's `children` (shapes + x/y/w/h) and `groupId` to add type:'text' specs INTO the regions — pass that groupId so the text is one unit with the frame. • TEMPLATE = a multi-component layout (Alerts, Forms, Tables, Charts, device frames). Place the WHOLE thing: addWhiteboardElements({type:'stencil', stencilKey, x, y, width?, height?}); the placement RESULT returns `stencils[].children` (each child's id + text + colour + position x/y/w/h, so you can group children into rows/sections) so you then keep / retext / recolour / DELETE specific parts via updateWhiteboardScene (e.g. delete the info + error rows to keep only the green success alert). Do NOT pass a single `text` to a template read its `labels` to see its parts, then edit them by id. To make several similar items, build one then duplicateWhiteboardElements({groupId, dx}) to stamp consistent copies (like copy-paste in the UI). SEARCH TIPS: prefer BROAD single words ('decision','alert','form','phone','process'); content words match the embedded `labels` too (searching 'success' finds the Alerts template). If nothing exact matches, results auto-broaden (broadened:true); pass pack/category to browse. For cloud/architecture ICONS (AWS/Azure/GCP/Docker/Kubernetes/databases) use listArchitectureIcons; for a sticky/post-it use addWhiteboardElements({type:'sticky'}), not a stencil.
758
778
  */
759
779
  post: operations["listWhiteboardStencils"];
760
780
  delete?: never;
@@ -6591,7 +6611,7 @@ interface operations {
6591
6611
  /** @description Elements to write. For mode 'patch', each may be a partial { id, ...changedFields } merged into the matching element by id; full Excalidraw elements for 'replace'/'append' (or new ids in 'patch'). */
6592
6612
  elements?: Record<string, never>[];
6593
6613
  /**
6594
- * @description patch (DEFAULT — merge by id, keep the rest), append (add only), or replace (overwrite the whole scene).
6614
+ * @description How to apply your `elements`. patch (DEFAULT — use this for ANY partial edit): merges each item into the element with the same id and leaves everything else untouched, like find-and-replace by id; new ids are added. append: only adds your items, changes nothing else. replace: OVERWRITES THE WHOLE CANVAS — every existing element you don't resend is DELETED — so use it ONLY to set an entire board at once. To change or rebuild just a SECTION, use patch (+ deleteIds to remove specific ids), NEVER replace. A replace that would drop any existing element is rejected unless confirmReplace:true.
6595
6615
  * @enum {string}
6596
6616
  */
6597
6617
  mode?: "patch" | "append" | "replace";
@@ -6601,6 +6621,10 @@ interface operations {
6601
6621
  appState?: Record<string, never>;
6602
6622
  /** @description Optional Excalidraw BinaryFiles map (for embedded images), merged in. */
6603
6623
  files?: Record<string, never>;
6624
+ /** @description Optional optimistic-locking token from getWhiteboard. Only used for mode 'replace': if the board changed since you read it, the replace is rejected so you don't overwrite a collaborator's newer edits — re-read with getWhiteboard and retry. Not needed for patch/append, which automatically merge onto the latest scene. */
6625
+ versionTimestamp?: number;
6626
+ /** @description Safety acknowledgement for mode 'replace' ONLY. A replace that would DELETE ANY existing element not present in your `elements` is rejected unless this is true. Leave it unset and use mode:'patch' to edit part of a board (it merges by id and keeps the rest); set true only when you truly intend to overwrite the WHOLE scene. */
6627
+ confirmReplace?: boolean;
6604
6628
  };
6605
6629
  };
6606
6630
  };
@@ -6683,8 +6707,143 @@ interface operations {
6683
6707
  content: {
6684
6708
  "application/json": {
6685
6709
  documentId: string;
6686
- /** @description Non-empty array of shape specs to append. */
6687
- shapes: Record<string, never>[];
6710
+ /** @description Non-empty array of shape specs to append. Prefer stencils / sticky notes / architecture icons over raw rectangles wherever a standard form fits (see the `type` enum below and the tool description). */
6711
+ shapes: ({
6712
+ /**
6713
+ * @description Element kind. 'sticky' = a first-class sticky/post-it note (solid fill + auto-fitting bound label; set text + backgroundColor) — use this for sticky notes, NOT a stencil. 'stencil' = a hand-drawn library graphic from listWhiteboardStencils, of kind 'symbol' (one atomic labelled node — flowchart box, BPMN task, org node: set `id` + `text` + width/height, text auto-fits, connect arrows via start/end {id}) or 'template' (a multi-element layout — Alerts, Forms, Tables, Charts: place whole, then customise its returned children by id; do NOT set a single `text`). Set `stencil` (fuzzy name, one call) or `stencilKey` (exact). 'image' with `iconPath` = a software-architecture icon from listArchitectureIcons. Reserve rectangle/ellipse/diamond for when no standard form fits.
6714
+ * @enum {string}
6715
+ */
6716
+ type: "rectangle" | "ellipse" | "diamond" | "sticky" | "text" | "arrow" | "line" | "frame" | "image" | "stencil";
6717
+ /** @description For type:'stencil' — fuzzy-match a library stencil by name in ONE call, no prior listWhiteboardStencils needed (e.g. 'decision', 'actor', 'phone frame', 'kanban column'). NOTE: there is no sticky-note stencil — use type:'sticky' for sticky/post-it notes. */
6718
+ stencil?: string;
6719
+ /** @description For type:'stencil' — exact stencil key from listWhiteboardStencils (takes precedence over `stencil`). */
6720
+ stencilKey?: string;
6721
+ /** @description For type:'stencil' — optional pack to disambiguate a fuzzy `stencil` match (e.g. 'Flowchart', 'BPMN', 'UML & ER', 'Scrum Board'). */
6722
+ pack?: string;
6723
+ /** @description For type:'image' — a software-architecture icon path from listArchitectureIcons (e.g. 'dev/docker.svg'). */
6724
+ iconPath?: string;
6725
+ /** @description For type:'image' — any other public image URL (use iconPath for curated architecture icons). */
6726
+ imageUrl?: string;
6727
+ /** @description Optional id so connectors (arrows/lines) can reference this shape via start/end. On a type:'stencil' it adds a transparent bindable anchor covering the stencil, so an arrow's start/end {id} connects to the whole stencil as a unit. */
6728
+ id?: string;
6729
+ /** @description Join an existing group. Pass a placed stencil's `groupId` (returned in the placement result) on a type:'text' or shape spec to FILL that frame as part of the same unit — the text then moves, duplicates and renders together with the frame (e.g. a title in a UML class box's top band, members in its body). */
6730
+ groupId?: string;
6731
+ /** @description Top-left x on the canvas. OMIT both x and y to auto-place this element in clear empty space below the board's existing content. Strongly preferred when adding a note/shape to a board that already has content: a guessed coordinate usually lands ON TOP of existing shapes (the 'added a sticky but can't see it' bug). Set x/y only for deliberate layout among shapes you add in this same call. */
6732
+ x?: number;
6733
+ /** @description Top-left y on the canvas. Omit together with x to auto-place (see x). */
6734
+ y?: number;
6735
+ /** @description Shape width; for type:'stencil' it scales the whole stencil to fit this width. */
6736
+ width?: number;
6737
+ /** @description Shape height; for type:'stencil' it scales the whole stencil to fit this height. */
6738
+ height?: number;
6739
+ /** @description For type:'stencil' — uniform scale factor for the whole stencil (alternative to width/height). */
6740
+ scale?: number;
6741
+ /** @description Label/caption. On a shape it's a centered auto-wrapped bound label (prefer over a separate type:'text'); on a type:'sticky' it's the note text; on a type:'stencil' of kind 'symbol' it fills + re-fits its single label (IGNORED for 'template' stencils — customise their children by id instead). */
6742
+ text?: string;
6743
+ /** @description Fill colour: a name ('blue'/'green'/'yellow'/'pink'/'violet'/'orange'/'teal'/…) or a hex value. */
6744
+ backgroundColor?: string;
6745
+ /** @description For arrows/lines: { id } of the source shape (auto-clips to the edge + auto-routes around shapes in between). */
6746
+ start?: Record<string, never>;
6747
+ /** @description For arrows/lines: { id } of the target shape. */
6748
+ end?: Record<string, never>;
6749
+ } & {
6750
+ [key: string]: unknown;
6751
+ })[];
6752
+ };
6753
+ };
6754
+ };
6755
+ responses: {
6756
+ /** @description Tool result (shape varies per tool — refer to the tool's docs for the exact return value). */
6757
+ 200: {
6758
+ headers: {
6759
+ [name: string]: unknown;
6760
+ };
6761
+ content: {
6762
+ "application/json": {
6763
+ [key: string]: unknown;
6764
+ };
6765
+ };
6766
+ };
6767
+ /** @description Validation error. */
6768
+ 400: {
6769
+ headers: {
6770
+ [name: string]: unknown;
6771
+ };
6772
+ content: {
6773
+ "application/json": components["schemas"]["ErrorResponse"];
6774
+ };
6775
+ };
6776
+ /** @description Missing or invalid credentials. */
6777
+ 401: {
6778
+ headers: {
6779
+ [name: string]: unknown;
6780
+ };
6781
+ content: {
6782
+ "application/json": components["schemas"]["ErrorResponse"];
6783
+ };
6784
+ };
6785
+ /** @description Authenticated but lacking the required permission or feature flag. */
6786
+ 403: {
6787
+ headers: {
6788
+ [name: string]: unknown;
6789
+ };
6790
+ content: {
6791
+ "application/json": components["schemas"]["ErrorResponse"];
6792
+ };
6793
+ };
6794
+ /** @description Resource not found. */
6795
+ 404: {
6796
+ headers: {
6797
+ [name: string]: unknown;
6798
+ };
6799
+ content: {
6800
+ "application/json": components["schemas"]["ErrorResponse"];
6801
+ };
6802
+ };
6803
+ /** @description Body did not match the tool's input schema. */
6804
+ 422: {
6805
+ headers: {
6806
+ [name: string]: unknown;
6807
+ };
6808
+ content: {
6809
+ "application/json": components["schemas"]["ErrorResponse"];
6810
+ };
6811
+ };
6812
+ /** @description Server error. */
6813
+ 500: {
6814
+ headers: {
6815
+ [name: string]: unknown;
6816
+ };
6817
+ content: {
6818
+ "application/json": components["schemas"]["ErrorResponse"];
6819
+ };
6820
+ };
6821
+ };
6822
+ };
6823
+ duplicateWhiteboardElements: {
6824
+ parameters: {
6825
+ query?: never;
6826
+ header?: never;
6827
+ path?: never;
6828
+ cookie?: never;
6829
+ };
6830
+ requestBody?: {
6831
+ content: {
6832
+ "application/json": {
6833
+ /** @description The whiteboard's documentId. */
6834
+ documentId: string;
6835
+ /** @description Element ids to copy. Each id's full group + any bound text are auto-included. Use this and/or groupId. */
6836
+ ids?: string[];
6837
+ /** @description Copy EVERY element in this group as one unit — e.g. a placed stencil's `groupId` returned by addWhiteboardElements. */
6838
+ groupId?: string;
6839
+ /** @description Horizontal offset for the copy (default 40). Use the element width + a gap to place copies side by side. */
6840
+ dx?: number;
6841
+ /** @description Vertical offset for the copy (default 40). */
6842
+ dy?: number;
6843
+ /** @description Group the copy into one new unit so it moves/duplicates together (default true). */
6844
+ group?: boolean;
6845
+ /** @description Auto-include the full group of any id you pass (default true). */
6846
+ includeGroupPeers?: boolean;
6688
6847
  };
6689
6848
  };
6690
6849
  };
@@ -6974,9 +7133,9 @@ interface operations {
6974
7133
  requestBody?: {
6975
7134
  content: {
6976
7135
  "application/json": {
6977
- /** @description Free-text search across name + pack + category (e.g. 'sticky note', 'decision', 'database table', 'phone frame', 'actor'). */
7136
+ /** @description Free-text search across name + pack + category (e.g. 'decision', 'database table', 'phone frame', 'actor', 'kanban column'). */
6978
7137
  query?: string;
6979
- /** @description Restrict to one pack, e.g. 'Sticky Notes', 'Flowchart', 'BPMN', 'UML & ER', 'Scrum Board', 'Lo-Fi Wireframes', 'Org Chart'. */
7138
+ /** @description Restrict to one pack, e.g. 'Flowchart', 'BPMN', 'UML & ER', 'Scrum Board', 'Lo-Fi Wireframes', 'Org Chart'. */
6980
7139
  pack?: string;
6981
7140
  /** @description Filter by category: 'Notes & Planning', 'Diagramming', 'UI & Wireframing', 'Data & Charts', 'People & Fun'. */
6982
7141
  category?: string;