surehand-mcp
OfficialAn MCP server that lets an AI app drive Adobe After Effects through ExtendScript — inspecting the project, making edits, measuring results, and proving changes — while every call is one undo step.
Run any script:
ae_run_scriptandae_run_script_fileexecute JavaScript/JSX inside After Effects (with modern-JS transpiling, helpers, args, log output, timeouts), plusae_get_scripting_guidefor an API cheat sheet.Check the connection:
ae_statusreports the AE version, open project, active item, permission mode and busy state, and can switch between multiple running After Effects instances.See the result:
ae_render_framerenders a frame (zoom, layer-only, checkerboard/background, difference image) andae_render_contact_sheetrenders a labelled grid of frames to judge motion and easing.Inspect the project:
ae_get_project_info,ae_get_comp_info(paged layer lists),ae_get_layer_info,ae_get_selection,ae_get_properties,ae_find_properties, andae_get_comp_map(precomp trees, parenting, mattes, expression references).Build and edit:
ae_create_comp,ae_add_layer(solid, text, shape, null, adjustment, camera, light, footage/comp),ae_add_shape,ae_set_property,ae_set_keyframes(time or frame, linear/bezier/hold, ease speed + influence), andae_set_expression.Effects:
ae_apply_effect, andae_get_effect_paramsto learn exact parameter names, types and ranges without touching layers.Measure precisely:
ae_get_layer_boundsgives exact on-screen boxes after transforms, parenting, 3D and camera, with visibility and title-/action-safe checks.Batch work:
ae_batchruns up to 200 tool steps or scripts as one undo step, atomic by default, with a single change report.Stay safe:
ae_checkpointsaves/lists/restores timestamped project copies, andae_undoreverts edits.Verify edits:
ae_prove_identicalcaptures reference frames, lets an edit happen (or runs it via batch steps), then compares pixel by pixel for identical / within tolerance / differs with a difference image.Discover more:
ae_toolslists and describes the wider tool set (114 tools across project, comps, layers, animation, text, 3D, audio, footage, render and checks), andae_callruns any of them with the same validation, permissions and logging.
Registers with VS Code's MCP configuration used by GitHub Copilot Agent mode, enabling Copilot to operate After Effects through Surehand's editing and verification tools.
Surehand MCP lets the AI app you already use work inside Adobe® After Effects®, and shows you what it did. It is for motion designers, finishing artists and technical directors who can't deliver on "the AI says it's done". Every edit is one undo step and comes back with an exact list of what changed. Structural changes come with pixel proof that the picture didn't change. Deliveries are checked against your own spec, templates are pushed through worst-case inputs, and every version built from data is checked row by row. Verified, not trusted.
AI apps: Claude (Desktop and Code), ChatGPT (desktop app and web), Codex, Cursor, VS Code (GitHub Copilot), Windsurf / Devin Desktop, LM Studio, or any MCP client. Inside After Effects, the Surehand panel can also chat through Codex, Claude Code or Antigravity on your own sign-in.
After Effects: 2025 and 2026 on macOS and Windows, in any language, are tested release by release. The extension loads in CC 2019 (16.0) and newer; versions before 2025 are best effort.
Install: signed and notarized
.pkgfor Mac, signedSetup.exefor Windows. No administrator rights, no account. Free and open source (MIT).Website and downloads: conformlabs.co/get.
It doesn't generate images and ships no presets or canned looks. It works on your project, by your rules, and measures the result.
AI app ──MCP──> surehand-ae server (Node, on your computer) ──localhost──> Surehand panel (CEP, inside After Effects) ──> ExtendScriptWhat you can ask it
Real requests, in your words. The AI picks the tool; the tool does the measuring.
You ask | The tool |
"Check Endcard against our broadcast spec before I send it." |
|
"Stress-test the lower third with long German names and Arabic." |
|
"Un-precompose Logo_Lockup and prove nothing changed." |
|
"Why does this render slowly? Speed it up only where the picture stays identical." |
|
"Split the render across 3 processes and prove every frame is there." |
|
"Make a version of Score Card for every row of scores.csv, and check each one before you queue them." |
|
"Export the texts for the Hebrew and French translators. When they come back, fit them: tracking down to -40, never below 36 px." |
|
"Make a 9:16 of Promo. Logo pinned 80 px from the top, titles inside title-safe." |
|
"I inherited this project. What does the render queue actually pull in, and what's fragile?" |
|
"What changed between v11 and v12?" |
|
Everyday edits work the same way: comps, layers, keyframes at Graph Editor precision, expressions, effects, text, masks, 3D, audio, footage, Essential Graphics and render settings, plus any After Effects script when no tool fits. See the full tool list.
Related MCP server: levea-mcp-server
Install
Your setup | Download |
Mac |
|
Windows |
|
Claude Desktop only |
|
Setups the installers don't cover |
|
Nothing else is needed: the .pkg and Setup.exe include Node.js 24, the .mcpb uses Claude Desktop's built-in
Node.js, and the zip's installer downloads Node.js if it is missing.
Step-by-step setup guides for each AI app: Claude, ChatGPT and Codex, Cursor, VS Code, Windsurf, LM Studio.
Mac and Windows installers
Mac: double-click
Surehand-MCP-<version>.pkgand follow the steps. No administrator password: everything goes into your own home folder. Windows: runSurehand-MCP-Setup-<version>.exe. It installs per user, with no administrator rights.Restart After Effects once.
Restart the AI apps that were open during the install.
Both installers put a private Node.js 24, the server and the After Effects extension on your computer, connect the AI apps they find, and write the Surehand skills for them (see The installer).
First run
The bridge starts with After Effects; nothing needs to be opened. To see it, open Window > Extensions > Surehand MCP. A green dot means connected. The panel shows the latest calls, the permission mode and Pause AI.
Then ask your AI app something simple:
"Check After Effects is connected, then make a 1080p comp with an animated title and show me frame 1."
If something is off, the panel's ☰ › Test the connection (or surehand-ae selftest) says what and how to fix it.
Claude Desktop only (.mcpb)
Double-click Surehand-MCP.mcpb and click Install in Claude Desktop, then restart After Effects once. On first
start the server installs its After Effects extension by itself. Use either the .mcpb or an installer for Claude
Desktop, not both.
The zip
The same installer as double-click scripts, for setups the installers don't cover:
Surehand-MCP/
START HERE.txt
1. Claude Desktop (easiest)/ Surehand-MCP.mcpb
2. Mac/ 1. Install, 2. Test Installation, 3. Connect ChatGPT, 4. Uninstall (.command)
3. Windows/ 1. Install, 2. Test Installation, 3. Connect ChatGPT, 4. Uninstall (.bat)
Support files/ run.sh, run.ps1, surehand-ae.mjs, this READMEDouble-click 1. Install in 2. Mac or 3. Windows, then restart After Effects once. With After Effects open,
2. Test Installation checks everything. START HERE.txt (from installer/START HERE.txt) has the same steps in
plain language, including what to do if macOS Gatekeeper or Windows SmartScreen blocks the files.
The installer
What every installer (.pkg, Setup.exe, or 1. Install from the zip) does:
uses the private Node.js 24 that the
.pkg/Setup.exeput in~/.surehand/node; the zip's scripts use the Node.js on your PATH, or download a private Node.js 22 LTS into~/.surehand/node(checksum-verified)copies the MCP server to
~/.surehand/ae/server/surehand-ae.mjs(one self-contained file)installs the After Effects extension into your user CEP extensions folder. The extension is signed, so it loads without enabling unsigned extensions (
PlayerDebugMode)creates
~/.surehand/ae/config.jsonwith a random access tokenregisters the server, under the name
surehand-ae, with the AI apps it finds: Claude Desktop, Claude Code, ChatGPT desktop / Codex (~/.codex/config.toml, created if the ChatGPT or Codex app is installed), Cursor, VS Code (its usermcp.json, used by GitHub Copilot's Agent mode), Windsurf / Devin Desktop (~/.config/devin/mcp_config.json,%APPDATA%\devinon Windows, and Windsurf's~/.codeium/windsurf/mcp_config.jsonwhile that folder is there) and LM Studio (~/.lmstudio/mcp.json). Before a config file is changed, a timestamped backup is made next to it (*.surehand-<time>.bak, the newest three are kept); the very first original also stays as*.surehand.bak. If Claude Desktop is open it offers to restart it, because a running Claude Desktop overwrites its config filewrites the Surehand skills (see Skills) for the AI apps that read skill files, and the zips to upload in Claude Desktop chat
The server also checks the After Effects extension every time it starts and installs or updates it if needed.
To uninstall: double-click 4. Uninstall from the zip, or run surehand-ae uninstall (and remove the .mcpb in
Claude Desktop > Settings > Extensions if you used it). Checkpoints are kept unless you pass --all.
Skills
Four Agent Skills teach the AI how to work with Surehand well:
surehand-ae: the basics. Check the connection, read before editing, confirm each edit with its change report, look at the result, never work around a refusal, plus the ExtendScript traps seen live.surehand-ae-delivery: preflight against your own delivery spec, stress tests, versions from data checked row by row, the localization round trip, farm renders.surehand-ae-safe-restructure: structural edits and render speed-ups with pixel proof.surehand-ae-timing-layout: exact keyframes, easing, measured alignment and reformats.
The source is skills/ in this repo.
The installer writes them to
~/.claude/skills/(Claude Code; Cursor and VS Code read it too) and~/.agents/skills/(ChatGPT desktop / Codex, Cursor, VS Code, Windsurf / Devin Desktop);%USERPROFILE%on Windows. A folder is written only when one of those apps is on the computer (or the folder is there already). Only the foursurehand-ae*folders are written, replaced on update and removed on uninstall; other skills are never touched.For Claude Desktop chat: upload the skills in Customize › Skills › Upload a skill (files in
~/.surehand/ae/skills, one zip per skill). claude.ai takes the same zips.surehand-ae skills [--json]shows where they are installed;surehand-ae skills install/uninstallwrites or removes them.
Claude Code plugin
In Claude Code you can also install Surehand as a plugin (the server and the four skills, from the latest release; needs Node.js on your PATH):
/plugin install surehand-ae --marketplace ConformLabs/surehand-mcpThe server installs the After Effects extension the first time it starts; restart After Effects afterwards.
Other MCP clients
Point them at the installed server (stdio):
{
"mcpServers": {
"surehand-ae": { "command": "/path/to/node", "args": ["/Users/<you>/.surehand/ae/server/surehand-ae.mjs"] }
}
}The panel's ☰ › Connect an AI app shows which apps are connected and connects the others.
ChatGPT
ChatGPT desktop app (Mac and Windows): no tunnel needed. It runs local MCP servers itself and reads the same
~/.codex/config.toml as Codex, which the installer fills in. Restart ChatGPT after installing; surehand-ae
appears under Settings > Plugins > Servers (switch it on). To add it by hand: Add > MCP server > STDIO,
command = the Node path printed by the installer, argument = ~/.surehand/ae/server/surehand-ae.mjs.
ChatGPT on the web (chatgpt.com) can only reach MCP servers over public HTTPS, so the server runs in HTTP mode behind a temporary tunnel. The panel's ☰ › ChatGPT on the web screen runs it in the background (and can download Cloudflare's cloudflared for you); see the wiki page. By hand:
Install a tunnel tool once: cloudflared (no account needed:
brew install cloudflaredon macOS,winget install --id Cloudflare.cloudflaredon Windows) or ngrok.Double-click 3. Connect ChatGPT in the zip's
2. Macor3. Windowsfolder (or runsurehand-ae chatgpt). It prints a URL likehttps://xxxx.trycloudflare.com/mcp/<token>.In ChatGPT: Settings > Apps & Connectors > Advanced settings > Developer mode on, then Create a connector, paste the URL, choose No authentication (the token is in the URL), and save.
In a chat, enable the connector from the tools menu. Keep the tunnel running while you use it.
The URL contains your secret token: anyone with it can run scripts on your machine while the tunnel is up.
Quick-tunnel URLs change on every start, so update the connector URL each time (or set up a named Cloudflare
tunnel). To rotate the token, delete token from ~/.surehand/ae/config.json and re-run the installer, then
restart After Effects.
Safety model
Surehand is built so that you stay in charge of the project, and so that what the AI says it did can be checked.
Permissions, Pause AI and undo
Permissions. The mode selector Full / Ask / Read-only at the top of the Surehand panel (or "permissions"
in ~/.surehand/ae/config.json) applies to the next request, with no restart:
Mode | What happens |
Full (default) | Everything runs. Your AI app may still ask you before each tool call. |
Ask | Every edit and script waits in the Surehand panel, showing the exact code or arguments, until you click Allow or Deny. When the panel is closed, an approval pop-up appears instead. Reads are not held. |
Read-only | Tools that edit are refused. Scripts still run (to read information), but if one changes the project it is undone immediately and the AI is told what it tried to change. Scripts that touch the undo history ( |
Pause AI. One click in the panel, and every AI call is refused until you resume.
Undo. Every tool call is one undo step, and ae_undo reverts it and reports what was reverted. ae_batch runs
many steps as one undo step, all or nothing by default. The panel's activity feed has Undo on the most recent
change, offered only when nothing has changed the project since. After Effects itself can split a few operations into
several undo steps (seen with comp duplicates, layer copies and source replacements); where that can happen, the
result names the exact way back instead (a checkpoint, or a command that removes exactly the copies it made). See
Limits.
Checkpoints. ae_checkpoint saves a timestamped copy of the project, and restores one as a new file next to the
original; the original is never overwritten. Tools that make big changes (precomp surgery, render optimizations,
versions, reformats) can save one first. The panel lists them under ☰ › Checkpoints.
Existing files are never replaced silently. Save As, frame and contact-sheet output paths, frame exports,
handoff packages, farm plans and farm renders refuse when a file is already there; the AI passes overwrite: true
only when replacing it is intended.
Shell commands in scripts (system.callSystem) can be switched off separately (☰ › Shell commands in
scripts).
What the AI can and can't do
It can do anything an After Effects script can:
ae_run_scriptruns JavaScript in After Effects (modern syntax is converted for ExtendScript), and the ready-made tools cover the common work with checks built in.It can't approve its own requests, get past Pause AI, or press the panel's buttons. Approvals, Pause AI and the panel's own actions need a secret that the bridge keeps in memory and hands only to the Surehand panel and the approval pop-up through After Effects' extension events, never over the network or in a file. A new request can't be answered in its first second on screen, and Enter never allows.
It sees what it asks to see: tool results, and frames it renders. Your project files stay on your computer; what your AI app sends to its provider (your messages, tool results, rendered frames) follows that provider's terms.
Permissions are guardrails against mistakes, not a sandbox. A script can still read and write files. An AI app with full shell access as your user account can read and change everything Surehand can, including
config.json.
Activity log. Every tool call is recorded in ~/.surehand/ae/activity.jsonl with time, AI app, tool, arguments
(including the full script code), duration and result. The panel shows the latest calls, ☰ › Activity history
lists them (click one for what changed), Open log file there reveals the file, and surehand-ae activity
prints it.
Security
The bridge listens on
127.0.0.1only and requires the token from~/.surehand/ae/config.json(file mode 600); requests from web pages (with anOriginheader) are rejected.ae_run_scriptcan do anything an After Effects script can, including reading and writing files and running shell commands viasystem.callSystem. Only connect AI apps you trust, and keep the ChatGPT tunnel running only while you use it.What the token protects against: other users of the computer, and programs that can't read your files. What it doesn't: a program running as your own user account with access to your files.
Chat in After Effects never stores or handles an API key or sign-in: the AI agent runs on its own sign-in.
Settings files of AI apps are only changed when they can be read (a file with a mistake in it is left as it is and reported), with a timestamped backup first (the newest three are kept) and an atomic write.
surehand-ae diagnosticsand Copy diagnostics in the panel contain no secrets.
Self-test
surehand-ae selftest (or 2. Test Installation, or the panel's Test the connection) checks every link of the
chain: the config and token, the extension and its signature, the AI apps' settings, the bridge inside After
Effects, ExtendScript, the scripting preference, a small non-destructive test job (a temporary comp with text,
keyframes and an effect) and a frame preview. A failed check says how to fix it.
surehand-ae selftest --full runs every major tool (over 60 steps) against temporary comps (removed afterwards; if
the open project has no unsaved changes, the Save As and checkpoint-restore checks briefly switch to a scratch
project and then reopen it), lists which scripting features your After Effects version has, and saves a report to
~/.surehand/ae/compat/. All steps pass on After Effects 2025 (25.6) and 2026 (26.5) on macOS and on 2026 on
Windows 11, also with 2025 and 2026 running side by side; the panel, permissions, approvals and background
rendering are verified on macOS and Windows. Please share reports from other versions.
What it does, by job
Check and deliver
Preflight (ae_preflight) checks the comp, and optionally the rendered file, against your delivery spec: a small
JSON file with the numbers from your client's or broadcaster's document. Nothing is built in. It covers comp
settings, missing items, text inside safe areas on every frame, cap height and reading speed, and in the file:
codec, levels, loudness, black and frozen frames and a flash pre-check. A check that couldn't run makes the verdict
INCOMPLETE, never PASS. The stress test (ae_stress_test) pushes worst-case inputs (long German and Finnish
strings, Hebrew and Arabic, CJK, emoji, huge and negative numbers) through every control a template exposes and
measures each result on a scratch copy; it also lists expressions that break in other After Effects languages.
ae_project_health lists missing footage, fonts and effects, expression errors and unused items.
Details: Preflight, Preflight: rendered files, Stress test.
Restructure safely
Every edit returns a change report computed by After Effects itself. ae_prove_identical renders reference
frames, lets the edit happen and renders them again: identical, identical within tolerance, or differs
with a difference image. ae_precomp_surgery un-precomposes or deep-duplicates with every expression reference
rewritten, rehearses the change on a scratch copy and applies it only when the pixels match; what it can't reproduce
exactly is refused with the reason. ae_replace_in_expressions does project-wide find and replace with a dry run.
Details: Change report, Proven edits, Precomp surgery.
Timing and layout
The keyframe table (ae_get_keyframes, ae_set_keyframe_table) reads and writes keys in frames or seconds with the
exact speed and influence After Effects stores. ae_copy_ease copies an ease to other keys, ae_audit_easing checks
motion against the project's own most-used curves, and ae_retime_keyframes scales, offsets, staggers or conforms
by whole frames. ae_align_layers aligns and distributes by measured on-screen bounds, not anchor points, and reports
any residual. ae_get_layer_bounds, ae_sample_pixels, ae_render_frame and ae_render_contact_sheet let the AI
measure and look at the result.
Versions, localization and reformats
ae_versions_from_data turns a CSV or JSON file into versions of a template comp in one undo step, then reads every
row back where it renders: text, number format, colour rules, overflow, safe areas, bar sizes against your mapping.
ae_localize exports texts with their context to CSV or XLIFF and brings translations back as a version per
language, fitted only by the adjustments you allow, with right-to-left handled. ae_reformat makes 9:16, 1:1, 4:5 or
any size from your rules (cover, safe areas, pins, scale limits) and checks the result on every frame. When a rule
can't be met, the report says FAIL and why; it doesn't decide for you.
Details: Versions from data, Localization, Reformat.
Renders and farms
ae_render_profile shows where render time goes across the whole timeline, then applies chosen speed-ups one at a
time and keeps only those proven identical, with the time saved. ae_handoff_package collects a project for someone
else with a manifest of what they need (fonts, plug-ins, colour settings) and can prove the package renders the same.
ae_farm lists what a render needs on a node and checks a node against it, splits a render into chunks for local
processes or other machines, runs them here in parallel, and proves the chunks add up. ae_render_background runs
aerender in a separate process while After Effects stays usable.
Details: Render profile, Handoff package, Render farm.
Understand a project
ae_project_xray explains an inherited project without changing it: what the render queue renders, what every
expression depends on and which links are fragile, what is missing, footage specs and what makes it heavy.
ae_project_history snapshots the project and diffs any two versions or checkpoints into a readable change list.
ae_get_comp_map maps nested precomps, parenting, mattes and expression links.
Details: Project X-ray, Project history.
Chat in After Effects
☰ › Chat with your AI app in the Surehand panel runs Codex, Claude Code or Antigravity, on your own sign-in and subscription, with Surehand's tools as its only tools. The same mode, approvals, Pause AI and activity log apply. In AI apps that show interactive views (for example Claude Desktop, ChatGPT, VS Code and Cursor), Preflight, X-ray, the stress test, proofs and history diffs come with an in-chat view: findings on a timeline, frames, before and after. Other apps get the same results as text. Details: Chat with your AI app, In-chat views.
Reference
All tools
Surehand has up to 114 ready-made tools, plus ae_run_script for anything else.
Run anything:
Tool | |
| Run JavaScript in After Effects; |
| Run a |
| ExtendScript cheat sheet for the model (also an MCP resource |
By area:
Workflow:
ae_batch(many tool steps or scripts in one call and ONE undo step, with one change report; atomic by default: if a step fails everything is undone),ae_checkpoint(save a timestamped copy of the project, list, restore as a new file next to the original; the original is never overwritten; each checkpoint also gets a history snapshot),ae_list_scripts(your scripts: AE's Scripts folder, ScriptUI Panels, and folders listed as"scriptFolders"in~/.surehand/ae/config.json, with their descriptions) +ae_run_script_file,ae_toolsandae_call(every tool on demand, see Tool profiles)Verification:
ae_prove_identical(Proven edits),ae_precomp_surgery(Precomp surgery),ae_project_history(Project history)Checks and delivery:
ae_preflight(Preflight),ae_stress_test(Stress test),ae_project_health(missing footage/fonts/effects, expression errors, unused footage, empty comps/folders, duplicate comp names)Versions:
ae_versions_from_data(Versions from data),ae_localize(Localization),ae_reformat(Reformat)Understanding:
ae_project_xray(Project X-ray),ae_get_comp_map(nested precomps, parenting, track mattes, expression references)Seeing the result:
ae_render_frame(a frame as an image; options: zoom into a region, render only some layers, transparency on a checkerboard or a color, difference image against another time or comp),ae_render_contact_sheet(a grid of frames across time, labelled with time and frame number, to judge motion and easing). The temporary comp stays until After Effects has written the image, then it is removed and anything switched for the render set back by hand, and the project is compared with how it was. They never use Edit > Undo (it could revert your own last step); After Effects may list a "Surehand MCP preview" step, which only brings the preview's own changes back. In a 32 bpc project, or one with "Blend Colors Using 1.0 Gamma", frames are rendered at 16 bpc without it, so colors look as in the viewer (After Effects writes such frames far too dark); the project settings are put back.ae_export_framesdoes the same.ae_prove_identicalalways renders with the project's own settings, so a capture and its comparison match.Measuring:
ae_get_layer_bounds(exact on-screen boxes after transforms, parenting, 3D and camera; in-frame and action/title-safe checks),ae_sample_pixels(rendered RGBA/hex at points)Status & app:
ae_status,ae_system_info,ae_execute_menu_command,ae_undo,ae_redo,ae_purge,ae_get_fonts,ae_reload_helpersProject:
ae_get_project_info,ae_list_items,ae_get_item_info,ae_import_files,ae_create_folder,ae_move_items,ae_rename_item,ae_remove_items,ae_replace_footage,ae_save_project,ae_open_project,ae_new_projectCompositions:
ae_list_comps,ae_get_comp_info,ae_create_comp,ae_set_comp_settings,ae_duplicate_comp,ae_open_comp,ae_precompose,ae_add_comp_markerLayers:
ae_get_layer_info,ae_add_layer(solid, text, shape, null, adjustment, camera, light, footage/comp),ae_set_layer_attributes(switches, timing, parent, blend mode, track matte, order...),ae_delete_layers,ae_duplicate_layer,ae_split_layer,ae_get_selection,ae_select_layers,ae_set_textProperties & animation:
ae_get_properties,ae_find_properties(search all layers by name/match name, or list animated / expression properties),ae_set_property,ae_set_keyframes(interpolation + easing),ae_remove_keyframes,ae_set_expression,ae_get_expressionsExpressions:
ae_check_expression(try an expression and see errors and values without keeping it),ae_replace_in_expressions(project-wide find & replace, dry run, errors after the change)Keyframes (Graph Editor level):
ae_edit_keyframes(value, move in time, in/out interpolation, speed + influence per dimension, continuous/auto-Bezier, spatial tangents, roving, keyframe color labels, delete),ae_copy_keyframes(between properties/layers/comps, time range, offset),ae_set_time_remap(keys or freeze frame). The keyframe tools take whole frames (frame,moveToFrame,frames,offsetFrames) as well as seconds.Precision timing and easing:
ae_get_keyframes(a keyframe table across many layers and properties: whole frame and exact time of every key, exact value, interpolation, speed + influence per dimension exactly as After Effects stores them, tangents, roving; keys between frames are flagged; optional normalised curve numbers per segment),ae_set_keyframe_table(write such a table back, many properties in one undo step, every attribute exact),ae_copy_ease(the exact ease of a reference key onto keys of other properties and layers, with a stated rule for different dimension counts),ae_audit_easing(motion consistency against the project's own most-used curves: lists the segments that match none),ae_retime_keyframes(scale around an anchor, offset or stagger by whole frames, conform to a new frame rate; keeps the curves' shape, refuses keys colliding on a frame)Measured layout:
ae_align_layers(align, distribute and centre by real on-screen bounds, through parenting, scale, rotation and text glyph boxes, not anchor points; reports any residual after the move)Effects, shapes & masks:
ae_list_available_effects,ae_get_effect_params(an effect's exact parameter names, types, defaults and ranges, without touching your layers),ae_apply_effect,ae_set_effect_params,ae_remove_effect,ae_apply_preset(an animation preset.ffxfile by path),ae_add_shape,ae_add_maskText:
ae_style_text_range(per-character styling by range or matching words),ae_set_paragraph(justification, indents, spacing, box size),ae_add_text_animator(animator properties + range/wiggly/expression selector)3D:
ae_set_camera(one/two-node, focal length in mm, depth of field; reports angle of view),ae_set_light(type, color, intensity, cone, falloff, shadows),ae_set_material(material options, lists the 3D renderers)Audio:
ae_audio_to_keyframes(Convert Audio to Keyframes),ae_audio_markers(markers at beats/peaks)Color:
ae_color_settings(Adobe or OCIO color engine, working space, bit depth, linearization, OCIO spaces)Footage:
ae_set_footage_interpretation(conform frame rate, alpha, fields, pulldown, loop, pixel aspect),ae_set_proxy,ae_relink_footage(find missing files by name in a folder tree, keeps sequences)Files and exports:
ae_find_files(globs,~, Unicode names in either normalisation, depth and result limits, no symlink loops; After Effects not needed),ae_export_frames(PNG stills of comps, single layers or footage, frame lists and ranges, several exports per call, never replacing a file withoutoverwrite: true);ae_import_filessays when a file couldn't be imported the wayimportAsaskedEssential Graphics:
ae_essential_graphics(add properties as controllers, template name),ae_export_mogrtRender:
ae_list_render_queue,ae_add_to_render_queue,ae_get_render_settings/ae_set_render_settings(every render-settings and output-module setting as editable key/value pairs),ae_queue_in_media_encoder,ae_render_background+ae_render_jobs(aerender in a separate process, with progress and cancel; After Effects stays usable),ae_render_queue_start,ae_clear_render_queue,ae_render_profile(Render profile),ae_handoff_package(Handoff package),ae_farm(Render farm)
Comps can be referenced by id, name, or omitted for the active comp; layers by 1-based index or name; properties by
paths like "Transform/Position" or "Effects/Gaussian Blur/Blurriness" (display names or match names).
Any After Effects language. Property, effect and menu names are translated in non-English After Effects. Common
English names still work everywhere: property paths like Transform/Opacity, effects like "Gaussian Blur" and menu
commands like "Pre-compose..." are mapped to internal match names and command ids, which are the same in every
language. Match names (ADBE ..., as returned by ae_get_properties / ae_get_effect_params) always work, and an
unknown effect name gets suggestions.
Tool profiles
Every tool description is sent to the AI in every chat, so by default only a core set of 29 tools is loaded
(about 12k tokens instead of 50k for all 114), and every other tool stays available on demand: ae_tools lists
all tools by category (or gives full parameter details of chosen ones), and ae_call runs any tool by name with the
same validation, permissions, change report and activity log. In AI apps that show in-chat views, the four tools with
a view (ae_preflight, ae_project_xray, ae_project_history, ae_stress_test) join the core set, because a view
only shows when the AI app calls the tool directly.
Loading everything up front is optional: switch to All tools in the Surehand panel (☰ › Tools the AI sees ›
All tools), in Claude Desktop's extension settings ("Enable all tools") for the .mcpb, or with
"toolProfile": "full" in ~/.surehand/ae/config.json, then restart the AI app. Advanced:
"toolProfile": "core,ae_import_files,ae_render_queue_start" adds single tools.
Core set: ae_status, ae_run_script, ae_get_scripting_guide, ae_render_frame, ae_render_contact_sheet,
ae_get_project_info, ae_get_comp_info, ae_get_layer_info, ae_get_selection, ae_get_properties,
ae_find_properties, ae_get_layer_bounds, ae_get_comp_map, ae_create_comp, ae_add_layer, ae_add_shape,
ae_set_property, ae_set_keyframes, ae_set_expression, ae_apply_effect, ae_get_effect_params, ae_undo,
ae_batch, ae_checkpoint, ae_prove_identical, ae_list_scripts, ae_run_script_file, ae_tools, ae_call.
Feature reference
How each verification feature works, what it checks and what it doesn't.
Preflight
Before you deliver, ask the AI to preflight the comp (ae_preflight). It checks the project, and optionally the
rendered file, against your delivery spec: a small JSON file with the numbers from your client's or
broadcaster's delivery document (or the same thing inline in the chat). Nothing is built in: there are no house
presets, every section of the spec is optional, and a check only runs when its section is there. The AI can help you
write the spec (action: "schema" gives it the fields).
In the project, for the delivered comp (comp in the spec, otherwise the active comp):
Video: comp size, frame rate, pixel aspect ratio and duration (exact, with a tolerance in frames, or a range).
Project: bit depth, working color space, missing footage, fonts and effects, expression errors, disabled layers that still carry effects (the same collector as Project X-ray, limited to the delivered comp and its precomps).
Safe areas over time: every visible text layer, and any layer you name (wildcards like
Logo*), on every frame (or every Nth frame) where it is visible: its box after position, scale, rotation, anchor point and parents, and through the precomps it sits in, against title-safe, action-safe or the frame. Problems come back as time ranges, for example "Title: outside title-safe 00:00:02:03–00:00:03:10 (2.12s–3.40s), 46 px past it on the right at most". Layers that are off, transparent (opacity 0) or outside their in/out points are not visible and are not checked. 3D layers are reported as not checked (check them withae_get_layer_bounds, which projects through the camera); auto-orient, and effects that move or scale the pixels outside the transform (Transform, Offset, layer styles, text animators), are flagged as a warning that the bounds may be off. AlayersMustBeInname that matches no layer is a warning, not a pass.Text: smallest cap height (estimated as 0.7 x the font size x the layer's scale, since real fonts vary from about 0.65 to 0.75), reading speed (characters per second while the text is visible, spaces included, line breaks not), shortest time on screen, paragraph text that overflows its box (After Effects 24.6 or later), and characters the font has no glyph for (After Effects 25.1 or later); on older versions the report says the check isn't available.
On a rendered file (target: "file" or "both"): codec, container, bit depth, chroma subsampling, alpha, field order,
color tags, legal range, black and frozen frames, loudness and true peak, and a flash check. File checks need ffmpeg:
the one on your system, or a one-time download. The flash check is a pre-check to catch obvious problems early; it
is not a certified PSE / Harding test.
The report starts with the verdict: FAIL (n) when anything failed; otherwise INCOMPLETE (n checks not run)
when a check the spec asks for couldn't run or ran on incomplete data (no ffmpeg, an RGB file for legal range, a check
that needs a newer After Effects, a file that couldn't be read to the end), so a check that didn't run is never a pass;
otherwise WARNINGS (n) or PASS. Then the checks that were requested but not run and why, the findings grouped by
check (failures first, then warnings, by time), with timecode in the comp's frame rate and seconds, where the problem is
(comp > layer) and a short fix, then what this run doesn't cover (a section not in the spec, a file check on a project
target). For files it also shows what ffprobe found and up to four frames at the worst problems. Preflight changes
nothing in the project and leaves no undo step, so it also runs in read-only mode. Long comps are checked within a
time budget (timeBudgetSeconds, default 120 s); a partial check says so.
Preflight: rendered files
Preflight also checks the rendered file itself against the same delivery spec, with ffprobe and one ffmpeg pass over the picture and sound. Each check runs only when its section is in the spec; a requested check that can't run is listed with the reason (no ffmpeg, an RGB file for legal range, a value ffmpeg didn't report...) and makes the verdict INCOMPLETE. A file with no audio stream fails when the spec asks for audio (usually Audio Output was off in the output module). Every decoded frame is counted against the picture's own duration: a truncated or damaged file fails ("only 2.8 s of 8 s could be decoded") instead of passing on the part that was read, and decoding errors are a warning. Durations (and black / frozen at the end) are the picture's, not the container's; sound that runs longer or shorter than the picture by more than a frame is a warning.
Spec section | What is measured in the file |
| container (file extension), codec, frame size, pixel aspect, frame rate ( |
| sample rate, channels, |
| every pixel of every frame, in the file's own bit depth scaled to 8-bit (a 10-bit 941 is 235.25: out of 16-235); a frame fails when more than |
| ffmpeg |
| a pre-check, not a certified PSE / Harding test: the picture as a 32x18 grid, relative luminance per cell; a transition is a change of at least |
Times in the findings are seconds in the file. Up to four JPEG frames (960 px wide at most) from the most important
failing times are written to ~/.surehand/ae/tmp, shown in the report and deleted right after (also when the check is
cancelled; leftovers older than a day are swept). A one-minute 1080p ProRes 422 HQ file with every check takes about 4 s on
an Apple Silicon Mac (legal range marks the out-of-range pixels and measures that mask averaged down to a small grid,
which is exact and much faster than full statistics on every frame).
ffmpeg. Surehand MCP uses, in this order: "ffmpegPath" / "ffprobePath" in ~/.surehand/ae/config.json, a private
copy in ~/.surehand/ffmpeg, then the PATH (plus /opt/homebrew/bin and /usr/local/bin on a Mac). If there is none, it
can download FFmpeg 9.0.2 once into ~/.surehand/ffmpeg, only after you allow it (in "ask" permission mode you also
approve it in the Surehand MCP panel; in read-only mode it never downloads). The download is a pinned build checked
against a SHA-256 written in the source, and must start and report the expected version before it is used; anything
else is refused and nothing is installed:
macOS (Apple Silicon and Intel): Martin Riedl's static release builds (ffmpeg.martin-riedl.de),
ffmpeg.zip+ffprobe.zip, about 60 MB. These are GPL v3 builds (they include x264 / x265).Windows x64 (and Windows on Arm, which runs x64 programs): BtbN/FFmpeg-Builds
ffmpeg-n9.0.2-...-win64-lgpl-shared-9.0.zipfrom a month-end release (those are kept), about 77 MB. LGPL v2.1+.
Surehand MCP doesn't ship or redistribute FFmpeg: it downloads the publisher's own file on your machine and runs it as a
separate program, so FFmpeg's licence (the GPL / LGPL terms above, with its source available from ffmpeg.org) applies to
that copy and not to Surehand MCP. ~/.surehand/ffmpeg/SOURCE.json records what was installed and from where. To use your
own FFmpeg instead, install it (brew install ffmpeg, winget install ffmpeg) or set "ffmpegPath".
Stress test
ae_stress_test finds what breaks in an editor's or client's hands before they do: it pushes worst-case inputs
through every variable a comp exposes and measures each result.
What it varies: the comp's Essential Graphics controllers (text, numbers, checkboxes, menus, colours, media replacement) and text that reads data, or the layers you name. Inputs are test data, not looks: German and Finnish long strings scaled from the current text, Hebrew and Arabic with digits, Japanese, Chinese, Korean, Thai, Hindi, combining marks, emoji, all caps, empty, one character, no spaces; zero, negative, huge, past the slider limit, many decimals, both separator styles, percent; every checkbox and menu state. Your own values or CSV / JSON rows work too. Combinations are sampled evenly up to a cap, and the report says what was kept.
What it measures, at the animation's key frames and where each text starts and stops being visible: box overflow and by how many pixels and lines (After Effects 24.6+), the frame / title- / action-safe area (your margins), the size text renders at (your minimum, or smaller than the comp's own text), missing glyphs (25.1+) and substituted fonts, right-to-left and complex scripts without the direction or composer they need, line count and breaks inside a word (24.3+), overlap with layers you name, and whether a number shows right in the text that shows it. What already fails in the comp as it is is listed once, as the baseline.
Expressions in other languages: references by an English display name (
effect("Slider Control")("Slider"),thisLayer("Transform")("Opacity"), default shape and mask names) break in After Effects in another language; each is listed with the language-safe form (index, match name or attribute).Never touches your comp: every variant is set on a scratch copy that the same step removes; your comp is read back afterwards (every property value) and must be identical, or the report says so (
proveUnchanged: trueadds a pixel proof). Read-only mode returns the plan and the expression scan.The report: PASS / FAIL with what breaks, where, at which frame and by how much ("Title overflows its box by 184 px; 3 lines, the box shows 2 at f48"), a grid of variants and checks, and a contact sheet PNG per failing variant. Where the AI app shows views, the grid comes with each failing frame marked.
Change report
Every call that edits the project ends with a Changes list, computed by After Effects itself (a snapshot before and after the call), for example:
Changes (layers/properties compared in: Main):
+ layer "Headline" in "Main"
~ layer "Plate" in "Main": name "Plate" -> "Background"; locked off -> on
+ Headline > Effects/Glow
~ Headline > Transform/Opacity: 100 -> 0, expression added
~ Headline > Transform/Position: [640,360] -> [640,800], keyframes 0 -> 2Project items are always compared; layers, properties, keyframes, expressions, effects and masks are compared in the
active comp and any comp named in the call. If a script fails halfway, the report lists what it had already changed.
ae_undo reports what was reverted. On very large comps (tens of thousands of properties) this adds up to about a
second per edit; turn it off with "changeReport": false in ~/.surehand/ae/config.json, or per script with report: false.
Proven edits
Some changes should not change the picture at all: un-precomposing, duplicating a comp deeply, baking or collapsing
expressions, reordering effects, simplifying a rig. ae_prove_identical checks that. It renders reference frames of the
comps (by default the active comp, 5 frames across the work area, full size, at most 1920 px), you or the AI make the
change, and it renders the same frames again and compares them pixel by pixel. The answer is identical,
identical within tolerance (by default less than half an 8-bit step, so only the rounding of 16/32-bit projects passes; tolerance: 0 asks for bit-identical), or differs, with, for each frame, the largest
channel difference, how many pixels changed, the largest color difference (ΔE), the area that changed, and a
difference image of the worst frame (black = identical). If a comp was deleted or resized since the capture, it says so.
What is compared is the sampled video frames, alpha included: audio, the comp's background color and the times between
the sampled frames are not, and 32-bit values above 1.0 are clamped when the frames are saved, so differences in
over-bright areas can be missed. Comp ids belong to one project: a proof captured in a saved project is only compared in
that same file (otherwise the verdict is not proven); one captured in an unsaved project is compared if every comp still
has its name, with a note that the project itself couldn't be confirmed.
action: "run" does it in one call: capture, the edits as ae_batch steps (one undo step, all or nothing), compare.
For un-precomposing and deep duplicates, ae_precomp_surgery (see Precomp surgery) makes the edit itself, with the
expression rewrites, and proves it the same way before applying it.
Reference frames are stored in ~/.surehand/ae/proofs/ for 7 days (30 proofs at most). Rendering works like
ae_render_frame: through a temporary comp that is removed again and leaves no undo step behind (After Effects still
marks the project as changed); if the temporary comp can't be removed, the result says so. Capture and compare are
allowed in read-only mode; run makes edits, so it follows the same permissions as ae_batch.
Precomp surgery
Inherited projects often need restructuring: a precomp that should not be one, or a comp to copy with all its nested
precomps unlinked (a "deep duplicate"). After Effects' own commands and free scripts can drop what the precomp layer
did and silently break expressions such as comp("Logo").layer("Title") or thisComp.layer(3). ae_precomp_surgery
does it exactly or not at all.
unprecomposebrings a precomp layer's layers into its comp at its place. A null carries the precomp layer's anchor point, position, scale and rotation (keyframes and expressions included) and the moved top-level layers are parented to it (parents inside the precomp are kept;bakeNullleaves the null out when the transform is the identity). Layers move by the precomp layer's start time and are trimmed to its span; a layer entirely outside it is moved switched off. Names that are taken in the comp get a number. Expressions are read with a real JavaScript parser and rewritten by position: in the moved layersthisComp.layer("x")points at the moved copy,thisComp.layer(3)at its new index,thisComp.width(and every other comp attribute) becomescomp("<precomp>").width; references by index to the comp's own layers, from anywhere in the project, follow the layers that move down. Track mattes and Layer Control parameters are pointed at the moved layers. One visible layer takes over the precomp layer's opacity and blend mode. The source comp is kept (removeSourceremoves it only if nothing else uses it).deep_duplicatecopies a comp and every nested precomp, each once (a precomp used in several places maps to one copy), points the copies' precomp layers at the copies, and rewritescomp("X")in the copies when X is in the tree (references to comps outside it stay).suffix(default " copy", a number is added when the name is taken). The copies are made next to their originals: After Effects records every move into a folder as an undo step of its own, so moving them (ae_move_items) is left to a separate step. Footage and solids are shared, not copied.
Refused, with the exact reason, when it can't be reproduced exactly: effects, masks, layer styles, time remapping,
time stretch, track mattes, 3D, collapse transformations, motion blur or frame blending on the precomp layer; its blend
mode or opacity when the precomp has more than one visible layer; layers in the precomp that would interact with the
comp's other layers (blend modes, adjustment layers, Preserve Underlying Transparency, cameras, lights, 3D layers);
different frame rates or motion blur settings; Essential Graphics overrides; layers reaching outside the precomp's frame
where that part would show; and expressions whose references can't be rewritten safely: names or indices computed when
the expression runs, a layer's own index or wiggle / random (seeded by the layer index) when the index changes,
time when the layers move in time, toComp and friends, references to the precomp layer itself, ambiguous comp names,
expressions with an error before the surgery (they could start working). override: ["expressions"] or ["bounds"]
goes ahead anyway: those are still listed, left as they are, and the proof decides. dryRun returns the plan only:
what moves, what is renamed, every expression rewrite (before → after) and every problem.
Proof first, then the change. A checkpoint is saved (the project must be saved), reference frames are rendered (by
default 6 frames across the precomp layer's time span, first and last included; deep duplicate: 5 across the work area),
and the surgery is rehearsed on a scratch copy (a duplicate of the parent comp; for a deep duplicate, the copies). The
scratch copy is compared with the original pixel by pixel, the same comparison as ae_prove_identical (default
tolerance), and removed again. Only when it is IDENTICAL is the same surgery applied to the project, in one undo group,
and the result is checked layer for layer against the rehearsal (otherwise it is undone at once). After Effects can split
such an undo group (seen with layer copies and source replacements), so ae_undo may take several steps and the result
says what the exact way back is instead: for an un-precompose, the checkpoint saved first (ae_checkpoint restore, with
its id); for a deep duplicate, which never changes the originals and only adds copies, {action: "remove_copies", id}
removes exactly the copies it lists (refused while anything outside them uses one). DIFFERS means nothing was applied: the result lists the frames that differ with the largest difference, a
difference image, and the likely cause (for example a precomp layer that is scaled: the precomp was resampled as a whole,
while the moved layers are transformed once). Expression rewrites in other comps are exact text edits; the pixel proof
covers the parent comp (or the copied tree).
Versions from data
ae_versions_from_data turns a CSV or JSON file (or rows in the chat) into versions of a template comp, and then
checks every row. Filling data in is the easy part; this is about knowing that each version is right. Nothing is
built in: every format, colour, size and margin comes from your data and your own rules.
Mapping: each column goes to a layer of the template comp (or an Essential Graphics controller): text; a number in your format (decimals, decimal and thousands separators, prefix, suffix, how negatives are written); a colour from the cell or from your rules (for example "below 0: #C62828, otherwise #2E7D32"); a footage file that replaces the layer's source; any property value; or a bar's on-screen width or height through your value-to-pixels mapping (for example 0 → 0 px, 100 → 800 px). Names come from a pattern like
{comp} - {City}.Two modes.
duplicate(layer targets) duplicates the comp per row. Duplicating a comp doesn't duplicate the precomps inside it (every version shares them), so targets are layers of the template comp itself.essentialGraphics(controller targets) makes a comp per row with the template as a precomp and sets that row's Essential Graphics values, the way After Effects keeps per-instance values; a row's layout can't be measured there, so those checks don't run.One undo step, with the Changes list and an optional checkpoint first.
dryRun: truechecks the mapping against the template and the data and shows what each row would get, without changing anything. Names already in the project, keyframed targets and output files that exist are refused before anything is built.Every row is checked: each value is read back where it renders (with expressions applied), so the text shows exactly the formatted string and the colour is what the rule says; paragraph text must not overflow its box, and the mapped text must stay inside the frame (or title- / action-safe with your margins) on every frame, measured with Preflight's own code; characters the font has no glyph for and missing fonts fail the row; bars are measured on screen (through parents) against your mapping within a tolerance you set; footage files must exist.
The report: a verdict (
FAIL (n of m rows),INCOMPLETE,WARNINGSorPASS), totals, then one line per row: PASS, or FAIL with what and where. A check that didn't run (an older After Effects, a layer not visible at the checked time, Essential Graphics mode) makes the row INCOMPLETE, never PASS.Render (optional):
queueadds every version to the render queue with your output module template and an output path pattern (/renders/{City}_{#3}.mov);render: truerenders only the versions that pass. Existing files are never replaced unlessoverwrite: true.
Localization
ae_localize takes a comp's texts to translators and back, with every language checked.
Export (
action: "export"): every text layer of the comp and its precomps (visible or not; keyframed Source Text per keyframe) to a CSV for Excel (UTF-8 with a BOM, so Hebrew and Arabic open correctly; one column per language) or XLIFF 1.2 for CAT tools (Trados, memoQ, Phrase...; one file per language). XLIFF 1.2 is the version CAT tools import most widely; 2.0 files are read too. Each string has its context: comp and layer, time on screen, the paragraph box or the width a point text has to the edge of the frame (or your safe area), a character limit (yours, or estimated from the box withmaxChars: "fromBox") and your notes.Import (
action: "import"): one version per language. The comp tree is duplicated the way versions from data duplicates a comp: the root and every precomp that holds a translated text, the copies using each other ("{comp} [{lang}]"). One undo step with the Changes list;dryRun: trueshows what each language gets; names already in the project are refused unlessoverwrite: true.Fit by your rules, never invented: the adjustments you allow, in your order: tracking down to a minimum, font size down to a minimum (or a minimum cap height in comp pixels, measured on the font), horizontal scale down to a minimum, the paragraph box growing by at most so many pixels (away from the edge the text is aligned to); point text within a width you give. Each step goes only as far as needed. A text that still doesn't fit is left at the best attempt and FAILs with what was tried; nothing goes below your minimum. Without rules nothing is adjusted.
Right to left: Hebrew, Arabic, Persian, Urdu, Yiddish (by the language code, or
direction) get right-to-left paragraph direction and the Universal composer (formerly South Asian and Middle Eastern, After Effects 24.0+), and their alignment is mirrored (left becomes right); a point text whose alignment flips keeps its place. Your font per language (fonts: {"he": {"*": "YourHebrewFont"}}). Not available to scripts, so not done: mirroring the layout itself, kashida justification, per-character direction.Checks per language, worded like Preflight (
FAIL (1 of 3 languages),INCOMPLETE,PASS): each text read back where it renders, the fit, the direction, box overflow, text inside the frame or safe area on every frame, missing glyphs (the common Hebrew / Arabic problem: a Latin font without those letters) and missing fonts. Untranslated strings FAIL (or warn withallowUntranslated: true).Drift (
action: "drift"): which master texts changed since the export, per language, compared with the file's source text; the import warns about them too.
Reformat
ae_reformat makes the comp at another size (16:9 to 9:16, 1:1, 4:5 or any size) by rules you set, then checks
the result on every frame. Nothing is guessed for you: no presets and no "smart crop".
Rules: background layers that must cover or fit the new frame; layers that must stay inside title-safe, action-safe or the frame (with your margins); layers pinned to an edge or corner with a margin in px; which layers may scale and how far (a range in % of their size); a minimum text cap height; layers to switch off. Layers are named exactly or with wildcards (
Logo*). A layer no rule names keeps its offset from the frame centre, as After Effects' own Composition Settings resize does with the centre anchor.The edit: a duplicate of the comp (the source is never changed), in one undo step, with an optional checkpoint first and the Changes list. Position and Scale keys are mapped by the same move and scale, with spatial tangents and ease speeds scaled too, so the motion keeps its shape. Parented layers are moved in their parent's space, a track matte moves with its layer, 3D layers move with the frame centre. Precomps are reused unless a rule names a layer inside a full-frame precomp: then that precomp is duplicated and reformatted too, and the report says why (
precomps: "reuse"or"duplicate"to choose).The check: Preflight's project checks on the new comp (your safe-area rules and cap height, on every frame or every Nth), plus cover / fit and pins, plus the plan against what After Effects actually made. The verdict is Preflight's: PASS, FAIL (n), INCOMPLETE or WARNINGS (n).
When a rule can't be met (a title too wide for 9:16 without going below the minimum cap height, a pin that conflicts with title-safe), the layer keeps the best attempt and the report says FAIL, with the reason and what you could decide: a shorter text, a line break, a smaller minimum, another scale limit. The AI doesn't pick one for you.
dryRun: trueshows the plan and the predicted result without changing anything.
Render profile
After Effects' own profiler shows one frame. ae_render_profile shows where a comp's render time goes over the whole
timeline, and keeps a speed-up only when the picture is proven unchanged.
measuretimes sampled frames (by default 24 across the work area, the image cache purged before each render, the median of 3 renders counts) and shows them as a text heat map with the slowest ranges. Then, at the slowest frames, it switches each layer and effect off in turn and times the difference (cost in ms and %). Findings come with their evidence: invisible layers that still cost time, 32 bpc where 16 bpc is proven to give the same picture, expressions recomputed under motion blur, oversized precomps, hidden costs. Each finding is marked can apply (optimize can apply and prove it), advice (you decide) or unknown (for example Multi-Frame Rendering support, which scripting can't read).timeBudgetSeconds(default 300) stops new measurements and the report says what was measured.The project is left as it was. Every switch is put back and read back, and the result says so ("Project unchanged"). The switches still show as steps in Edit > Undo history that cancel each other, and After Effects may mark the project as having unsaved changes. In read-only mode only the frame times are measured.
optimizeapplies the findings you choose, one at a time, after a checkpoint. Each is proven withae_prove_identicalat the default tolerance; one that isn't identical is put back automatically. The result reports the time saved on the measured frames.Limits: frames between the samples are estimates; layer and effect costs overlap (mattes, adjustment layers, expressions), so they don't add up; the proof covers the sampled frames, not audio or the times between them. Profiles are kept in
~/.surehand/ae/profilesfor 7 days (30 at most).
Handoff package
Sending a project to a client, another studio or a render farm? ae_handoff_package collects it into a folder you
choose, with the layout of File > Dependencies > Collect Files: the project, and the footage it uses in
(Footage)/<Project panel folders>/, each image sequence in a folder of its own, proxies included. The project in the
package is a copy relinked to the collected files (footage items keep their names, which expressions may use);
collect: "all" copies unused footage too, and reduce: true leaves unused items out of the copy. Files that are
already in the folder are never replaced without overwrite: true, and the package can never be written over your
project or its footage.
Next to the project it writes handoff.json (for tools) and HANDOFF.txt (for people): the fonts the project uses and
the layers using each one (with version and Adobe Fonts where After Effects says so), every effect by match name with
its display name, category and version (the version After Effects reports for a plug-in, where it reports one; it
isn't the version in a plug-in's About box), the After Effects version, the bit depth and color settings (working space,
OCIO config and color spaces, linearize, blending), the expressions engine, each footage item's specs and where it went,
what is missing (footage, placeholders, fonts, plug-ins), and the total size. The first line says Opens clean and
what the recipient needs (fonts, third-party plug-ins with their versions, an OCIO config), or what doesn't open
clean: missing items, footage still pointing outside the package, unused footage that would show as missing, expression
errors (every expression is evaluated in the copy).
verify: true proves the package renders the same as your project. aerender, After Effects' command-line renderer,
renders sample frames (default 5 per comp across the work area; the render queue's comps in any status, else the active comp, or verifyComps) from a
copy of your project and from the package's copy, each in a process of its own, and the frames are compared pixel by
pixel with the same comparison as ae_prove_identical. The verdict is IDENTICAL, DIFFERS (with the frames, the
area and a difference image) or NOT VERIFIED with the reason (aerender not found, no PNG output module, a render
that failed). It takes minutes: aerender starts its own After Effects twice. What it can't prove is listed every time:
fonts and plug-ins on the recipient's machine (only this machine is checked), the package moved elsewhere (After
Effects finds collected footage relative to the project, as with Collect Files), frames between the samples, audio,
and expressions at other times than each comp's work area start. In the copies used for the proof, the render queue
holds only the sample frames, so your own queued renders never run.
Your open project is never edited, but scripts in After Effects can't save a copy of a project without opening it: the package is made with Save As, and your project is opened again from disk at the end. So the project must be saved (a project with unsaved changes is refused), its undo history starts fresh, and the result confirms the file on disk is unchanged (size, date and SHA-256) and that it reopened without unsaved changes. It follows the permission mode like any edit (refused in read-only; one approval in ask mode, before anything is written).
Render farm
A render that works here can fail on a farm node or a colleague's machine: a plug-in or font that isn't installed
there, footage on a path only this machine sees, another After Effects version, an OCIO config that isn't there.
ae_farm measures what a render needs instead of guessing, and splits long renders into chunks whose result is proven
complete. Your own render queue items and output modules are the source of truth: nothing is rendered with settings
of its own. It never runs anything on another machine; other machines get a manifest to check against and scripts to
run there.
manifest: for the queued render queue items (orrqIndex), exactly what a node needs: the After Effects version and build, bit depth, colour settings (working space, linear blending, OCIO config and whether it is inside the project folder), expressions engine, Multi-Frame Rendering where the preference can be read, every effect by match name (third-party ones marked, versions where After Effects reports them, the comps using them), the fonts of the text layers the render reaches, and every file the render pulls in through its precomps: path, size, an image sequence's frame range and gaps, proxies the render uses, and whether the path is local to this machine (home folder, Desktop, a local disk) or on a share (a network mount, a UNC path, or a folder you name withsharedPaths). Output modules: format, codec where scripting exposes it, path, and whether the folder exists and is writable.save: truewrites<project>.farm-manifest.jsonand.txtnext to the project (never over existing ones withoutoverwrite: true).check: a machine against a manifest: After Effects and aerender installed and the version, the project, footage (every frame of a sequence), proxies, OCIO config and output folders reachable, fonts in the font folders (PostScript names read from the font files), third-party plug-ins in the Plug-ins folders (by their match names), and the expressions engine. On a node, without After Effects:surehand-ae farm check <manifest.json> [--map /Volumes/Jobs=J:\Jobs] [--ae <install folder>] [--json](exit code 0 ready, 1 missing or different, 3 not everything could be checked). In a chat, the running After Effects' own lists of effects and fonts count too.plan: one render queue item split into frame ranges forprocesseson this machine or for namedmachines(each with its platform, aerender, path map and relative speed). Each chunk gets its aerender command (-project,-rqindex,-s/-eas the frame numbers After Effects shows (from the comp's start frame: 90000-90099 for a 4-second comp at 25 fps that starts at 01:00:00:00), an-outputwhere needed,-mfron a share of the CPU when several processes share a machine), and each machine a script (.commandon macOS,.baton Windows), written withfarm-plan.jsonnext to the project. Image sequences: every chunk writes into the same sequence; a plan is refused when the output module numbers files from "Starting #" (every chunk would overwrite the same files), and too short[####]padding is flagged. Movies: each chunk writes its own file, plus the ffmpeg concat step that joins them; the plan says when that isn't lossless (long-GOP codecs such as H.264, AAC audio, PCM joins that fall between samples) and recommends rendering an image sequence instead. Refused: several output modules on the item, render settings with their own frame rate, an audio-only output. The time estimate comes fromae_render_profile's measurements of the comp, else from a few frames sampled now, and says what it leaves out (aerender's start-up, encoding).run_local: the chunks as parallel aerender processes on this machine, as background-render jobs (logs, progress, cancel, the panel's job files): at most as many at once as the cores and memory allow, the others start as those finish. On Windows each starts once the one before has rendered its first frame (two aerender processes started at the same moment collide there); a chunk whose aerender ends before its first frame is started again once, andstatussays so with its log. Withoutplanit uses the plan next to the open project (and says which), and refuses when several render queue items have one. Existing output is never rendered over withoutoverwrite: true; a plan is refused once the project was saved again. The renders go on when the AI app reloads the server:statusfinds the run again from its files and shows each chunk's progress and time per frame (aerender's total time over its frames).statusonly reports (the latest run of the open project;all: truefor every run): it never starts or retries a render. A run whose chunks were still waiting when the server stopped is reported as interrupted, with the aerender commands of what is left;run_localwith itsrunresumes it, but only within 6 hours of its start and while the project is unchanged since its plan.verify: wherever the chunks ran, proof of the result. Sequences: every frame present once, no extras, no empty or cut-off files (a complete PNG, a JPEG end marker, a DPX size field; other formats by header), with the exact missing frames and the-s/-eranges to render again (missing, empty and cut-off frames). A few frames are looked at: when they are all the same flat picture (what frames outside the comp render as), it fails. With After Effects open on the project, 2 sampled frames are also compared with its own render of them (a tolerance of 4/255 for colour conversion; it fails on a different picture, by area: over 1% of the frame, or spread over a quarter of it; small local differences such as text edges, which aerender and the app anti-alias a little differently, are a note with their pixel count and place). Movies: each part's frame count and duration with ffprobe, then the joined file's frame count, size, frame rate and codec against the comp and the output module;join: truejoins the parts when that is lossless (never over an existing file).proveFramesmakes the pixel proof strict, on as many frames as asked (theae_prove_identicalcomparison and tolerance). The verdict is PASS, FAIL (n) or INCOMPLETE with what couldn't be checked.
Project X-ray
Opening someone else's project? Ask the AI to X-ray it (ae_project_xray). It reads the whole project without changing
anything and explains how it works instead of tidying it: which comps the render queue actually renders and the
precomps each one pulls in (and which comps nothing renders), what every expression reads and which layers the rig
hangs on, which links are already broken or will break when a layer is renamed or reordered or the project is opened
in another After Effects language, which plug-ins, footage and fonts are missing, how the footage is specified
(frame rates that don't match their comps, very large sources) and what makes it slow to render (heavy effects, effects
hidden on shy or disabled layers, high motion blur samples, the 3D renderer, frame blending, footage scaled far down).
You get a plain-language answer; the AI gets precise locations (comp > layer > property). Big projects are read
within a time budget and say so when the answer is partial; comps and sections narrow it down.
Project history
"What changed between v11 and v12?" ae_project_history answers it. A snapshot is a record of the open project:
every item (comps, footage with its file paths, solids, folders), comp settings, every layer with its switches,
timing, parent and track matte, every property that isn't at its default or is animated (values, keyframes with
interpolation and easing), expressions, effects, masks, text, markers and the render queue. Taking one doesn't change
the project and adds no undo step; snapshots are kept in ~/.surehand/ae/history (the last 100 per project), and every
ae_checkpoint save stores one too, so checkpoints can be compared (with a 15 s time budget, so saving stays quick; if
that isn't enough, the checkpoint says the snapshot is partial and a full one can be taken with snapshot). A diff compares two snapshots, or a snapshot with
the project as it is now, and lists what changed, grouped by comp, with a summary first:
Summary: 1 layer added, 1 layer renamed, 2 values changed, 1 keyframe change, 1 expression changed, 1 effect added
Comp "Main" (id 12):
+ layer #1 "Logo" (shape)
~ layer #2 "Title": renamed from "Headline"
+ Title > Effects/Glow (ADBE Glo2)
~ Title > Transform/Opacity: keyframes: @1s 100 -> 80
~ Title > Transform/Position: expression changed:
- wiggle(2, 10)
+ wiggle(3, 10)Refer to versions by label ("v11"), snapshot or checkpoint id, latest, previous or current. Long diffs are cut
with a count of what's left; detail shows one comp in full. A big project takes a while to read (seconds for
thousands of layers): comps limits a snapshot to some comps and timeBudgetSeconds caps the time (comps not reached
are reported, never silently skipped). Checkpoints saved before this feature have no snapshot; comparing them would
mean opening the old .aep in place of your project, so it isn't done automatically.
Chat with your AI app
The Surehand panel's ☰ › Chat with your AI app runs an AI agent you already have installed and signed in to: Codex, Claude Code or Antigravity. Your own subscription runs the model; Surehand never stores or handles a key or a sign-in. For each chat the agent gets Surehand's tools as its only tools, and it works on the open project.
Nothing bypasses your controls. The agent's calls are ordinary AI calls: Full / Ask / Read-only, Pause AI, the approval card and the activity log apply exactly as for any AI app. In Ask mode the approval card moves into the chat while it is open (Esc denies).
Built-in tools are off. The agent's shell, file edits and web access are switched off or not allowed; the agent's own approval prompt for Surehand's tools is off, so Surehand's mode is the one that decides.
Your agent's settings are left alone for Codex and Claude Code (options apply to the run only). Antigravity has no per-session MCP option, so the Chat screen asks once to Connect: it adds Surehand to Antigravity's MCP servers and one allow rule for Surehand's tools, after a backup; Disconnect and the uninstaller remove both.
Sign-in: the AI apps for chat screen shows each app as Ready, Not signed in or Not installed, with how to sign in (
claude auth login,codex login, or startagyonce).
Design notes, command lines and what each agent's stream looks like: docs/chat-in-ae.md.
In-chat views
In AI apps that show interactive views (MCP Apps; for example Claude Desktop, ChatGPT, VS Code and Cursor), some results come with a view in the chat:
Preflight report: the verdict, a timeline of the findings, and each finding's frame.
Project X-ray: what renders, from the render queue down to the footage, with what's missing, fragile, heavy while hidden or unused.
Stress test: a grid of variants and checks, each failing frame marked, and the expressions that break in other After Effects languages.
What changed, and the proof: a proven edit's verdict with before, after and difference frames, and what changed in the project (also for the history diff).
Views only navigate and look; they never change the project. Every edit goes through the chat. AI apps without views (Claude Code, Windsurf, LM Studio) get the same results as text.
Command line
The installed server is also a command: surehand-ae <command> (or node ~/.surehand/ae/server/surehand-ae.mjs <command>). surehand-ae --help lists everything.
Command | What it does |
| Check the installation and the connection; |
| A report to paste into a bug report (no secrets) |
| The last n tool calls |
| The AI apps on this computer and whether they are connected ( |
| HTTP server + public tunnel for ChatGPT on the web |
| Install the latest release, or only report |
| A project's checkpoints, what changed since one, save one |
| Where the Surehand skills are installed; write or remove them |
| On a render node, without After Effects: does it have what the render needs? |
| Install, remove, or only install/update the extension, config and skills |
Commands for the panel (with --json they print one JSON object and never ask anything; an unknown command exits
with an error): clients → {clients: [{id, name, installed, configured, inUse?, note?, action?}], snippet?};
connect <app> / disconnect <app> → {ok, message}; checkpoints [--project <path>] →
{checkpoints: [{id, at, label, file, history?}]}; checkpoint-diff <id> [--project <path>] → text ({text}; needs
After Effects: it compares with the open project); test --json → {checks: [{ok, name, message?, fix?: {connect, label?}}]}; update --check → {latest, current, updateAvailable, url, checkedAt, channel, notes?, keptBeta?}
(installs nothing). Errors come as {error}. The panel runs them with the Node and server named in
~/.surehand/ae/runtime.json. The activity log entries also carry changeList, revision, undoGroup and, for
ae_preflight / ae_prove_identical, result: {verdict, summary}; background renders keep
~/.surehand/ae/renders/<id>.json up to date.
Environment variables: SUREHAND_AE_CONFIG (config file;
instances are looked up next to it), SUREHAND_AE_BRIDGE_PORT, SUREHAND_AE_TOKEN, SUREHAND_AE_HTTP_PORT,
SUREHAND_AE_HTTP_TOKEN, SUREHAND_AE_TOOLS (core / full), SUREHAND_AE_INSTANCE,
SUREHAND_AE_BLOCKED_AFTER_SECONDS, SUREHAND_AE_STARTUP_WAIT_SECONDS, SUREHAND_AE_NO_UPDATE_CHECK,
SUREHAND_AE_NO_AUTOSETUP, SUREHAND_AE_NO_ACTIVITY_LOG.
Updates
Updating: click the version at the bottom of the panel (or ☰ › Check for updates…) and install from the
Updates screen, or run surehand-ae update (update --check only reports). It downloads the server from the
latest GitHub release, checks its SHA-256 checksum and that it starts, replaces the installed one (the old one is
kept as surehand-ae.mjs.previous) and updates the After Effects extension. Restart After Effects and your AI apps
afterwards. If you use the Claude Desktop extension (.mcpb), install the new Surehand-MCP.mcpb from the release
page instead. The panel shows · update ready next to the version when a new version is out (checked against
GitHub at most once a day; turn off with "updateCheck": false in ~/.surehand/ae/config.json).
Beta updates: turn on ☰ › Settings › Beta updates in the panel (or run surehand-ae update --channel beta;
"updateChannel": "beta" in config.json) to be offered pre-releases too: the newest of the betas and the stable
releases, checked and installed the same way. Turning it off (--channel stable) never goes back to an older
version: a newer beta stays until a newer stable release is out.
Updating from 1.3
Automatic. The first time 1.4 runs (installer, update, or just starting), your settings, checkpoints, project
history, access token and AI app connections carry over, so a ChatGPT connector URL keeps working. Nothing is
deleted: if something can't be moved (a file in use), everything keeps working where it was and the move is tried
again later; the reason is in ~/.surehand/migration.log. Restart After Effects once to load the new panel; until
then Surehand says so. With the Claude Desktop extension: the 1.4 .mcpb installs as a new extension
(surehand-ae), so after installing it remove the previous version's entry in Settings > Extensions. What moves
where is under Names for developers.
Troubleshooting
Problem | Fix |
"Cannot reach After Effects" | Make sure AE is running. Open Window > Extensions > Surehand MCP to see the bridge status. If Surehand MCP is missing from the menu, re-run the installer and fully restart AE. |
Extension missing from the menu | Run |
"Ports 8765-8774 are all in use" | Each After Effects takes the first free port from 8765 to 8774, so this means ten bridges are running or other programs hold those ports. Close other After Effects instances (or the program using the ports), or change |
"Token mismatch" | Re-run the installer (it keeps the existing token) and restart AE. |
Scripts can't run shell commands or use the network ("Permission denied") | Enable Settings > Scripting & Expressions > Allow Scripts to Write Files and Access Network in After Effects (Windows: Edit > Preferences > Scripting & Expressions). Surehand's own tools don't need it, and scripts can read and write files without it; |
A call times out | ExtendScript can't be interrupted: long scripts or renders keep AE busy, and modal dialogs block it. Check AE, then retry. Pass |
"After Effects is busy or showing a dialog" | A dialog or settings window (Project Settings, Preferences, an alert) is open in AE, or AE is still starting. Close it and retry: the call did not run and won't run later. Reported after 3s; change with |
Claude Desktop doesn't show the tools | Quit Claude Desktop completely (menu bar / tray) and reopen it. Check |
Reporting a problem: run 2. Test Installation or surehand-ae selftest. If anything fails, it prints a
diagnostics report at the end (no secrets in it). You can also click Copy diagnostics in the Surehand panel, or
run surehand-ae diagnostics, and open an issue. More help:
the wiki (Troubleshooting,
The Surehand panel).
Several After Effects versions at once. Each running After Effects registers its own bridge (ports 8765–8774).
The AI controls the one you used most recently; ae_status lists all of them and switches with instance: "2025"
(or a version or port). Set a permanent preference with "instance": "2026" in the config.
Cancel and stuck detection. When the AI app cancels a request, it is dropped if After Effects hasn't started it
yet. If After Effects doesn't answer, the error says what it is busy with and for how long, and suggests checking
for an open dialog. ae_status shows the same.
Limits
What Surehand doesn't do, or can't do yet. Each feature's own limits are in its reference section.
CEP today. The panel and bridge are a CEP extension, the extension system After Effects supports today. Adobe is bringing UXP, its newer extension system, to After Effects; a UXP panel is planned, and the scripting layer stays the same.
After Effects must be running. Surehand works through the open After Effects (a few things, such as
ae_find_filesandsurehand-ae farm check, don't need it). Tested release by release on After Effects 2025 and 2026, macOS and Windows 11; older versions back to CC 2019 load the extension but are best effort, and some checks need a newer After Effects (paragraph overflow 24.6, missing-glyph checks 25.1) and say so instead of passing.One undo step, with exceptions. Every tool call is one undo group, but After Effects can split some groups (seen with comp duplicates, layer copies and source replacements). Precomp surgery and deep duplicates name the exact way back instead. The handoff package reopens your project from disk, so its undo history starts fresh. The panel's Undo only offers the most recent change, and only when nothing changed since.
"Allow Scripts to Write Files and Access Network". Surehand's own tools don't need this After Effects setting, and scripts can read and write files without it. Scripts that run shell commands or use the network do;
ae_statusand the panel's test screen show whether it is on.ffmpeg is needed for Preflight's checks on rendered files and for the farm's movie chunks (counting frames, joining parts). Surehand uses yours, or downloads a pinned, checksum-verified build once, only after you allow it. Everything in the project itself works without it.
aerender (installed with After Effects) is needed for background renders, the handoff package's render proof and the farm's local runs.
Proofs sample frames.
ae_prove_identical, precomp surgery and render optimizations compare the sampled video frames, alpha included. Audio, the comp's background colour and the times between samples are not compared.Preflight's flash check is a pre-check, not a certified PSE / Harding test.
Read-only mode and the permissions are guardrails, not a sandbox. See What the AI can and can't do.
Chat in After Effects supports Codex, Claude Code and Antigravity. Antigravity's output format isn't documented yet: Surehand reads the format Antigravity's CLI 1.4 writes, so a later Antigravity version may need an update.
Right to left: paragraph direction, the composer and alignment are set; mirroring the layout itself, kashida justification and per-character direction are not available to scripts.
FAQ
Does it make motion graphics from a prompt? No. It operates After Effects on your project: your layers, keyframes, expressions and rules. It doesn't generate images and ships no presets or looks.
Does my project leave my computer? The project files stay local. Your AI app sends your messages and the tool results (including frames the AI renders to look at) to its provider, under that provider's terms.
Does it cost anything, or need an account? No. It is free and MIT licensed. You need an AI app you already use; its own plan applies.
Which AI app works best? Any app that supports MCP tools works. Apps that show in-chat views (Claude Desktop, ChatGPT, VS Code, Cursor) also show the Preflight, X-ray, stress-test and proof views.
Will the AI break my project? It can make mistakes like anyone. That is why every edit is one undo step with a change report, structural edits are proven, Ask mode shows you each edit first, and checkpoints keep safety copies.
Is a non-English After Effects supported? Yes. Property, effect and menu names are mapped to match names, which are the same in every language, and the stress test and X-ray flag expressions that break in another language.
Development
server/ MCP server (TypeScript) -> bundled into server/dist/surehand-ae.mjs
src/aemcp.jsxinc ExtendScript helper library, loaded into AE on demand (reloaded when it changes)
src/tools/ tool definitions (each tool is a small ExtendScript function body)
src/cli/ install / uninstall / selftest / chatgpt / setup commands (surehand-ae <command>)
src/chat/ the panel's Chat with your AI app (agents, runner)
scripts/smoke.mjs end-to-end test against a running After Effects
scripts/package.mjs builds the shareable release folder, zip and .mcpb
scripts/release.mjs cuts a release: version, sign, check, Mac + Windows tests, package, installers, release PR, CI, merge, GitHub release
scripts/test-mac.mjs installs the build on this Mac and runs the full self-test on each open After Effects
scripts/test-windows.mjs the same on a Windows PC over SSH
scripts/test-guard.mjs lock and build checks so parallel test:mac runs don't test each other's build
scripts/sign-extension.mjs signs the After Effects extension
scripts/package-mac-pkg.mjs the signed, notarized Mac installer (.pkg)
scripts/package-win-installer.mjs the Windows installer (.exe, NSIS, built on the Mac)
scripts/sign-win.mjs signs Windows files with the Certum certificate (SimplySign)
scripts/ci-check.mjs assertions for the CI install / uninstall dry runs
extension/ After Effects extension (signed): invisible bridge (auto-starts) + status panel
skills/ the Agent Skills (embedded in the server bundle; `install` writes them)
docs/ design notes (chat-in-ae.md)
installer/ run.sh / run.ps1: find or download Node.js, then run a surehand-ae command
START HERE.txt plain-language install guide (copied into the release)
mac/, windows/ double-click launchers for a source checkout (the release generates its own)
brand/ the logo: master SVGs, PNG sizes, Surehand.icns / Surehand.ico (see brand/README.md)
.github/workflows/ CI: unit tests + real launcher install/test/uninstall on macOS and Windowscd server
npm install
npm run check # what CI runs: type-check, all tests, build (run before pushing)
npm test # unit tests only
npm run build # -> dist/surehand-ae.mjs
node scripts/smoke.mjs # live test: needs After Effects running with the bridge
npm run package # -> ../dist-zip/Surehand-MCP/ (launchers, server, Surehand-MCP.mcpb) + zip
npm run sign # re-sign the After Effects extension after changing extension/ or the version
# (needs the certificate in ~/.aemcp-signing; see scripts/sign-extension.mjs)
npm run test:mac # install this build here and run the full self-test on each open After Effects
# (one run per Mac at a time: waits for ~/.surehand/test-mac.lock; reports the commit tested)
npm run test:windows # the same on the Windows PC over SSH
npm run package:mac-pkg # -> ../dist-zip/Surehand-MCP-<version>.pkg, signed and notarized (--no-notarize: faster)
npm run package:win-installer # -> ../dist-zip/Surehand-MCP-Setup-<version>.exe (--sign: needs SimplySign logged in)
npm run release -- 1.4.0 --notes notes.md # everything above, then a release PR, its CI, merge and the GitHub release
# (1.4.0-beta.1 makes a GitHub pre-release; --skip-installers skips both installers)The After Effects extension in extension/ is embedded in the server bundle at build time, and the server installs
or updates it when it starts. After changing the server or the panel: rebuild, re-run the installer, restart After
Effects.
To add a tool, add an entry to one of the arrays in server/src/tools/*.ts: a zod input schema plus an ExtendScript
function body that receives args and can use the aemcp helpers. The tool counts in this README are checked by
server/test/readme-tool-count.test.ts.
Names. The family is Surehand (Photoshop and Premiere may follow), so this app's names are surehand-ae: the
command (ae-mcp stays as an alias), the server file surehand-ae.mjs, the MCP server name and the key in each AI
app's settings (SERVER_NAME; 1.3 used after-effects), the .mcpb name (its display_name is "Surehand MCP"),
and the folders ~/.surehand/ae (this app) and ~/.surehand (shared: node/, ffmpeg/); all in
server/src/paths.ts. Unchanged so scripts and the extension keep working: the tool names (ae_*), the After
Effects extension id com.aemcp (and its bundle ids), the aemcp helper object and aemcp:// resource URIs.
Environment variables are SUREHAND_AE_*; the AEMCP_* names still work. Releases carry the server as
surehand-ae.mjs and also as ae-mcp.mjs (what 1.3's updater downloads). The npm package name is surehand-mcp.
Moving from 1.3 (server/src/migrate.ts): 1.3 kept everything in ~/.aemcp. 1.4 moves settings,
checkpoints, project history and other files to ~/.surehand/ae, the private Node.js and ffmpeg to ~/.surehand,
and points AI apps that ran the old server at the new one (after-effects becomes surehand-ae; an
after-effects entry that isn't ours is left alone). Until After Effects is restarted once, the old extension still
runs and uses ~/.aemcp, so a copy of config.json, an instances folder, a small server/ae-mcp.mjs that starts
the new server and MOVED.txt stay there; uninstalling removes them too.
Testing a build on Windows
Confirmed working on Windows 11: install (including the automatic Node.js download), self-test, and the ChatGPT desktop app. Use this checklist to test other machines.
You need a Windows 10/11 PC (or VM) with After Effects. Your Creative Cloud license allows two activations, so a second machine works. On a Mac, a Windows VM in Parallels/VMware also works, but performance under x64 emulation on Apple Silicon may be slow, so a real PC is better.
Copy
Surehand-MCP-<version>.zipto the PC, right-click > Extract All.Make sure After Effects is closed, then open
3. Windowsand double-click 1. Install.If SmartScreen appears: More info > Run anyway.
Expect: Node.js downloads if missing, then check marks for the server, the extension ("Extension is signed") and apps found.
Start After Effects and wait for it to finish loading.
Double-click 2. Test Installation (same folder). All lines should show check marks, ending with "All checks passed".
In After Effects, open Window > Extensions > Surehand MCP: the dot should be green.
Open Claude Desktop (restart it if it was open during the install) and ask: "Check After Effects is connected, then make a 1080p comp with an animated title and show me frame 1."
Optional, more thorough: with Node installed, run
node server\scripts\smoke.mjsfrom a full source checkout (npm installinserver\first). This calls all major tools and needs After Effects open.Also try the
.mcpb: run 4. Uninstall, double-click1. Claude Desktop (easiest)\\Surehand-MCP.mcpb, install it in Claude Desktop, ask Claude to check the connection (it should say to restart After Effects), restart AE, ask again.
Things worth checking specifically on Windows: paths with spaces or non-English characters in the user name,
a machine without Node.js (tests the automatic download), and Windows on ARM.
If something fails, send the full output of 2. Test Installation and %USERPROFILE%\.surehand\ae\bridge-status.json.
License and credits
MIT, see LICENSE. A Conform Labs product, created and maintained by Ron Yitzhaki (@ronyitzhaki).
Surehand doesn't ship FFmpeg: when you allow it, it downloads the publisher's own build (Martin Riedl's builds on macOS, BtbN/FFmpeg-Builds on Windows) under that build's licence; see ffmpeg. JavaScript in scripts is converted for ExtendScript with Babel.
Adobe and After Effects are either registered trademarks or trademarks of Adobe in the United States and/or other countries. Surehand MCP is not affiliated with or endorsed by Adobe.
Available Tools
29 toolsae_add_layerAdd layerA
Add one new layer to a composition: solid, text, shape (empty, use ae_add_shape to draw), null, adjustment, camera, light, or an existing project item (footage/comp). Each call adds another layer, on top unless moveToIndex is given. Returns the new layer's index, id and name. Text options apply to text layers only. To edit existing text use ae_set_text, for switches, timing or parent ae_set_layer_attributes (both via ae_call).
| Name | Required | Description | Default |
|---|---|---|---|
| comp | No | Composition: item id (number) or exact name. Omit (or "active") for the active/open composition. | |
| font | No | PostScript font name, e.g. "Arial-BoldMT", "Helvetica", "Montserrat-Bold". | |
| item | No | For type 'item' (required there): project item to add. | |
| name | No | Layer name (default: After Effects' name, e.g. "Solid", "Camera"). | |
| text | No | For type 'text': the text (default empty). | |
| type | Yes | Layer kind; 'item' adds the project item given in item. | |
| color | No | Solid/adjustment color, or light color. | |
| width | No | Solid/adjustment width in pixels (default: comp width). | |
| height | No | Solid/adjustment height in pixels (default: comp height). | |
| threeD | No | Make the layer 3D. | |
| allCaps | No | Text: all caps. | |
| boxSize | No | Paragraph (box) text size [w,h]; omit for point text. | |
| leading | No | Text: line spacing in pixels (turns auto leading off). | |
| duration | No | Layer duration in seconds (default comp duration). | |
| fauxBold | No | Text: faux bold. | |
| fontSize | No | Text: font size in pixels. | |
| position | No | Layer position [x,y] or [x,y,z] in comp pixels (cameras and lights default to the comp center). | |
| tracking | No | Text: tracking (After Effects units, 1/1000 em). | |
| direction | No | Paragraph direction (AE 24+). Default: text without Hebrew/Arabic characters is set left to right whatever the user's AE type preference is. | |
| fillColor | No | Text: fill color, "#rrggbb" or [r,g,b]. | |
| lightType | No | For type 'light' (default: After Effects' default). | |
| startTime | No | Layer start time in seconds (comp time). | |
| fauxItalic | No | Text: faux italic. | |
| moveToIndex | No | Move the new layer to this 1-based index (new layers are added on top). | |
| strokeColor | No | Text: stroke color, "#rrggbb" or [r,g,b]. | |
| strokeWidth | No | Text: stroke width in pixels. | |
| justification | No | Text: paragraph alignment. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare non-readonly and non-idempotent; the description reinforces this by saying each call adds another layer and where it lands (on top unless moveToIndex). It also discloses the return payload (new layer's index, id and name), which the annotations cannot express. It stops short of noting undo/recovery or that the target comp must be open.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four sentences, front-loaded with the layer-kind enumeration before the placement and return behavior. Dense but every clause carries information (sibling routing, defaults, return shape); the parenthetical asides are the only minor clutter.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 27-param creation tool with no output schema, the description covers the return value, default placement, and conditional parameter applicability. Missing only ancillary context such as permission/open-project prerequisites or the undo path, which is a modest gap rather than a blocker.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and all 27 parameters are individually documented, so the baseline is 3. The description adds cross-parameter semantics the schema cannot: text options apply only to text layers, moveToIndex overrides default top placement, and shape layers are created empty. That grouping genuinely helps the agent pick valid parameter subsets for a 27-param tool.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (add) and resource (one layer to a composition) and enumerates the supported layer kinds: solid, text, shape, null, adjustment, camera, light, item. It explicitly carves out the empty-shape case to ae_add_shape, so an agent can separate this from the shape sibling without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Names the alternatives and the conditions that select them: use ae_add_shape to draw into an empty shape, ae_set_text to edit existing text, ae_set_layer_attributes (via ae_call) for switches/timing/parent. It also tells the agent that each call adds exactly one layer and lands on top unless moveToIndex is given, which is the key routing decision between repeat calls.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ae_add_shapeAdd shapeA
Draw a shape (rectangle, ellipse, polygon, star, or custom path) with fill and/or stroke, as a new shape group on a new shape layer or added to an existing shape layer (its other groups are kept). Positions are relative to the layer (new layers are centered in the comp, so [0,0] is the comp center). Returns the layer and the new group. To cut out part of a layer use ae_add_mask (via ae_call).
| Name | Required | Description | Default |
|---|---|---|---|
| comp | No | Composition: item id (number) or exact name. Omit (or "active") for the active/open composition. | |
| fill | No | Fill color; omit for no fill (unless no stroke either: defaults to white). | |
| name | No | Name of the new shape group, and of a new layer (default "Shape Layer"). | |
| size | No | [w,h] in pixels for rectangle/ellipse (default [400,400]); polygon/star radii default from its width. | |
| layer | No | Existing shape layer to add to (other layer types fail); omit to create a new one. | |
| shape | Yes | ||
| closed | No | For 'path': close the path (default true). | |
| points | No | Polygon/star: number of points (default 5). | |
| stroke | No | Stroke color; omit for no stroke. | |
| position | No | Shape center within the layer (default [0,0]); not used for 'path'. | |
| vertices | No | For 'path' (required): points [[x,y],...] in layer coordinates. | |
| roundness | No | Rectangle corner roundness in pixels (default 0). | |
| inTangents | No | For 'path': incoming Bezier handle per vertex, [[x,y],...] relative to the vertex (default: straight segments). | |
| innerRadius | No | Star: inner radius in pixels (default size[0]/4). | |
| outTangents | No | For 'path': outgoing Bezier handle per vertex, relative to the vertex. | |
| outerRadius | No | Polygon/star: outer radius in pixels (default size[0]/2). | |
| strokeWidth | No | Stroke width in pixels (default 4); only with stroke. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, it explains that a new shape group is created, existing groups are preserved, coordinate positions are layer-relative, new layers are centered in the comp, and it returns the layer and new group. It does not elaborate on non-idempotency or permission requirements, but the annotations already establish the mutation and safety profile.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core operation, then adds coordinate semantics, return values, and the mask alternative in a compact sequence. Every sentence contributes actionable information without redundant restatement of schema defaults.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 17-parameter mutation tool with high schema coverage and no output schema, the description covers layer targeting, coordinate behavior, return values, and the key alternative tool. Nothing essential about invoking it correctly appears to be missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already documents 94% of the 17 parameters, so the baseline is 3. The description adds useful semantic context about coordinate positioning relative to the layer and the comp-center convention for new layers, which is not fully captured by the schema alone.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
It names the specific action (draw a shape) and enumerates the shape types, fill/stroke support, and whether it creates a new shape layer or adds to an existing one. It also explicitly distinguishes itself from ae_add_mask for cut-out operations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description states when to use an existing layer versus creating a new one, notes that existing groups are kept, and names ae_add_mask as the alternative for cutting out part of a layer. This gives clear routing guidance without leaving the agent to infer alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ae_apply_effectApply effectA
Apply an effect to a layer by match name (preferred, e.g. "ADBE Gaussian Blur 2", "ADBE Fill", "ADBE Glo2", "ADBE Drop Shadow") or display name, optionally setting parameters. Each call adds a new instance at the bottom of the layer's effect stack. Returns its index in the stack, its parameters and the values set; an unknown effect name fails with suggestions. Check parameter names first with ae_get_effect_params; change an applied effect with ae_set_effect_params, search installed effects with ae_list_available_effects (both via ae_call).
| Name | Required | Description | Default |
|---|---|---|---|
| comp | No | Composition: item id (number) or exact name. Omit (or "active") for the active/open composition. | |
| name | No | Name for the new effect instance (default: After Effects' name for it). | |
| layer | Yes | Layer: 1-based index (number) or exact layer name. | |
| effect | Yes | Match name (e.g. "ADBE Gaussian Blur 2", works in every AE language) or display name ("Gaussian Blur"). | |
| params | No | Effect parameters by display name or match name, e.g. {"Blurriness": 20, "Repeat Edge Pixels": true} or {"Color": "#ff0000"}. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly=false and idempotent=false, but the description adds substantive behavior: each call appends a NEW instance at the bottom of the stack, unknown names fail with suggestions, and the return payload (stack index, parameters, values set) is disclosed. That is exactly the non-idempotent side effect an agent needs to know before calling.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the action and its preferred argument form, followed by side-effect behavior, return shape, and sibling routing. Dense but nearly every sentence earns its place; the final parenthetical '(both via ae_call)' is a minor aside that could be trimmed.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, yet the description explains the return value (stack index, parameters, set values) and the failure mode (unknown name with suggestions). Combined with 100% schema coverage and full sibling routing, an agent has everything needed to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so all five parameters are already documented in the schema, including match-name vs display-name semantics. The description reinforces match-name preference with examples but adds no new syntax or constraints, and the optional `name` and `params` merging behavior is only briefly touched. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Apply an effect to a layer'), lists concrete match-name examples, and names the display-name alternative. An agent can distinguish it from ae_set_effect_params and ae_list_available_effects purely from the description.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes the agent: check parameter names with ae_get_effect_params first, use ae_set_effect_params to change an applied effect, and ae_list_available_effects to search installed effects. The when-to-use and when-not-to-use cases are both named.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ae_batchBatch editsADestructive
Run many steps in ONE call: each step is a tool with its arguments (any project/comp/layer/property/keyframe/effect/text/footage tool) or {tool: "ae_run_script", args: {code}}. All steps form a single undo step and return one change report. Atomic by default: if any step fails, everything is undone and you get the error of the failing step. Use it for repetitive or multi-part edits (e.g. style 30 layers, build a scene) to save round trips; for a single edit call the tool directly. Not usable as steps: tools that can't be part of an undo step (open/save project, undo/redo), renders and ae_checkpoint.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Undo step name shown in After Effects (default "Surehand MCP Batch"). | |
| steps | Yes | 1-200 steps run in order, each {tool, args} with the same args as calling that tool. | |
| atomic | No | Undo everything if a step fails (default true). false = keep successful steps and continue. | |
| verbose | No | Return each step's full result (default: short summaries). | |
| checkpoint | No | Save a project checkpoint before running (see ae_checkpoint). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark this as destructive, non-read-only, non-idempotent, and open-world, and the description adds important batch semantics: all steps form one undo step, atomic rollback happens by default, and failures return the failing step's error. This adds meaningful behavioral context beyond the annotations without contradicting them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core batch behavior, then covers atomicity, usage guidance, and exclusions. It is dense but appropriately sized for a complex orchestration tool, with no wasted filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex batch tool with no output schema, the description explains the return model as one change report, the atomic rollback behavior, and the failing-step error behavior. Combined with the fully described schema, it gives an agent enough context to invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents the parameters. The description still adds useful meaning by explaining that each step is a tool plus arguments, that any project/comp/layer/property/keyframe/effect/text/footage tool is allowed, and that ae_run_script is a special step form.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: running many tool steps in one batch call. It clearly distinguishes this from calling a single edit tool directly and explains the step structure, so an agent can identify the tool's role among siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly says to use this for repetitive or multi-part edits, to call tools directly for a single edit, and names tool categories that cannot be used as steps. These are clear when-to-use, when-not-to-use, and alternative-selection instructions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ae_callRun any toolADestructive
Run any After Effects tool by name with its arguments, e.g. tools listed by ae_tools that aren't loaded in this chat. Same validation, permissions, change report and activity log as calling the tool directly. Get the parameters with ae_tools {describe: [name]}. Invalid arguments come back as an error listing them. Tools loaded in this chat don't need it: call them directly.
| Name | Required | Description | Default |
|---|---|---|---|
| args | No | The tool's arguments. | |
| tool | Yes | Tool name, e.g. "ae_set_camera". |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds real context beyond the annotations: the call gets the same validation, permission checks, change report and activity log as a direct invocation, and malformed arguments return an error enumerating them. It does not restate the destructive/openWorld hints or warn that destructive consequences are inherited from the target tool, which is the one behavioral nuance an agent would still have to infer.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four short sentences, front-loaded with the purpose, then discovery, then the equivalence guarantee, then the exclusions. No filler; each sentence carries a distinct instruction.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a generic dispatcher with a free-form nested args object and no output schema, it covers discovery, error behavior, and parity with direct invocation well. The return shape (presumably the target tool's result) and any depth/recursion limits are left implicit.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and both parameters are described in-schema, so the baseline is 3. The description does point to ae_tools {describe} for resolving the free-form args object, which is useful routing but not semantic detail about the arguments themselves.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource — run any After Effects tool by name with its arguments — and immediately scopes it to tools listed by ae_tools that aren't loaded in the chat. An agent can distinguish it from ae_batch and the direct per-tool siblings without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use (tools not loaded in this chat), explicit when-not-to-use ("Tools loaded in this chat don't need it: call them directly"), and names the discovery path ae_tools {describe: [name]} to obtain the target parameters. Both the positive and negative routing decisions are spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ae_checkpointProject checkpointsADestructive
Safety copies of the project: save (saves the open project, then keeps a timestamped copy), list the checkpoints of this project, or restore one (opens it as a NEW file next to the original; neither the original nor an earlier restore is ever overwritten). Use before large or risky changes. The project must have been saved once. save returns the checkpoint id and file; list the ids, times and labels; restore without id takes the latest and refuses while the open project has unsaved changes unless discardChanges. Keeps the 50 latest. To revert just the last edits use ae_undo.
| Name | Required | Description | Default |
|---|---|---|---|
| id | No | Checkpoint id to restore (from list). | |
| label | No | Short label for a new checkpoint. | |
| action | Yes | save a new checkpoint, list this project's checkpoints, or restore one. | |
| discardChanges | No | Restore even if the open project has unsaved changes (they are discarded). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: restore never overwrites the original or an earlier restore, retention is capped at the 50 latest, restore-without-id defaults to the latest, and the unsaved-changes guard is disclosed. The destructiveHint=true annotation is consistent with discardChanges discarding unsaved edits rather than with overwriting files.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the action enumeration and the safety rule before the operational details. It is dense with nested parentheticals, which costs a little readability, but essentially every clause carries operational information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, and the description compensates by stating what save returns (id and file) and what list returns (ids, times, labels). Preconditions, defaults, retention and side effects are all covered for a 4-parameter, three-mode tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds real semantics: omitting `id` on restore selects the latest, `discardChanges` overrides the unsaved-changes refusal, and `label` is only meaningful for save. Only the exact id format is left to the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names the resource (project checkpoints) and enumerates the three concrete operations with verbs: save, list, restore. The parentheticals define what each verb actually does (save = save project then snapshot; restore = opens a NEW file), so it is clearly distinguishable from siblings like ae_undo.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit when-to-use rule ('Use before large or risky changes'), a prerequisite ('The project must have been saved once'), and routes the agent elsewhere for the adjacent case ('To revert just the last edits use ae_undo'). It also states the restore precondition (refuses with unsaved changes unless discardChanges).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ae_create_compCreate compositionA
Create a new, empty composition in the open project and (by default) open it in the viewer. Returns the new comp's id, name and settings: pass the id as comp to later calls (names need not be unique). Then add layers with ae_add_layer / ae_add_shape. To copy an existing comp use ae_duplicate_comp, to move existing layers into a new comp ae_precompose (both via ae_call).
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Name of the new comp (After Effects allows duplicate names). | |
| open | No | Open in viewer (default true). | |
| width | No | Pixels, 4-30000 (default 1920). | |
| folder | No | Project folder to put the comp in: id or exact name (default: the project root). | |
| height | No | Pixels, 4-30000 (default 1080). | |
| bgColor | No | Background color, "#rrggbb" or [r,g,b]. | |
| duration | No | Seconds (default 10). | |
| frameRate | No | Frames per second, 1-999 (default 30). | |
| pixelAspect | No | Pixel aspect ratio (default 1, square pixels). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, idempotentHint=false, and destructiveHint=false, so the description does not need to re-establish basic safety. It adds useful context beyond the annotations: the comp is empty, it opens in the viewer by default, names need not be unique, and the returned id should be used in later calls. It does not discuss failure modes or permissions, but with annotations covering the core safety profile this is a strong disclosure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three dense sentences with no filler. The core creation behavior is front-loaded, followed by return-value guidance and then the sibling alternatives.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, but the description explains exactly what is returned ('the new comp's id, name and settings') and how to use the id in subsequent calls. It also covers defaults, follow-up layer creation, and alternative tools for copying or precomposing, leaving no essential gap for correctly invoking or chaining this tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the input schema already explains every parameter including defaults and ranges. The description adds only the name-non-uniqueness caveat and the id-return workflow, and does not elaborate on dimensions, duration, frame rate, or folder targeting beyond what the schema provides. The baseline of 3 is appropriate when the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a precise verb and resource: 'Create a new, empty composition in the open project', and immediately states the default viewer behavior. It clearly distinguishes creation from copying an existing comp or precomposing layers by naming ae_duplicate_comp and ae_precompose as alternatives.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit sequencing guidance ('Then add layers with ae_add_layer / ae_add_shape') and states when to use the alternatives: ae_duplicate_comp for copying an existing comp and ae_precompose for moving existing layers into a new comp. The default behavior and follow-up path leave little ambiguity about when and how to use this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ae_find_propertiesFind propertiesARead-onlyIdempotent
Search every layer of a comp (or one layer) for properties whose name or match name contains the query, e.g. "opacity", "blur", "Source Text", "ADBE Fill Color". Returns ready-to-use paths with values (and expressions with their errors). Filter to animated or expression properties. Needs a query or a filter; stops at limit and sets truncated. Read-only. Use it when you know a property's name but not its layer or path; to browse one layer's tree use ae_get_properties.
| Name | Required | Description | Default |
|---|---|---|---|
| comp | No | Composition: item id (number) or exact name. Omit (or "active") for the active/open composition. | |
| layer | No | Only search this layer: 1-based index or exact name (default: every layer). | |
| limit | No | Max results, 1-1000 (default 100). | |
| query | No | Case-insensitive text to match in the property name or match name. Omit to list all matches of the filters. | |
| onlyAnimated | No | Only properties with keyframes. | |
| onlyExpressions | No | Only properties with an expression. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the read-only, idempotent, non-destructive profile, and the description reinforces this. Beyond annotations, it adds useful behavior: returned paths include values and expression errors, limit truncation sets 'truncated', and the tool requires a query or filter. It does not cover permissions or output structure in exhaustive detail, so a 4 is appropriate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense and front-loaded: use case, scope, examples, return behavior, filters, constraints, and the sibling alternative are all stated without repetition. Every sentence adds actionable information for an agent.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, but the description compensates by explaining that results include ready-to-use paths, values, expression errors, and truncation state. With six fully described parameters and clear usage guidance, an agent has enough information to invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents each parameter well. The description adds meaningful framing about what query matches, what the animated/expression filters do, and that limit truncation is signaled, which goes beyond the individual schema fields.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource ('Search every layer of a comp... for properties') and clearly states what the tool returns. It also distinguishes this tool from the sibling browse tool by naming ae_get_properties as the alternative for browsing a layer's tree.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly states when to use this tool — 'when you know a property's name but not its layer or path' — and names the alternative for browsing a single layer's tree. It also states the prerequisite that a query or filter is required, preventing misuse.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ae_get_comp_infoGet composition infoARead-onlyIdempotent
Composition settings and markers plus a summary of its layers (index, id, name, type, timing, parent, switches). Large comps are paged: use layerOffset/layerLimit (see totalLayers / nextLayerOffset in the result). Read-only. Use it to see what a comp contains; for one layer in full use ae_get_layer_info, for nested precomps, parenting and expression links ae_get_comp_map.
| Name | Required | Description | Default |
|---|---|---|---|
| comp | No | Composition: item id (number) or exact name. Omit (or "active") for the active/open composition. | |
| layerLimit | No | Max layers to return (default 150). | |
| layerOffset | No | Skip this many layers (default 0). | |
| includeLayers | No | Include the layer summary (default true); false returns only the comp's settings and markers. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint/idempotentHint/destructiveHint=false, so "Read-only" is largely redundant, but the description adds genuinely new behavior: large comps are paged and the response carries totalLayers and nextLayerOffset. It does not explain what markers or switches contain, but the core operational behavior is disclosed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with what is returned, then paging, then disambiguation. The parenthetical field list is dense but informative, and no sentence is filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description has to describe returns, and it does so at the field-name level plus pagination guidance. It stops short of explaining the shape of settings/markers or default page size interplay, which leaves a minor gap for a zero-required-param read tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3; the description earns above baseline by tying layerOffset/layerLimit to the paged result fields rather than restating them. includeLayers is only implied through "summary of its layers," which is why this is not a 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (get comp info) and enumerates exactly what comes back: settings, markers, and a layer summary with index, id, name, type, timing, parent, switches. It is clearly differentiable from ae_get_layer_info and ae_get_comp_map, which are named for their narrower scopes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit routing: use this to see what a comp contains, ae_get_layer_info for one layer in full, ae_get_comp_map for nested precomps, parenting and expression links. It also states when to page and which result fields drive pagination (totalLayers / nextLayerOffset).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ae_get_comp_mapComposition structure mapARead-onlyIdempotent
Overview of how a composition is built: the tree of nested precomps (with how many times each is used), parenting chains, track mattes, and which layers/comps each expression references. Read-only. Use it to understand an unfamiliar comp before editing; for one comp's settings and layer list use ae_get_comp_info, for the whole project (render queue, missing items, fragile links) ae_project_xray (via ae_call).
| Name | Required | Description | Default |
|---|---|---|---|
| comp | No | Composition: item id (number) or exact name. Omit (or "active") for the active/open composition. | |
| depth | No | How deep to follow nested precomps (default 4). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, so the redundant 'Read-only' line adds little; however, the description does disclose the analytical scope of the call (static dependency analysis across precomps, mattes, expressions) which tells the agent what class of information it will get. It stops short of noting cost on heavily nested comps or how depth truncation is reported.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One dense but well-ordered sentence describing outputs, then a short routing sentence. Every clause earns its place; the purpose is front-loaded before the alternatives.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description carries the burden of describing return content and does so by enumerating the data categories an agent will receive. Combined with explicit sibling routing and fully documented parameters, nothing needed for correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and already documents the comp id/name/'active' semantics and the depth default of 4 with its 1-10 range. The description adds no parameter guidance beyond that, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Overview of how a composition is built') and enumerates exactly the structures returned: nested precomp tree with usage counts, parenting chains, track mattes, and expression cross-references. This is clearly distinguishable from ae_get_comp_info and ae_project_xray at a glance.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says to use it 'to understand an unfamiliar comp before editing' and names both alternatives with their conditions (ae_get_comp_info for one comp's settings/layer list, ae_project_xray for whole-project issues). Routing is fully determined.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ae_get_effect_paramsInspect effect parametersAIdempotent
List an effect's parameters (names, match names, value types, defaults, min/max) so you know the exact parameter names for ae_apply_effect / ae_set_effect_params (via ae_call). By default it reads a fresh instance: it applies the effect on a temporary comp and removes that comp again in the same undo step, so your comps and layers are left as they were. Pass comp+layer to read an effect already applied to that layer instead (current values). Unknown effect names fail with suggestions.
| Name | Required | Description | Default |
|---|---|---|---|
| comp | No | Composition: item id (number) or exact name. Omit (or "active") for the active/open composition. | |
| layer | No | Inspect the effect on this layer instead of a fresh default instance. | |
| effect | Yes | Match name (e.g. "ADBE Glo2") or display name ("Glow"); with comp+layer, also an index in the stack. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds real context beyond annotations: it explains that the 'read' temporarily applies the effect on a temp comp and removes it within the same undo step, which justifies readOnlyHint=false and reassures the agent that comps/layers are untouched. It also documents failure behavior (unknown effect names fail with suggestions). Minor gap: no mention of whether the temporary application can fail on effects requiring specific layer types.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three dense sentences, front-loaded with the purpose and payoff, then the side-effect/undo behavior, then the alternate mode. No filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, so the description usefully enumerates what is returned (names, match names, value types, defaults, min/max). Side effects, mode selection and error behavior are covered; only edge cases (invalid comp/layer, effects that cannot be instantiated) are unaddressed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3; the description adds cross-parameter semantics the schema does not convey, notably that comp+layer must be combined to target an already-applied effect and that omitting them yields a fresh default instance. The effect-name vs. index nuance is left to the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb (List) plus resource (an effect's parameters) with the exact returned fields enumerated in parentheses. It is clearly distinguished from siblings ae_apply_effect, ae_set_effect_params and generic property readers like ae_get_properties.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states the purpose is to obtain exact parameter names for ae_apply_effect / ae_set_effect_params, and gives a clear selection rule between the two modes: default fresh instance vs. pass comp+layer to read an already-applied effect with current values.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ae_get_layer_boundsLayer boundsAIdempotent
Exact on-screen bounding boxes of layers in composition pixels at a time, after all transforms, parenting, 3D and the active camera (via AE's own toComp()). Also reports whether each layer is visible at that time, fully/partly/not in frame, and inside action-safe (5% margin) and title-safe (10% margin). Use it to check alignment, spacing, overlaps and safe areas with numbers; to move layers by these bounds use ae_align_layers (via ae_call). It measures through a temporary probe layer removed in the same undo step; your layers are left as they were.
| Name | Required | Description | Default |
|---|---|---|---|
| comp | No | Composition: item id (number) or exact name. Omit (or "active") for the active/open composition. | |
| time | No | Seconds (default: the comp's current time). | |
| frame | No | Whole frame number from the comp's start (frame 0 = time 0), instead of time. | |
| layers | No | Layers to measure (default: all layers, up to 300). | |
| selectedOnly | No | Measure only the layers selected in After Effects. | |
| includeExtents | No | Include stroke widths, effects and other extents (default false = content box). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Critical context the annotations cannot convey: readOnlyHint=false is surprising for a measuring tool, and the description explains exactly why — it inserts a temporary probe layer and removes it in the same undo step, leaving the user's layers untouched. That resolves the apparent mutation risk and confirms the destructiveHint=false claim in prose.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core definition, then usage and alternative, then the side-effect disclosure. Every sentence carries information — the toComp reference, the safe-area margins, and the undo behavior all matter to a caller.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, and the description names the reported categories (bounds, visibility, in-frame status, action-safe and title-safe) which is enough to interpret the result at a high level. It stops short of describing the actual response shape, so an agent still has to inspect the return value to learn field names.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so every parameter (comp, time, frame, layers, selectedOnly, includeExtents) is already documented in structured data. The description clarifies the semantics of the measurement (post-transform, camera-aware) but adds no per-parameter meaning such as layer-name vs index behavior or default-time resolution.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Exact on-screen bounding boxes of layers in composition pixels') and pins down the measurement pipeline (after transforms, parenting, 3D and the active camera via toComp()). It is clearly distinguishable from measurement-adjacent siblings like ae_get_layer_info and from the mutation path ae_align_layers.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete use cases ('check alignment, spacing, overlaps and safe areas with numbers') and explicitly routes the related mutation to ae_align_layers via ae_call. It lacks an explicit when-not clause (e.g., versus ae_get_layer_info or ae_get_comp_map), so it falls just short of full routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ae_get_layer_infoGet layer infoARead-onlyIdempotent
Full info for one layer: switches, timing, parent, source, transform values, effects, mask count, markers, text, and every animated/expression property. Read-only; fails if the comp or layer isn't found. For all layers in brief use ae_get_comp_info, for the full property tree (paths to set) ae_get_properties, for the on-screen box ae_get_layer_bounds.
| Name | Required | Description | Default |
|---|---|---|---|
| comp | No | Composition: item id (number) or exact name. Omit (or "active") for the active/open composition. | |
| layer | Yes | Layer: 1-based index (number) or exact layer name. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover safety (readOnly, idempotent, non-destructive), so the bar is lower, and the description still adds a real behavioral fact: the call fails if the comp or layer isn't found. It does not mention that 'full info' on a heavy layer may be a large payload, nor any cost/size guidance, which keeps it just short of a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the returned payload followed by the failure condition and the sibling routing. Every clause carries information; nothing is redundant.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, yet the description compensates by enumerating the returned fields, so an agent knows what to expect. Error behavior and alternatives are also covered, leaving no meaningful gap for a two-parameter read tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the schema itself documents the id-or-name duality for both comp and layer, including the 'active' default. The description adds nothing about parameter semantics, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("Full info for one layer") and then enumerates exactly what is included — switches, timing, parent, source, transforms, effects, masks, markers, text, animated/expression properties. This level of specificity makes it immediately distinguishable from the info-gathering siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes the agent to three named alternatives with the condition that selects each: ae_get_comp_info for all layers in brief, ae_get_properties for the full property tree, ae_get_layer_bounds for the on-screen box. When-to-use and when-not-to-use are both covered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ae_get_project_infoGet project infoARead-onlyIdempotent
Summary of the open project: file path (null if never saved), unsaved-changes (dirty) state, item counts by type, bit depth, render queue size, active item. Read-only and quick: call it first to orient. For the connection and permission mode use ae_status; to list comps or items ae_list_comps / ae_list_items, for problems ae_project_health, for how a project works ae_project_xray (all via ae_call).
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive, so the safety profile is covered. The description adds meaningful traits beyond that: the tool is 'quick', the file path is null when the project has never been saved, and it enumerates the return payload since no output schema exists. It does not mention behavior when no project is open, which keeps it from a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, neither padded. The return contents are front-loaded before the routing guidance, so an agent skimming the first clause already knows what it gets back.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description carries the burden of describing returns and it does so field by field, plus it routes every adjacent need to the correct sibling. Nothing an agent needs in order to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is nothing for the description to disambiguate and the baseline is 4. The description correctly spends no words on arguments.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Summary of the open project') and then enumerates exactly what that summary contains: file path, dirty state, item counts, bit depth, render queue size, active item. An agent can tell immediately that this is orientation/overview and not a listing tool like ae_list_comps.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit ordering instruction ('call it first to orient') and then names four alternatives with their respective domains: ae_status for connection/permission mode, ae_list_comps / ae_list_items for comps and items, ae_project_health for problems, ae_project_xray for how a project works. Both when-to-use and when-not-to-use are covered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ae_get_propertiesGet propertiesARead-onlyIdempotent
Inspect the property tree of one layer (or a sub-group via path): names, match names, values, keyframe counts, expressions. Read-only. Use it to discover property paths before ae_set_property / ae_set_keyframes / ae_set_expression. To search a whole comp by name use ae_find_properties; for exact keyframe timing and easing use ae_get_keyframes (via ae_call). Large trees are truncated: lower depth or start at a path.
| Name | Required | Description | Default |
|---|---|---|---|
| comp | No | Composition: item id (number) or exact name. Omit (or "active") for the active/open composition. | |
| path | No | Start at this group/property (default: the whole layer). | |
| depth | No | Group depth to expand (default 2). | |
| layer | Yes | Layer: 1-based index (number) or exact layer name. | |
| keyframes | No | Include each keyframe's time, value, interpolation and ease (default false). | |
| includeHidden | No | Also list NO_VALUE properties such as group markers and buttons (default false). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false, and openWorldHint=false, so the safety profile is covered. The description adds useful behavioral context beyond annotations, especially that large trees are truncated and can be narrowed by depth or path, and it lists the kinds of property data returned. A 4 rather than 5 reflects that the exact return shape and any truncation limits are only lightly described.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose, then immediately adds routing guidance and truncation behavior. Every sentence earns its place: the field list, read-only note, setter prep guidance, sibling alternatives, and truncation workaround all provide actionable information without filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a six-parameter discovery tool with no output schema, the description is complete enough: it names the returned property fields, explains path/depth usage, warns about truncation, and routes to sibling tools for search and keyframe detail. An agent has what it needs to call this correctly without relying on missing output documentation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all six parameters are already documented in the input schema. The description adds some context for path and depth in relation to subgroup inspection and truncation, but it does not meaningfully elaborate keyframes or includeHidden beyond what the schema already states. Baseline 3 is appropriate because the schema is doing most of the parameter-documentation work.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb, 'Inspect', and a precise resource, 'property tree of one layer (or a sub-group via path)', then lists the contents surfaced: names, match names, values, keyframe counts, and expressions. It also distinguishes the tool from ae_find_properties and ae_get_keyframes, so an agent can identify it without opening sibling schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit when-to-use guidance: discover property paths before ae_set_property, ae_set_keyframes, and ae_set_expression. It also names concrete alternatives and the conditions selecting them: ae_find_properties for whole-comp name search and ae_get_keyframes for exact timing/easing. Truncation guidance to lower depth or start at a path is included.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ae_get_scripting_guideExtendScript guideARead-onlyIdempotent
Returns the After Effects ExtendScript cheat sheet (ES3 rules, helpers, common match names). Read before writing complex ae_run_script code; not needed for the dedicated tools.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so safety is covered. The description adds what the payload actually contains — ES3 rules, helpers, match names — which helps the agent decide whether fetching is worthwhile. It does not state the return format or approximate size, a minor gap for a content-retrieval tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two compact clauses with zero filler: the first declares the return contents, the second gates usage. The core purpose is front-loaded ahead of the usage caveat.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, read-only retrieval tool with no output schema, the description covers what is returned and when to call it. The only missing pieces are the response's form (raw text vs. structured) and rough length, which matter somewhat when deciding to spend context on it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the baseline is 4 and there is no parameter semantics for the description to carry. Nothing is missing on this dimension.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource — 'Returns the After Effects ExtendScript cheat sheet' — and enumerates its contents (ES3 rules, helpers, common match names). It also explicitly distinguishes itself from the dedicated tools, notably ae_run_script, so an agent can separate it from siblings without opening anything.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives both sides of the decision: use it 'before writing complex ae_run_script code' and it is 'not needed for the dedicated tools.' That names the trigger condition and the exclusion, leaving nothing to infer.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ae_get_selectionGet selectionARead-onlyIdempotent
What the user has selected right now: project items, and in the active comp the selected layers and selected properties (with paths usable by ae_set_property). Read-only. Use it when the user says "this layer" or "the selected ones". Lists are empty when nothing is selected, and comp is null when no comp is active. To change the selection use ae_select_layers (via ae_call).
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint and non-destructive, so the safety profile is covered; the description still adds value by declaring the empty-state semantics (empty lists when nothing is selected, comp null when no comp is active). It leaves the exact return structure undocumented, which with no output schema is a modest gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two dense sentences, front-loaded with what is returned, then when to reach for it, then the redirect to the mutation sibling. No filler and no repetition of annotation metadata beyond a brief 'Read-only' confirmation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a no-param read tool with no output schema, the description covers scope, empty-state edge cases, and cross-tool compatibility of returned paths. It could go slightly further on what a 'project item' entry contains, but an agent has everything needed to call it and interpret an empty result.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is nothing for the description to disambiguate and the baseline applies. The description correctly spends no words on parameter syntax.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names the exact resource and its three scopes: project items, selected layers in the active comp, and selected properties. It even states that returned property paths are consumable by ae_set_property, which separates it cleanly from siblings like ae_get_properties or ae_get_layer_info.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives a concrete trigger ("when the user says 'this layer' or 'the selected ones'") and routes the inverse operation elsewhere ("To change the selection use ae_select_layers (via ae_call)"). Both when-to-use and what-not-to-use-it-for are explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ae_list_scriptsList scriptsARead-onlyIdempotent
List the user's own After Effects scripts: AE's Scripts folder (and ScriptUI Panels) plus folders configured as "scriptFolders" in ~/.surehand/ae/config.json, with each script's name, path, kind (script or panel) and description from its header comment. Needs After Effects running (to find its Scripts folder). Run one with ae_run_script_file; for code you write yourself use ae_run_script.
| Name | Required | Description | Default |
|---|---|---|---|
| nameContains | No | Only scripts whose file name (without extension) contains this text, case-insensitive. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent, non-destructive, and closed-world behavior. The description adds useful context beyond annotations: the exact folders searched, the fact that AE must be running, and what fields each script entry includes. It does not discuss ordering or pagination, but that is a minor omission for a local read-only listing.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded: it first defines the list scope, then what each result contains, then the prerequisite, then the alternatives. Every sentence adds actionable information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only listing tool with no output schema, the description explains search locations, returned fields, the AE-running prerequisite, and how to proceed after listing. There are no significant gaps for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the single optional nameContains parameter is already fully documented in the schema. The description does not add filtering semantics beyond the schema, which is acceptable at the baseline when schema coverage is complete.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: list the user's own After Effects scripts, including the concrete search locations (AE Scripts folder, ScriptUI Panels, and configured scriptFolders). It also names the returned fields and distinguishes this discovery tool from ae_run_script_file and ae_run_script.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It clearly says to use this tool to find scripts, then explicitly routes execution to ae_run_script_file and routes self-written code to ae_run_script. It also gives the prerequisite that After Effects must be running.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ae_prove_identicalProve the render is unchangedADestructive
Prove a structural change (un-precompose, bake expressions, reorder effects, simplify a rig) left the render unchanged, or show which frames and areas differ. capture: render reference frames (default: active comp, 5 frames over the work area), returns a proof id. compare: render them again and compare pixel by pixel (verdict, per-frame max difference, changed pixels, ΔE, area, difference image). run: capture, ae_batch steps, compare, in one call. For un-precompose, prove the parent comp. Not for edits meant to change the picture (look at those with ae_render_frame). Only the sampled video frames are compared (alpha included; not audio, the comp background color or times between samples; 32 bpc values above 1.0 are clamped).
| Name | Required | Description | Default |
|---|---|---|---|
| id | No | compare: the proof id from capture (default the latest proof). | |
| name | No | run: undo step name. | |
| comps | No | capture/run: comps to prove (item id or exact name; default the active comp). | |
| steps | No | run: the edits, as ae_batch steps. | |
| times | No | capture/run: exact times in seconds (snapped to frames) instead of evenly spaced frames. | |
| action | Yes | ||
| atomic | No | run: as ae_batch (default true: a failed step undoes everything, and nothing is compared). | |
| frames | No | capture/run: number of frames spread over each comp's work area (default 5). | |
| maxSize | No | capture/run: longest rendered side in pixels (default 1920; larger comps are scaled down). | |
| verbose | No | run: full result of each step. | |
| tolerance | No | compare/run: allowed difference per channel, 0-255 (default 0.5: less than one 8-bit step, so only 16/32 bpc rounding is allowed; 0 = bit-identical). | |
| checkpoint | No | run: save a project checkpoint before the edits. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructive/open-world/non-idempotent; the description adds substantial beyond-schema behavior: only sampled video frames are compared, alpha is included, audio and comp background color are excluded, and 32 bpc values above 1.0 are clamped. It does not explicitly state that run leaves the project edited (or restores it), which is the key remaining unknown for a destructive tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the goal, then action-by-action breakdown, then exclusions and limitations – a clean information hierarchy. The limitation parenthetical is dense and the run semantics (whether edits persist) are compressed to the point of ambiguity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema and 12 parameters, the description does the necessary work: it names the return payload (proof id, verdict, per-frame max difference, changed pixels, ΔE, area, difference image) and the sampling limits. The main gap is what happens to the project state after run, which matters given destructiveHint=true.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 92%, so the baseline is 3; the description still earns credit by tying parameters to actions ('default: active comp, 5 frames over the work area') and by revealing that capture returns a proof id, which the schema cannot express. It doesn't add extra semantics for tolerance, maxSize or atomic beyond what the schema says.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and goal ('prove a structural change left the render unchanged') and then enumerates the three concrete actions (capture/compare/run) with what each does. It explicitly names the sibling ae_render_frame as the wrong tool for picture-changing edits, so an agent can distinguish it without reading schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use ('prove a structural change... or show which frames and areas differ'), when-not-to-use ('Not for edits meant to change the picture (look at those with ae_render_frame)'), and a non-obvious case rule ('For un-precompose, prove the parent comp'). That is a full routing decision tree in three sentences.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ae_render_contact_sheetPreview animation (contact sheet)ADestructiveIdempotent
Render several frames of a composition into ONE image (a grid, each cell labelled with its time and frame number), so you can judge motion, timing and easing, not just a single frame. Defaults to 9 frames spread over the work area. For one frame in detail use ae_render_frame. Writes a file only with outputPath, never replacing one unless overwrite.
| Name | Required | Description | Default |
|---|---|---|---|
| end | No | End time in seconds (default: work area end). | |
| comp | No | Composition: item id (number) or exact name. Omit (or "active") for the active/open composition. | |
| start | No | Start time in seconds (default: work area start). | |
| times | No | Exact times (seconds) instead of evenly spaced frames. | |
| width | No | Width of the returned image in pixels (default 1600). | |
| frames | No | Number of evenly spaced frames (default 9). | |
| columns | No | Grid columns (default: square-ish). | |
| overwrite | No | Replace an existing file at outputPath (default false: refuse). | |
| outputPath | No | Optional absolute path to also save the PNG to. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations flag destructiveHint=true and readOnlyHint=false; the description clarifies exactly what that means in practice — a file is written only when outputPath is supplied, and an existing file is never replaced unless overwrite is set. That is genuine added context beyond the annotation. Minor gap: it doesn't say whether rendering perturbs the open composition's playhead/state, which matters for idempotentHint=true.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences: purpose and output shape first, defaults second, alternative tool and write-safety last. Nothing is wasted or buried.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-required-parameter preview tool with full schema coverage and annotations, the description covers output shape, defaults, file-write safety, and sibling routing. Only the interaction between `times` and `frames` (mutually exclusive selection of sampling) is left to the schema, which is a small residual gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all nine parameters already carry defaults and constraints. The description restates the frame-count and work-area defaults and the outputPath/overwrite relationship, which is useful reinforcement but adds no semantics the schema lacks.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb ('render several frames') plus specific output form (one grid image with per-cell time/frame labels), and it explicitly distinguishes itself from ae_render_frame. An agent knows exactly what this produces without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives the use case ('judge motion, timing and easing, not just a single frame') and names the alternative with the selecting condition ('For one frame in detail use ae_render_frame'). This is explicit when-to-use routing, not inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ae_render_framePreview frameADestructiveIdempotent
Render a frame of a composition and return it as an image, so you can SEE the result. Inspection options: zoom into a region, render only some layers, show transparency on a checkerboard or a color, and compare against another time or comp as a difference image (black = identical). Large frames are downscaled to maxSize. Use it after visual edits; for motion use ae_render_contact_sheet, for exact colors ae_sample_pixels (via ae_call). Renders through a temporary comp, removed afterwards (hidden layers put back); writes a file only with outputPath, never replacing one unless overwrite.
| Name | Required | Description | Default |
|---|---|---|---|
| comp | No | Composition: item id (number) or exact name. Omit (or "active") for the active/open composition. | |
| time | No | Time in seconds (default: the comp's current time). | |
| layers | No | Render only these layers (others are hidden for the render and restored). | |
| region | No | Zoom into [x, y, width, height] in comp pixels (scaled up to maxSize, at most 8x). | |
| maxSize | No | Longest side in pixels of the returned image (default 1280). | |
| overwrite | No | Replace an existing file at outputPath (default false: refuse). | |
| background | No | "checkerboard" to show transparency, or a color like "#808080" behind the comp. | |
| outputPath | No | Optional absolute path to also save the PNG to. | |
| compareWith | No | Difference image against another time and/or comp (black where identical). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, it discloses important behavior: rendering goes through a temporary comp that is removed afterward, hidden layers are restored, large frames are downscaled, and files are written only with outputPath and never replaced unless overwrite is set. These details substantially clarify side effects and lifecycle.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but well structured: purpose first, then inspection options, downscaling, alternatives, and side effects. Every sentence carries operational value, and no space is wasted on restating schema details.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given nine parameters, a nested compareWith object, destructive file-write potential, and no output schema, the description covers what the tool returns and the important behavioral caveats. An agent has enough information to invoke it correctly and understand its side effects.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so parameter documentation is already strong. The description adds useful semantic context for key options: region zooming, layer-only rendering, checkerboard/color transparency, difference-image comparison with black meaning identical, and overwrite refusal behavior.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: render a frame of a composition and return it as an image. It explicitly distinguishes itself from ae_render_contact_sheet for motion and ae_sample_pixels for exact colors, so an agent can select it without inspecting sibling schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides explicit usage guidance: use after visual edits, use ae_render_contact_sheet for motion, and use ae_sample_pixels via ae_call for exact colors. The alternatives and selection conditions are named directly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ae_run_scriptRun ExtendScriptADestructive
Execute JavaScript inside After Effects (its ExtendScript scripting API) and return the result. This is the most powerful tool: anything in the After Effects scripting API is available (app, app.project, CompItem, layers, properties, render queue, File/Folder, system.callSystem...).
The code runs as the body of a function: use
return valueto send data back. Returned AE objects (comps, layers, properties, items) are summarized to JSON automatically.args(the JSON you pass inargs) andlog(...)are available; log output is returned too.Modern JavaScript is fine: let/const, arrow functions, template strings, destructuring, spread, classes, ?. and ??, for...of, plus map/filter/forEach/find/includes, Object.keys/assign and JSON (converted for AE automatically). Not available: async/await, Promise, Map/Set, generators.
The
aemcphelper library is available: aemcp.findComp(idOrName), aemcp.findLayer(comp, indexOrName), aemcp.findItem(ref), aemcp.resolveProp(layer, 'Transform/Position'), aemcp.color('#ff0000'), aemcp.compInfo(comp, true), aemcp.layerInfo(layer, true), aemcp.propInfo(prop, {depth:2}), aemcp.projectInfo().Collections are 1-based: app.project.item(1), comp.layer(1), prop.property(1).
The whole script is one undo step. Errors come back with the failing line and code around it. ae_get_scripting_guide has an API cheat sheet.
Prefer the dedicated tools for common edits (clearer validation and results); use this for anything they don't cover. For a script file on disk use ae_run_script_file.
| Name | Required | Description | Default |
|---|---|---|---|
| args | No | JSON object exposed to the script as `args`. | |
| code | Yes | JavaScript source; a function body, use `return` to return data. | |
| depth | No | How deep to serialize the returned value (default 4). | |
| report | No | List what the script changed in the project (default true). Set false for read-only queries on huge projects. | |
| transpile | No | Convert modern JS for ExtendScript (default true). Set false to send the code exactly as written. | |
| undoGroup | No | Undo step name (default "Surehand MCP Script"). Pass "" to skip the undo group. | |
| timeoutSeconds | No | Max seconds to wait for the result (default 120). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and openWorldHint=true, and the description layers on execution semantics the agent could not otherwise know: the script runs as a function body, the whole script is one undo step, errors return with the failing line and surrounding code, log output is returned, and returned AE objects are auto-summarized to JSON. It also names the language limits (no async/await, Promise, Map/Set, generators) and the 1-based collection indexing, which materially affect how code is written.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the one-line purpose, then bulleted detail with zero filler sentences. The aemcp helper enumeration and the JavaScript feature list are dense but each entry carries actionable information; a slightly tighter presentation could trim a few characters without losing meaning.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, and the description compensates fully: it describes what comes back (returned value, summarized AE objects, log output, errors with line context) and how deeply objects are serialized. For a 7-parameter, open-world, destructive execution tool, nothing an agent needs to invoke it safely is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds genuine meaning on top: it explains that `code` is a function body using `return`, that `args` is exposed to the script as a variable, and that transpilation exists because of ExtendScript's older JS dialect (with the exact supported/unsupported feature list). `depth` and `report` are left to the schema, which already documents them well.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (execute) and resource (JavaScript inside After Effects' ExtendScript API) plus the return behavior. It explicitly differentiates itself from siblings by saying dedicated tools are preferable for common edits and that ae_run_script_file handles on-disk scripts, so an agent can place it in the toolset without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit when-to-use (anything the dedicated tools don't cover) and when-not-to-use (common edits → dedicated tools; script file on disk → ae_run_script_file), plus a pointer to ae_get_scripting_guide for the API cheat sheet. Alternatives and the conditions that select them are named, not implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ae_run_script_fileRun JSX fileADestructive
Run an existing .jsx/.jsxbin script file from disk inside After Effects (like File > Scripts > Run Script File), e.g. one found with ae_list_scripts. args is exposed to the script as the global AEMCP_ARGS. Returns the value of the script's last expression and a change report; the run is one undo step. A missing file is an error; refused in Read-only mode. For code you write yourself use ae_run_script.
| Name | Required | Description | Default |
|---|---|---|---|
| args | No | JSON object exposed to the script as the global AEMCP_ARGS (default {}). | |
| path | Yes | Absolute path to the .jsx / .jsxbin file. | |
| timeoutSeconds | No | Max seconds to wait for the script, 1-3600 (default 300). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations (which only say destructive/openWorld/non-idempotent): it discloses that the run is a single undo step, that it returns the last expression's value plus a change report, how args are injected as the AEMCP_ARGS global, and the failure modes (missing file, Read-only mode). That is exactly the behavioral context the annotations cannot convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the action and the File > Scripts analogy, then the return/undo/error facts in compact clauses. No filler sentences; each one carries a distinct, actionable fact.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, and the description compensates by explaining what comes back (last expression value plus a change report). For a destructive, open-world tool with three params, the safety, return, and failure behavior are all covered.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so path, args and timeoutSeconds are already documented in the schema, including the AEMCP_ARGS default and the 1–3600 timeout range. The description's mention of args as the AEMCP_ARGS global largely restates the schema rather than adding new syntax or format guidance, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb+resource: runs an existing .jsx/.jsxbin file from disk inside After Effects, with a concrete analogy (File > Scripts > Run Script File). It explicitly distinguishes itself from the closest sibling, ae_run_script, and points at ae_list_scripts as the discovery path.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
States when to use this tool (an existing script file on disk, e.g. one found via ae_list_scripts) and when not to (code you author yourself → ae_run_script). It also names two hard preconditions: a missing file is an error, and the call is refused in Read-only mode.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ae_set_expressionSet expressionADestructiveIdempotent
Set, replace or clear (empty string) the expression on one property. Returns the expression, whether it is enabled, any error AE reports and the resulting value at the current time. To try an expression without keeping it use ae_check_expression, to edit text across many expressions ae_replace_in_expressions, to list them ae_get_expressions (all via ae_call).
| Name | Required | Description | Default |
|---|---|---|---|
| comp | No | Composition: item id (number) or exact name. Omit (or "active") for the active/open composition. | |
| path | Yes | Property path from the layer, "/"-separated display names or match names, e.g. "Transform/Position", "Effects/Gaussian Blur/Blurriness", "ADBE Transform Group/ADBE Opacity", "Contents/Rectangle 1/Fill 1/Color". | |
| layer | Yes | Layer: 1-based index (number) or exact layer name. | |
| enabled | No | Set false to keep the expression but switch it off, true to switch it on (ignored when clearing). | |
| expression | Yes | Expression code; an empty string removes the expression. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, idempotentHint=true and readOnlyHint=false, so the safety profile is covered; the description adds the return payload (expression, enabled flag, AE error, evaluated value at current time), which matters since there is no output schema. It does not state that an existing expression is overwritten irreversibly or point at ae_undo, which is the main remaining behavioral gap for a destructive write.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the action and the clear-case before the sibling routing list. The dense parenthetical of four tool names is information-dense rather than wasteful, and no sentence is filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a no-output-schema mutation tool, the description supplies the return fields, the clearing convention and alternatives, which is nearly everything an agent needs. It stops short of noting irreversibility of overwrite or the recovery path via ae_undo, a minor gap given destructiveHint=true.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, including the enabled flag and the 'empty string removes the expression' semantics, so the schema carries the parameter burden. The description only restates the empty-string clearing convention and adds the 'one property' scoping; it contributes nothing about path/layer/comp resolution beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb set (set, replace, clear) applied to a specific resource (an expression on one property), and the parenthetical '(empty string)' defines the clear case immediately. It explicitly distinguishes itself from ae_check_expression, ae_replace_in_expressions and ae_get_expressions, so an agent can differentiate without opening other schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The second sentence gives explicit routing rules: use ae_check_expression to try without keeping, ae_replace_in_expressions for bulk text edits, ae_get_expressions to list. Each alternative comes with the condition that selects it, and it notes all are reached via ae_call.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ae_set_keyframesSet keyframesADestructiveIdempotent
Create keyframes on a property in one call, with optional interpolation (linear/bezier/hold) and temporal easing. Place keys by time (seconds) or frame (whole frames). Example: path "Transform/Position", keyframes [{time:0,value:[0,540]},{frame:24,value:[960,540],easeIn:80}]. A key at a time that already has one replaces it; other existing keys stay unless clearExisting. Returns the property's keyframes. For one static value use ae_set_property; to edit existing keys ae_edit_keyframes, for exact tables across many properties ae_set_keyframe_table (both via ae_call).
| Name | Required | Description | Default |
|---|---|---|---|
| comp | No | Composition: item id (number) or exact name. Omit (or "active") for the active/open composition. | |
| path | Yes | Property path from the layer, "/"-separated display names or match names, e.g. "Transform/Position", "Effects/Gaussian Blur/Blurriness", "ADBE Transform Group/ADBE Opacity", "Contents/Rectangle 1/Fill 1/Color". | |
| layer | Yes | Layer: 1-based index (number) or exact layer name. | |
| easyEase | No | Apply easy ease (33%) to all new keyframes that don't specify easing. | |
| keyframes | Yes | Keyframes to set, each with time or frame and a value. | |
| clearExisting | No | Remove existing keyframes first. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructive=true and idempotent=true; the description adds valuable semantics beyond them: an existing key at the same time is replaced while other keys survive unless clearExisting, and the tool returns the property's keyframes. It never addresses failure modes (invalid path, locked property) or undo, which keeps it from a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose, then behavior, then a compact concrete example, then sibling routing — no filler sentences. It is a dense single block of prose, but each clause (replacement semantics, return value, alternatives) earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 6-parameter destructive mutation with no output schema, the description covers selection of time vs frame, replacement/retention semantics, the return value, and routing. The main gap is no guidance on failure conditions or the need for ae_undo after destructive clears, but the core call is fully specified.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents comp, path, layer, keyframes, ease, interpolation, and clearExisting in detail. The description's example illustrates the keyframe object shape (time/frame, value, easeIn) but adds no syntax or constraints the schema lacks, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb+resource: 'Create keyframes on a property in one call'. It then distinguishes itself from ae_set_property, ae_edit_keyframes, and ae_set_keyframe_table by naming each and what they do differently, so an agent can route correctly without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit alternatives with conditions: static value → ae_set_property, editing existing keys → ae_edit_keyframes, exact tables across many properties → ae_set_keyframe_table. It also states the time vs frame placement choice and clearExisting behavior, leaving little to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ae_set_propertySet property valueAIdempotent
Set the value of any property (transform, effect parameter, shape attribute, text...). If time is given (or the property already has keyframes) a keyframe is set at that time. Examples: path "Transform/Opacity" value 50; "Transform/Position" [960,540]; "Transform/Scale" [50,50]; "Effects/Fill/Color" "#ff0000". Returns the property's new state; fails if the path is a group or not found. For several keyframes with easing use ae_set_keyframes, for expressions ae_set_expression, for many parameters of one effect ae_set_effect_params (via ae_call).
| Name | Required | Description | Default |
|---|---|---|---|
| comp | No | Composition: item id (number) or exact name. Omit (or "active") for the active/open composition. | |
| path | Yes | Property path from the layer, "/"-separated display names or match names, e.g. "Transform/Position", "Effects/Gaussian Blur/Blurriness", "ADBE Transform Group/ADBE Opacity", "Contents/Rectangle 1/Fill 1/Color". | |
| time | No | Seconds (comp time): set a keyframe here, replacing one at that time. Omit for a static value (on an animated property: a keyframe at the current time). | |
| layer | Yes | Layer: 1-based index (number) or exact layer name. | |
| value | Yes | Value: number, array ([x,y] / [x,y,z] / color), string for text, or object for text style / shape path. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only say write, non-destructive, idempotent; the description adds the important hidden behavior that a keyframe is set implicitly when time is given or the property is already animated, plus that the new property state is returned. It stops short of mentioning side effects such as undo or checkpointing and behavior on expression-driven properties.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action, then the keyframe rule, then examples, then alternatives — a sensible order. The examples cluster is dense and slightly repetitive with the path schema examples, but each sentence still carries information needed to call the tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With five parameters, no output schema, and an annotation profile that covers safety, the definition covers the return value, the failure case, the implicit-keyframe gotcha, and the sibling routing needed to pick the right tool. Nothing an agent needs in order to invoke it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so 3 is the baseline; the description earns more by pairing example paths with example values (path 'Transform/Opacity' value 50; 'Effects/Fill/Color' '#ff0000'), showing accepted value shapes. The time parameter's keyframe-replacement semantics are restated but gain the extra animated-property caveat.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
A specific verb plus resource ('Set the value of any property') scoped to transform, effect parameter, shape attribute and text, so the range is unambiguous. Concrete examples (Transform/Opacity, Transform/Position) and explicit sibling routing make it distinguishable from ae_set_keyframes and ae_set_effect_params.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It states the alternative tools and the condition that selects each: 'For several keyframes with easing use ae_set_keyframes, for expressions ae_set_expression, for many parameters of one effect ae_set_effect_params (via ae_call).' It also names the failure conditions (path is a group or not found), which is clear guidance on when this call will fail.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ae_statusAfter Effects statusARead-onlyIdempotent
Check the connection to After Effects: app version, OS, open project, active item, permission mode, and whether AE is busy. Lists every running After Effects instance when several are open; pass instance (e.g. "2025", "2026" or a port) to choose which one this session controls. Call this first if unsure AE is reachable; if it isn't, the error says why (e.g. not running, or not taking scripts). For the project's contents use ae_get_project_info.
| Name | Required | Description | Default |
|---|---|---|---|
| instance | No | Switch to another running After Effects: "2026", "26.5", or a bridge port. Omit to keep the current one. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive, closed-world), so the description focuses on what annotations can't say: it lists every running instance, explains how the session's target is selected, and describes failure behavior (the error states why, e.g. not running or not accepting scripts). Only return formatting/pagination-like detail is absent, which is minor here.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four short sentences, each doing distinct work: what it reports, multi-instance handling, when to call it, and where to go instead. The most decision-relevant facts (what it returns, call-first advice) are front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With a single optional parameter, no output schema, and annotations covering safety, the description still enumerates the returned fields and explains error behavior and sibling routing. There is no meaningful gap an agent would need filled before calling it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3; the description goes beyond the schema by explaining the scenario in which `instance` matters (multiple AE instances open) and that omitting it retains the current target. That situational framing is genuinely additive rather than a restatement.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb+resource ('check the connection to After Effects') followed by an enumeration of exactly what is reported: version, OS, open project, active item, permission mode, busy state. It explicitly distinguishes itself from ae_get_project_info, which covers a different surface (project contents).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a clear entry condition ('Call this first if unsure AE is reachable') and names the alternative for a related need ('For the project's contents use ae_get_project_info'). The multi-instance case is also routed explicitly: pass `instance` to choose the target when several are open.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ae_toolsMore toolsARead-onlyIdempotent
Discover every After Effects tool, including ones not loaded in this chat: list them by category (one line each), or describe chosen tools (full parameters, up to 10). Then run any of them with ae_call. Tools already loaded here need no lookup: call them directly. Categories: status & app, scripts, project, comps, layers, properties & keyframes, effects, shapes & masks, text, 3D, audio, footage, files & export, checks, see & measure, essential graphics, render.
| Name | Required | Description | Default |
|---|---|---|---|
| category | No | Only list this category. | |
| describe | No | Tool names to get full parameter details for. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish that this is a safe, read-only, idempotent lookup. The description adds useful behavioral context beyond annotations: it can discover unloaded tools, lists them one line per tool by category, and can describe up to 10 chosen tools with full parameters. It does not describe the exact response shape or pagination, but for a discovery tool with strong annotations this is a minor gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose and usage model, then lists categories that matter because the schema does not provide a formal enum. Every sentence supports discovery, lookup filtering, or execution handoff, with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given a two-parameter read-only discovery tool with no output schema, the description is complete enough to use correctly. It explains both output modes, the category filter, the describe limit, the relationship to ae_call, and the fact that already-loaded tools do not need lookup.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents both optional parameters. The description still adds meaningful semantics by enumerating the category values and clarifying that describe returns full parameter details for up to 10 chosen tools, which goes beyond the raw schema text.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a specific verb and resource: discover/list/describe After Effects tools, including ones not loaded in this chat. It clearly distinguishes discovery from execution by naming ae_call as the way to run a discovered tool, and it distinguishes lookup from direct invocation for already-loaded tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly states when to use this tool: when a tool is not loaded or when you need its full parameter details. It also states when not to use it: tools already loaded need no lookup and can be called directly, and running a discovered tool should go through ae_call.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ae_undoUndoA
Undo the last action(s) in After Effects, like Edit > Undo; each Surehand MCP edit call (an ae_batch included) is one undo step. Returns how many steps were undone and a change report across all comps. If After Effects undoes nothing (nothing left to undo, or a dialog open in After Effects) it fails and says so. Reverse it with ae_redo (via ae_call); to go back further, restore an ae_checkpoint.
| Name | Required | Description | Default |
|---|---|---|---|
| steps | No | Number of undo steps, 1-50 (default 1). Stops early, with a note, when nothing more can be undone. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: it discloses the undo granularity (one MCP edit call, including an ae_batch, equals one step), the failure behavior when nothing is undone, and the return payload of count plus a cross-comp change report. This is exactly the mutation-and-failure context an agent needs before committing.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four tight sentences, front-loaded with what the tool is, followed by granularity, failure mode, and alternatives. No filler and no repetition of the schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, yet the description states what is returned (steps undone and a change report across all comps) and what happens on failure. Nothing an agent needs to invoke this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and already documents the 1-50 range and early-stop behavior, so the schema carries the load. The description still adds real meaning by explaining what counts as a single step and that a multi-step undo yields an aggregate change report.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Undo the last action(s) in After Effects') and anchors it to a familiar UI analog ('Edit > Undo'). It also defines the unit of an undo step, which no sibling tool does, so an agent can distinguish it from ae_checkpoint and ae_redo.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit routing: use ae_redo to reverse this, restore an ae_checkpoint to go back further, and ae_call to reach ae_redo. It also states the precondition that After Effects must have something undoable and no modal dialog open.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
15 tool updates
v0.1.3- Changed
ae_add_layer20 fields changed- added
Input schema / properties / allCaps / descriptionAdded value: +"Text: all caps." - added
Input schema / properties / fauxBold / descriptionAdded value: +"Text: faux bold." - added
Input schema / properties / fauxItalic / descriptionAdded value: +"Text: faux italic." - changed
Input schema / properties / fillColor / descriptionPrevious value: -"Color as \"#rrggbb\" or [r,g,b] (0-1 or 0-255)."New value: +"Text: fill color, \"#rrggbb\" or [r,g,b]." - added
Input schema / properties / fontSize / descriptionAdded value: +"Text: font size in pixels." - added
Input schema / properties / height / descriptionAdded value: +"Solid/adjustment height in pixels (default: comp height)." - changed
Input schema / properties / item / descriptionPrevious value: -"For type 'item': project item to add."New value: +"For type 'item' (required there): project item to add." - added
Input schema / properties / justification / descriptionAdded value: +"Text: paragraph alignment." - added
Input schema / properties / leading / descriptionAdded value: +"Text: line spacing in pixels (turns auto leading off)." - added
Input schema / properties / lightType / descriptionAdded value: +"For type 'light' (default: After Effects' default)." - added
Input schema / properties / name / descriptionAdded value: +"Layer name (default: After Effects' name, e.g. \"Solid\", \"Camera\")." - added
Input schema / properties / position / descriptionAdded value: +"Layer position [x,y] or [x,y,z] in comp pixels (cameras and lights default to the comp center)." - added
Input schema / properties / startTime / descriptionAdded value: +"Layer start time in seconds (comp time)." - changed
Input schema / properties / strokeColor / descriptionPrevious value: -"Color as \"#rrggbb\" or [r,g,b] (0-1 or 0-255)."New value: +"Text: stroke color, \"#rrggbb\" or [r,g,b]." - added
Input schema / properties / strokeWidth / descriptionAdded value: +"Text: stroke width in pixels." - changed
Input schema / properties / text / descriptionPrevious value: -"For text layers."New value: +"For type 'text': the text (default empty)." - added
Input schema / properties / threeD / descriptionAdded value: +"Make the layer 3D." - added
Input schema / properties / tracking / descriptionAdded value: +"Text: tracking (After Effects units, 1/1000 em)." - added
Input schema / properties / type / descriptionAdded value: +"Layer kind; 'item' adds the project item given in item." - changed
Input schema / properties / width / descriptionPrevious value: -"Solid size (default comp size)."New value: +"Solid/adjustment width in pixels (default: comp width)."
- Changed
ae_add_shape14 fields changed- added
Input schema / properties / closed / descriptionAdded value: +"For 'path': close the path (default true)." - added
Input schema / properties / inTangents / descriptionAdded value: +"For 'path': incoming Bezier handle per vertex, [[x,y],...] relative to the vertex (default: straight segments)." - added
Input schema / properties / innerRadius / descriptionAdded value: +"Star: inner radius in pixels (default size[0]/4)." - changed
Input schema / properties / layer / descriptionPrevious value: -"Existing shape layer; omit to create a new one."New value: +"Existing shape layer to add to (other layer types fail); omit to create a new one." - added
Input schema / properties / name / descriptionAdded value: +"Name of the new shape group, and of a new layer (default \"Shape Layer\")." - added
Input schema / properties / outTangents / descriptionAdded value: +"For 'path': outgoing Bezier handle per vertex, relative to the vertex." - added
Input schema / properties / outerRadius / descriptionAdded value: +"Polygon/star: outer radius in pixels (default size[0]/2)." - changed
Input schema / properties / points / descriptionPrevious value: -"Polygon/star points."New value: +"Polygon/star: number of points (default 5)." - changed
Input schema / properties / position / descriptionPrevious value: -"Shape position within the layer (default [0,0])."New value: +"Shape center within the layer (default [0,0]); not used for 'path'." - changed
Input schema / properties / roundness / descriptionPrevious value: -"Rectangle corner roundness."New value: +"Rectangle corner roundness in pixels (default 0)." - changed
Input schema / properties / size / descriptionPrevious value: -"[w,h] for rectangle/ellipse (default 400x400)."New value: +"[w,h] in pixels for rectangle/ellipse (default [400,400]); polygon/star radii default from its width." - changed
Input schema / properties / stroke / descriptionPrevious value: -"Color as \"#rrggbb\" or [r,g,b] (0-1 or 0-255)."New value: +"Stroke color; omit for no stroke." - added
Input schema / properties / strokeWidth / descriptionAdded value: +"Stroke width in pixels (default 4); only with stroke." - changed
Input schema / properties / vertices / descriptionPrevious value: -"For 'path': [[x,y],...]."New value: +"For 'path' (required): points [[x,y],...] in layer coordinates."
- Changed
ae_apply_effect2 fields changed- added
Input schema / properties / effect / descriptionAdded value: +"Match name (e.g. \"ADBE Gaussian Blur 2\", works in every AE language) or display name (\"Gaussian Blur\")." - changed
Input schema / properties / name / descriptionPrevious value: -"Rename the effect instance."New value: +"Name for the new effect instance (default: After Effects' name for it)."
- Changed
ae_batch1 field changed- added
Input schema / properties / steps / descriptionAdded value: +"1-200 steps run in order, each {tool, args} with the same args as calling that tool."
- Changed
ae_checkpoint1 field changed- added
Input schema / properties / action / descriptionAdded value: +"save a new checkpoint, list this project's checkpoints, or restore one."
- Changed
ae_create_comp8 fields changed- changed
Input schema / properties / bgColor / descriptionPrevious value: -"Color as \"#rrggbb\" or [r,g,b] (0-1 or 0-255)."New value: +"Background color, \"#rrggbb\" or [r,g,b]." - changed
Input schema / properties / duration / descriptionPrevious value: -"Seconds, default 10."New value: +"Seconds (default 10)." - changed
Input schema / properties / folder / descriptionPrevious value: -"Project item id (number) or exact name."New value: +"Project folder to put the comp in: id or exact name (default: the project root)." - changed
Input schema / properties / frameRate / descriptionPrevious value: -"Default 30."New value: +"Frames per second, 1-999 (default 30)." - changed
Input schema / properties / height / descriptionPrevious value: -"Default 1080."New value: +"Pixels, 4-30000 (default 1080)." - added
Input schema / properties / name / descriptionAdded value: +"Name of the new comp (After Effects allows duplicate names)." - changed
Input schema / properties / pixelAspect / descriptionPrevious value: -"Default 1."New value: +"Pixel aspect ratio (default 1, square pixels)." - changed
Input schema / properties / width / descriptionPrevious value: -"Default 1920."New value: +"Pixels, 4-30000 (default 1920)."
- Changed
ae_find_properties2 fields changed- changed
Input schema / properties / layer / descriptionPrevious value: -"Layer: 1-based index (number) or exact layer name."New value: +"Only search this layer: 1-based index or exact name (default: every layer)." - changed
Input schema / properties / limit / descriptionPrevious value: -"Default 100."New value: +"Max results, 1-1000 (default 100)."
- Changed
ae_get_comp_info1 field changed- changed
Input schema / properties / includeLayers / descriptionPrevious value: -"Default true."New value: +"Include the layer summary (default true); false returns only the comp's settings and markers."
- Changed
ae_get_properties2 fields changed- changed
Input schema / properties / includeHidden / descriptionPrevious value: -"Include NO_VALUE properties."New value: +"Also list NO_VALUE properties such as group markers and buttons (default false)." - changed
Input schema / properties / keyframes / descriptionPrevious value: -"Include keyframe details."New value: +"Include each keyframe's time, value, interpolation and ease (default false)."
- Changed
ae_list_scripts1 field changed- added
Input schema / properties / nameContains / descriptionAdded value: +"Only scripts whose file name (without extension) contains this text, case-insensitive."
- Changed
ae_run_script_file2 fields changed- added
Input schema / properties / args / descriptionAdded value: +"JSON object exposed to the script as the global AEMCP_ARGS (default {})." - added
Input schema / properties / timeoutSeconds / descriptionAdded value: +"Max seconds to wait for the script, 1-3600 (default 300)."
- Changed
ae_set_expression2 fields changed- added
Input schema / properties / enabled / descriptionAdded value: +"Set false to keep the expression but switch it off, true to switch it on (ignored when clearing)." - added
Input schema / properties / expression / descriptionAdded value: +"Expression code; an empty string removes the expression."
- Changed
ae_set_keyframes3 fields changed- added
Input schema / properties / keyframes / descriptionAdded value: +"Keyframes to set, each with time or frame and a value." - added
Input schema / properties / keyframes / items / properties / inInterpolation / descriptionAdded value: +"Incoming side only (overrides interpolation)." - added
Input schema / properties / keyframes / items / properties / outInterpolation / descriptionAdded value: +"Outgoing side only (overrides interpolation)."
- Changed
ae_set_property1 field changed- added
Input schema / properties / time / descriptionAdded value: +"Seconds (comp time): set a keyframe here, replacing one at that time. Omit for a static value (on an animated property: a keyframe at the current time)."
- Changed
ae_undo1 field changed- added
Input schema / properties / steps / descriptionAdded value: +"Number of undo steps, 1-50 (default 1). Stops early, with a note, when nothing more can be undone."
85 tool updates
v0.1.1- Removed
ae_add_comp_marker - Removed
ae_add_mask - Removed
ae_add_text_animator - Removed
ae_add_to_render_queue - Removed
ae_align_layers - Removed
ae_apply_preset - Removed
ae_audio_markers - Removed
ae_audio_to_keyframes - Removed
ae_audit_easing - Removed
ae_check_expression - Removed
ae_clear_render_queue - Removed
ae_color_settings - Removed
ae_copy_ease - Removed
ae_copy_keyframes - Removed
ae_create_folder - Removed
ae_delete_layers - Removed
ae_duplicate_comp - Removed
ae_duplicate_layer - Removed
ae_edit_keyframes - Removed
ae_essential_graphics - Removed
ae_execute_menu_command - Removed
ae_export_frames - Removed
ae_export_mogrt - Removed
ae_farm - Removed
ae_find_files - Removed
ae_get_expressions - Removed
ae_get_fonts - Removed
ae_get_item_info - Removed
ae_get_keyframes - Removed
ae_get_render_settings - Removed
ae_handoff_package - Removed
ae_import_files - Removed
ae_list_available_effects - Removed
ae_list_comps - Removed
ae_list_items - Removed
ae_list_render_queue - Removed
ae_localize - Removed
ae_move_items - Removed
ae_new_project - Removed
ae_open_comp - Removed
ae_open_project - Removed
ae_precomp_surgery - Removed
ae_precompose - Removed
ae_preflight - Removed
ae_project_health - Removed
ae_project_history - Removed
ae_project_xray - Removed
ae_purge - Removed
ae_queue_in_media_encoder - Removed
ae_redo - Removed
ae_reformat - Removed
ae_relink_footage - Removed
ae_reload_helpers - Removed
ae_remove_effect - Removed
ae_remove_items - Removed
ae_remove_keyframes - Removed
ae_rename_item - Removed
ae_render_background - Removed
ae_render_jobs - Removed
ae_render_profile - Removed
ae_render_queue_start - Removed
ae_replace_footage - Removed
ae_replace_in_expressions - Removed
ae_retime_keyframes - Removed
ae_sample_pixels - Removed
ae_save_project - Removed
ae_select_layers - Removed
ae_set_camera - Removed
ae_set_comp_settings - Removed
ae_set_effect_params - Removed
ae_set_footage_interpretation - Removed
ae_set_keyframe_table - Removed
ae_set_layer_attributes - Removed
ae_set_light - Removed
ae_set_material - Removed
ae_set_paragraph - Removed
ae_set_proxy - Removed
ae_set_render_settings - Removed
ae_set_text - Removed
ae_set_time_remap - Removed
ae_split_layer - Removed
ae_stress_test - Removed
ae_style_text_range - Removed
ae_system_info - Removed
ae_versions_from_data
114 tool updates
v0.1.0- First observed
ae_add_comp_marker - First observed
ae_add_layer - First observed
ae_add_mask - First observed
ae_add_shape - First observed
ae_add_text_animator - First observed
ae_add_to_render_queue - First observed
ae_align_layers - First observed
ae_apply_effect - First observed
ae_apply_preset - First observed
ae_audio_markers - First observed
ae_audio_to_keyframes - First observed
ae_audit_easing - First observed
ae_batch - First observed
ae_call - First observed
ae_check_expression - First observed
ae_checkpoint - First observed
ae_clear_render_queue - First observed
ae_color_settings - First observed
ae_copy_ease - First observed
ae_copy_keyframes - First observed
ae_create_comp - First observed
ae_create_folder - First observed
ae_delete_layers - First observed
ae_duplicate_comp - First observed
ae_duplicate_layer - First observed
ae_edit_keyframes - First observed
ae_essential_graphics - First observed
ae_execute_menu_command - First observed
ae_export_frames - First observed
ae_export_mogrt - First observed
ae_farm - First observed
ae_find_files - First observed
ae_find_properties - First observed
ae_get_comp_info - First observed
ae_get_comp_map - First observed
ae_get_effect_params - First observed
ae_get_expressions - First observed
ae_get_fonts - First observed
ae_get_item_info - First observed
ae_get_keyframes - First observed
ae_get_layer_bounds - First observed
ae_get_layer_info - First observed
ae_get_project_info - First observed
ae_get_properties - First observed
ae_get_render_settings - First observed
ae_get_scripting_guide - First observed
ae_get_selection - First observed
ae_handoff_package - First observed
ae_import_files - First observed
ae_list_available_effects - First observed
ae_list_comps - First observed
ae_list_items - First observed
ae_list_render_queue - First observed
ae_list_scripts - First observed
ae_localize - First observed
ae_move_items - First observed
ae_new_project - First observed
ae_open_comp - First observed
ae_open_project - First observed
ae_precomp_surgery - First observed
ae_precompose - First observed
ae_preflight - First observed
ae_project_health - First observed
ae_project_history - First observed
ae_project_xray - First observed
ae_prove_identical - First observed
ae_purge - First observed
ae_queue_in_media_encoder - First observed
ae_redo - First observed
ae_reformat - First observed
ae_relink_footage - First observed
ae_reload_helpers - First observed
ae_remove_effect - First observed
ae_remove_items - First observed
ae_remove_keyframes - First observed
ae_rename_item - First observed
ae_render_background - First observed
ae_render_contact_sheet - First observed
ae_render_frame - First observed
ae_render_jobs - First observed
ae_render_profile - First observed
ae_render_queue_start - First observed
ae_replace_footage - First observed
ae_replace_in_expressions - First observed
ae_retime_keyframes - First observed
ae_run_script - First observed
ae_run_script_file - First observed
ae_sample_pixels - First observed
ae_save_project - First observed
ae_select_layers - First observed
ae_set_camera - First observed
ae_set_comp_settings - First observed
ae_set_effect_params - First observed
ae_set_expression - First observed
ae_set_footage_interpretation - First observed
ae_set_keyframe_table - First observed
ae_set_keyframes - First observed
ae_set_layer_attributes - First observed
ae_set_light - First observed
ae_set_material - First observed
ae_set_paragraph - First observed
ae_set_property - First observed
ae_set_proxy - First observed
ae_set_render_settings - First observed
ae_set_text - First observed
ae_set_time_remap - First observed
ae_split_layer - First observed
ae_status - First observed
ae_stress_test - First observed
ae_style_text_range - First observed
ae_system_info - First observed
ae_tools - First observed
ae_undo - First observed
ae_versions_from_data
TDQS
Scored across 29 tools
Most tools target distinct resources or actions, but execution paths overlap heavily: ae_run_script, ae_call, ae_batch, and ae_tools can all invoke operations, while dedicated tools coexist with callable but unloaded tools. Descriptions clarify preferences, yet an agent must still decide between a direct tool, ae_call, or scripting for many tasks.
All tools use an ae_ snake_case prefix, mostly following verb_noun patterns such as get_, set_, add_, apply_, and render_. A handful are noun-only or bare verbs (ae_status, ae_batch, ae_checkpoint, ae_undo, ae_tools, ae_call), but the overall convention remains readable and predictable.
29 loaded tools is above the practical 3-15 range and exceeds the 25-tool threshold where selection cost becomes a concern. The AE domain is broad and meta-tools expose more unloaded tools, but the direct surface still feels over-scoped.
Core AE workflows are well covered: project/comp/layer inspection, property/keyframe/expression edits, effects, shapes, rendering, undo/checkpoint, and batching. Direct gaps remain for common operations like delete/remove, text editing, project save/open, align/select, and precompose, but most are reachable through ae_call or ae_run_script.
Maintenance
Related MCP Connectors
AI/VFX, CGI, motion & animation production preflight by objekts: locks, continuity, PoCs, estimates.
One sentence to a finished animation: your AI writes motion graphics as code and checks real frames.
Validate AI-made motion graphics and package them as editable HyperCodeMotion projects.
Compose, edit and render video with your AI agent. Turn footage into finished edits with content-aware reframing, word-timed captions and motion graphics. Hosted MCP with OAuth sign-in; cloud processing uses credits.
Related MCP Servers
- AlicenseAqualityBmaintenanceEnables AI assistants to operate Adobe After Effects with the dexterity of an editor: reading projects, creating and rigging layers, setting real velocity curves, animating text, building native SVG-based shapes, applying effects, expressions, masks, and viewing render snapshots to verify results.176 npm1MIT
- AlicenseNot gradedqualityAmaintenanceEnables AI agents to turn natural-language creative direction, transcripts, and source media into fully structured, editable video projects, then verify and render delivery files.2MIT
- AlicenseNot gradedqualityBmaintenanceLets AI live-connect to Adobe After Effects to read project and comp structure, render and inspect frames, edit keyframes, expressions, and effects, and build or render projects end to end, all with undo support and safety guards.64MIT
- AlicenseAqualityBmaintenanceEnables AI assistants to build, animate, inspect, and script fully editable Adobe After Effects projects through a bridge panel, including frame and storyboard review.341MIT