> For the complete documentation index, see [llms.txt](https://docs.flora.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.flora.ai/mcp/tools/canvas.md).

# Canvas tools

Reference for the FLORA MCP tools that read a project canvas and add, edit, wire, arrange, run and delete its nodes.

These [FLORA MCP](https://flora.ai/mcp) tools read and edit a project's canvas: its nodes, the edges between them, their layout, and the timeline and deck documents some nodes carry. Read the canvas with [`flora_get_canvas`](#flora_get_canvas) first and use the short node IDs it reports (like `n7`) in every write. Adding or editing a node never runs it; [`flora_run_canvas_nodes`](#flora_run_canvas_nodes) does, and that spends money.

For a worked example, see [Put results on a canvas](/mcp/recipes/canvas.md).

{% hint style="info" %}
**Polling rule.** Save every `run_id`. Wait at least 15 seconds between polls, or 2 seconds per run for bigger batches (40 seconds for 20 runs). Then read every `run_id` in one `flora_list_generations` call (up to 20 per call). For example: `flora_list_generations({"run_ids": ["run_a", "run_b"]})`. For Technique runs, also pass `"technique_id"`. Polling faster returns `429` or cooldown errors with `retry_after_seconds`.
{% endhint %}

| Tool                                                                      | What it does                                                                                                                       | Labels                                   |
| ------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- |
| [`flora_get_canvas`](#flora_get_canvas)                                   | Read a whole canvas: every node with its short ID, settings, position, size and status, plus the edges and a revision.             | read-only                                |
| [`flora_list_canvas_nodes`](#flora_list_canvas_nodes)                     | List a canvas's media nodes with their file URLs.                                                                                  | read-only                                |
| [`flora_add_to_canvas`](#flora_add_to_canvas)                             | Add nodes and edges to a canvas: generation nodes, media from a URL, notes, group frames, timelines and decks.                     | writes                                   |
| [`flora_update_canvas_nodes`](#flora_update_canvas_nodes)                 | Edit existing nodes and edges in place: prompt, model, params, label, position, group, notes text, or a media node's file.         | writes, destructive                      |
| [`flora_run_canvas_nodes`](#flora_run_canvas_nodes)                       | Run generation and timeline nodes already on a canvas, in dependency order, with each node's own model, prompt, params and inputs. | writes, destructive, spends money, async |
| [`flora_arrange_canvas`](#flora_arrange_canvas)                           | Lay out nodes with FLORA's layout engine: Tidy, or a row, column or grid.                                                          | writes, destructive                      |
| [`flora_organize_canvas_fields`](#flora_organize_canvas_fields)           | Sort existing nodes into named fields (group frames), reusing frames that already exist.                                           | writes, destructive                      |
| [`flora_remove_from_canvas`](#flora_remove_from_canvas)                   | Delete nodes from a canvas, with every edge that touches them. Deleting a group deletes its members.                               | writes, destructive                      |
| [`flora_get_canvas_node_document`](#flora_get_canvas_node_document)       | Read the full document of a timeline, deck or notes node, with its revision.                                                       | read-only                                |
| [`flora_update_canvas_node_document`](#flora_update_canvas_node_document) | Replace a timeline's or deck's document, or apply scoped deck edits, guarded by the revision you read.                             | writes, destructive                      |

## flora\_get\_canvas <a href="#flora_get_canvas" id="flora_get_canvas"></a>

Read a whole canvas: every node with its short ID, settings, position, size and status, plus the edges and a revision.

**Labels:** read-only

**Shown in clients as:** Get canvas

**Use when:** Before any canvas write, to get the short node IDs (like `n7`) that writes accept, or to see idle nodes that haven't run yet.

**Don't use when:** You only need finished media URLs: use [`flora_list_canvas_nodes`](#flora_list_canvas_nodes). For a timeline's or deck's full content, use [`flora_get_canvas_node_document`](#flora_get_canvas_node_document).

**Arguments**

| Argument       | Type   | Required | Notes                                                                                                                                                                  |
| -------------- | ------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `workspace_id` | string | no       | Workspace the project belongs to (ws\_…). Optional: when omitted it is looked up from project\_id. A guessed or placeholder value returns not\_found.                  |
| `project_id`   | string | yes      | Project to read (prj\_…). Use project\_id from flora\_list\_projects or flora\_create\_project. An API-issued canvas URL's /projects/\<id> segment becomes prj\_\<id>. |

**Returns:** Every node (short ID, UUID, type, label, group, prompt, model, params, position, size, generation status and current output), the edges between nodes, and an opaque `revision` that changes whenever the canvas does.

**Cost:** Free. This tool doesn't spend money.

**Usually comes after:** [`flora_list_projects`](/mcp/tools/workspaces-and-projects.md#flora_list_projects)

**Usually comes before:** [`flora_add_to_canvas`](#flora_add_to_canvas), [`flora_update_canvas_nodes`](#flora_update_canvas_nodes), [`flora_run_canvas_nodes`](#flora_run_canvas_nodes), [`flora_arrange_canvas`](#flora_arrange_canvas)

**Example prompt:** "Show me what's on the canvas of my Spring campaign project."

**Example call:**

```json
{
  "project_id": "prj_abc"
}
```

<details>

<summary>Full description from the server</summary>

{% code overflow="wrap" %}

```
Read a project canvas in full: every node with its short id (n7), UUID, type, label, group (direct parent field short id, null for top-level nodes; omitted on older APIs), prompt, model, params, position (the anchor: top-center of the box for every type but group, which anchors top-left), size (the measured or authored box, or a conservative estimate until painted), generation status and current output, the edges between them, and an opaque revision that changes whenever anything here does. Idle nodes (added but never run) appear here; flora_list_canvas_nodes lists only media outputs. The short ids are what every canvas write accepts. A timeline node reports only a document summary: read the whole document with flora_get_canvas_node_document. A notes node carries its whole body in text.
```

{% endcode %}

</details>

## flora\_list\_canvas\_nodes <a href="#flora_list_canvas_nodes" id="flora_list_canvas_nodes"></a>

List a canvas's media nodes with their file URLs.

**Labels:** read-only

**Shown in clients as:** List canvas nodes

**Use when:** You want the finished images, videos, audio or 3D files on a canvas and their URLs.

**Don't use when:** You need the graph, the edges, or idle nodes that haven't run: use [`flora_get_canvas`](#flora_get_canvas).

**Arguments**

| Argument     | Type   | Required | Notes                                                                                                                                                                  |
| ------------ | ------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `project_id` | string | yes      | Project to read (prj\_…). Use project\_id from flora\_list\_projects or flora\_create\_project. An API-issued canvas URL's /projects/\<id> segment becomes prj\_\<id>. |
| `limit`      | number | no       | Max items to return (default 20).                                                                                                                                      |
| `cursor`     | string | no       | Pagination cursor from a previous call's meta.next\_cursor.                                                                                                            |

**Returns:**

* `project_id` (string): Project identifier
* `canvas_url` (string (uri)): Project canvas URL
* `nodes` (array of object)
* `meta` (object)

**Cost:** Free. This tool doesn't spend money.

**Usually comes after:** [`flora_list_projects`](/mcp/tools/workspaces-and-projects.md#flora_list_projects)

**Usually comes before:** [`flora_run_action`](/mcp/tools/techniques-and-actions.md#flora_run_action), [`flora_create_generations`](/mcp/tools/generations.md#flora_create_generations)

**Example prompt:** "List the images on my Spring campaign canvas with their links."

**Example call:**

```json
{
  "project_id": "prj_abc",
  "limit": 50
}
```

<details>

<summary>Full description from the server</summary>

{% code overflow="wrap" %}

```
List a project canvas's media nodes with their asset URLs. Idle generation nodes (added but never run) do not appear here — use flora_get_canvas to see them and the graph structure.
```

{% endcode %}

</details>

## flora\_add\_to\_canvas <a href="#flora_add_to_canvas" id="flora_add_to_canvas"></a>

Add nodes and edges to a canvas: generation nodes, media from a URL, notes, group frames, timelines and decks.

**Labels:** writes

**Shown in clients as:** Add to canvas

**Use when:** You're building on the canvas: placing media by URL, wiring an image into a new video node to animate it, adding notes or a group frame, or creating a timeline or deck.

**Don't use when:** You want to generate right away: [`flora_create_generations`](/mcp/tools/generations.md#flora_create_generations) adds and runs nodes in one call. To change or delete existing nodes, use [`flora_update_canvas_nodes`](#flora_update_canvas_nodes) or [`flora_remove_from_canvas`](#flora_remove_from_canvas). Mermaid and other diagram text are rejected.

**Arguments**

| Argument            | Type            | Required | Notes                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| ------------------- | --------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `workspace_id`      | string          | no       | Workspace the project belongs to (ws\_…). Optional: when omitted it is looked up from project\_id. A guessed or placeholder value returns not\_found.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `project_id`        | string          | yes      | Project to add to (prj\_…). Use project\_id from flora\_list\_projects or flora\_create\_project. An API-issued canvas URL's /projects/\<id> segment becomes prj\_\<id>.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `idempotency_key`   | string          | no       | Unique key for this logical add. Reuse it after a timeout to prevent duplicate creation; use a new key for intentionally new content.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `add`               | array of object | no       | Nodes to create. Each: {type, ref?, label?, prompt?, model?, params?, position?, group?, content\_url?, document?, size?, fit\_text?}. type is one of image, video, text, audio, timeline, deck, notes, group, static\_image, layer\_editor — model3d is not creatable here (generate 3D with flora\_create\_generations; existing model3d nodes still run via flora\_run\_canvas\_nodes). prompt, model and params configure a generation node (params such as aspect\_ratio or resolution are validated against the model's schema and reject the whole call when invalid). content\_url (https) places existing media instead and excludes prompt, model and params. A timeline takes no prompt, model, params or content\_url: its content is document (see the document field for the shape; validated with the workspace's limits), or omit document and wire media nodes into it with edges. A deck likewise takes no prompt, model, params or content\_url: its label is the title and its content is document ({kind:"deck", schema\_version:1, slides}; the flora-deck-editor skill carries the slide, layer and geometry vocabulary), or omit document to create a blank deck. A notes node is canvas documentation, not a generation: its body is text (plain text, up to 20,000 characters, stored verbatim), size can resize its box, and fit\_text:true fits the body height to its width; flora\_get\_canvas reports the resulting size. It takes no prompt, model, params, content\_url or group, and it never runs; a text node is a generation prompt, so do not use one to document a canvas. group parents the node into an existing group's short id or a group ref from this same call. Up to 200 items. |
| `add[].ref`         | string          | no       | Optional handle echoed in created with real IDs. Supply a unique ref when connect or group refers to this new node; otherwise the tool assigns one.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `add[].type`        | string          | yes      | One of `image`, `video`, `text`, `audio`, `timeline`, `deck`, `notes`, `group`, `static_image`, `layer_editor`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `add[].label`       | string          | no       | Display label pinned on the node.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| `add[].prompt`      | string          | no       | Generation prompt. Mutually exclusive with content\_url.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `add[].model`       | string          | no       | Model name or endpoint id from flora\_list\_models; omit for the modality default.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| `add[].params`      | object          | no       | Model parameters, validated against the model's schema. Hidden media inputs (image\_url, image\_urls, video\_url, audio\_url, model\_url) are supplied by connect edges, not params. Use an existing node of the matching media type; model\_url takes a model3d source. For an image URL, add a static\_image node with content\_url and connect it.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `add[].position`    | object          | no       | Absolute canvas position. Omit to place automatically. Keys: `x`, `y`, all required.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `add[].group`       | string          | no       | Group to parent into: an existing group's short id or a group ref in this call. Not accepted on notes nodes (notes always stay at the top level of the canvas — place one beside a frame with position) or on group nodes (frames do not nest); either rejects the whole call.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `add[].content_url` | string          | no       | HTTPS URL of existing image, video or audio to place instead of generating.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `add[].text`        | string          | no       | Body of a notes node (notes only): plain text up to 20,000 characters, stored verbatim. Rejected on every other type.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `add[].size`        | object          | no       | Notes only: resize the box in canvas pixels with width, height, or both (width 200–1024, height 120–1024). An omitted side keeps the default. Rejected on every other type. Groups and media nodes cannot be sized: lay them out with flora\_arrange\_canvas with a row, column, or grid layout to refit a group's frame around its members.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `add[].size.width`  | number          | no       | 200 to 1024.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `add[].size.height` | number          | no       | 120 to 1024.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `add[].fit_text`    | boolean         | no       | Notes only: fit the height to the whole body at its width; flora\_get\_canvas reports the resulting size. Capped at the maximum height and warns if text still overflows. Groups and media nodes cannot be sized: lay them out with flora\_arrange\_canvas with a row, column, or grid layout to refit a group's frame around its members.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `add[].document`    | object          | no       | Timeline or deck document (timeline and deck nodes only), forwarded as-is: the API owns the vocabulary, and unknown fields or per-type violations reject server-side naming the field by JSON pointer. Send nested guides, slide document, frame and layers as JSON objects, never JSON-encoded strings. A deck document is {kind:"deck", schema\_version:1, slides} — load flora-deck-editor for its slide and layer vocabulary. Timeline shape (snake\_case, every key below required unless marked ?): {kind:"timeline", schema\_version:1, fps, composition\_width, composition\_height, tracks:\[{id, items:\[itemId, …], hidden, muted}], items:{\[itemId]:{id, from, duration\_in\_frames, type:"video"\|"image"\|"gif"\|"audio"\|"solid"\|"text"\|"captions", asset\_id (media items), video\_start\_from\_in\_seconds?, top?, left?, width?, height? (all four or none)}}, assets:{\[assetId]:{id, type:"video"\|"image"\|"gif"\|"audio", filename, mime\_type, width, height, media\_url (https), duration\_in\_seconds and has\_audio\_track (video/audio)}}. items and assets are objects keyed by id, tracks list item ids, the first track paints on top, and unknown keys reject by JSON pointer. Optional keys: `kind`, `schema_version`, `fps`, `composition_width`, `composition_height`, `tracks`, `items`, `assets`, `slides`.                                                                                                                                                                                                                                                                                                                                                                              |
| `connect`           | array of object | no       | Edges to create: {from, to, in?}. Either end is an existing node's short id (n7) or UUID, or a ref from add in this same call. in names a target input handle id (e.g. "imageUrl"), a modality word such as "image", a named action input, or "enabled"; model parameter names like "image\_url" match the handle; omit to connect by modality. One edge per pair — a duplicate is skipped with a warning. Up to 500 items.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `connect[].from`    | string          | yes      | Source node: short id, UUID, or a ref from add.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `connect[].to`      | string          | yes      | Target node: short id, UUID, or a ref from add.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `connect[].in`      | string          | no       | Target input handle id (e.g. "imageUrl") or modality word (e.g. "image"); model parameter names like "image\_url" match the handle; omit to connect by modality.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |

**Returns:** A `created` map from each `ref` to the short ID and UUID the canvas assigned, plus `warnings` for anything skipped, such as a duplicate edge. Use the assigned IDs, never your refs, in later calls.

**Cost:** Free. Adding a generation node doesn't run it; [`flora_run_canvas_nodes`](#flora_run_canvas_nodes) does, and that spends money.

**Usually comes after:** [`flora_get_canvas`](#flora_get_canvas)

**Usually comes before:** [`flora_run_canvas_nodes`](#flora_run_canvas_nodes), [`flora_arrange_canvas`](#flora_arrange_canvas)

**Example prompt:** "Put my product photo on the Spring campaign canvas and wire it into a new video node."

**Example call:**

```json
{
  "project_id": "prj_abc",
  "idempotency_key": "spring-hero-video-1",
  "add": [
    {
      "ref": "photo",
      "type": "static_image",
      "content_url": "https://example.com/product.jpg"
    },
    {
      "ref": "clip",
      "type": "video",
      "prompt": "Slow push-in on the product, soft morning light",
      "model": "i2v-gengateway-seedance-2-5-i2v"
    }
  ],
  "connect": [
    {
      "from": "photo",
      "to": "clip"
    }
  ]
}
```

<details>

<summary>Full description from the server</summary>

{% code overflow="wrap" %}

```
Before creating a Deck, call flora_discover_skills with name="flora-deck-editor" and follow its workflow, including document readback. Add nodes and edges to a project canvas. A ref is optional for an unwired new node; omitted refs receive unique handles in created. Supply a unique ref when connect or group refers to a new node in this call. Use dedicated FLORA tools for canvas edits. Each add carries a type, an optional caller-chosen ref, and the node's prompt, model, params, or content_url (or, for a notes node, its text); resize a note with size, or fit_text:true to show the whole body without scrolling; flora_get_canvas reports the resulting size. Each connect wires two nodes, either an existing short id (n7) or a ref declared in the same call. Actions cannot connect directly to other actions. Run the source action first and wait for its outputs with flora_list_generations. A browser materializes its RESULT nodes; a headless run may finish without creating canvas result nodes. Read flora_get_canvas and connect a result node only if it exists. If absent, run the next action headlessly with flora_run_action using those output URLs/text as inline inputs. To continue a media chain on the canvas, add image/video/audio output URLs with flora_add_to_canvas using type and content_url, then connect the created node to the next action and run it. Adding a generation node does NOT run it — the node sits idle until flora_run_canvas_nodes starts it. For retries after a timeout, reuse idempotency_key so the API rejects a duplicate instead of creating copies. Finish a new batch with flora_arrange_canvas using the returned IDs, then read back to verify spacing. For incremental rows under an existing grid, match its column positions and gaps while keeping the existing nodes fixed. Graph positions are node anchors (usually top-center); layout.origin is the painted top-left: subtract half the first node width from its anchor x. Set gap to the existing distance between column anchors minus node width, not the default 64. For a new row, gap controls horizontal spacing only: set origin.y to continue the existing row-anchor interval, since horizontal and vertical gaps may differ. Never recreate existing nodes to organize them into fields. Prefer flora_organize_canvas_fields when advertised to reuse named frames, move existing IDs, and separate the fitted frames. If flora_update_canvas_nodes does not advertise group, preserve the nodes and explain that safe grouping is unavailable on this API. This is ADD-ONLY: it never updates or removes anything (edit existing nodes and edges with flora_update_canvas_nodes, delete nodes with flora_remove_from_canvas); a ref that matches a live node id is rejected. The response's created map gives each ref the short id and UUID the canvas assigned — use those for later reads and runs, never your refs. Omit position to place a node automatically below the existing canvas content; pass one only when the user asked for a specific spot. Warnings in the response mean part of the request was skipped (a duplicate edge, for instance), so a 200 with warnings is not a clean apply. Video-generation nodes require the workspace video entitlement; without it the whole changeset is rejected. Static video uploads via content_url are exempt. If rejected, ask the user to enable video access or build with image nodes; do not retry the unchanged request.
```

{% endcode %}

</details>

## flora\_update\_canvas\_nodes <a href="#flora_update_canvas_nodes" id="flora_update_canvas_nodes"></a>

Edit existing nodes and edges in place: prompt, model, params, label, position, group, notes text, or a media node's file.

**Labels:** writes · destructive

**Shown in clients as:** Update canvas nodes

**Use when:** The user wants to change a node without losing its ID, outputs or wiring, move nodes into a group frame, or disconnect edges.

**Don't use when:** You want to add nodes ([`flora_add_to_canvas`](#flora_add_to_canvas)), delete them ([`flora_remove_from_canvas`](#flora_remove_from_canvas)), replace a timeline or deck document ([`flora_update_canvas_node_document`](#flora_update_canvas_node_document)), or lay out many nodes at once ([`flora_arrange_canvas`](#flora_arrange_canvas)).

**Arguments**

| Argument               | Type            | Required | Notes                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| ---------------------- | --------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `workspace_id`         | string          | yes      | Workspace the project belongs to (ws\_…).                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `project_id`           | string          | yes      | Project to edit (prj\_…). Use project\_id from flora\_list\_projects or flora\_create\_project. An API-issued canvas URL's /projects/\<id> segment becomes prj\_\<id>.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `update`               | array of object | no       | Existing nodes to modify, one entry per node: {id, label?, prompt?, model?, params?, position?, text?, size?, fit\_text?, group?, content\_url?, asset\_id?}. Only the fields present change. prompt and model apply to generation nodes; params to generation nodes and, as the action's own parameter values, to action nodes; text, size, and fit\_text apply to notes nodes only. Use size to resize a note or fit\_text:true to show the whole body without scrolling; flora\_get\_canvas reports the resulting size. Any other field is rejected — a timeline or deck document is replaced with flora\_update\_canvas\_node\_document. Up to 200 items. |
| `update[].id`          | string          | yes      | Node to modify: its short id (n7) or UUID from flora\_get\_canvas.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `update[].label`       | string          | no       | Replacement display label.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `update[].prompt`      | string          | no       | Replacement generation prompt.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `update[].model`       | string          | no       | Replacement model name or endpoint id from flora\_list\_models.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| `update[].params`      | object          | no       | Model parameters merged key by key into the node's stored parameters; validated against the model's schema.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `update[].position`    | object          | no       | New absolute canvas position. Keys: `x`, `y`, all required.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `update[].text`        | string          | no       | Replacement body of a notes node (notes only): plain text up to 20,000 characters, stored verbatim.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `update[].size`        | object          | no       | Notes only: resize the box in canvas pixels with width, height, or both (width 200–1024, height 120–1024). An omitted side keeps its current value. Groups and media nodes cannot be sized: lay them out with flora\_arrange\_canvas with a row, column, or grid layout to refit a group's frame around its members.                                                                                                                                                                                                                                                                                                                                          |
| `update[].size.width`  | number          | no       | 200 to 1024.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `update[].size.height` | number          | no       | 120 to 1024.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `update[].fit_text`    | boolean         | no       | Notes only: fit the height to the post-update body at its width; flora\_get\_canvas reports the resulting size. Capped at the maximum height and warns if text still overflows. Groups and media nodes cannot be sized: lay them out with flora\_arrange\_canvas with a row, column, or grid layout to refit a group's frame around its members.                                                                                                                                                                                                                                                                                                              |
| `update[].group`       | string or null  | no       | Group frame to move this node into, by its short id or UUID from flora\_get\_canvas, or null to ungroup it to the canvas top level. The node keeps its canvas spot; a frame it joins grows to wrap it. Not accepted on group nodes (frames do not nest), on a notes node joining a group, or on a pinned label.                                                                                                                                                                                                                                                                                                                                               |
| `update[].content_url` | string          | no       | HTTPS URL of an image, video, or audio file that replaces a static media node's content in place, keeping its id, edges, group and label. The file is copied onto Flora's CDN as on an add. Cannot combine with asset\_id, prompt, model, params, text, size or fit\_text.                                                                                                                                                                                                                                                                                                                                                                                    |
| `update[].asset_id`    | string          | no       | An asset id (asset\_…) already in this workspace's library that replaces a static media node's content in place, keeping its id, edges, group and label; its kind must match the node's. The asset is referenced, not copied or deleted. Cannot combine with content\_url, prompt, model, params, text, size or fit\_text.                                                                                                                                                                                                                                                                                                                                    |
| `disconnect`           | array of object | no       | Edges to remove: {from, to, in?}, both ends existing nodes' short ids or UUIDs. in names the input slot the edge feeds, as flora\_get\_canvas reports it; omit it to remove every edge between the pair. Up to 500 items.                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `disconnect[].from`    | string          | yes      | Source node: short id or UUID.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `disconnect[].to`      | string          | yes      | Target node: short id or UUID.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `disconnect[].in`      | string          | no       | Input slot of the edge to remove; omit to remove every edge between the pair.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |

**Returns:** Applied counts, the new `revision` and any `warnings`. An unknown node ID or edge rejects the whole call with `ref_not_found`, and nothing changes.

**Cost:** Free. Editing a generation node doesn't run it; its old output stays until [`flora_run_canvas_nodes`](#flora_run_canvas_nodes) runs it again.

**Usually comes after:** [`flora_get_canvas`](#flora_get_canvas)

**Usually comes before:** [`flora_run_canvas_nodes`](#flora_run_canvas_nodes)

**Example prompt:** "Change the prompt on node n7 to golden hour light and disconnect it from n3."

**Example call:**

```json
{
  "workspace_id": "ws_123",
  "project_id": "prj_abc",
  "update": [
    {
      "id": "n7",
      "prompt": "Same product, golden hour light",
      "params": {
        "aspect_ratio": "16:9"
      }
    }
  ],
  "disconnect": [
    {
      "from": "n3",
      "to": "n7"
    }
  ]
}
```

<details>

<summary>Full description from the server</summary>

{% code overflow="wrap" %}

```
Edit nodes and edges that already sit on a project canvas, in place, keeping their ids, outputs and other wiring. One call is one canvas changeset API operation with two kinds of write: update overwrites the fields it names on existing nodes, and disconnect removes edges. It never adds or deletes nodes, never runs a generation and spends no credits. Each update names one existing node by the short id (n7) or UUID flora_get_canvas reports and replaces only the fields it carries: label, prompt, model, params (merged key by key into the stored parameters — a named key is overwritten, omitted keys survive), position (absolute canvas coordinates; move a node by writing the x/y you want, reading its current position and neighbours from flora_get_canvas) and, for a notes node, text (its whole body), size, or fit_text:true to show the whole body without scrolling; flora_get_canvas reports the resulting size. One update per node; an unknown id rejects the whole call with ref_not_found and nothing changes. Each disconnect removes the edge between two nodes ({from, to, in?}; omit in to drop every edge between the pair); naming an edge that does not exist rejects the whole call with ref_not_found, so read the edges from flora_get_canvas first. Editing a generation node does NOT run it: its current output stays until flora_run_canvas_nodes runs it again, and params are validated against the model's schema before anything is written. Outside this tool: add nodes or edges with flora_add_to_canvas, delete nodes with flora_remove_from_canvas, replace a timeline or deck document with flora_update_canvas_node_document, and lay many nodes out at once with flora_arrange_canvas rather than computing every position by hand. The response reports applied counts, a revision and warnings — an update that matched the canvas already is reported there rather than failing. Organize existing work by moving nodes, never by adding copies. Create a new empty group first, then update the existing IDs with group. Arrange each field's members, then the field frames themselves with flora_arrange_canvas and read back to verify membership and spacing. Move a node into a group frame with group — a group's short id or UUID, or null to ungroup the node to the top level; the node keeps its canvas spot and the frame it joins grows to wrap it. Swap a static image, video or audio node's media in place with content_url (a file copied onto Flora's CDN) or asset_id (a library asset, referenced not copied); the node keeps its id, edges, group and label. Pass content_url or asset_id, never both, and not alongside prompt, model, params, text, size or fit_text.
```

{% endcode %}

</details>

## flora\_run\_canvas\_nodes <a href="#flora_run_canvas_nodes" id="flora_run_canvas_nodes"></a>

Run generation and timeline nodes already on a canvas, in dependency order, with each node's own model, prompt, params and inputs.

**Labels:** writes · destructive · spends money · async

**Shown in clients as:** Run canvas nodes

**Use when:** Nodes are set up on the canvas (for example a video node wired to an image) and the user approved the cost.

**Don't use when:** Nothing is on the canvas yet: [`flora_create_generations`](/mcp/tools/generations.md#flora_create_generations) is simpler and can quote first. For action nodes, use [`flora_run_canvas_action`](/mcp/tools/techniques-and-actions.md#flora_run_canvas_action).

**Arguments**

| Argument       | Type            | Required | Notes                                                                                                                                                                                                                 |
| -------------- | --------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `workspace_id` | string          | no       | Workspace the project belongs to (ws\_…). Optional: when omitted it is looked up from project\_id. A guessed or placeholder value returns not\_found.                                                                 |
| `project_id`   | string          | yes      | Project holding the nodes (prj\_…). Use project\_id from flora\_list\_projects or flora\_create\_project. An API-issued canvas URL's /projects/\<id> segment becomes prj\_\<id>.                                      |
| `node_ids`     | array of string | yes      | Nodes to run: the short ids (n1, n2, …) or node UUIDs reported by flora\_get\_canvas or in the created map flora\_add\_to\_canvas returns. The refs you chose in your own add call are NOT valid here. 1 to 50 items. |

**Returns:** One entry per node. Started entries carry a `run_id` to poll with [`flora_list_generations`](/mcp/tools/generations.md#flora_list_generations). Skipped entries carry a reason, such as `no_model_configured` or `generation_already_running`, and never stop the rest.

**Cost:** Spends money as soon as it runs, with no confirmation step and no quote option. Estimate first from each node's model (`estimated_cost_usd` in [`flora_list_models`](/mcp/tools/models-and-loras.md#flora_list_models)), show the user the total in US dollars, and get approval. Timeline nodes bill video editor render usage instead.

**Usually comes after:** [`flora_add_to_canvas`](#flora_add_to_canvas), [`flora_update_canvas_nodes`](#flora_update_canvas_nodes)

**Usually comes before:** [`flora_list_generations`](/mcp/tools/generations.md#flora_list_generations)

**Example prompt:** "Run the video node I just wired to the product photo."

**Example call:**

```json
{
  "project_id": "prj_abc",
  "node_ids": [
    "n8"
  ]
}
```

<details>

<summary>Full description from the server</summary>

{% code overflow="wrap" %}

```
Run generation nodes (image, video, text, audio, model3d) and timeline (video editor) nodes that already sit on a project canvas. Generation nodes run using the model, prompt, parameters and wired upstream inputs each node carries — configure the node first with flora_add_to_canvas or flora_update_canvas_nodes. A timeline node renders its document through the video editor render pipeline instead: it needs a document (written via flora_add_to_canvas, flora_update_canvas_node_document, or the editor) and spends timeline render usage rather than generation usage, so its started entry carries no model or cost estimate. SPENDS USAGE immediately, with no confirmation step; quote a cost to the user first. Returns one entry per node_id: started entries carry a run_id to poll with flora_list_generations (generations) or GET /runs/{runId} (timeline renders report progress and the finished video there), skipped entries carry a machine-readable reason (node_not_found, node_not_executable, no_model_configured, generation_already_running, timeline_no_document, timeline_not_entitled, …) and never fail the rest of the batch. Connected nodes run in dependency order, so a whole chain can be started in one call. For action nodes use flora_run_canvas_action instead.
```

{% endcode %}

</details>

## flora\_arrange\_canvas <a href="#flora_arrange_canvas" id="flora_arrange_canvas"></a>

Lay out nodes with FLORA's layout engine: Tidy, or a row, column or grid.

**Labels:** writes · destructive

**Shown in clients as:** Arrange canvas

**Use when:** The user asks for a row, column, grid, comparison strip or "side by side", or you just added a batch of nodes.

**Don't use when:** You'd compute positions by hand with [`flora_update_canvas_nodes`](#flora_update_canvas_nodes). Pass `node_ids` (with optional `layout`) or `all: true` alone, never both, and use `all: true` only when the user asked to reorganize the whole canvas.

**Arguments**

| Argument         | Type            | Required | Notes                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| ---------------- | --------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `workspace_id`   | string          | no       | Workspace the project belongs to (ws\_…). Optional: when omitted it is looked up from project\_id. A guessed or placeholder value returns not\_found.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `project_id`     | string          | yes      | Project canvas to arrange (prj\_…). Use project\_id from flora\_list\_projects or flora\_create\_project. An API-issued canvas URL's /projects/\<id> segment becomes prj\_\<id>.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `node_ids`       | array of string | no       | Nodes to arrange: the short ids (n1, n2, …) or node UUIDs exactly as flora\_get\_canvas, flora\_list\_canvas\_nodes, or a flora\_add\_to\_canvas / flora\_attach\_asset response reported them (including api\_asset\_… node ids for attached assets) — never ids you predicted, and never a bare asset id (asset\_…). With layout, this order is the placement order. 1 to 500 items.                                                                                                                                                                                                                                                                                                   |
| `all`            | boolean         | no       | Tidy every node on the canvas. Only when the user asked for it; cannot be combined with layout.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| `layout`         | object          | no       | Place node\_ids in a row, a column, or a grid instead of Tidy: {mode, columns?, gap?, origin?}. All top-level, or all members of one group; a label pinned to a node is rejected.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `layout.mode`    | string          | yes      | row: left to right. column: top to bottom. grid: row-major, columns per row. One of `row`, `column`, `grid`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `layout.columns` | integer         | no       | Nodes per row, grid only; defaults to the square root of the count rounded up. Ignored on row and column; mode determines the row or column. 1 to 500.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `layout.gap`     | number          | no       | Space between neighbours in canvas units, on both axes. Defaults to 64, the canvas's own grid gap. 0 to 4096.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `layout.origin`  | object          | no       | Absolute painted top-left of the block (where the first box starts painting), not a node anchor. Graph positions for ordinary blocks are top-center: origin.x = first anchor.x - first width/2. Omit to keep the set where it is (its current bounding-box corner), or to start group members at their frame's padded corner; inside a group it may not sit above or left of that corner. For members of one field, omit origin to use its padded content corner. The exact frame anchor (both x and y equal the frame's graph position) is also accepted as that padded corner; other explicit origins remain literal and must be inside the padded area. Keys: `x`, `y`, all required. |

**Returns:** `{arranged, moved, overlaps, bounds, revision}`. `moved: 0` means the nodes were already laid out. A non-empty `overlaps` lists node pairs that now collide.

**Cost:** Free. This tool doesn't spend money.

**Usually comes after:** [`flora_create_generations`](/mcp/tools/generations.md#flora_create_generations), [`flora_add_to_canvas`](#flora_add_to_canvas)

**Usually comes before:** [`flora_get_canvas`](#flora_get_canvas)

**Example prompt:** "Arrange the four new images in a 2 by 2 grid."

**Example call:**

```json
{
  "project_id": "prj_abc",
  "node_ids": [
    "n7",
    "n8",
    "n9",
    "n10"
  ],
  "layout": {
    "mode": "grid",
    "columns": 2
  }
}
```

<details>

<summary>Full description from the server</summary>

{% code overflow="wrap" %}

```
Lay out nodes on a project canvas with FLORA's own layout engine instead of computing positions by hand. Two ways to place a set: omit layout for Tidy — the editor's own layout, which follows edges (sources left of the nodes they feed) and keeps group members inside their frame — or pass layout to put the named nodes in a row, a column, or a grid, in node_ids order, with cells sized to the measured/authored boxes or conservative unpainted estimates (a column as wide as its widest node, a row as tall as its tallest) and a gap between neighbours; the block starts at origin, or where the set already is when origin is omitted. Use a layout whenever the user asks for a row, a column, a grid, a comparison strip, or 'side by side' — never hand-compute a grid with flora_update_canvas_nodes. To align a new row with existing columns, origin.x is the painted left edge: for ordinary top-center anchors, origin.x = existing anchor x - node width/2 (a width-384 node anchored at x=0 starts painting at x=-192). Set gap to the existing column-anchor step minus node width; do not reuse an anchor x as origin.x. Already aligned explicit add positions need no further arrangement unless the layout must change. A layout needs node_ids that all sit at the top level or all inside the same group; members are laid out from the frame's padded corner and the frame is refit around all of its members (an explicit origin only grows it). Pass node_ids to arrange that subset, or all:true ONLY when the user asked to reorganize the whole canvas with Tidy, since that moves work they positioned by hand; with neither the call is rejected, and all:true takes no layout. On an older API, a subset is arranged in isolation and can overlap untouched work. Inspect overlaps after arranging; choose an origin clear of other work when needed. Unknown ids reject the whole call and nothing moves — pass ids exactly as flora_get_canvas, flora_list_canvas_nodes, or a flora_add_to_canvas / flora_attach_asset response reported them (api_asset_… node ids are valid); never predict an id and never pass a bare asset id (asset_…). Returns {arranged, moved, overlaps, bounds, revision}; moved:0 means the set was already laid out, bounds is the block's absolute box (place the next batch at origin y = bounds.y + bounds.height + gap), and a non-empty overlaps lists the short-id pairs that now collide — re-run with an origin clear of other work, all:true for a full Tidy reflow, or move nodes explicitly with flora_update_canvas_nodes. This API supports obstacle-safe row, column and grid layouts: when layout.origin is omitted, the entire block is translated clear of untouched work while preserving its order and spacing. Explicit origins can collide. For members of one field, omit origin to use its padded content corner. The exact frame anchor (both x and y equal the frame's graph position) is also accepted as that padded corner; other explicit origins remain literal and must be inside the padded area.
```

{% endcode %}

</details>

## flora\_organize\_canvas\_fields <a href="#flora_organize_canvas_fields" id="flora_organize_canvas_fields"></a>

Sort existing nodes into named fields (group frames), reusing frames that already exist.

**Labels:** writes · destructive

**Shown in clients as:** Organize canvas fields

**Use when:** The user wants work sorted into fields such as Concepts and Finals. It moves the nodes, lays out each field in a grid and spaces the frames.

**Don't use when:** Existing positions must stay fixed, or you need exact coordinates: use [`flora_arrange_canvas`](#flora_arrange_canvas) or [`flora_update_canvas_nodes`](#flora_update_canvas_nodes). Never recreate nodes to organize them.

**Arguments**

| Argument            | Type            | Required | Notes                                                                                                                                                                   |
| ------------------- | --------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `workspace_id`      | string          | no       | Workspace (ws\_…). Omit to resolve from the exact project\_id.                                                                                                          |
| `project_id`        | string          | yes      | Existing project (prj\_…). Use project\_id from flora\_list\_projects or flora\_create\_project. An API-issued canvas URL's /projects/\<id> segment becomes prj\_\<id>. |
| `fields`            | array of object | yes      | 1 to 50 items.                                                                                                                                                          |
| `fields[].label`    | string          | yes      | 1 to 500 characters.                                                                                                                                                    |
| `fields[].node_ids` | array of string | yes      | 1 to 200 items.                                                                                                                                                         |

**Returns:** How many nodes it organized, and each field's label and frame ID. If it's interrupted, read the canvas and retry with the same labels and node IDs.

**Cost:** Free. This tool doesn't spend money.

**Usually comes after:** [`flora_get_canvas`](#flora_get_canvas)

**Usually comes before:** [`flora_get_canvas`](#flora_get_canvas)

**Example prompt:** "Sort my canvas into Concepts and Finals fields."

**Example call:**

```json
{
  "project_id": "prj_abc",
  "fields": [
    {
      "label": "Concepts",
      "node_ids": [
        "n3",
        "n4",
        "n5"
      ]
    },
    {
      "label": "Finals",
      "node_ids": [
        "n9"
      ]
    }
  ]
}
```

<details>

<summary>Full description from the server</summary>

{% code overflow="wrap" %}

```
Organize existing nodes into named fields without recreating nodes or changing their content or edges. Pass fields with labels and existing node_ids from flora_get_canvas (up to 200 requested members total). Prefer this tool for sorting work into Concepts/Finals or other fields: it validates all members first, reuses a unique matching top-level field label or creates an empty field, moves the existing nodes, grids each field's members, then separates the fitted field frames in a row clear of untouched work. Existing members of reused fields are preserved and reflowed. If existing positions must stay fixed, add or arrange only the new IDs with the dedicated add/arrange tools instead. Duplicate member IDs, ambiguous labels, nested frames, notes, labels and groups as members reject before writes. This is a multi-request workflow, not an atomic transaction: if interrupted, read the canvas and retry with the same field labels and member IDs to reuse committed frames. No explicit coordinates are accepted; use flora_update_canvas_nodes and flora_arrange_canvas for precise placement. Does not run generations.
```

{% endcode %}

</details>

## flora\_remove\_from\_canvas <a href="#flora_remove_from_canvas" id="flora_remove_from_canvas"></a>

Delete nodes from a canvas, with every edge that touches them. Deleting a group deletes its members.

**Labels:** writes · destructive

**Shown in clients as:** Remove from canvas

**Use when:** The user asked you to delete specific nodes.

**Don't use when:** You only want to clear a node's content or wiring: use [`flora_update_canvas_nodes`](#flora_update_canvas_nodes). Deleting can't be undone through the API.

**Arguments**

| Argument       | Type            | Required | Notes                                                                                                                                                                         |
| -------------- | --------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `workspace_id` | string          | yes      | Workspace the project belongs to (ws\_…).                                                                                                                                     |
| `project_id`   | string          | yes      | Project to delete from (prj\_…). Use project\_id from flora\_list\_projects or flora\_create\_project. An API-issued canvas URL's /projects/\<id> segment becomes prj\_\<id>. |
| `node_ids`     | array of string | yes      | Nodes to delete: the short ids (n1, n2, …) or node UUIDs flora\_get\_canvas reports. 1 to 200 items.                                                                          |

**Returns:** A `removed` count that includes group members deleted with their group. An unknown ID rejects the whole call, and nothing is deleted.

**Cost:** Free. This tool doesn't spend money.

**Usually comes after:** [`flora_get_canvas`](#flora_get_canvas)

**Example prompt:** "Delete nodes n4 and n5 from the Spring campaign canvas."

**Example call:**

```json
{
  "workspace_id": "ws_123",
  "project_id": "prj_abc",
  "node_ids": [
    "n4",
    "n5"
  ]
}
```

<details>

<summary>Full description from the server</summary>

{% code overflow="wrap" %}

```
Delete nodes from a project canvas. Every edge touching a deleted node goes with it, and deleting a group deletes its members too; the response's removed count includes them. Deletion is immediate and cannot be undone through the API, so pass only the nodes the user asked to remove — to clear a node's content or wiring instead, edit it with flora_update_canvas_nodes. Nodes are addressed by the short id (n7) or UUID flora_get_canvas reports; an unknown id rejects the whole call with ref_not_found and nothing is deleted.
```

{% endcode %}

</details>

## flora\_get\_canvas\_node\_document <a href="#flora_get_canvas_node_document" id="flora_get_canvas_node_document"></a>

Read the full document of a timeline, deck or notes node, with its revision.

**Labels:** read-only

**Shown in clients as:** Get node document

**Use when:** Before editing a timeline or deck, or to read one deck slide or layer. [`flora_get_canvas`](#flora_get_canvas) only carries a summary of these nodes.

**Don't use when:** The node carries no document, like image and video nodes: use [`flora_get_canvas`](#flora_get_canvas) for their settings and [`flora_list_canvas_nodes`](#flora_list_canvas_nodes) for their files.

{% hint style="info" %}
Before reading or editing a deck, the agent loads the `flora-deck-editor` skill with [`flora_discover_skills`](/mcp/tools/skills-and-discovery.md#flora_discover_skills) and follows it.
{% endhint %}

**Arguments**

| Argument       | Type   | Required | Notes                                                                                                                                                                           |
| -------------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `workspace_id` | string | no       | Workspace the project belongs to (ws\_…). Optional: when omitted it is looked up from project\_id. A guessed or placeholder value returns not\_found.                           |
| `project_id`   | string | yes      | Project holding the node (prj\_…). Use project\_id from flora\_list\_projects or flora\_create\_project. An API-issued canvas URL's /projects/\<id> segment becomes prj\_\<id>. |
| `node_id`      | string | yes      | The node's short id (n7) or UUID, as flora\_get\_canvas or the created map returned by flora\_add\_to\_canvas reports it.                                                       |
| `slide`        | string | no       | Deck nodes only: read this slide id instead of the whole document. Combine with layer to read a single layer.                                                                   |
| `layer`        | string | no       | Deck nodes only: read this layer id; requires slide.                                                                                                                            |

**Returns:** The document and its `revision`. A notes node reads as `{kind: "notes", text}` at revision 0. A timeline with no document yet returns `not_found`.

**Cost:** Free. This tool doesn't spend money.

**Usually comes after:** [`flora_get_canvas`](#flora_get_canvas)

**Usually comes before:** [`flora_update_canvas_node_document`](#flora_update_canvas_node_document)

**Example prompt:** "Read the slides in the deck on my launch canvas."

**Example call:**

```json
{
  "project_id": "prj_abc",
  "node_id": "n12"
}
```

<details>

<summary>Full description from the server</summary>

{% code overflow="wrap" %}

```
Before reading or editing a Deck, call flora_discover_skills with name="flora-deck-editor" and follow its workflow. Read the full authored content of a document-bearing canvas node — a timeline's tracks, items and assets, a deck's slides and layers, or a note's whole text body — with its revision. For a timeline or deck, flora_get_canvas carries only a summary. To edit: read the document here, change it, and send the whole document back with flora_update_canvas_node_document, passing base_revision set to the revision read here; a stale base_revision is rejected with revision_conflict instead of overwriting another edit. Deck updates require base_revision; change only the requested slides/layers and preserve the others, including their IDs and source bindings. Deck revision checks reject observed stale reads but do not serialize simultaneous collaborators. A node that carries no document is rejected — use flora_get_canvas for its prompt, model and params; use flora_list_canvas_nodes for media outputs, including Model3D files; a timeline with no document yet returns not_found (write one with base_revision 0). A note reads as {kind:"notes", text} at revision 0 and is edited with flora_update_canvas_nodes carrying text, not with flora_update_canvas_node_document. For a deck node, pass slide to read one slide — its frame, guides and layers — instead of the whole document, and slide plus layer to read one layer; both return the revision a scoped write needs.
```

{% endcode %}

</details>

## flora\_update\_canvas\_node\_document <a href="#flora_update_canvas_node_document" id="flora_update_canvas_node_document"></a>

Replace a timeline's or deck's document, or apply scoped deck edits, guarded by the revision you read.

**Labels:** writes · destructive

**Shown in clients as:** Update node document

**Use when:** The user wants to change a timeline's tracks and items, or a deck's slides and layers.

**Don't use when:** You're editing a notes node (use [`flora_update_canvas_nodes`](#flora_update_canvas_nodes) with `text`). Writing a timeline doesn't render it ([`flora_run_canvas_nodes`](#flora_run_canvas_nodes) does), and decks have no render or PDF export here.

{% hint style="info" %}
Before editing a deck, the agent loads the `flora-deck-editor` skill with [`flora_discover_skills`](/mcp/tools/skills-and-discovery.md#flora_discover_skills) and follows it.
{% endhint %}

**Arguments**

| Argument        | Type            | Required | Notes                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| --------------- | --------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `workspace_id`  | string          | no       | Workspace the project belongs to (ws\_…). Optional: when omitted it is looked up from project\_id. A guessed or placeholder value returns not\_found.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `project_id`    | string          | yes      | Project holding the node (prj\_…). Use project\_id from flora\_list\_projects or flora\_create\_project. An API-issued canvas URL's /projects/\<id> segment becomes prj\_\<id>.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `node_id`       | string          | yes      | The node's short id (n7) or UUID, as flora\_get\_canvas reports it.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `document`      | object          | no       | The complete replacement document, kind matching the node type. A deck is {kind:"deck", schema\_version:1, slides}; load flora-deck-editor for its slide and layer vocabulary. Timeline shape (snake\_case, every key below required unless marked ?): {kind:"timeline", schema\_version:1, fps, composition\_width, composition\_height, tracks:\[{id, items:\[itemId, …], hidden, muted}], items:{\[itemId]:{id, from, duration\_in\_frames, type:"video"\|"image"\|"gif"\|"audio"\|"solid"\|"text"\|"captions", asset\_id (media items), video\_start\_from\_in\_seconds?, top?, left?, width?, height? (all four or none)}}, assets:{\[assetId]:{id, type:"video"\|"image"\|"gif"\|"audio", filename, mime\_type, width, height, media\_url (https), duration\_in\_seconds and has\_audio\_track (video/audio)}}. items and assets are objects keyed by id, tracks list item ids, the first track paints on top, and unknown keys reject by JSON pointer. Optional keys: `kind`, `schema_version`, `fps`, `composition_width`, `composition_height`, `tracks`, `items`, `assets`, `slides`. |
| `base_revision` | integer         | yes      | The document revision this write is based on, as flora\_get\_canvas\_node\_document reported it; 0 when the node has no document yet. Minimum 0.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `commands`      | array of object | no       | Deck nodes only: ordered scoped edits such as {type:"update\_layers", slide\_id, layers:\[…]} or {type:"remove\_slide", slide\_id} — pass this OR document.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |

**Returns:** The write result with the new revision. A stale `base_revision` is rejected with `revision_conflict` and nothing is written: read the document again and reapply the change.

**Cost:** Free. This tool doesn't spend money.

**Usually comes after:** [`flora_get_canvas_node_document`](#flora_get_canvas_node_document)

**Usually comes before:** [`flora_run_canvas_nodes`](#flora_run_canvas_nodes)

**Example prompt:** "Remove slide 3 from the launch deck."

**Example call:**

```json
{
  "project_id": "prj_abc",
  "node_id": "n12",
  "base_revision": 4,
  "commands": [
    {
      "type": "remove_slide",
      "slide_id": "slide_3"
    }
  ]
}
```

<details>

<summary>Full description from the server</summary>

{% code overflow="wrap" %}

```
Before editing a Deck, call flora_discover_skills with name="flora-deck-editor" and follow its workflow. Replace the authored document of a document-bearing canvas node — a timeline's whole document ({kind:"timeline", schema_version:1, fps, composition_width, composition_height, tracks, items, assets}) or a deck's whole document ({kind:"deck", schema_version:1, slides}), snake_case, not a patch. Read it first with flora_get_canvas_node_document, change only what was asked and preserve the rest (a deck's other slides and layers keep their IDs and source bindings), and send the entire document back with base_revision set to the revision you read (0 for a timeline that has no document yet). A stale base_revision is rejected with revision_conflict and nothing is written: read again and reapply the change. The document is validated with the workspace's limits before anything is written, and a rejection names the field by JSON pointer. Writing a document does not render it: a timeline renders through flora_run_canvas_nodes; a deck has no render or PDF export on this server. For a deck node, pass commands instead of document to edit in place — slide ops (add_slide, duplicate_slide, remove_slide, move_slide, set_slide_hidden, set_slide_background, set_guides) and layer ops (add_layers, update_layers, update_layer_geometry, remove_layers, reorder_layers) naming slides and layers by id — without resending the whole document. commands and document are mutually exclusive; a rejected command fails the call naming its index. The flora-deck-editor skill carries the layer vocabulary.
```

{% endcode %}

</details>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.flora.ai/mcp/tools/canvas.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
