Skip to main content
Glama

AE Bridge MCP

A Model Context Protocol server that lets an AI agent (Claude, or any MCP-compatible client) inspect and drive a live Adobe After Effects session — read the active composition, list selected layers, inspect a layer's transform/effects, or evaluate arbitrary ExtendScript.

Extracted from Dimension's ae_bridge_mcp/ae_eval dev tooling so other NeuralIO 444 AE-adjacent products can reuse it without depending on Dimension itself.

Part of a small set of related repos:

  • AE_Eval — the same evaluate-ExtendScript-in-AE capability as a plain terminal CLI, no MCP client needed. Independent of this repo — pick whichever fits, or use both (they share the same AE-side listener file).

  • IPC_Client — the general-purpose version of the socket transport both of the above are built on.

What it does

Four moving pieces:

  1. ae_bridge_mcp/jsx/ae_bridge_listener.jsx — loaded into a running After Effects session. Opens a TCP socket on 127.0.0.1:45445 and evaluates whatever ExtendScript it receives, using a simple length-prefixed JSON protocol.

  2. IPC_Client (a real dependency, not vendored code) — the Python-side client for that same protocol (execute_job()).

  3. ae_bridge_mcp/eval.py — evaluate() tries the socket transport first, falling back to macOS AppleScript (osascript) if the listener isn't loaded or AE isn't reachable. No CLI of its own — see AE_Eval for that.

  4. ae_bridge_mcp/server.py — the actual MCP server: a stdio JSON-RPC loop exposing 4 tools (see below) to any MCP client.

Tests in tests/.

Related MCP server: After Effects MCP Server

Tools exposed over MCP

Tool

What it does

ae_eval_script

Evaluate arbitrary ExtendScript, return the result or error.

ae_get_active_comp

Name, id, width, height, fps, duration, layer count for the active comp.

ae_get_selected_layers

Index, name, label, comment, enabled, 3D, hasVideo for every selected layer.

ae_get_layer_properties

Transform (position/scale/rotation/opacity/anchor), sourceRect, and applied effects for a given 1-based layer index.

Setup

1. Load the AE-side listener

In After Effects: File → Scripts → Run Script File... and pick ae_bridge_mcp/jsx/ae_bridge_listener.jsx. It starts listening immediately ($.global.AEBridgeListener.start() runs at the bottom of the file) and writes a confirmation line to the ExtendScript console.

To have it load automatically, drop it (or a script that $.evalFile()s it) into AE's Scripts/Startup folder for your AE version, or wire it into whatever your product's own panel/launcher already loads at boot.

To stop it: $.global.AEBridgeListener.stop(); from the ExtendScript console, or just close AE.

2. Install the Python package

pip install -e .
# or, for running tests too:
pip install -e ".[dev]"

One runtime dependency: IPC_Client (itself pure stdlib, no further dependencies) — installed automatically from its pinned commit via the git+https://... URL in pyproject.toml.

3. Point an MCP client at it

Example config (Claude Code, or any MCP client using the same command/args shape):

{
  "mcpServers": {
    "ae-bridge": {
      "command": "python3",
      "args": ["-m", "ae_bridge_mcp"]
    }
  }
}

Or run it directly to sanity-check it starts: python3 -m ae_bridge_mcp (it will sit waiting for JSON-RPC on stdin — that's expected, it's not meant to be run interactively).

This repo has no standalone CLI of its own by design — for a terminal command with the same evaluate/active-comp/selected-layers capability, install AE_Eval instead (or alongside — they share the same AE-side listener).

Transport fallback

evaluate() tries, in order:

  1. TCP socket (127.0.0.1:45445) — needs ae_bridge_listener.jsx loaded in AE. Sub-5ms round-trip. The connect phase fails fast (connect_timeout, default 2s) so an unloaded listener falls through to AppleScript quickly; the response wait itself honors the caller's full requested timeout — a legitimately slow script (many layers/effects, a render trigger) isn't cut short at 2s.

  2. AppleScript (osascript, macOS only) — works even without the listener loaded, at the cost of a slower round-trip (writes a temp .jsx file, has AE run it via DoScriptFile, reads a temp JSON output file back).

If neither works, evaluate() returns a structured error rather than hanging — check that After Effects is running and the listener is loaded.

Security

ae_bridge_listener.jsx is an unauthenticated socket — any local process that can reach 127.0.0.1:45445 and speaks the wire protocol can execute arbitrary ExtendScript through it (including filesystem access and system.callSystem()-style OS command execution) for as long as After Effects is running with the listener loaded. This is inherent to what the tool does — an AI agent is meant to evaluate arbitrary ExtendScript through it — but it's worth knowing plainly before loading it on a shared machine (a render farm node, CI runner, or multi-user workstation), where any other local process/user could reach the same port.

Testing

pip install -e ".[dev]"
pytest tests/

Tests mock the AE-facing boundary (execute_job, eval_extendscript_socket, eval_extendscript_applescript) — they don't require a real After Effects instance to run.

Known limitations

  • ae_get_layer_properties reads position/scale/etc. via .value, which reads the property at the current playhead for keyframed properties, not a deterministic rest pose. If you need a deterministic read for an animated property, evaluate a custom script via ae_eval_script instead (e.g. prop.valueAtTime(prop.keyTime(1), true)).

  • The AppleScript fallback is macOS-only; on Windows/Linux, only the socket transport is available, so ae_bridge_listener.jsx must be loaded for anything to work at all.

  • ExtendScript's return is illegal outside a function body — if you're calling ae_eval_script with a multi-statement script that needs to return a value, wrap it in an IIFE yourself: (function(){ ...; return x; })(). eval.py's own wrap_iife() helper does this for the built-in structured tools.

Changelog

  • Hardened handle_call_tool so a malformed tool argument (e.g. a non-numeric layer_index) returns an isError result instead of raising and killing the persistent stdio server process.

  • Fixed evaluate() silently capping the entire socket-transport wait at 2 seconds regardless of the requested timeout — only the connect phase is capped now (connect_timeout), the response wait honors the real request.

  • Switched to depending on the IPC_Client package instead of a vendored copy (also picks up its connect-timeout and message-size-cap fixes).

  • Fixed packaging: ae_bridge_listener.jsx moved inside the package directory and is now actually included in a built wheel/sdist — a real pip install previously shipped a package with no way to reach After Effects on Windows/Linux (only worked by accident via editable installs from a live git checkout).

  • Removed the redundant ae-eval console-script entry point (it collided with the standalone AE_Eval package's own ae-eval command if both were installed together) and the CLI code it pointed to, which fully duplicated AE_Eval.

License

MIT — see LICENSE.

Available Tools

4 tools
ae_eval_scriptB

Evaluates arbitrary ExtendScript (JSX) in Adobe After Effects and returns result or errors.

Inputs: script (required), timeout.

ae_get_active_compA

Returns metadata (name, id, width, height, fps, duration, numLayers) for the active composition in After Effects.

Inputs: no named parameters.

ae_get_layer_propertiesA

Returns transform coordinates, bounding box sourceRect, and applied effects list for a specific layer index in the active comp.

Inputs: layer_index (required).

ae_get_selected_layersA

Returns currently selected layers in the active comp with indices, names, comments, and labels.

Inputs: no named parameters.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.6/5.0

    Scored across 4 tools

    Disambiguation5/5

    Each tool has a clearly distinct purpose: evaluation of scripts, retrieval of active comp metadata, retrieval of selected layers, and retrieval of specific layer properties. There is no semantic overlap between these operations, making selection unambiguous.

    Naming Consistency3/5

    All tools use a consistent 'ae_' prefix followed by a verb-object pattern (e.g., 'eval_script', 'get_active_comp'), which is good. However, 'ae_get_selected_layers' and 'ae_get_layer_properties' could be more consistent in verb ordering, though the naming is still readable and predictable.

    Tool Count4/5

    With 4 tools, the server is on the minimal side but still reasonable for a specialized After Effects bridge. It covers the essential read and evaluation operations without bloat, though a few more tools could enrich the surface.

    Completeness2/5

    The server provides read-only access (evaluation, comp metadata, layer selection, layer properties) but lacks any modification or creation tools (e.g., add layer, set property, render comp). This leaves a significant gap for an automation server, as agents cannot perform common After Effects scripting tasks beyond evaluation and inspection.

    Maintenance

    ActivityNo data
    ResponsivenessSyncing

    Related MCP Connectors

    Related MCP Servers