illustrator_execute_script
Run raw JavaScript/ExtendScript in Adobe Illustrator to perform custom operations, access the full DOM, and read document state when higher-level tools fall short.
Instructions
Execute raw JavaScript/ExtendScript code in Adobe Illustrator.
CONTRACT: readOnly=False, destructive=True, idempotent=False, openWorld=True
WHEN TO USE:
Single one-off items, quick prototypes, or operations not covered by higher-level tools
Full DOM access when structured tools are insufficient
Reading document state with custom logic
To SEE the artwork, use illustrator_observe instead: it returns the image inline with a numbered map of items, their handles and bounds, so there is no file to export, locate and open
EXECUTION CONTRACT:
Your script is evaluated at the top level, not inside a function.
- The value of the LAST EXPRESSION is the result. End with the value
you want back, usually a JSON.stringify(...) call.
- A bare return is a syntax error: "Illegal return outside of a
function body". Wrap the code in a function and call it immediately
when you need an early exit.
- Returning an object is fine; it is serialised for you. Returning
nothing is a valid outcome and is reported as data: null.
Injected helper libraries are declared at the same top level, so they
are in scope either way. See EXAMPLES for both forms.
Top-level {ok:false}, {success:false}, or a string error field produces
a warning, not an execution failure. Nested values remain opaque.
Use throw or mcpFail(message, details) for an explicit failure:
try { doWork(); } catch (e) { mcpFail("Label failed", {cause:String(e)}); }
mcpFail throws an ordinary catchable Error; details are bounded to 2048
characters. Neither throwing nor returning an error rolls back edits.
Host line numbers, when available, refer to injected host code, not
necessarily to the caller's source lines. Verification is separate.
ABSTRACTION LADDER — prefer higher levels before using raw script: Level 5 — illustrator_path_boolean: boolean sculpt (unite/subtract/intersect/xor) Level 4 — illustrator_execute_task + element_create_batch: batch-create identical shapes Level 3 — illustrator_path_import_svg: import SVG d-string paths Level 2 — illustrator_execute_task + element_create: smooth curves, handles, mirror Level 1 — illustrator_execute_script (THIS tool): raw ExtendScript
DECISION RULES:
Subtract/unite shapes — MUST use illustrator_path_boolean
Creating >=3 identical shapes — MUST use illustrator_execute_task + element_create_batch
setEntirePath with >12 coord pairs — STOP and use smooth:true or illustrator_path_import_svg
COORDINATE SYSTEM:
Geometry helpers use artboard-relative coordinates: origin at the active artboard's top-left, with y increasing downward (screen space)
Raw Illustrator DOM positions use document-space coordinates, with y increasing upward; do not assume that the active artboard starts at (0, 0)
Units: points (1 pt = 1/72 inch)
HELPERS — ARTBOARD-RELATIVE, Y-DOWN (includes: ['geometry']): Use these to avoid manual conversion to raw document coordinates: rectXY(x, y, w, h) — rectangle at screen-space (x,y) ellipseXY(x, y, w, h) — ellipse at screen-space (x,y) lineXY(x1, y1, x2, y2) — line between screen-space points polygonXY([[x,y],...], closed)— polygon from screen-space points pointXY(x, y) — returns {left, top} for position assignments drawPathPoints(spec) — full path with handles, UUID, heap registration Example: var rect = rectXY(100, 200, 50, 30); // no -y needed
RAW DOM — DOCUMENT-SPACE, Y-UP (only when helpers are insufficient): These are API snippets to put inside a script, not tool calls. Convert an artboard-relative point before passing it to the DOM: var ab = doc.artboards[doc.artboards.getActiveArtboardIndex()].artboardRect; var position = [ab[0] + x, ab[1] - y]; // Nonzero-origin example: ab top-left (72, 720), (x, y) = (100, 200) // gives the raw DOM position [172, 520]. Rectangle: doc.pathItems.rectangle(position[1], position[0], width, height) ⚠ width & height must be POSITIVE. Negative height → shape above artboard (invisible). Ellipse: doc.pathItems.ellipse(position[1], position[0], width, height) Line: convert each artboard-relative point with the same ab-offset formula Color: var c = new RGBColor(); c.red=255; c.green=0; c.blue=0; shape.fillColor = c; Text: var tf = doc.textFrames.add(); tf.contents = "text"; tf.position = position; Grid helpers: artboardGrid(cols, rows), itemsInCell(cell, mode)
EXAMPLES: Read with a native-coordinate crop: { "params": { "script": "app.activeDocument.name;", "return_preview": true, "clip_box": [ 0, 125, 125, 0 ], "clip_space": "illustrator_native_y_up" } } Draw in artboard-relative Y-down coordinates with geometry helpers: { "params": { "script": "var r = rectXY(50, 80, 200, 100); r.fillColor = makeRGBColor(255, 0, 0); r.name;", "includes": [ "geometry" ], "description": "red banner" } } Position text from an offset artboard using raw DOM coordinates: { "params": { "script": "var doc = app.activeDocument; var ab = doc.artboards[doc.artboards.getActiveArtboardIndex()].artboardRect; var x = 100; var y = 200; var tf = doc.textFrames.add(); tf.contents = 'Offset'; tf.position = [ab[0] + x, ab[1] - y]; tf.position;", "description": "raw DOM offset-artboard placement" } } Read state back; the last expression is the result: {"params": {"script": "JSON.stringify({items: app.activeDocument.pageItems.length});"}} Return early, which needs a function wrapper: { "params": { "script": "(function () { var d = app.activeDocument; if (d.pageItems.length === 0) return 'empty'; return d.pageItems[0].name; })()" } } A readback, declared so it is not treated as an edit: { "params": { "script": "JSON.stringify({name: app.activeDocument.name});", "read_only": true } }
ELEMENT DISCOVERY:
Use artboardGrid(cols, rows) to partition the artboard into a labeled grid
Use itemsInCell(cell, mode) to find items in a specific grid cell
Modes: 'containsCenter' (default) or 'intersects'
Cell labels follow A1 scheme (letter row + number col, e.g. A1, B3)
MUTATION SAFETY:
Each call increments a per-document mutation counter
Failed executions decrement it again, so failures do not accumulate
A raw script is opaque to this server, so it cannot tell which kind of change you made. Evidence is therefore requested on a backlog rule rather than on the operations performed, unlike illustrator_execute_task
Use final_step=true on the last mutation to require final evidence
NOTES:
When evidence is required the result carries a VERIFICATION REQUIRED block naming what to confirm, and diagnostics.evidence says whether an image was actually supplied
return_preview=false suppresses capture but not the requirement, which is then reported unmet rather than dropped
setEntirePath() creates corner points only; set handles after creation
ExtendScript can access File/Folder and OS — treat as open-world
SAFETY:
__mcp_check() watchdog: call as FIRST line inside every for/while body
Never iterate live Illustrator collections if adding/removing items
Use __mcp_forEachSnapshot(collection, fn) or __mcp_snapshot(collection) instead
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |