0.0 / 30
What changed in the harness
Selection accuracy 100→98, token cost up 5%, unconfirmed writes 0%→0%.
Category breakdown
Where the score comes from.
Earned points across the four signals Gradable measures. Safety and Legibility are scored out of 30; Economics and Discoverability are scored out of 20.
01Safety
02Legibility
18.0 / 30
03Economics
8.5 / 20
04Discoverability
14.9 / 20
Highest-impact fix
Estimated gain +30 pointsAdd explicit identity and permission preflight tools
Expose machine-readable principal/tenant confirmation and a non-mutating permission check so agents can verify both before destructive actions.
Description evidence
Defects and rewrites.
40 defects found across the exposed tool descriptions. Suggested rewrites make purpose, inputs, boundaries, and returns easier for an agent to understand.
| Tool | Defect types | Suggested rewrite |
|---|---|---|
run-script |
no_return_description |
Run a predefined read-only script in After Effects, passing optional parameters to it, and return the results the script produces. |
get-results |
name_restates_behavior |
Return the results of the most recently executed script in the After Effects session, including output values and any error information from the last run. |
get-help |
name_restates_behavior no_return_description |
Return guidance on using the After Effects MCP integration, including how to run scripts, retrieve results, and the available operations. |
create-composition |
name_restates_behavior no_return_description |
Create a new composition in After Effects from the given name, width, height, pixel aspect ratio, duration, frame rate, and background color, and return the composition index so it can be referenced by other tools. |
create-adjustment-layer |
name_restates_behavior no_return_description |
Add an adjustment layer to the named composition, or to the active composition when compName is omitted, applying the given name, position, size, start time, and duration, and return the index of the created layer. |
center-layers |
name_restates_behavior no_return_description |
Reposition one layer, the selected layers, or all layers so they are centered within the composition, targeting layers by index or name, and return the indexes of the centered layers. |
get-layer-clip-frames |
name_restates_behavior no_return_description |
Return a layer's clip in-point and out-point frames, source frame range, and total duration in frames, for the layer identified by index or name in the given composition. |
setLayerKeyframe |
name_restates_behavior no_return_description |
Set a keyframe for a layer property such as Position, Scale, Rotation, or Opacity at a given time in the target composition, using the supplied value, and return a confirmation with the keyframe details. |
setLayerExpression |
no_return_description |
Set a JavaScript expression on a layer property such as Position, Scale, Rotation, or Opacity, or remove the expression by passing an empty string, and return a confirmation of the change. |
test-animation |
name_restates_behavior no_return_description |
Verify animation functionality in After Effects by running a keyframe or expression operation on the specified composition and layer, and return the result of the test including any animation data applied. |
apply-effect |
name_restates_behavior no_return_description |
Apply an effect to a layer, targeting it by display name or matchName with optional preset path and effect settings, and return a confirmation with the applied effect details. |
add-any-effect |
name_restates_behavior no_return_description |
Add an After Effects effect to a layer, identified by matchName or display name (prefer matchName for reliability), optionally setting effect parameters immediately, and return a confirmation of the added effect. |
apply-effect-template |
name_restates_behavior no_return_description |
Apply one of the predefined effect templates such as gaussian-blur, glow, drop-shadow, or text-pop to a layer, optionally overriding default settings, and return a confirmation of the applied template. |
list-layer-effects |
name_restates_behavior no_return_description |
Return the effects on a layer, optionally including recursive property trees, current property values, and a configurable maximum recursion depth, for the layer in the target composition. |
list-available-effects |
name_restates_behavior no_return_description |
Return the effects available in the After Effects installation, optionally filtered by a text query matching name, matchName, or category, with control over obsolete effects and result count. |
set-effect-property |
name_restates_behavior no_return_description |
Set or keyframe a property on an existing layer effect, targeting it by name, index, or property path with optional value, time, expression, and graph/easing options, and return a confirmation of the change. |
set-effect-keyframe |
name_restates_behavior no_return_description |
Set a keyframe on an effect property at a given time, optionally applying interpolation, easy-ease, temporal, and spatial tangent controls, and return a confirmation of the keyframe. |
search-presets |
name_restates_behavior no_return_description |
Return After Effects .ffx presets whose filename or path matches the query, searching optional preset root directories with configurable recursion, depth, and result limits. |
apply-preset |
name_restates_behavior no_return_description |
Apply a preset (.ffx) file to a layer, loading the effects defined in the preset at the given absolute path, and return a confirmation of the applied preset. |
mcp_aftereffects_get_effects_help |
no_return_description |
Return usage guidance on After Effects effects, including how to apply, list, and configure effects through the MCP integration. |
run-bridge-test |
name_restates_behavior no_return_description |
Run the bridge test effects script to verify communication between the MCP server and After Effects, applying test effects, and return the test output and communication status. |
remove-effect |
name_restates_behavior no_return_description |
Remove a single effect from a layer, identified by index, display name, or matchName, or remove all effects when removeAll is true, and return a confirmation of the removed effects. |
add-marker |
no_return_description |
Add a marker to a layer or composition at a given time, or the current time when omitted, optionally including a comment, label color, chapter name, URL, and duration, and return the details of the created marker. |
set-audio-levels |
name_restates_behavior no_return_description |
Set the audio level of an audio or AV layer in decibels, supporting per-channel left/right control and optional keyframing at a specified time, and return a confirmation of the applied level. |
get-audio-info |
no_return_description |
Get audio metadata, source file path, existing markers, and audio level keyframes for a layer in After Effects, selected by 1-based compIndex (required) and either layerIndex or layerName. Returns the audio details as structured JSON: sourceFilePath for the layer's audio, metadata such as sample rate/channels/duration, existing markers with their times/comments, and audio level keyframes. |
animate-to-audio |
no_return_description |
Generate After Effects keyframes for a layer property directly from an audio file's waveform, in one call - no need to call analyze-audio-waveform and compute keyframes by hand first. Two modes: 'waveform' follows the amplitude envelope continuously (a VU-meter style effect - glow intensity, scale, or opacity riding the music), one keyframe per analyzed sample. 'peaks' pulses the property at each detected transient/beat and decays back to baseline (a beat-pop style effect - e.g. a logo scaling up on every kick). Accepts any audio format ffmpeg supports (mp3, m4a/aac, ogg, flac, ...) the same way analyze-audio-waveform does; uncompressed WAV needs no extra dependency. Targets a plain layer property (e.g. 'ADBE Opacity') by default, or an effect's property when effectIndex/effectName/effectMatchName is given. Returns a summary of the generated keyframes, such as the target property, keyframe count and times, and the resulting value range. |
add-markers-bulk |
no_return_description |
Add multiple layer or composition markers at once. Use this after analyze-audio-waveform to place markers at detected peaks, or to add any set of markers in a single call. Each marker is given by timeInSeconds, optional comment, duration (0 = point marker), label color index (0-16), chapter and URL; pass markers for layer markers with a layer, or markerType 'comp' for composition-level markers. Returns a confirmation of how many markers were added. |
check-bridge |
no_return_description |
Health check: verify the After Effects MCP Bridge panel is open and responding, report its version, the AE version, the shared bridge folder, and the open project/active comp. Run this FIRST when anything times out or behaves oddly. It returns the bridge version, After Effects version, shared folder path, and open project/active composition as structured JSON. If it reports a version mismatch, re-run `npm run install-bridge` and restart After Effects. |
create-text-layer |
no_return_description |
Create a text layer with full Arabic / RTL support. Direction is auto-detected from the text by default (Arabic -> right-to-left, right-aligned), or force it with `direction`. Configure position, fontSize, color (0-1 channels), fontFamily, alignment, startTime and duration. Returns the created layer's name and index (and comp it was added to). |
localize-comp |
no_return_description |
Create a localized duplicate of a composition: swap in translated text for one or more text layers, auto-detecting Arabic and applying right-to-left direction/alignment (same logic as create-text-layer). Every other layer, effect, and animation is preserved unchanged because the whole composition is duplicated first. Text layers nested inside precompositions are reachable too via `path`: every precomposition on the path is safely duplicated the first time it's encountered (and reused if referenced again from another path), so the original precomps are never modified. Translation itself is the caller's job; pass the already-translated strings in `translations`. Returns the name of the new localized composition (default '<source name> (localized)'). |
create-camera |
name_restates_behavior no_return_description |
Create a camera layer in a composition, selected by compName/compIndex or the active comp. Configure name, zoom, position, point of interest (ignored for one-node cameras), or pass oneNode to create a one-node camera with no point of interest. Returns the created camera layer's name and index. |
duplicate-layer |
name_restates_behavior no_return_description |
Duplicate a layer in a composition, optionally renaming the copy with newName. Target the source layer by layerIndex or layerName (the comp can be selected by compName/compIndex or the active comp). Returns the new duplicated layer's index and name. |
delete-layer |
name_restates_behavior no_return_description |
Permanently remove a layer from a composition, selected by layerIndex or layerName (comp by compName/compIndex or the active comp). Returns confirmation of the deleted layer's name/index. |
set-layer-mask |
params_unexplained no_return_description |
Create or modify a mask on a layer. Provide the shape as maskRect (rectangle shorthand) OR maskPath (array of [x,y] vertices, >= 3). Omit maskIndex to add a new mask, or pass it to modify an existing one. Options include maskMode (default 'add'), maskFeather, maskOpacity, maskExpansion, and an optional maskName to label the mask. Returns the mask's index and a summary of its properties. |
batch-set-layer-properties |
no_return_description |
Set transform/visibility properties on MANY layers in one call. Each operation targets a layer by layerIndex or layerName and may set any of: threeDLayer, position, scale, rotation, opacity, blendMode, startTime, outPoint. Setting position clears its existing keyframes first. Returns a per-operation result summary (success/failure and the properties changed for each layer). |
set-composition-properties |
no_return_description |
Change a composition's settings: duration, frameRate, and/or width+height. Select the comp by compName/compIndex (or active comp). Width and height must be set together. Returns confirmation of the updated composition settings. |
inspect-comp |
no_return_description |
Map a whole composition: its settings (size, fps, duration, work area) plus every layer with a useful summary - index, id, name, type, enabled/locked/shy/solo, 3D/adjustment/null flags, in/out/start, parent, blend mode, effect count, mask count, has-audio. Use this to navigate a comp and decide what to edit, then call inspect-layer for one layer's full detail. Select the comp by compName/compIndex, or leave both empty for the active comp. Returns the composition's settings and the per-layer summaries as structured JSON. |
inspect-layer |
no_return_description |
Deeply inspect ONE layer so you can SEE its exact state before making precise edits: type, enabled/locked/shy/solo, in/out points, parent, blend mode, 3D flag; the full Transform group (each property's value + expression + keyframes with times/values/interpolation); all effects with their property values; masks (mode/inverted/opacity/feather/expansion); markers; source file/dimensions; and text (font/size/fill) for text layers. Select the comp by compName/compIndex (or active comp) and the layer by layerIndex or layerName. Optionally disable per-keyframe detail with includeKeyframes and cap the count with maxKeyframes. Returns the layer's full details as structured JSON. |
start-render |
no_return_description |
Render all QUEUED items in the After Effects render queue. IMPORTANT: this BLOCKS After Effects until the render finishes - the AE UI is unresponsive during the render. Add items first with add-to-render-queue. For long renders, raise timeoutMs; if the wait times out the render still continues in AE and you can check status later with render-queue. Returns the render result (success/failure and output paths) for each completed queue item. |
render-status |
no_return_description |
Check background aerender renders started with render-aerender: which are still running, which finished, and the tail of each render log. Pass an optional pid to report only that render; otherwise reports all tracked renders. Returns per-render status (running/finished), PID, and the tail of each render log. |
Selection evidence
Confusable tool pairs.
18 pairs where similar names or overlapping descriptions may send an agent toward the wrong tool.
| Tool A | Tool B | Confidence | Why they collide |
|---|---|---|---|
apply-effect |
add-any-effect |
high | Both add an arbitrary AE effect to a layer by display name or matchName with near-identical compIndex/layerIndex+effect parameters, so a task like 'add Gaussian Blur to layer 2' is genuinely ambiguous. |
set-effect-property |
set-effect-keyframe |
high | Schemas and descriptions overlap almost completely: both target an effect property by name/path and accept value, timeInSeconds, and keyframeOptions, so 'set an easy-ease keyframe on the effect's Blurriness at 1.5s' maps to either tool. |
apply-effect |
apply-effect-template |
medium | Templates are named after effects ('gaussian-blur', 'glow', 'drop-shadow'), so 'apply a glow effect to the layer' could select apply-effect or the matching template tool. |
apply-effect |
apply-preset |
medium | apply-effect itself accepts a presetPath for .ffx files, so 'apply this preset file to layer 3' is ambiguous between the generic effect tool and the dedicated apply-preset. |
apply-effect-template |
apply-preset |
medium | Users say 'preset' and 'template' interchangeably; 'apply the cinematic glow preset' could be a named template or an .ffx file, and both tools have nearly the same comp/layer targeting. |
add-marker |
add-markers-bulk |
medium | A task like 'add markers at 1s, 2s, 3s to the layer' is plural but add-marker accepts only one marker, so the agent may pick the single tool instead of the bulk one (or vice versa for a one-marker task). |
run-script |
execute-script |
medium | 'Run a script in After Effects' is ambiguous between the predefined read-only scripts (run-script takes a script name) and arbitrary ExtendScript (execute-script takes code); only the read-only vs arbitrary distinction separates them. |
render-queue |
render-status |
medium | Both report on renders: render-queue lists queue item status while render-status reports background aerender runs, so 'check the status of my render' is ambiguous when the user does not say how the render was started. |
render-queue |
start-render |
medium | The name 'render-queue' suggests it renders the queue, but it only lists/clears/removes items; a task like 'render the queued items' may select render-queue instead of start-render. |
start-render |
render-aerender |
medium | Both actually render comps; 'render my comp to a file' is ambiguous between queue-based start-render (after add-to-render-queue) and background aerender, and the distinguishing constraint (AE UI freezes) is often not stated in the task. |
add-to-render-queue |
start-render |
medium | 'Start rendering the current comp' is ambiguous between configuring/queuing the output (add-to-render-queue) and actually rendering all queued items (start-render), especially when the user says 'render' without naming templates. |
add-to-render-queue |
render-queue |
medium | Both concern the render queue; 'put the comp into the render queue' could pick render-queue (which only lists/clears/removes) instead of add-to-render-queue because the name matches 'render queue'. |
list-layer-effects |
list-available-effects |
medium | A bare task like 'list the effects' is ambiguous between effects already on a layer (list-layer-effects) and all effects installed (list-available-effects); only phrasing about a specific layer vs the installation disambiguates. |
setLayerKeyframe |
set-effect-keyframe |
medium | Both create keyframes on a named property with very similar wording; 'set a keyframe on this property at 1s' is ambiguous unless it states whether it is a plain layer property or an effect property. |
setLayerKeyframe |
setLayerExpression |
medium | Both target a named layer property (Position/Scale/Rotation/Opacity); a task like 'set up the position so it moves' could be satisfied by either keyframes or an expression, so the agent may pick the wrong one. |
list-presets |
search-presets |
medium | Both enumerate .ffx preset files with the same presetRoots/recursive options; 'find me the blur presets' could be answered by either, since search requires a query while list returns everything, making selection ambiguous. |
analyze-audio-waveform |
animate-to-audio |
medium | A task like 'analyze the audio and generate keyframes that follow it' may make the agent pick the analysis tool (analyze-audio-waveform) and skip animate-to-audio, which generates the keyframes directly in one call. |
get-help |
mcp_aftereffects_get_effects_help |
low | A vague 'I need help with After Effects' or 'help with effects' is ambiguous between general MCP help (get-help) and effect-specific help, though the effect-scoped tool is usually the more precise match. |
Compare the field