Skip to main content
Glama

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault
INKSCAPE_MCP_MAX_PROCSNoMax concurrent Inkscape subprocesses.2
INKSCAPE_MCP_TOOL_DESCNoTool-description mode: full or short.full
INKSCAPE_MCP_ENGINE_MODENoEngine transport for render/export/path/boolean/action-chain: per_call or shell.per_call
INKSCAPE_MCP_LIVE_ENABLEDNoMaster gate for live mode.true
INKSCAPE_MCP_TOOL_PROFILENoTool-disclosure profile: full or core.full
INKSCAPE_MCP_MAX_EXPORT_PXNoMax raster dimension for render/export.8192
INKSCAPE_MCP_LIVE_RENDEZVOUSNoOptional explicit path to the live helper's rendezvous file.
INKSCAPE_MCP_MAX_INPUT_BYTESNoMax size of an input SVG.52428800
INKSCAPE_MCP_SNAPSHOT_KEEP_NNoSnapshots retained per document.50
INKSCAPE_MCP_WORKSPACE_ROOTSYesRequired. OS-path-separated list of directories the server may read/write.
INKSCAPE_MCP_ACTION_ALLOWLISTNoOS-path-separated list of Inkscape Action ids added to the built-in allowlist.
INKSCAPE_MCP_MAX_OUTPUT_BYTESNoMax size of a produced artifact.104857600
INKSCAPE_MCP_PROCESS_TIMEOUT_SNoPer-Inkscape-process timeout (seconds).60
INKSCAPE_MCP_ARTIFACT_KEEP_DAYSNoArtifact age retention.14
INKSCAPE_MCP_ARTIFACT_MAX_BYTESNoTotal artifact byte budget.2147483648
INKSCAPE_MCP_RAW_ACTION_ENABLEDNoAdvanced-mode gate for the run_raw_action escape hatch.false
INKSCAPE_MCP_SNAPSHOT_KEEP_DAYSNoSnapshot age retention.30
INKSCAPE_MCP_EXTENSION_ALLOWLISTNoOS-path-separated list of Inkscape extension ids added to the execution allowlist.
INKSCAPE_MCP_SNAPSHOT_HARD_MAX_NNoHard cap on snapshots per document.500
INKSCAPE_MCP_ENGINE_MAX_PROCESSESNoMax concurrent warm shell workers when engine_mode=shell.2
INKSCAPE_MCP_LIVE_CACHE_MAX_BYTESNoTotal byte budget for the live render cache.268435456
INKSCAPE_MCP_LIVE_FRAME_KEEP_DAYSNoAge retention for loop/live render frames.7
INKSCAPE_MCP_LIVE_FRAME_MAX_BYTESNoTotal byte budget for loop/live render frames.536870912
INKSCAPE_MCP_ENGINE_IDLE_TIMEOUT_SNoSeconds before an idle warm shell worker is reaped.300
INKSCAPE_MCP_LIVE_CACHE_MAX_ENTRIESNoMax frames in the per-session live render cache.64
INKSCAPE_MCP_LIVE_COALESCE_BUDGET_MSNoFrame-coalescing latency budget (0 disables).200
INKSCAPE_MCP_SNAPSHOT_HARD_MAX_BYTESNoHard cap on snapshot bytes.5368709120
INKSCAPE_MCP_ARTIFACT_MAX_BYTES_PER_DOCNoPer-document artifact byte budget.536870912

Instructions

Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.

This server publishes no instructions, or was last inspected before Glama recorded them.

Capabilities

Features and capabilities supported by this server

Protocol revision2025-11-25

CapabilityDetails
tools
{
  "listChanged": true
}
logging
{}
prompts
{
  "listChanged": false
}
resources
{
  "subscribe": false,
  "listChanged": false
}
extensions
{
  "io.modelcontextprotocol/ui": {}
}
experimental
{}

Tools

Functions exposed to the LLM to take actions

NameDescription
diagnose_runtimeA

Probe the local Inkscape + Python runtime fresh and return the capability matrix.

When to use: to FORCE a fresh probe (e.g. after installing Inkscape/fonts). For a cheap cached read use list_capabilities; for live-transport detail use check_live_support.

Key params: none. Re-runs the probe every call and refreshes the cache that list_capabilities and inkscape://runtime/capabilities serve.

Return shape: Capabilities — Inkscape version, available actions, export formats, data dirs, inkex, DBus/live transport availability, fonts, the curated intents map, and the authoritative MCP tool surface (tool_count + tools: name + one-line purpose + risk class, from the live registry). Missing backends are reported in notes, never crashed.

Example: diagnose_runtime()

Risk class: low (read-only probe).

list_capabilitiesA

Return the cached runtime capability matrix (probed once, then reused).

When to use: the cheap default for "what can this host/server do". To FORCE a re-probe use diagnose_runtime; to map a single goal to a tool use how_do_i.

Key params: none.

Return shape: Capabilities — same shape as diagnose_runtime, served from cache. Includes an intents section: the curated natural-language goal → tool(s) map (the same map how_do_i matches against) so an agent can browse "which tool does X" without one call per goal. Also carries the authoritative MCP tool surface: tool_count (the one true count of registered @mcp.tools) and tools (name + one-line purpose + risk class), sourced from the live registry — so agents read one number instead of deriving it.

Example: list_capabilities()

Risk class: low (read-only).

stat_artifactA

Return the on-disk byte size + sha256 digest of one sandboxed artifact.

When to use: to VERIFY what you wrote (an export, a render, a saved SVG) — its exact byte size and content digest — without a wc -c / sha256sum Bash fallback. For a whole SET (and an aggregate byte total) use stat_artifacts; for image pixel dimensions read the producing tool's result fields instead.

Key params: path may be workspace-RELATIVE (anchored to the first workspace root, matching open_document / save_document_as) or absolute; either is sandbox-validated and a ../-escape, an absolute path outside the workspace, or a symlink whose target leaves the sandbox is rejected with path rejected: outside workspace. The file must exist and be within the configured size limit; the sha256 is computed streaming so a large file is bounded in memory.

Return shape: ArtifactStat{path, bytes, sha256} where path is the WORKSPACE-RELATIVE POSIX path (never a host path) and sha256 is the lowercase hex digest.

Example: stat_artifact("dist/logo.png")

Risk class: low (read-only stat; nothing is mutated, no Operation Record / snapshot).

stat_artifactsA

Stat a SET of sandboxed artifacts: per-file size + sha256 plus an aggregate byte total.

When to use: to verify a whole produced collection (an icon set, a dist/ tree) and read its TOTAL byte budget in one call — the readback half of a batch export, without a du -cb. For a single file use stat_artifact.

Key params: paths is a non-empty list; each entry is resolved EXACTLY as stat_artifact resolves its path (workspace-relative or absolute, sandbox + symlink validated, size-capped). The first entry that escapes the sandbox or exceeds the size limit fails the whole call with a stable message — nothing partial is returned.

Return shape: ArtifactStatSet{artifacts: [{path, bytes, sha256}], total_bytes, count} where total_bytes is the sum of the per-file sizes and every path is workspace-relative (never a host path).

Example: stat_artifacts(["dist/16.png", "dist/32.png", "dist/64.png"])

Risk class: low (read-only stat; nothing is mutated, no Operation Record / snapshot).

apply_editsA

Apply an ordered list of typed DOM edits to a document as ONE atomic, reversible operation.

When to use: making SEVERAL edits to one document in a single call (draw + style + arrange, re-theme + rename, …) instead of N separate tool round-trips. Each member is the SAME typed edit the dedicated tool exposes — apply_edits adds atomicity + one snapshot, not new authority. For a single edit, call the dedicated tool (set_fill, move_object, …); for path geometry or cross-document composition use those tools directly (they are NOT batchable).

Key params: edits is a non-empty, ordered list (max 64) of typed edits, each tagged by an op field that selects its schema — e.g. {"op": "create_rect", "x": 0, "y": 0, "width": 100, "height": 60, "fill": "#3366cc"}, {"op": "set_fill", "object_ids": ["logo"], "color": "red"}, {"op": "move_object", "object_id": "logo", "dx": 10, "dy": 0}. Supported ops mirror the typed DOM tools: set_fill / set_stroke / set_opacity / replace_color / apply_palette / replace_text / set_font / duplicate_object / rename_object / delete_object (high) / move_object / scale_object / rotate_object / resize_canvas / normalize_viewbox / tile / create_rect / create_circle / create_ellipse / create_line / create_polygon / create_polyline / create_path / create_text / create_group / group_objects / reparent_object / create_use / add_linear_gradient / add_radial_gradient. Validation is two-phase: ALL members are validated before any mutation (one bad edit leaves the document byte-identical), then applied in order with all-or-nothing rollback on any failure. If ANY member is high-risk (a delete_object edit) the WHOLE batch is HIGH and requires a non-empty approval_token; otherwise it is medium.

Render and look before you trust the edit: a batch changes several things at once, so call render_preview (or live_render_view in live mode) afterwards and inspect the result before relying on it — and restore_snapshot(doc_id, snapshot_id) reverts the whole batch in one step.

Return shape: BatchEditResult — the pipeline fields for the single batch operation (operation_id, snapshot_id, changed, before/after preview; reversible) PLUS edit_count and the effective risk_class.

Example: apply_edits(doc_id, [{"op": "create_rect", "x": 0, "y": 0, "width": 100, "height": 60, "fill": "#eee", "object_id": "bg"}, {"op": "create_text", "x": 10, "y": 30, "text": "Hi"}])

Risk class: medium (effective risk is the MAX over members; a delete_object member escalates the batch to high and requires approval_token). Reversible via the single pre-batch snapshot.

set_document_svgA

REPLACE the whole working copy with an agent-composed SVG string (root must be <svg>).

When to use: adopting a full SVG composed in memory, replacing the working copy wholesale (no file round-trip). To ADD to (not replace) a document use insert_svg_fragment; for a blank start use create_document.

Key params: svg root must be <svg>; it is byte-size-checked, safe-parsed, and allowlist-scrubbed — <script>, any on* handler, javascript: hrefs, and external refs (http(s):// / // / file: / data:) are REJECTED; only a same-document #id reference is allowed. A real run REQUIRES a non-empty approval_token. The original/source file is never touched.

Return shape: ComposeResult — an EditResult (operation + pre-mutation snapshot links, reversible via restore_snapshot) extended with the post-adopt validate_document findings (validation).

Example: set_document_svg(doc_id, "<svg ...>...</svg>", approval_token="ok")

Render and look before you trust this edit: render with render_preview (or live_render_view) and inspect the result before relying on it; restore_snapshot reverts it if it is wrong.

Risk class: HIGH — requires a non-empty approval_token; without it the op is refused and nothing is written.

insert_svg_fragmentA

Insert an agent-composed SVG fragment under a parent (parent_id) or the document root.

When to use: grafting one composed subtree into an existing document (no file round-trip). To REPLACE the whole document use set_document_svg; for a single typed shape use the create_* tools.

Key params: svg is ONE element subtree (wrap several siblings in a <g>). parent_id (must exist) sets where it lands, else the document root. unwrap (default True) controls a <svg> root: when True the wrapper <svg> is unwrapped and its children grafted (an empty wrapper is rejected); pass unwrap=False to KEEP an explicit nested <svg> container, inserted as-is (still allowlist-scrubbed; an empty nested <svg> is then allowed). unwrap has no effect on a non-<svg> root, which is always inserted intact. Same hardening as set_document_svg (safe-parse + strict allowlist; <script>, on* handlers, javascript: hrefs, external refs rejected; only same-document #id allowed). A real run REQUIRES a non-empty approval_token. The original/source file is never touched.

Return shape: ComposeResult — an EditResult (operation + pre-mutation snapshot links, reversible via restore_snapshot) extended with the post-adopt validate_document findings (validation).

Example: insert_svg_fragment(doc_id, "<g>...</g>", parent_id="layer1", approval_token="ok"); to keep a nested container: insert_svg_fragment(doc_id, "<svg>...</svg>", unwrap=False, approval_token="ok").

Render and look before you trust this edit: render with render_preview (or live_render_view) and inspect the result before relying on it; restore_snapshot reverts it if it is wrong.

Risk class: HIGH — requires a non-empty approval_token; without it the op is refused and nothing is written.

compose_gridA

Lay out N DIFFERENT assets in a grid (contact / spec sheet) in ONE reversible call.

When to use: building a multi-asset sheet — one cell per DIFFERENT document or object — in a single call (no per-asset loop, no lxml subtree extract). To repeat ONE object into a grid use tile; to graft a single composed subtree use insert_svg_fragment.

Key params: supply EXACTLY ONE source mode — doc_ids (one whole document per cell) OR object_ids together with source_doc_id (objects from one document per cell). The grid fills ROW-MAJOR over rows x cols cells of size cell (user units); fewer assets than cells leaves trailing cells empty. Each asset is deep-copied (every id re-minted, intra-clone refs rewritten, no id clashes), wrapped in a <g> translated to its cell origin and, with scale_to_fit (default True), uniformly DOWN-scaled to fit cell - 2*padding (never upscaled). gap/padding (default 0) space the cells. target_doc_id composes INTO an existing document; omit it to create a new blank document sized to the whole grid. Bounded: rows*cols ≤ the engine cell cap; the asset count must not exceed the cell count.

Return shape: ComposeGridResult — an EditResult (one operation_id + one pre-mutation snapshot for the whole sheet, reversible via restore_snapshot) plus target_doc_id (the new id when a blank doc was created), rows/cols, and cells (the ordered placement plan: per asset its grid coords, new cell-group id, and a short source label).

Example: compose_grid(3, 4, 64, doc_ids=["d1","d2",...,"d12"]) lays a 12-icon system into a 3x4 sheet in one call.

Render and look before you trust this edit: render with render_preview (or live_render_view) and inspect the result before relying on it; restore_snapshot reverts it if it is wrong.

Risk class: medium (creates a new tracked document or composes into one; sources never mutated).

place_documentA

Place an existing document or object INTO another document at (x, y) with scale.

When to use: re-composing existing geometry cross-document without re-authoring or extracting SVG by hand — the single-asset companion of compose_grid. To lay out MANY assets in a grid use compose_grid; to graft agent-COMPOSED markup use insert_svg_fragment; to instance a same-document object use create_use.

Key params: supply EXACTLY ONE source — source_doc_id (place that whole document's root) OR object_id together with source_doc_id (place that one object from the source document). The source subtree is deep-copied (every id re-minted, intra-clone refs rewritten, no id clashes — the source is NEVER mutated) and wrapped in a <g> translated to (x, y) and uniformly scaled by scale (> 0) about that origin. The whole place lands under ONE snapshot + Operation Record.

Return shape: PlaceResult — an EditResult (reversible via restore_snapshot) plus target_doc_id, placed_id (the new wrapper-group id), and source (a short label).

Example: place_document("sheet", 100, 0, source_doc_id="logo") drops the whole logo document into sheet at (100, 0); place_document("sheet", 0, 0, source_doc_id="kit", object_id="star") places just the star object from kit.

Render and look before you trust this edit: render with render_preview (or live_render_view) and inspect the result before relying on it; restore_snapshot reverts it if it is wrong.

Risk class: medium (write-new on the target working copy, reversible; sources never mutated).

create_rectA

Create a <rect> at (x, y) sized width / height (> 0), with optional corner radii.

When to use: drawing a rectangle / square / box. For an ellipse use create_circle / create_ellipse; for a freeform shape use create_path.

Key params: width / height > 0; rx / ry optional corner radii; inserted into parent_id (must exist) or the document default parent (first layer, else root); object_id to pin the id. Optional fill / stroke / stroke_width paint the shape IN THIS CALL — validated exactly like set_fill / set_stroke (colour or url(#id); CSS length) — so no mandatory second styling call (default None = unpainted, prior behaviour).

Return shape: CreateResultobject_id (new id), analytic bbox, plus the pipeline fields (operation_id, snapshot_id, changed, before/after preview).

Example: create_rect(doc_id, 10, 10, 100, 60, rx=8, fill="#3366cc")

Render and look before you trust this edit: render with render_preview (or live_render_view) and inspect the result before relying on it; restore_snapshot reverts it if it is wrong.

Risk class: medium (reversible write-new on the working copy; original untouched).

create_circleA

Create a <circle> centred at (cx, cy) with radius r (> 0).

When to use: drawing a circle / disc. For an oval use create_ellipse; for a box use create_rect.

Key params: r > 0; inserted into parent_id (must exist) or the document default parent; object_id to pin the id. Optional fill / stroke / stroke_width paint it in this call (validated like set_fill / set_stroke; default None = unpainted).

Return shape: CreateResultobject_id (new id), analytic bbox, plus the pipeline fields (operation_id, snapshot_id, changed, before/after preview).

Example: create_circle(doc_id, 50, 50, 25, fill="red")

Render and look before you trust this edit: render with render_preview (or live_render_view) and inspect the result before relying on it; restore_snapshot reverts it if it is wrong.

Risk class: medium (reversible write-new on the working copy; original untouched).

create_ellipseA

Create an <ellipse> centred at (cx, cy) with radii rx / ry (> 0).

When to use: drawing an oval / ellipse. For a perfect circle use create_circle; for a box use create_rect.

Key params: rx / ry > 0; inserted into parent_id (must exist) or the document default parent; object_id to pin the id. Optional fill / stroke / stroke_width paint it in this call (validated like set_fill / set_stroke; default None = unpainted).

Return shape: CreateResultobject_id (new id), analytic bbox, plus the pipeline fields (operation_id, snapshot_id, changed, before/after preview).

Example: create_ellipse(doc_id, 50, 50, 30, 18, fill="#0a0")

Render and look before you trust this edit: render with render_preview (or live_render_view) and inspect the result before relying on it; restore_snapshot reverts it if it is wrong.

Risk class: medium (reversible write-new on the working copy; original untouched).

create_lineA

Create a <line> from (x1, y1) to (x2, y2).

When to use: a single straight segment. For a multi-segment open run use create_polyline; for a closed shape use create_polygon.

Key params: endpoints (x1, y1) / (x2, y2); inserted into parent_id (must exist) or the document default parent; object_id to pin the id. Optional stroke / stroke_width paint the segment in this call (a line is unfilled by nature, so no fill; validated like set_stroke; default None = unpainted).

Return shape: CreateResultobject_id (new id), analytic bbox (the segment's axis-aligned extent), plus the pipeline fields (operation_id, snapshot_id, changed, preview).

Example: create_line(doc_id, 0, 0, 100, 100, stroke="black", stroke_width="2")

Render and look before you trust this edit: render with render_preview (or live_render_view) and inspect the result before relying on it; restore_snapshot reverts it if it is wrong.

Risk class: medium (reversible write-new on the working copy; original untouched).

create_polygonA

Create a closed <polygon> from points (≥ 1 (x, y) pairs).

When to use: a closed many-sided shape (triangle, hexagon, ...). For an OPEN run use create_polyline; for curves use create_path.

Key params: points ≥ 1 (x, y) pairs; inserted into parent_id (must exist) or the document default parent; object_id to pin the id. Optional fill / stroke / stroke_width paint it in this call (validated like set_fill / set_stroke; default None = unpainted).

Return shape: CreateResultobject_id (new id), analytic bbox (extent of the points), plus the pipeline fields (operation_id, snapshot_id, changed, preview).

Example: create_polygon(doc_id, [(0, 0), (50, 0), (25, 40)], fill="#fc0")

Render and look before you trust this edit: render with render_preview (or live_render_view) and inspect the result before relying on it; restore_snapshot reverts it if it is wrong.

Risk class: medium (reversible write-new on the working copy; original untouched).

create_polylineA

Create an open <polyline> from points (≥ 1 (x, y) pairs).

When to use: a connected open run of segments. For a CLOSED shape use create_polygon; for a single segment use create_line; for curves use create_path.

Key params: points ≥ 1 (x, y) pairs; inserted into parent_id (must exist) or the document default parent; object_id to pin the id. Optional fill / stroke / stroke_width paint it in this call (validated like set_fill / set_stroke; default None = unpainted).

Return shape: CreateResultobject_id (new id), analytic bbox (extent of the points), plus the pipeline fields (operation_id, snapshot_id, changed, preview).

Example: create_polyline(doc_id, [(0, 0), (50, 20), (100, 0)], stroke="blue")

Render and look before you trust this edit: render with render_preview (or live_render_view) and inspect the result before relying on it; restore_snapshot reverts it if it is wrong.

Risk class: medium (reversible write-new on the working copy; original untouched).

create_pathA

Create a <path> with the validated d data string.

When to use: freeform / bezier / curve geometry from a d string. For simple primitives prefer create_rect / create_circle / create_polygon; to edit an existing path's geometry use the paths tools (simplify_path, combine_paths, ...).

Key params: d validated against a strict charset (digits, whitespace, ,, ., sign, exponent, SVG path command letters only) and length-bounded; geometry is NOT fully parsed; into parent_id (must exist) or the document default parent. Optional fill / stroke / stroke_width paint it in this call (validated like set_fill / set_stroke; default None = unpainted).

Return shape: CreateResultobject_id (new id), bbox=None (paths are not analytically measured), plus the pipeline fields (operation_id, snapshot_id, changed, preview).

Example: create_path(doc_id, "M0 0 L100 0 L50 80 Z", fill="#222")

Render and look before you trust this edit: render with render_preview (or live_render_view) and inspect the result before relying on it; restore_snapshot reverts it if it is wrong.

Risk class: medium (reversible write-new on the working copy; original untouched).

create_textA

Create a <text> element anchored at (x, y) holding text.

When to use: adding a new label / caption. To change EXISTING text content use replace_text; to restyle its font use set_font.

Key params: text is length-bounded and rejects control characters other than tab / newline / carriage return (stored as a text node, no markup injection); inserted into parent_id (must exist) or the document default parent. Optional fill / stroke / stroke_width paint the glyphs in this call (validated like set_fill / set_stroke; default None = unpainted). For font family/size/weight use set_font.

Return shape: CreateResultobject_id (new id), bbox=None (text is not analytically measured), plus the pipeline fields (operation_id, snapshot_id, changed, preview).

Example: create_text(doc_id, 20, 40, "Hello", fill="#111")

Render and look before you trust this edit: render with render_preview (or live_render_view) and inspect the result before relying on it; restore_snapshot reverts it if it is wrong.

Risk class: medium (reversible write-new on the working copy; original untouched).

add_linear_gradientA

Add a <linearGradient> to the document <defs> (created if absent).

When to use: defining a directional colour fade to paint with. For a centred/radial fade use add_radial_gradient; after defining, apply it via set_fill(doc_id, ids, "url(#grad-id)").

Key params: stops is a list of {offset, color, opacity?} (≥ 1): offset a 0..1 number or 0%..100% percentage, color a validated colour, optional opacity in [0, 1]. The vector runs (x1, y1) -> (x2, y2) (numbers or percentages; default a left-to-right sweep).

Return shape: CreateResultobject_id is the gradient id (use as url(#id) paint), bbox=None (a def, not a drawn shape), plus the pipeline fields.

Example: add_linear_gradient(doc_id, [{"offset": 0, "color": "#fff"}, {"offset": 1, "color": "#3366cc"}])

Render and look before you trust this edit: render with render_preview (or live_render_view) and inspect the result before relying on it; restore_snapshot reverts it if it is wrong.

Risk class: medium (reversible write-new on the working copy; original untouched).

add_radial_gradientA

Add a <radialGradient> to the document <defs> (created if absent).

When to use: defining a centred/radial colour fade to paint with. For a directional fade use add_linear_gradient; after defining, apply via set_fill(doc_id, ids, "url(#gradient-id)").

Key params: stops is a list of {offset, color, opacity?} (≥ 1), as for the linear gradient. Centred at (cx, cy) with radius r (numbers or percentages; default a centred 50% circle); fx / fy optionally set the focal point.

Return shape: CreateResultobject_id is the gradient id (use as url(#id) paint), bbox=None, plus the pipeline fields.

Example: add_radial_gradient(doc_id, [{"offset": 0, "color": "#fff"}, {"offset": 1, "color": "#000"}])

Render and look before you trust this edit: render with render_preview (or live_render_view) and inspect the result before relying on it; restore_snapshot reverts it if it is wrong.

Risk class: medium (reversible write-new on the working copy; original untouched).

create_groupA

Create an empty <g> group inside parent_id (must exist) or the document default parent.

When to use: making an EMPTY group to populate later. To wrap EXISTING objects in a new group use group_objects; to move one object into an existing group use reparent_object.

Key params: parent_id (must exist) or the document default parent; object_id to pin the id.

Return shape: CreateResultobject_id is the new group id, bbox=None (empty), plus the pipeline fields (operation_id, snapshot_id, changed, preview).

Example: create_group(doc_id)

Render and look before you trust this edit: render with render_preview (or live_render_view) and inspect the result before relying on it; restore_snapshot reverts it if it is wrong.

Risk class: medium (reversible write-new on the working copy; original untouched).

group_objectsA

Wrap existing objects (object_ids, ≥ 1, all must exist) in a NEW <g>.

When to use: collecting several existing objects under one group. For an EMPTY group use create_group; to move a single object into an existing group use reparent_object.

Key params: object_ids ≥ 1, all must exist; object_id to pin the new group id. The objects keep their own transforms / styles; only their parent changes.

Return shape: CreateResultobject_id is the new group id (inserted at the position of the first target), bbox=None, plus the pipeline fields.

Example: group_objects(doc_id, ["icon", "label"])

Render and look before you trust this edit: render with render_preview (or live_render_view) and inspect the result before relying on it; restore_snapshot reverts it if it is wrong.

Risk class: medium (reversible write-new on the working copy; original untouched).

reparent_objectA

Move an object (object_id) under a new parent (new_parent_id); both must exist.

When to use: re-nesting one existing object into another group. To wrap SEVERAL objects in a new group use group_objects; to reposition without re-nesting use move_object.

Key params: object_id and new_parent_id both must exist; rejected if the new parent is the object itself or one of its descendants. NOTE: re-parenting changes the inherited coordinate space — the object's visual position can shift if old/new parents carry different transforms.

Return shape: CreateResultobject_id echoes the moved object, bbox=None, plus the pipeline fields (operation_id, snapshot_id, changed, preview).

Example: reparent_object(doc_id, "star", "layer2")

Render and look before you trust this edit: render with render_preview (or live_render_view) and inspect the result before relying on it; restore_snapshot reverts it if it is wrong.

Risk class: medium (reversible edit on the working copy; original untouched).

create_useA

Create a <use href="#href_id"> referencing an existing same-document object.

When to use: instancing / cloning an existing element so edits to the original propagate. To deep-COPY (independent) use duplicate_object; to grid-repeat use tile.

Key params: href_id MUST name an existing element (safe-id charset, required to exist); external / javascript: / url(...) references are rejected — only a same-document #id. Into parent_id (must exist) or the document default parent. Placement (translate-scaling trap): <use> applies x / y as a translation BEFORE its transform, so scale(2) + x="10" shifts by 20 — prefer EITHER x / y alone OR fold the translation into transform (e.g. translate(10,0) scale(2)); do not mix x / y with a scaling transform.

Return shape: CreateResultobject_id is the new <use> id, bbox=None, plus the pipeline fields (operation_id, snapshot_id, changed, preview).

Example: create_use(doc_id, "logo", x=200, y=0)

Render and look before you trust this edit: render with render_preview (or live_render_view) and inspect the result before relying on it; restore_snapshot reverts it if it is wrong.

Risk class: medium (reversible write-new on the working copy; original untouched).

how_do_iA

Map a natural-language goal to the concrete inkscape-mcp tool(s) that achieve it.

When to use: when you know what you want in words but not which typed tool does it. To browse the whole map at once read the intents section of list_capabilities; to then resolve an object id for an id-taking edit use find_objects. Guidance only — not a portmanteau or raw tool (ADR-002/003); it executes nothing.

Key params: goal is a natural-language description, e.g. "draw a rectangle", "make my svg smaller for web", "find the red shapes", "export a png".

Return shape: HowDoIResult — exactly one of: an in-scope hit (out_of_scope=False, matches best-first, each {goal_pattern, tools, how_to, group}); an out-of-scope goal (edit a JPEG/photo's pixels, run an arbitrary Action/extension/script, fetch from a URL, execute code) → out_of_scope=True, empty matches, note naming WHY (vector-only / ADR-003 / no-network / no-exec); or no match → out_of_scope=False, empty matches, note suggesting list_capabilities / inspect_document.

Example: how_do_i("make my svg smaller for web")

Risk class: low (read-only guidance; no snapshot / Operation Record).

open_documentA

Open an SVG into a tracked workspace document and return its id + summary.

When to use: the entry point for working on an EXISTING file — you need the doc_id before any other tool. To start from nothing use create_document; to adopt agent-composed SVG use set_document_svg / insert_svg_fragment; to resync external edits use reload_document.

Key params: path may be workspace-RELATIVE (anchored to the first workspace root, NOT the server CWD — matching save_document_as / live_sync_to_workspace) or absolute; either is sandbox-validated and a ../-escape, an absolute path outside the workspace, or a symlink whose target leaves the sandbox is rejected with path rejected: outside workspace. WORKING-COPY MODEL: opening copies your source SVG byte-for-byte into a per-document workspace as an immutable original.svg and seeds a single live WORKING COPY. The returned doc_id addresses that copy; EVERY subsequent tool operates on it, and your ORIGINAL is NEVER mutated. Edits are reversible (pre-edit snapshot + Operation Record); restore_snapshot rolls back.

Return shape: OpenDocumentResultdoc_id (opaque, pass to every other tool) and summary (size, viewBox, units, counts).

Example: open_document("logo.svg")

Risk class: low (opens via working copy; original never mutated).

create_documentA

Create a blank, tracked working-copy document from scratch — NO source file required.

When to use: starting fresh authoring with the create_* / compose tools when there is no SVG to open. To open an EXISTING file use open_document; to set the whole SVG body afterwards use set_document_svg.

Key params: width / height are the page size in user units (both > 0). viewBox is an optional explicit "minx miny w h" box (a 0 0 width height box is synthesized when omitted, so the document is never viewBox-less). background is an optional validated colour (hex / rgb() / hsl() / named keyword — never CSS-injectable) painted as a full-page rect; omit for a transparent page. The generated document is validate_document-clean.

Return shape: OpenDocumentResult (same as open_document) — doc_id (addresses a fully tracked working copy: snapshots, reversibility, reload) and summary.

Example: create_document(800, 600, background="#ffffff")

Risk class: medium (creates a new tracked document; no existing state mutated).

reload_documentA

Refresh a working copy FROM ITS SOURCE under the SAME doc_id, discarding working edits.

When to use: external edits changed the source file and you want to resync in place (keep the same doc_id). To undo a single edit instead use restore_snapshot; to open a different file use open_document.

Key params: doc_id must be open. Flow (reversible): take a PRE-reload snapshot of the current working copy (undo via restore_snapshot), re-resolve the source through the sandbox and re-validate it is STILL inside the workspace (a moved/vanished source is rejected with a stable "path rejected" message), then re-copy the source over the working copy. A create_document document has no external source, so its reload restores from its blank seed.

Return shape: ReloadDocumentResult — refreshed summary plus pre_reload_snapshot_id (the pre-reload checkpoint).

Example: reload_document(doc_id)

Risk class: low (only the working copy is rewritten, reversibly; the original is never written).

inspect_documentA

Inspect a loaded document: tree, layers, styles, fonts, external assets.

When to use: the go-to overview to understand a document's structure AND discover targetable object ids before editing. To search for SPECIFIC objects by filter use find_objects; for quality metrics use quality_report; for well-formedness use validate_document.

Key params: doc_id only (read-only).

Return shape: InspectDocumentResultsummary, tree, layers, styles, fonts, assets, and objects (flat list of every id-bearing object with tag / bbox / paint / text, the same ObjectRef shape find_objects returns).

Example: inspect_document(doc_id)

Risk class: low (read-only, direct DOM per ADR-005).

delete_objectA

Delete objects by id from a document in ONE reversible, snapshot-backed operation.

When to use: dropping one or more existing elements (e.g. stray seed paths) without a Read + set_document_svg full-document rebuild. Get ids from find_objects / inspect_document. To MOVE an object into another group use reparent_object; to rename rather than remove use rename_object.

Key params: object_ids is a non-empty list of ids to remove; an id that is not present is silently skipped (deleting an already-absent object is a successful no-op, not an error). The document root cannot be deleted. Because deletion is HIGH risk, a real removal requires a non-empty approval_token (minted out of band, bound to this one operation); without it the policy gate refuses the op and nothing is written.

Return shape: DeleteResult — all EditResult fields (operation_id, snapshot_id, changed, before/after preview; the edit lands on the working copy only, reversible via restore_snapshot) PLUS affected_ids, the ids that were actually removed. When NONE of the ids existed the call is a genuine no-op: changed=False, empty operation_id/snapshot_id, and affected_ids=[] (no snapshot or Operation Record written).

Example: delete_object(doc_id, ["seed1", "seed2"], approval_token="…")

Render and look before you trust this edit: render with render_preview (or live_render_view) and inspect the result before relying on it; restore_snapshot reverts it if it is wrong.

Risk class: high (delete; approval-gated, reversible via pre-op snapshot — original untouched).

render_previewA

Render a PNG preview of the whole document into the artifacts dir.

When to use: a quick visual check of the whole document. For a final file use `export_document`;
for one object use `export_object`; for an ordered run series use `capture_frame`.

Key params: `width_px` scales the raster (height follows the document aspect ratio); omit for
intrinsic size. Oversized requests are rejected before Inkscape runs. `name` tags the file
(successive calls do NOT clobber, — each render gets a unique frame name). INLINE RASTER

: by default the PNG is also returned as an MCP image block so the agent SEES it without a second Read; gated by max_output_bytes (~5 MiB default) and skipped for an oversized render; inline=False returns only the structured result.

Return shape: `PreviewResult` — `artifact_path` / `workspace_relative_path` (same root-relative
value), `format`, `width_px`/`height_px` (TRUE on-disk size), `stale`. With an inline
image, a `ToolResult` carrying the same structured fields plus the image block.

Example: `render_preview(doc_id, width_px=512)`

Risk class: low (render/export to artifact dir; no original overwrite).
capture_frameA

Capture the next numbered PNG screenshot in a per-run frame series.

When to use: documenting a scripted edit sequence step-by-step. For a one-off check use
`render_preview`; to gather a finished series use `list_frames`.

Key params: `series` (sanitized; defaults to `run`) groups frames into a folder under
`artifacts/frames/<series>/`; the index is derived from the filesystem (highest existing
`frame-NNN` + 1) — monotonic, survives a restart, never clobbers. `label` is folded into the
frame name. Renders the whole canvas exactly like `render_preview` (no UI chrome). INLINE RASTER

: the PNG is returned inline by default (gated by max_output_bytes); inline=False returns only the structured result.

Return shape: `FrameResult` — `artifact_path` / `workspace_relative_path` (same value),
`format`, `width_px`/`height_px`, `series`, `frame_index` (1-based), `stale`. With an inline
image, a `ToolResult` carrying the same fields plus the image block.

Example: `capture_frame(doc_id, series="cleanup", label="after-simplify")`

Risk class: low (render to the managed artifacts dir; no original overwrite, no Operation
Record).
list_framesA

List the frames of a capture_frame series, ordered by index.

When to use: gathering a whole run's PNGs at the end without re-deriving paths. To produce frames use capture_frame.

Key params: series is sanitized identically to capture_frame (defaults to run).

Return shape: FrameListResultdoc_id, series, and frames (each a FrameInfo with frame_index + a resolvable workspace_relative_path), ordered by index; empty when the series has no frames yet.

Example: list_frames(doc_id, series="cleanup")

Risk class: low (read-only listing of the managed artifacts dir).

export_documentA

Export the whole document to PNG, PDF, or SVG.

When to use: producing a final file of the whole document. For one object use export_object; for many sizes/formats at once use export_batch; for a web/print bundle use the profile tools.

Key params: format is one of "png"/"pdf"/"svg" (others rejected). PNG honors width_px (pixel-capped before Inkscape runs); PDF/SVG are vector and ignore it. out_dir writes into a caller-chosen dir — a relative out_dir anchors to the workspace ROOT and is sandbox-checked (out-of-workspace is rejected with "path rejected: outside workspace"); name_prefix tags the filename. INLINE RASTER: a PNG is returned inline by default (gated by max_output_bytes); PDF/SVG are never embedded; inline=False opts out.

Return shape: ExportResultartifact_path / workspace_relative_path (same value), format, width_px/height_px (TRUE size for PNG, None for vector), stale. With an inline image, a ToolResult carrying the same fields plus the image block.

Example: export_document(doc_id, "png", width_px=1024)

Risk class: low (render/export to a sandbox-checked dir; no original overwrite).

export_objectA

Export a single object (by id) to PNG, PDF, or SVG.

When to use: exporting one object, clipped to its own bbox (get the id from find_objects). For the whole document use export_document; for many at once use export_batch.

Key params: object_id must exist and match the safe SVG-id charset (else rejected before it reaches Inkscape). format is one of "png"/"pdf"/"svg". out_dir writes into a caller-chosen dir — a relative out_dir anchors to the workspace ROOT and is sandbox-checked (out-of-workspace is rejected with "path rejected: outside workspace"); name_prefix tags the filename. INLINE RASTER: a PNG is returned inline by default (gated by max_output_bytes); PDF/SVG never embedded; inline=False opts out.

Return shape: ExportResultartifact_path / workspace_relative_path (same value), format, width_px/height_px (TRUE size for PNG, None for vector), stale. With an inline image, a ToolResult carrying the same fields plus the image block.

Example: export_object(doc_id, "logo", "svg")

Risk class: low (render/export to a sandbox-checked dir; no original overwrite).

export_batchA

Run a bounded batch of typed export specs in one call (dry-run by default).

When to use: exporting many sizes/formats/objects in one call. For a single export use export_document / export_object; for a standard icon set use create_icon_set.

Key params: specs is a typed list (each: format png/pdf/svg, optional width_px, optional object_id for a single object). Bounded: at most a fixed number of specs per call and a total-output byte budget (byte_budget, default: the per-document artifact budget). dry_run=True (DEFAULT) validates and returns the plan + projected sizes + within_budget, writing nothing; dry_run=False refuses cleanly if the projection exceeds the budget. out_dir writes into a caller-chosen dir — relative anchors to the workspace ROOT, sandbox-checked (out-of-workspace rejected "path rejected: outside workspace"); name_prefix tags each file.

Return shape: BatchResultitem_count, per-item entries (each with a workspace_relative_path on a real run), projected/actual total size, and within_budget.

Example: export_batch(doc_id, [{"format": "png", "width_px": 256}], dry_run=False)

Risk class: low (artifact-only export to a sandbox-checked dir; composes the engine).

export_setA

Batch-export a SET of documents in one call: per-doc results + aggregate + verdict.

When to use: exporting a whole multi-document system (e.g. a 12-icon set) at the same sizes / formats in one call, with the set's total byte footprint and a cross-doc consistency check. For a SINGLE document use export_batch; for an icon set from one doc use create_icon_set.

Key params: doc_ids is a non-empty, duplicate-free set; specs is the SAME typed ExportSpec list export_batch takes (applied to EVERY document). dry_run / byte_budget / out_dir / name_prefix behave exactly as on export_batch (composed, not reimplemented), per document; a name_prefix is recommended with out_dir so the per-doc files do not collide. The whole set is rejected if ANY document's export_batch fails (no partial result).

Return shape: ExportSetResultper_doc (each {doc_id, result} with the standard BatchResult), total_items and total_bytes aggregated across the set (projected on a dry run, actual on a real run), and consistency — the structured cross-doc verdict over the set's viewBox / stroke-width / id-naming conventions (per property: agree/disagree + the differing values + which doc_ids differ).

Example: export_set(["d1","d2","d3"], [{"format": "png", "width_px": 64}], dry_run=False, out_dir="dist", name_prefix="icon")

Risk class: low (artifact-only export to a sandbox-checked dir; composes the per-doc engine).

find_objectsA

Find addressable object ids in a tracked document by tag / paint / text / id-prefix / bbox.

When to use: before an id-taking edit (set_fill, move_object, replace_text, rotate_object, …) on a document the agent did not author, or to enumerate "every blue rect", "every text mentioning 'Total'", etc. For the full structural picture (tree / layers / styles / fonts / assets) plus the same list use inspect_document; to map a goal to a tool, how_do_i.

Key params (all filters optional; supplied filters AND together; none → every addressable object): tag exact local name ("rect"/"text"/"path"); fill/stroke a paint matched casing- and hex-shorthand-insensitive ("#FFF" matches "#ffffff") — matching resolves the FULL CSS cascade so an object painted via a <style> rule / class / id selector or INHERITED from an ancestor <g> is matched too (the reported fill/stroke stay the per-element authored token); text a case-insensitive substring of text content; id_prefix an id prefix; bbox an {x, y, width, height} box kept on INTERSECTION. By default bbox uses the attribute-derived box and objects with no derivable box (path/text/group/transformed) are EXCLUDED; set accurate_bbox=true to compute geometry-accurate, transform-/outline-aware boxes via one batched Inkscape --query-all call (so those objects can match) — it degrades to the attribute box when the Inkscape engine is unavailable.

Return shape: FindResult{doc_id, count, objects: [{object_id, tag, bbox?, fill?, stroke?, text?}]}. Objects without an id are never returned (they cannot be targeted). With accurate_bbox=true, bbox carries the engine box where one was reported.

Example: find_objects("d_ab12", tag="rect", fill="#3366cc")

Risk class: low for the default direct-DOM path (read-only, ADR-005; no snapshot / Operation Record); accurate_bbox=true adds a read-only Inkscape --query-all invocation (medium, still no mutation).

check_live_supportA

Report which live transports are available on this host (read-only; no connection).

When to use: checking live readiness before live_connect. To install the socket helper use live_install_helper; for the full runtime matrix use list_capabilities.

Key params: none. Probes the extension-socket bridge (any OS) and the DBus fast-path (Linux/BSD) independently — never assuming one by OS. Safe regardless of whether live mode is enabled or a session is running.

Return shape: LiveSupportlive_enabled, any_available, best_transport, helper_installed, per-transport transports probes (best-first), and notes.

Example: check_live_support()

Risk class: low (read-only probe).

live_connectA

Connect to a running Inkscape over the best-ranked available transport (enables live).

When to use: starting a live session before any other live_* tool. To probe first use check_live_support; to tear down use live_disconnect.

Key params: prefer selects the profile. read (default) is the best READ-capable transport (extension-socket primary; full selection/inspect surface) but is MODAL on the socket bridge — the GUI freezes for the session. no_freeze drives the GUI WITHOUT freezing (Linux DBus path): the export-based active-doc read, live_render_view, live_set_viewport, and live_apply_to_selection are no-freeze; selection-id reads (live_get_selection / live_inspect_selection) and live_insert_svg / live_set_selected_text are NOT available over DBus and stay modal. Requires the master gate (INKSCAPE_MCP_LIVE_ENABLED). With no transport available it fails cleanly without affecting headless tools.

Return shape: LiveSession — the chosen transport, active document, and connection state.

Example: live_connect(prefer="no_freeze")

Risk class: medium (establishes a transport; read-only thereafter).

live_disconnectA

Disconnect the current live session (the X1 disable switch). Idempotent.

When to use: ending a live session (or as a hard kill switch). To start one use live_connect; to check state use live_status.

Key params: none. Idempotent — safe to call with no session.

Return shape: LiveSession — the now-disconnected session state.

Example: live_disconnect()

Risk class: low (tears down the transport; no document mutation).

live_statusA

Report live-session state: enabled, connected, active transport, available transports.

When to use: checking whether a session is live before issuing live tools. For per-host transport detail use check_live_support.

Key params: none. Never raises — reports "not connected" / "none available" cleanly.

Return shape: LiveSessionenabled, connected, active transport, available transports.

Example: live_status()

Risk class: low (read-only).

live_install_helperA

Install the shipped extension-socket helper into the Inkscape user extensions dir.

When to use: one-time setup so a running Inkscape can expose the socket bridge. After install, probe with check_live_support then live_connect.

Key params: none. Copies the fixed-purpose helper (inkscape_mcp_live.py + .inx). Requires the master gate (live is opt-in). Touches no workspace document.

Return shape: HelperInstallResultinstalled_files and extensions_dir (presented ~-relative, never an absolute host path/L5).

Example: live_install_helper()

Risk class: restricted (writes a server-bundled file under the Inkscape extensions dir).

live_arm_socketA

Auto-arm the extension-socket helper so a programmatic launch gets the FULL live surface.

When to use: bringing up the FULL perceive/compose live command set without a human Extensions-menu click — a programmatic launch otherwise yields only DBus's reduced action set. After this returns armed, call live_connect (the socket bridge is then the best transport). To install the helper files first use live_install_helper; to probe readiness use check_live_support.

Key params: none. Installs the helper if absent, then LAUNCHES a headful Inkscape with the helper effect auto-invoked so it binds its loopback socket and advertises a rendezvous — no menu click. The socket bridge is the cross-platform primary (NOT bound to one OS). Requires the master live gate. GUI-ONLY: the headful launch needs a display; on a HEADLESS host (CI / box, no DISPLAY/WAYLAND_DISPLAY) it fails with a clear, stable message (this leg is documented as deferred there) rather than spawning a doomed process. An already-armed session is reused.

Return shape: SocketArmResultarmed, launched (whether THIS call started Inkscape), helper_installed, transport, and notes. No host path is carried (sec.12).

Example: live_arm_socket() then live_connect()

Risk class: restricted (launches a headful Inkscape process and writes a server-bundled helper).

live_get_active_documentA

Identify the document open in the connected live instance (read-only).

When to use: confirming WHICH document the live GUI has open. For its full scene use live_get_scene; for the current selection use live_get_selection.

Key params: none. Requires an established session (live_connect).

Return shape: LiveDocumentRef — the active live document's identity.

Example: live_get_active_document()

Risk class: low (read-only over an established live session).

live_get_selectionA

Read the current selection in the live instance as object ids (read-only).

When to use: getting the ids the user selected in the GUI. For their semantic detail use live_inspect_selection; for the whole scene use live_get_scene. Not available over DBus (no_freeze) — stays on the modal socket transport.

Key params: none. Requires an established session (live_connect).

Return shape: LiveSelectioncount plus the selected object ids.

Example: live_get_selection()

Risk class: low (read-only).

live_inspect_selectionA

Inspect the selected objects in the live instance (semantic, by id; read-only).

When to use: getting structured detail (not just ids) of the GUI selection. For ids only use live_get_selection; for the whole scene use live_get_scene. Not available over DBus (no_freeze) — stays on the modal socket transport.

Key params: none. Requires an established session (live_connect).

Return shape: LiveSelectionInspectioncount plus per-object inspection (the headless object-inspection shape).

Example: live_inspect_selection()

Risk class: low (read-only).

live_render_viewA

Rasterize the live canvas to a PNG in the live artifacts dir (visual feedback).

When to use: a pixels-only view of the live canvas. For pixels PLUS structured scene use live_get_scene; for just the selection use live_export_selection.

Key params: with no region the whole canvas renders. Supply ALL four of region_x/region_y/region_width/region_height (user units; w/h > 0) for a targeted bbox, and optional scale (>0) to up/downscale. fast=True gives a cheap downscaled loop-preview; an explicit scale always wins. Every numeric is finite-checked and bounded server-side before it crosses the transport; the frame comes from the transport renderer, never an OS screenshot (deterministic, cross-platform — ADR-006). Served from a per-session cache keyed on (doc_revision, viewport, scale) so a stale frame is never returned after a change.

Return shape: LiveRenderResult — a workspace-relative PNG path plus render metadata.

Example: live_render_view(fast=True)

Risk class: low (render to artifact dir; view-only, no Operation Record).

live_get_sceneA

Capture one live frame as a PNG PLUS a structured, machine-readable LiveScene.

When to use: the core perception step — the agent reasons over STRUCTURE, not pixels. For pixels-only use live_render_view; for one loop iteration use live_session_step.

Key params: region/scale/fast work exactly as live_render_view (all four region parts at once, user units, w/h > 0; optional scale > 0; fast=True for the downscaled loop preview, explicit scale wins). Frame rendered through the transport, never an OS screenshot (deterministic, cross-platform — ADR-006); served from the per-session cache keyed on (doc_revision, viewport, scale). Scene pulled over the fixed get_scene command — no code or raw Action path (ADR-003). Requires an established session. READ-ONLY (no Operation Record, no approval).

Return shape: LiveSceneFramerender (the PNG) plus scene: a LiveScene carrying the active-document identity, selection (ids + bboxes), viewport (zoom/center/visible region), the canvas size, and a visible-object summary.

Example: live_get_scene(fast=True)

Risk class: low (read-only perception; no document mutation, no Operation Record).

live_wait_for_changeA

Block until the live state changes, or the bounded timeout elapses (read-only).

When to use: between live_session_step iterations so the loop reacts to the user's own GUI edits instead of busy-rendering. To then re-perceive use live_get_scene.

Key params: timeout_s is clamped to at most 60s and poll_interval_s is floored, so the wait never spins tightly nor blocks forever (it sleeps between cheap polls). Each poll pulls a CHEAP state token (small revision marker + selection ids + coarse viewport — never the full doc or a PNG; protocol v5), hashed + diffed against the last token. Requires a session; no code/raw-Action path (ADR-003). NOTE: the socket helper runs on a snapshot, so within one call it cannot observe later GUI edits; the token mechanism is transport-agnostic and detects user edits on any transport that recomputes per poll.

Return shape: LiveChangechanged, timed_out, and the delta flags selection_changed / document_changed / viewport_changed (more than one may fire).

Example: live_wait_for_change(timeout_s=10)

Risk class: low (read-only polling; no document mutation, no Operation Record).

live_set_viewportA

Control the live canvas viewport: zoom / pan / fit-to-selection / fit-to-page.

When to use: framing the canvas before a render/capture. To then render use live_render_view; to edit (not just view) use live_apply_to_selection.

Key params: mode is one of the fixed verbs zoom | pan | fit_selection | fit_page (no raw Action or code path — ADR-003). zoom takes a positive zoom and optional center_x/center_y to recentre; pan takes both dx and dy (a delta in user units); fit_selection/fit_page take no numerics. Every numeric is finite-checked and bounded server-side before it crosses the transport (sec.12). Requires a session. VIEW-ONLY (no Operation Record, no approval).

Return shape: LiveViewportResult — the applied viewport state.

Example: live_set_viewport("zoom", zoom=2.0)

Risk class: low (view-only; no document mutation, no Operation Record).

live_sync_to_workspaceA

Save the live document's current state into the workspace as a NEW tracked document.

When to use: capturing live work into the headless workspace so the typed tools can act on it. For pixels-only feedback use live_render_view; to save a HEADLESS doc to disk use save_document_as.

Key params: dest_path is the new workspace file; RELATIVE anchors to the first workspace root (NOT the server CWD) and a not-yet-existing SUBFOLDER is created in-sandbox first (matching save_document_as; a ..-escaping / out-of-sandbox dest creates nothing and is rejected with path rejected: outside workspace). Reads the live SVG and writes it through the policy layer (sandbox + symlink guard), registers it (working copy), and records an Operation Record + snapshot (ADR-004). An existing destination is REFUSED — sync never overwrites, so a live fault cannot damage a workspace file. Requires an established session.

Return shape: LiveSyncResult — the new doc_id, operation_id, and snapshot links.

Example: live_sync_to_workspace("from-live.svg")

Risk class: medium (writes a new workspace document, reversible + recorded).

live_apply_to_selectionA

Apply a validated style and/or simple transform to the current live selection.

When to use: editing the GUI selection's style/transform live. To insert markup use live_insert_svg; to edit text use live_set_selected_text; for headless edits use set_fill / move_object / etc.

Key params: reuses the headless safe-edit semantics — fill/stroke colour-validated, stroke_width a CSS length, opacity in [0, 1], transform composed from dx/dy (both required together), scale (positive), rotate (degrees); at least one input required. Semantic-only — no arbitrary code, no raw Action (ADR-003). Mutating a running user session is HIGH risk: REQUIRES an explicit approval_token (refused without one).

Return shape: LiveEditResult — a Live Operation Record with before/after canvas renders, syncable to a snapshot via live_sync_to_workspace.

Example: live_apply_to_selection(approval_token="ok", fill="#3366cc")

Risk class: high (approval-gated).

live_insert_svgA

Insert an SVG fragment into the running document.

When to use: grafting composed markup into the live document. To style the selection use live_apply_to_selection; for the headless equivalent use insert_svg_fragment.

Key params: svg_fragment is parsed through the normative safe parser (no entities, no external DTD, no network) and size-bounded before it crosses the transport — only well-formed, safe markup is inserted; no code path (ADR-003). Inserting into a running user session is HIGH risk: REQUIRES an explicit approval_token (refused without one).

Return shape: LiveEditResult — a Live Operation Record with before/after canvas renders, syncable to a snapshot.

Example: live_insert_svg("<rect .../>", approval_token="ok")

Risk class: high (approval-gated).

live_set_selected_textA

Replace the selected text object's content in the running document.

When to use: changing the selected text object's words live. To restyle the selection use live_apply_to_selection; for the headless equivalent use replace_text.

Key params: text is length-bounded and control-character-rejected (the same guard as the headless replace_text); it is stored as a text node, so no markup injection is possible. Editing a running user session is HIGH risk: REQUIRES an explicit approval_token (refused without one).

Return shape: LiveEditResult — a Live Operation Record with before/after canvas renders, syncable to a snapshot.

Example: live_set_selected_text("Hello", approval_token="ok")

Risk class: high (approval-gated).

live_export_selectionA

Export just the current live selection to a PNG under the live artifacts dir.

When to use: a PNG of only the GUI selection. For the whole canvas use live_render_view; for pixels plus structure use live_get_scene.

Key params: none. Read-only feedback (no mutation, no approval, no Operation Record), mirroring live_render_view. Requires an established session.

Return shape: LiveExportResult — a workspace-relative PNG path under the live artifacts dir.

Example: live_export_selection()

Risk class: low (render to artifact dir).

live_diff_viewA

Produce a FOCUSED, annotated before/after visual diff of a live operation.

When to use: visualizing what one live mutation changed. To produce a mutation to diff use live_apply_to_selection / live_insert_svg / live_set_selected_text (or live_session_step, which calls this internally).

Key params: operation_id names the Live Operation Record. The tool REUSES the before/after frames the mutation already captured (run_live_mutation persists preview_before / preview_after), pixel-diffs them to a CHANGED-REGION bbox, and emits ONE annotated overlay highlighting it plus the current selection outline (best-effort when a session is connected). Frames are resolved VIA the operation_id (never a raw client path) and sandbox-validated under the live artifacts dir before any bytes are read. Identical-dimension frames required; a size mismatch is a stable error. ARTIFACT-ONLY — no mutation, no Operation Record routing, no approval, no network.

Return shape: LiveDiffResult — a workspace-relative overlay PNG path, the operation_id, the pixel-space changed_bbox (null when the frames are identical), and highlighted_ids; the diff path is linked back onto the record's diff_artifacts.

Example: live_diff_view(operation_id)

Risk class: low (artifact-only; reads + annotates two existing frames, no mutation, no record).

live_session_stepA

Run ONE perceive→decide→act→observe iteration of the live-view loop.

When to use: the flagship loop step — call it repeatedly to drive a live edit loop (use live_wait_for_change between steps to react to the user's edits). It COMPOSES the existing live tools (ADR-006); for a single standalone edit call live_apply_to_selection / live_insert_svg / live_set_selected_text directly. Each call is one bounded iteration — no server-side autonomous run.

Key params: action is the AGENT's decision (this tool embeds no LLM), one of the FIXED set apply | insert_svg | set_text (no raw-Action/code path — ADR-002/003; an out-of-enum action is rejected). OMIT action for a PERCEIVE-ONLY step (mutates nothing, no Operation Record). When acting: apply takes fill/stroke/stroke_width/opacity and/or dx/dy/scale/rotate; insert_svg takes a safe-parsed svg_fragment; set_text takes a control-char-checked text. The act runs through run_live_mutation (the SAME path as the standalone tools); mutating a running session is HIGH risk and REQUIRES an explicit approval_token. Requires a session.

Return shape: LiveSessionStepResult — always the PERCEIVE scene + frame; after an act also the operation_id, a focused live_diff_view artifact, and the after scene/frame.

Example: live_session_step(action="apply", approval_token="ok", fill="#3366cc")

Risk class: high when it acts (routes through run_live_mutation — HIGH + approval); low when perceive-only (read-only; no mutation, no Operation Record).

svg_web_optimizeA

Web-optimize an SVG: strip editor metadata, drop dead structure, reduce coordinate precision.

When to use: losslessly shrinking an SVG for the web (direct-DOM, non-destructive). To inspect what WOULD be stripped first use quality_report; for lossy node reduction use simplify_path.

Key params: three reversible cleanups — (1) remove Inkscape/sodipodi editor-only elements, namespaced attributes, and XML comments; (2) drop unreferenced <defs>, every unreferenced id, and empty groups (referenced ids preserved so no #frag / url(#frag) / href breaks); (3) round geometry numbers (path d, transforms, x/y/width/…) to precision decimals (0-8, default 2; root viewBox untouched). keep_ids is an allowlist of ids that must NEVER be stripped as "unreferenced" — pass a deliberate human/a11y id (e.g. one from rename_object) to keep "one clean file with a stable id"; unknown ids are ignored. Re-running on optimized output removes/rounds nothing further.

Return shape: WebOptimizeResult — the reversible-edit fields (operation_id, snapshot_id, before/after preview) plus machine-diffable deltas bytes_before, bytes_after, and removed (a {code: count} map keyed IDENTICALLY to quality_report.opportunities), so an agent on a byte budget can compute the saving without parsing prose or stat-ing the file.

Example: svg_web_optimize(doc_id, precision=2, keep_ids=["header"])

Render and look before you trust this edit: render with render_preview (or live_render_view) and inspect the result before relying on it; restore_snapshot reverts it if it is wrong.

Risk class: medium.

optimize_setA

Web-optimize a SET of documents in one call: per-doc results + aggregate + verdict.

When to use: losslessly shrinking a whole multi-document system (e.g. a 12-icon set) in one call, reading the set's total byte saving and a cross-doc consistency check. For a SINGLE document use svg_web_optimize; to inspect the opportunities use quality_report_set.

Key params: doc_ids is a non-empty, duplicate-free set; precision / keep_ids are the SAME arguments svg_web_optimize takes (applied to EVERY document). Each document is optimized through the reversible pipeline, so a CHANGED document gets ONE pre-mutation snapshot + Operation Record (ADR-004) and a no-op writes none. The whole set is rejected if ANY document fails (no partial apply on the remainder is suppressed — earlier successful docs stay optimized and reversible via their snapshots).

Return shape: OptimizeSetResultper_doc (each {doc_id, result} with the standard WebOptimizeResult), total_bytes_before / total_bytes_after / total_bytes_saved aggregated across the set, changed_count, and consistency — the structured cross-doc verdict computed on the PRE-optimize state (per property: agree/disagree + the differing values + which doc_ids differ).

Example: optimize_set(["d1","d2","d3"], precision=2)

Render and look before you trust this edit: render with render_preview (or live_render_view) and inspect the result before relying on it; restore_snapshot reverts it if it is wrong.

Risk class: medium (each document optimized reversibly; one snapshot per changed doc).

export_web_profileA

Export a web-oriented asset set: a responsive PNG set plus one plain SVG.

When to use: producing a web-ready asset bundle. For a print PDF use export_print_profile; for a square icon set use create_icon_set; for a single export use export_document.

Key params: PNG widths resolve as — explicit widths (each a PNG); else density scales applied to width_px (e.g. [1,2,3] -> 1x/2x/3x); else width_px. Every PNG is pixel-capped before Inkscape runs and distinct on disk; responsive entries report their scale. out_dir writes the set into a caller-chosen dir so a dist/ tree assembles with no Bash cp — a relative out_dir anchors to the workspace ROOT and is sandbox-checked (out-of-workspace rejected "path rejected: outside workspace"); name_prefix tags each file.

Return shape: ProfileExportResultprofile, applied_settings, and ordered artifacts (ascending width, then one plain SVG last); each carries a workspace_relative_path plus content-truth fields (PNG: opaque_px/all_blank).

Example: export_web_profile(doc_id, scales=[1, 2, 3], out_dir="dist/web")

Risk class: low (export to a sandbox-checked dir; no original overwrite).

create_icon_setA

Export a multi-size square PNG icon set from the source document.

When to use: producing a standard square icon set in one call. For a responsive web bundle use export_web_profile; for arbitrary batch specs use export_batch.

Key params: sizes is the list of square px sizes (defaults to 16, 32, 48, 64, 128, 256). Each must be a positive integer no greater than the configured pixel cap; an out-of-range or non-positive size is rejected before Inkscape runs and no partial set is written. out_dir writes the set into a caller-chosen dir — a relative out_dir anchors to the workspace ROOT and is sandbox-checked (out-of-workspace rejected "path rejected: outside workspace"); name_prefix tags each file.

Return shape: ProfileExportResultprofile, applied_settings, and artifacts (each carries its requested_size_px, a workspace_relative_path, and content-truth opaque_px/all_blank).

Example: create_icon_set(doc_id, sizes=[16, 32, 64], out_dir="dist/icons")

Risk class: low (export to a sandbox-checked dir; no original overwrite).

export_print_profileA

Export a print-oriented PDF (vector, page area) of the whole document.

When to use: producing a press-safe PDF. For web assets use export_web_profile; for a plain (non-print) PDF/PNG/SVG use export_document.

Key params: applies real print-specific Inkscape settings (PDF version pinned to 1.4 + text outlined to paths) so output is press-safe and ALWAYS differs from a plain PDF export — even for text-free docs, since the plain export defaults to PDF 1.5 while this pins 1.4 (header %PDF-1.4, a deterministic byte difference). out_dir writes into a caller-chosen dir — a relative out_dir anchors to the workspace ROOT and is sandbox-checked (out-of-workspace rejected "path rejected: outside workspace"); name_prefix tags the file.

Return shape: ProfileExportResultprofile, the auditable applied_settings, and one PDF in artifacts with a workspace_relative_path plus content-truth is_vector / fonts_outlined (true vector when both hold).

Example: export_print_profile(doc_id, out_dir="dist/print")

Risk class: low (export to a sandbox-checked dir; no original overwrite).

quality_reportA

Build a machine-readable quality report for a document: validation findings plus metrics.

When to use: assessing a document's health and what optimizing would save. For pass/fail correctness only use validate_document; to actually strip the opportunities use svg_web_optimize.

Key params: none beyond doc_id.

Return shape: QualityReportok, the validate_document findings (missing fonts, external assets, large rasters, id problems, viewBox sanity), quantitative metrics (object/node/layer counts, embedded-raster weight in bytes, font coverage, viewBox health), and opportunities (keyed identically to svg_web_optimize.removed: editor metadata, unused defs, unreferenced ids, empty groups, reducible coordinate precision). Every field is structured (not prose).

Example: quality_report(doc_id)

Risk class: low (read-only; document unchanged).

quality_report_setA

Quality-report a SET of documents in one call: per-doc reports + aggregate + verdict.

When to use: auditing a whole multi-document system (e.g. a 12-icon set) for health AND cross-doc consistency in one read-only call. For a SINGLE document use quality_report; to actually strip the opportunities across the set use optimize_set.

Key params: doc_ids is a non-empty, duplicate-free set. Read-only — composes the single-doc quality_report engine over the set, so NO snapshot / Operation Record is written for any document. The whole set is rejected if ANY id is unknown or unparseable (no partial result).

Return shape: QualityReportSetResultper_doc (the standard QualityReport per document), all_ok, worst_score / mean_score and total_opportunities aggregated across the set, and consistency — the structured cross-doc verdict over the set's viewBox / stroke-width / id-naming conventions (the cross-doc audit a 12-icon system used to need a Bash/lxml loop for).

Example: quality_report_set(["d1","d2","d3"])

Risk class: low (read-only; no document mutated, no Operation Record / snapshot).

save_document_asA

Save a document's current working-copy state to a NEW file in the workspace.

When to use: persisting the working copy to disk. To export a raster/PDF instead use export_document; to snapshot in-server state (not a file) use create_snapshot. The original and source files are never touched.

Key params: dest_path may be RELATIVE or absolute — relative anchors to the FIRST configured workspace root (NOT the server CWD); absolute must resolve inside a configured root. A dest into a not-yet-existing SUBFOLDER (e.g. "output/final.svg") is supported: missing parents are created only after proving they resolve INSIDE the workspace (a ..-escaping / out-of-sandbox dest creates nothing and is rejected with path rejected: outside workspace). The dest is sandbox- and symlink-checked (incl. a pre-existing symlink at the final name) and the copy never follows a symlinked dest (sec.12). Overwriting an existing file requires overwrite=True PLUS a non-empty approval_token.

Return shape: SaveResultsaved_path (workspace-relative POSIX), operation_id, overwritten, and pre_validation / post_validation (the validate_document reports from before and after the write).

Example: save_document_as(doc_id, "output/final.svg")

Risk class: medium for a new-file save; high (approval-gated) when overwriting an existing file.

create_snapshotA

Snapshot the current working copy of a document and index it.

When to use: checkpointing before a risky edit so you can roll back. To browse checkpoints use list_snapshots; to roll back use restore_snapshot. (Mutating tools auto-snapshot; this is an explicit, manual checkpoint.)

Key params: optional label tags the snapshot (length-bounded; over the cap is rejected).

Return shape: SnapshotInfo — the new snapshot_id plus its metadata.

Example: create_snapshot(doc_id, label="before cleanup")

Risk class: low (write-new snapshot; original untouched).

list_snapshotsA

List a document's snapshots in order, with metadata.

When to use: choosing which checkpoint to roll back to. To make one use create_snapshot; to roll back use restore_snapshot.

Key params: none beyond doc_id.

Return shape: SnapshotListdoc_id plus snapshots (each a SnapshotInfo with its id + metadata), in order.

Example: list_snapshots(doc_id)

Risk class: low (read-only manifest).

restore_snapshotA

Revert a document's working copy to a chosen snapshot.

When to use: undoing/rolling back to an earlier checkpoint. To find a snapshot_id use list_snapshots; to make a new checkpoint use create_snapshot.

Key params: snapshot_id names the target checkpoint (must exist for this document).

Return shape: RestoreResult — the reversibility-chain links plus restored_sha256 (SHA-256 hex digest) and restored_size_bytes of the restored working copy, so a caller can assert recovery succeeded without reading the document off disk.

Example: restore_snapshot(doc_id, snapshot_id)

Risk class: medium (reverts working copy via Operation Record; never touches the original).

prune_snapshotsA

Apply the snapshot + live-frame retention policy, pruning superseded server state.

When to use: reclaiming disk from old snapshots/frames. To roll back instead use restore_snapshot; to list checkpoints use list_snapshots. No mutating tool triggers this implicitly — it is an explicit maintenance sweep.

Key params: none beyond doc_id. Retains the last N snapshots and all within the keep-days window (configurable), bounded by absolute hard caps on count and bytes; deletes the rest plus orphaned Operation Records. In the SAME pass it prunes the doc root's loop/live render frames by age + byte budget, never deleting a frame still referenced by a Live Operation Record. The current working copy and original are never touched, so the restore chain stays intact.

Return shape: PruneResultpruned_snapshot_ids, pruned_operation_ids, and live_frames (the frame pruning stats).

Example: prune_snapshots(doc_id)

Risk class: low (deletes only disposable, superseded server state under a deterministic policy; authoritative current state is never affected).

set_fillA

Set the fill colour (and optional fill opacity) of one or more objects.

When to use: recolouring specific objects' fill (get the ids from find_objects). To change every instance of a colour document-wide use replace_color; for a whole theme use apply_palette; for the outline use set_stroke.

Key params: color accepts hex, rgb()/rgba()/hsl()/hsla(), a named colour, or a url(#id) paint-server reference — a gradient/pattern in <defs>, e.g. an id from add_linear_gradient / add_radial_gradient (optionally with a fallback colour: url(#id) red). External urls, javascript:, and CSS-injection punctuation are rejected. opacity, if given, in [0, 1].

Return shape: EditResultoperation_id, snapshot_id, changed (false if the colour was already present), before/after preview; the edit lands on the working copy only (reversible).

Example: set_fill(doc_id, ["logo"], "#3366cc")

Render and look before you trust this edit: render with render_preview (or live_render_view) and inspect the result before relying on it; restore_snapshot reverts it if it is wrong.

Risk class: medium.

set_strokeA

Set the stroke colour, width, and/or opacity of one or more objects.

When to use: styling an object's outline/border. For the interior use set_fill; to turn a stroke into a filled outline path use stroke_to_path.

Key params: at least one of color, width, opacity must be supplied. color accepts a colour OR a url(#id) paint-server reference (gradient/pattern in <defs>, optionally with a fallback colour); width is a CSS length (number + optional unit); opacity must be in [0, 1]. External urls, javascript:, and CSS-injection punctuation are rejected.

Return shape: EditResultoperation_id, snapshot_id, changed, before/after preview; the edit lands on the working copy only (reversible).

Example: set_stroke(doc_id, ["border"], color="#000", width="2")

Render and look before you trust this edit: render with render_preview (or live_render_view) and inspect the result before relying on it; restore_snapshot reverts it if it is wrong.

Risk class: medium.

set_opacityA

Set the element-level opacity of one or more objects.

When to use: making whole objects more/less transparent. For fill-only or stroke-only opacity use set_fill / set_stroke with their opacity argument instead.

Key params: opacity must be in [0, 1] (this is the element opacity, affecting fill AND stroke together).

Return shape: EditResultoperation_id, snapshot_id, changed, before/after preview; the edit lands on the working copy only (reversible).

Example: set_opacity(doc_id, ["overlay"], 0.5)

Render and look before you trust this edit: render with render_preview (or live_render_view) and inspect the result before relying on it; restore_snapshot reverts it if it is wrong.

Risk class: medium.

replace_colorA

Replace one colour with another across the document (or within scope_ids subtrees).

When to use: swapping every occurrence of one colour for another. For a multi-colour theme swap use apply_palette; to recolour specific objects only use set_fill / set_stroke.

Key params: both colours are validated; matching is case- and hex-shorthand-insensitive and covers inline-style colour properties (fill, stroke, stop-color, ...) and the same-named presentation attributes. scope_ids, if given, confines the replacement to those elements' subtrees (each id must exist).

Return shape: EditResultoperation_id, snapshot_id, changed (false if the colour was not found anywhere in scope), before/after preview; lands on the working copy only (reversible).

Example: replace_color(doc_id, "#ff0000", "#3366cc")

Render and look before you trust this edit: render with render_preview (or live_render_view) and inspect the result before relying on it; restore_snapshot reverts it if it is wrong.

Risk class: medium.

apply_paletteA

Apply many from -> to colour replacements in a single reversible operation.

When to use: re-theming / rebranding a document's colours in one shot. For a single colour swap use replace_color; to recolour specific objects use set_fill / set_stroke.

Key params: mapping maps each source colour to its replacement; every key AND value is strictly colour-validated UP FRONT — a typo'd or non-colour entry (e.g. notacolor) is rejected with a ToolError BEFORE any mutation, op record, or snapshot is created. Each reuses the replace_color matching logic. scope_ids, if given, confines all replacements to those elements' subtrees.

Return shape: EditResultoperation_id, snapshot_id, changed (a real before/after content diff), before/after preview; the whole palette is applied under one snapshot (reversible).

Example: apply_palette(doc_id, {"#ff0000": "#3366cc", "#00ff00": "#66cc33"})

Render and look before you trust this edit: render with render_preview (or live_render_view) and inspect the result before relying on it; restore_snapshot reverts it if it is wrong.

Risk class: medium.

replace_textA

Replace the text content of a text element (<text> / <tspan> / flow text).

When to use: changing what a text object says (get its id from find_objects). To change the font/size use set_font; to rename the element's id use rename_object.

Key params: object_id must be a text-bearing element; text is length-bounded and may not contain control characters other than tab / newline / carriage return. If the <text> has <tspan> children they are dropped and the content collapses to a single run.

Return shape: EditResultoperation_id, snapshot_id, changed, before/after preview; the edit lands on the working copy only (reversible).

Example: replace_text(doc_id, "title", "Hello")

Render and look before you trust this edit: render with render_preview (or live_render_view) and inspect the result before relying on it; restore_snapshot reverts it if it is wrong.

Risk class: medium (reversible text edit on the working copy; original untouched).

set_fontA

Set font-family / font-size / font-weight on one or more text objects.

When to use: restyling text typography. To change the words use replace_text; for non-font fill/stroke use set_fill / set_stroke.

Key params: provide any of family, size, weight (at least one required); each is validated and written to every target's inline style.

Return shape: SetFontResult — all EditResult fields (operation_id, snapshot_id, changed, before/after preview; the edit lands on the working copy only, reversible) PLUS glyph coverage: coverage_ok is False when a target now names a family that cannot render its text, and font_coverage lists per object the uncovered_chars (read from the font's OWN cmap, never fontconfig substitution) and a suggested_family that covers them — so a non-covering font choice is checkable at apply time instead of silently shipping tofu.

Example: set_font(doc_id, ["title"], family="Inter", size="24px")

Render and look before you trust this edit: render with render_preview (or live_render_view) and inspect the result before relying on it; restore_snapshot reverts it if it is wrong.

Risk class: medium (reversible style edit on the working copy; original untouched).

duplicate_objectA

Duplicate an object or group in place, inserting the clone right after the original.

When to use: copying one object once. To copy into a grid use tile; to instance via <use> use create_use; to change an id without copying use rename_object.

Key params: the clone re-ids every contained id uniquely and rewrites its internal references so it is self-consistent. An optional new_id (validated safe and unused) names the clone's top element; otherwise a suffixed id is generated.

Return shape: EditResultoperation_id, snapshot_id, changed, before/after preview; the new top id is reported in the summary. Lands on the working copy only (reversible).

Example: duplicate_object(doc_id, "icon", new_id="icon_copy")

Render and look before you trust this edit: render with render_preview (or live_render_view) and inspect the result before relying on it; restore_snapshot reverts it if it is wrong.

Risk class: medium (reversible write-new on the working copy; original untouched).

rename_objectA

Change an object's id and/or its inkscape:label.

When to use: giving an object a stable/human id or label. To copy it use duplicate_object; to keep an id surviving svg_web_optimize add it to that tool's keep_ids.

Key params: provide new_id and/or label (at least one required). Changing the id validates the new id (safe charset, not already used) and rewrites all in-document references to the old id so nothing dangles. label is set on inkscape:label.

Return shape: EditResultoperation_id, snapshot_id, changed, before/after preview; the edit lands on the working copy only (reversible).

Example: rename_object(doc_id, "rect12", new_id="header", label="Header bar")

Render and look before you trust this edit: render with render_preview (or live_render_view) and inspect the result before relying on it; restore_snapshot reverts it if it is wrong.

Risk class: medium (reversible edit on the working copy; original untouched).

move_objectA

Translate an object/group by (dx, dy) in its parent coordinate space.

When to use: repositioning one object; get its id from find_objects. To resize use scale_object, to spin use rotate_object, to lay out copies use tile.

Key params: dx/dy are a delta in the parent coordinate space; a translate(dx,dy) is prepended to the target's transform (child geometry untouched).

Return shape: EditResultoperation_id, snapshot_id, changed (real before/after content diff), before/after preview; the edit lands on the working copy only (reversible).

Example: move_object(doc_id, "logo", 10, 0)

Render and look before you trust this edit: render with render_preview (or live_render_view) and inspect the result before relying on it; restore_snapshot reverts it if it is wrong.

Risk class: medium.

scale_objectA

Scale an object/group by factor sx (and sy, defaulting to sx for uniform).

When to use: resizing one object; get its id from find_objects. To reposition use move_object, to rotate use rotate_object, to resize the whole page use resize_canvas.

Key params: sx (and optional sy, defaulting to sx for uniform) scale about the parent coordinate-space ORIGIN; non-finite or non-positive factors are rejected.

Return shape: EditResultoperation_id, snapshot_id, changed (real before/after content diff), before/after preview; the edit lands on the working copy only (reversible).

Example: scale_object(doc_id, "logo", 2)

Render and look before you trust this edit: render with render_preview (or live_render_view) and inspect the result before relying on it; restore_snapshot reverts it if it is wrong.

Risk class: medium.

rotate_objectA

Rotate an object/group by degrees about a point.

When to use: spinning one object; get its id from find_objects. To move use move_object, to resize use scale_object.

Key params: degrees is the rotation angle; it rotates about (cx, cy) when BOTH are given, otherwise about the parent coordinate-space origin.

Return shape: EditResultoperation_id, snapshot_id, changed (real before/after content diff), before/after preview; the edit lands on the working copy only (reversible).

Example: rotate_object(doc_id, "arrow", 90, cx=50, cy=50)

Render and look before you trust this edit: render with render_preview (or live_render_view) and inspect the result before relying on it; restore_snapshot reverts it if it is wrong.

Risk class: medium.

resize_canvasA

Set the document canvas width / height to validated CSS lengths.

When to use: changing the PAGE size. To crop the page to the art use fit_to_content, to repair the viewBox use normalize_viewbox, to resize one OBJECT use scale_object.

Key params: width/height are validated CSS lengths; child geometry is not altered. By default an existing viewBox is preserved (synthesized only when absent). adjust_viewbox=True RETARGETS the viewBox to "0 0 W H" so it tracks the new canvas (opt-in; changes the coordinate system). BLEED (opt-in): bleed > 0 ALSO grows the viewBox outward by that many user units on every side and paints the new border strip with bleed_color (validated colour, default white) via one background <rect> behind all content — a print-bleed resize in ONE call instead of a second scale_object/background step. bleed needs a valid existing or derivable viewBox and is mutually exclusive with adjust_viewbox.

Return shape: EditResultoperation_id, snapshot_id, changed (real before/after content diff), before/after preview; the edit lands on the working copy only (reversible).

Example: resize_canvas(doc_id, "800", "600"); with bleed: resize_canvas(doc_id, "800", "600", bleed=8, bleed_color="#fff")

Render and look before you trust this edit: render with render_preview (or live_render_view) and inspect the result before relying on it; restore_snapshot reverts it if it is wrong.

Risk class: medium.

normalize_viewboxA

Normalize or repair the document's root viewBox.

When to use: tidying/repairing a missing or malformed root viewBox. To frame the page to the art use fit_to_content, to set the page size use resize_canvas.

Key params: none beyond doc_id. A valid 4-number viewBox is left unchanged (idempotent → changed=False); an absent one is synthesized from numeric width/height; a malformed one is repaired from width/height when possible.

Return shape: EditResultoperation_id, snapshot_id, changed (real before/after content diff), before/after preview; the edit lands on the working copy only (reversible).

Example: normalize_viewbox(doc_id)

Render and look before you trust this edit: render with render_preview (or live_render_view) and inspect the result before relying on it; restore_snapshot reverts it if it is wrong.

Risk class: medium.

fit_to_contentA

Fit the document's root viewBox to its CONTENT bounding box.

When to use: cropping the page so it frames the drawing exactly. To set an explicit page size use resize_canvas, to merely repair the viewBox use normalize_viewbox.

Key params: none beyond doc_id. The content bbox is computed by the Inkscape engine (--query-all, ADR-005 — real geometry, not naive XML) in the document's intrinsic user-coordinate space (probed against a px-identity copy so the value is STABLE across calls); only the root viewBox changes. IDEMPOTENT: a second call on an already-fitted document reports changed=False. Fails with a stable error if the engine is unavailable, the document has no drawable content, or the bbox is degenerate.

Return shape: EditResultoperation_id, snapshot_id, changed (real before/after content diff), before/after preview; the edit lands on the working copy only (reversible).

Example: fit_to_content(doc_id)

Render and look before you trust this edit: render with render_preview (or live_render_view) and inspect the result before relying on it; restore_snapshot reverts it if it is wrong.

Risk class: medium.

tileA

Lay out a rows x cols grid of an object in ONE reversible operation.

When to use: repeating one object into a grid in a single call. To move/scale/rotate one object use move_object / scale_object / rotate_object; to copy once use duplicate_object.

Key params: the target stays as the (0,0) cell; rows*cols - 1 deep copies (each re-id'd uniquely, intra-clone refs rewritten) are inserted, the copy at (r, c) translated by (c*dx, r*dy). rows/cols must each be >= 1 and their product must not exceed the engine's tile cap; dx/dy must be finite. A 4x4 grid is one call (not 30).

Return shape: EditResultoperation_id, snapshot_id, changed (a 1x1 tile reports changed=False), before/after preview; the whole grid lands under one snapshot (reversible).

Example: tile(doc_id, "dot", 4, 4, 20, 20)

Render and look before you trust this edit: render with render_preview (or live_render_view) and inspect the result before relying on it; restore_snapshot reverts it if it is wrong.

Risk class: medium.

transform_objectsA

Apply ONE typed op to EVERY object a selector matches — one atomic, reversible operation.

When to use: bulk editing keyed by a predicate rather than by hand-listing ids — "recolour every blue rect", "nudge every text down 4px", "delete every object whose id starts with tmp-". It is find_objects (the SELECTOR) wired to ONE typed op fanned across the matches, run through the SAME atomic batch kernel as apply_edits. For a known id list call the dedicated tool (set_fill, move_object, …) or apply_edits directly; this adds NO authority — only the select-then-apply fan-out (ADR-002/003: no free text, no raw Action, no loops/expressions).

Key params: selector is the SAME predicate find_objects takes (tag / fill / stroke / text / id_prefix / bbox, full CSS-cascade paint match); operation is exactly ONE op tagged by an op field — the accepted set is set_fill / set_stroke / set_opacity / set_font / move_object / scale_object / rotate_object / delete_object (high), each with the SAME params as its dedicated tool MINUS the target ids (those from the selector), e.g. {"op": "set_fill", "color": "#3366cc"}, {"op": "move_object", "dx": 0, "dy": 4}. Document- wide ops (replace_color, apply_palette, resize_canvas, normalize_viewbox), element CREATION ops, and identity-conflicting per-id ops (rename_object, replace_text, duplicate_object) are NOT accepted — they are not meaningful applied identically per match. dry_run=True (DEFAULT) resolves + validates and returns the matched ids + the projected plan, writing NOTHING; dry_run=False performs it. max_matches (default 64) REJECTS an over-broad selector before any mutation. A delete_object op makes the operation HIGH and requires a non-empty approval_token.

Render and look before you trust it: a transform changes many objects at once — call render_preview (or live_render_view in live mode) afterwards and inspect the result, and restore_snapshot(doc_id, snapshot_id) reverts the WHOLE transform in one step.

Return shape: TransformObjectsResultmatched_ids + match_count, the effective risk_class, the dry_run flag, the projected plan (per-edit op + target id(s)); on a real run also applied / changed / summary and the single operation_id / snapshot_id (the revert target).

Example: transform_objects(doc_id, {"tag": "rect", "fill": "#3366cc"}, {"op": "set_fill", "color": "#ff0000"}, dry_run=False)

Risk class: medium (the effective risk is the op's class; a delete_object op escalates the operation to high and requires approval_token). Reversible via the pre-transform snapshot.

validate_documentA

Validate a loaded document and return structured, machine-readable findings.

When to use: a pass/fail correctness check on a document. For quantitative metrics + optimize opportunities use quality_report; to fix size opportunities use svg_web_optimize.

Key params: none beyond doc_id.

Return shape: ValidationReportok (True iff no error-severity findings), error_count, warning_count, and findings (each a stable machine code, a severity error|warning|info, a human-readable message, and an optional locator). Covers missing fonts, glyph coverage (a missing_glyphs warning naming the characters a text element's declared font cannot render — read from the font's own cmap, not fontconfig substitution — plus a covering family to try), external asset refs, large embedded rasters, id problems (duplicate ids / dangling #id refs), and viewBox presence/sanity.

Example: validate_document(doc_id)

Risk class: low (read-only validation; document unchanged).

Prompts

Interactive templates invoked by user choice

NameDescription
compose_artworkOn-ramp the generative loop: create → draw → render(inline) → validate → export. Orients the agent to build new artwork toward `goal` from a blank canvas using the typed authoring tools, preview the inline raster, validate, then export. Guidance only — it executes nothing and adds no authority; the work flows through the gated tools it names.
restyle_artworkOn-ramp the OBJECT-TARGETED restyle loop: find → set_fill/set_stroke → render → export. Orients the agent to restyle SPECIFIC objects toward `goal` — address them with `find_objects`, change each one's fill/stroke/opacity, preview, then export. This is the per-object companion to the document-wide `theme_recoloring` prompt (which swaps colors across the WHOLE document via `replace_color` / `apply_palette`). Guidance only; adds no authority.
prepare_web_exportOrient the agent on exporting a document as web-ready assets (PNG + plain SVG).
prepare_icon_setOrient the agent on producing a multi-size square PNG icon set.
prepare_print_exportOrient the agent on exporting a print-ready vector PDF.
theme_recoloringOrient the agent on recoloring a document to a brand/theme palette.
live_canvas_assistEntry point for the live-view co-pilot loop: perceive→decide→act→observe (approval-gated). Orients the agent to drive a running Inkscape via the live tools toward `goal`, one bounded, cancelable iteration at a time. Acts are semantic-only and approval-gated; the loop adds no new authority.

Resources

Contextual data attached and managed by the client

NameDescription
documents_indexIndex of open documents and their per-document resource URIs (discoverability). The seven per-document resources above are registered as URI TEMPLATES (they carry a `{doc_id}` placeholder), so they appear under `resources/templates/list` but NOT under the plain `resources/list` that `ListMcpResourcesTool` reads — an agent could not otherwise discover the concrete URIs for an opened document. This static (no-placeholder) resource closes that gap: it lists every currently-open document id with the seven concrete `inkscape://document/<id>/<leaf>` URIs for it, so the per-doc read surface is discoverable through `ListMcpResourcesTool`. Host-path-free: only opaque document ids and their resource URIs are emitted — never a working path. Risk class: low (read-only resource).
live_sessionCurrent live-session state (enabled, connected, transport, available transports). Returns a not-connected `LiveSession` when no session is up — never an error. Risk class: low (read-only).
live_selectionCurrent selection in the live instance (object ids). Returns an empty selection when no live session is connected (clean, not an error path). Risk class: low (read-only).
live_viewCurrent live frame's structured metadata: the `LiveScene`, without the PNG bytes. Exposes the machine-readable scene — active-doc ref, selection ids + bboxes, viewport (zoom/center/visible region), canvas size, and a compact visible-object summary (reusing the headless object-inspection shape) — so a host can poll the canvas STRUCTURE, not pixels. Pulled over the fixed `get_scene` transport command (no code path — ADR-003). Returns an empty `LiveScene` when no live session is connected or the transport cannot report a scene (clean, not an error path). READ-ONLY — no document mutation, no Operation Record. Risk class: low (read-only perception).
live_eventsLatest live change state: the current cheap state token + classified deltas. Polls the cheap state token once (a small revision marker + selection ids + coarse viewport — never the full document or a PNG; protocol v5), hashes + diffs it against the session's last seen token, and returns the classified `LiveChange` (`selection_changed` / `document_changed` / `viewport_changed`, plus the new token). Surfaces the change stream so a host can poll the canvas for deltas cheaply without busy-rendering. Returns an empty `LiveChange` when no live session is connected or the transport cannot report a token (clean, not an error path). READ-ONLY — no document mutation, no Operation Record. Risk class: low (read-only perception).
live_operationsRecent Live Operation Records: what each live mutation changed and how. Makes live mutations observable — each record carries the transport, selection, affected ids, approval decision, before/after render paths, and status. Returns an empty log when there are none or no workspace root is configured (never an error path). Risk class: low (read-only).
prompts_indexIndex of registered MCP prompts (name + one-line purpose + arguments). Makes the shipped prompt library (`live_canvas_assist`, the export/recolor library, the authoring library) discoverable through the RESOURCE surface (`ListMcpResourcesTool`), which otherwise cannot see prompts at all. Fetch a prompt's full text via the MCP prompts API (`prompts/get`) using the name from this index. Shape: ``{"prompt_count": N, "prompts": [{name, purpose, arguments: [{name, description, required}]}, ...]}``. Sourced from the live registry (`mcp.list_prompts()`), so it cannot drift from the registered prompts. Risk class: low (read-only resource).
runtime_capabilitiesProbed Inkscape/runtime capability matrix (version, actions, export formats, fonts, live). Returns the same cached matrix as the `list_capabilities` tool, including the authoritative MCP tool surface (`tool_count` + `tools`, from the live registry). Use the `diagnose_runtime` tool to force a fresh probe. Risk class: low (read-only).
runtime_intentsCurated natural-language goal → tool(s) intent map, WITHOUT the full capabilities payload. Shape: ``{"intents": [{goal_pattern, tools, how_to, group}, ...]}``. This is the exact same curated map the `how_do_i` tool matches against and the `list_capabilities` `intents` section exposes — all three derive from `inkscape_mcp.intents.intents_summary`, so they cannot drift. Guidance only: it names which tool(s) achieve a goal, executes nothing, and offers no raw-action escape hatch (ADR-003). Host-independent (not probed), so it needs no Inkscape binary. Use this when you want just the discovery map without the heavier runtime probe matrix. Risk class: low (read-only).

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/jjjsood/inkscape-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server