Metadata-Version: 2.4
Name: mograph-mcp
Version: 0.9.1
Summary: MCP server to control Adobe Illustrator and After Effects, including an Illustrator-to-After-Effects transfer that keeps bezier curves, strokes and gradients.
Author: Victor Aragon
License-Expression: Apache-2.0
Project-URL: Homepage, https://gitlab.com/vic-lab/mograph-mcp
Project-URL: Repository, https://gitlab.com/vic-lab/mograph-mcp
Project-URL: Issues, https://gitlab.com/vic-lab/mograph-mcp/issues
Project-URL: Changelog, https://gitlab.com/vic-lab/mograph-mcp/blob/main/CHANGELOG.md
Keywords: mcp,model-context-protocol,illustrator,after-effects,adobe,extendscript,motion-graphics,animation
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: End Users/Desktop
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Multimedia :: Graphics
Classifier: Topic :: Multimedia :: Video
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE
Requires-Dist: mcp<3,>=2
Requires-Dist: pywin32>=306; platform_system == "Windows"
Requires-Dist: websockets>=12.0
Requires-Dist: pillow>=10.0
Requires-Dist: typing_extensions>=4.6; python_version < "3.12"
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == "dev"
Requires-Dist: ruff>=0.6; extra == "dev"
Dynamic: license-file

**English** · [Español](README.es.md)

# mograph

<!-- mcp-name: io.github.VicThor-wpp/mograph-mcp -->

[![PyPI](https://img.shields.io/pypi/v/mograph-mcp)](https://pypi.org/project/mograph-mcp/)
[![Python](https://img.shields.io/pypi/pyversions/mograph-mcp)](https://pypi.org/project/mograph-mcp/)
[![Licence](https://img.shields.io/badge/licence-Apache--2.0-blue)](LICENSE)
[![MCP](https://img.shields.io/badge/MCP-2026--07--28-6f42c1)](https://modelcontextprotocol.io)

**An MCP server that drives Adobe Illustrator and After Effects, and moves
artwork between them as editable shape layers.**

![The artwork animating in After Effects: letters rising in sequence, bars wiping open, the badge blooming with overshoot](https://gitlab.com/vic-lab/mograph-mcp/-/raw/main/docs/animation.gif)

*Nothing above was drawn by hand. The artwork was built in Illustrator, moved
into After Effects with `ai_to_ae_push`, animated with `ae_animate` — the
letters rise in sequence, the bars wipe open from their left edge, the badge
overshoots and settles — and rendered with `ae_aerender`. Every step is a tool
call in this server.*

Point an AI agent at a storyboard and it can read the artwork, clean it up,
transfer a frame into After Effects as real shape layers — bezier curves,
strokes, gradients, the group hierarchy rebuilt as parented nulls — animate it,
and then render both sides to tell you how far apart they are.

> **Not affiliated with Adobe.** "Adobe", "Illustrator" and "After Effects" are
> trademarks of Adobe Inc. This is an independent project that automates
> applications you already own, through Adobe's own scripting interfaces.

---

## What it looks like in use

You talk to your agent; it calls the tools. A session usually goes:

```text
You:   Look at the open Illustrator document and tell me what's in frame 3.
       → ai_see_document returns the render inline, ai_frame_tree the structure

You:   That price list should be six groups, not 40 loose paths. Fix it.
       → ai_cluster_items proposes, you approve, ai_apply_clusters applies

You:   Push frame 3 into After Effects, skip the subtitles.
       → ai_to_ae_push rebuilds it as shape layers, roles labelled

You:   Animate the rows in, staggered from the bottom.
       → ae_set_anchors, then ae_animate with anticipation and settle

You:   How close is it to the original?
       → ai_to_ae_verify renders both and answers with a number
```

Four of those sequences ship as MCP **Prompts**, so a client can offer them as
a starting point rather than making you remember the order.

## Status

| | Windows | macOS |
|---|---|---|
| Illustrator (`ai_*`) | ✅ tested end to end (COM) | ⚠️ implemented, **never run** (osascript) |
| After Effects (`ae_*`) | ✅ tested (CEP + WebSocket) | ⚠️ should work — CEP is cross-platform — but untested |
| Illustrator → After Effects (`ai_to_ae_*`) | ✅ tested against real client files | ⚠️ untested |
| Unit tests | ✅ | ✅ (no Adobe needed, run anywhere) |

Verified against **Illustrator 2026 (30.x)** and **After Effects 2026** on
Windows 11. Older releases are likely to work — the panel declares After Effects
16.0 and up, and the Illustrator side uses long-standing ExtendScript — but they
have not been run, so treat that as unverified rather than supported.

**macOS is written and has never been run.** That is not a soft "should be
fine". The known risks are itemised in [`AGENTS.md`](AGENTS.md).

**Protocol:** MCP revision **2026-07-28** on the official Python SDK 2.x
(`mcp>=2,<3`). Transport is stdio only — this drives desktop applications, so it
is bound to one machine by design.

---

## Install

Requires Python 3.10+ and the Adobe applications you intend to drive.

```bash
pip install mograph-mcp
mograph-mcp register codex     # or: claude, zcode
mograph-mcp doctor             # what this machine can and cannot do
```

`register --print` shows the config instead of writing it, for a client that is
not one of the three. For Claude Code, `claude mcp add mograph -- mograph-mcp`
works directly.

Whatever route you take, the entry needs a **generous per-tool timeout**. After
Effects takes 20–40 seconds to answer the first script of a cold session, and a
client that gives up at its own default aborts while the server is still
working — which reads as a hang rather than as a slow first call. `register`
sets it where the client supports it.

Illustrator needs nothing else. After Effects needs the panel below.

## After Effects: the panel

After Effects has no COM interface, so this reaches it through a small CEP
extension that runs inside the application and connects back to the server over
a local WebSocket. Two ways to install it, and the difference is worth a moment.

### Signed package — recommended

Download `mograph-bridge.zxp` from
[Releases](https://gitlab.com/vic-lab/mograph-mcp/-/releases):

```bash
mograph-mcp install-panel --zxp mograph-bridge.zxp
```

It loads with `PlayerDebugMode` off, so nothing about your Adobe installation
changes. The command hands the package to Adobe's own installer
(`UnifiedPluginInstallerAgent`, which ships with Creative Cloud, or `ExManCmd`).
Useful flags: `--print` shows the command without running it, `--installer
<path>` points at a tool in an unusual place, `--list` asks Adobe what it
believes is installed.

The certificate is self-signed, so the installer reports an unverified
publisher. That is accurate — a certificate from a public authority costs money
and buys nothing here except an Adobe Exchange listing. Build your own with
`python scripts/sign_panel.py` if you would rather not trust this one, or use
[ZXPInstaller](https://zxpinstaller.com/) to install the same file by hand.

### Folder copy — for development

```bash
mograph-mcp install-panel
```

Faster, and what you want while changing the panel itself. Adobe treats a copied
folder as unsigned, **so this enables `PlayerDebugMode`** — a setting that lets
CEP load unsigned extensions, *all* of them and not just this one, and that
stays on after the panel is removed. It lowers a defence in your Adobe
installation, so it is worth doing on purpose rather than by default.

### Either way

Restart After Effects and open **Window → Extensions → mograph bridge**. It
should say *"Connected and authenticated"* once your MCP client has started the
server.

Skipping the panel is fine — everything on the Illustrator side works without
it. Details, the manual install and what each disconnect code means are in
[`docs/panel.md`](docs/panel.md).

---

## What it can do

The authoritative list is whatever the server returns from `tools/list`. By
family:

**Illustrator (`ai_*`, 57 tools).** Documents, layers and items; export.
Inspection and triage of a delivered file (`ai_inspect_document`,
`ai_audit_for_animation`, `ai_audit_structure`). **Grouping derived from
geometry**, for when a file's hierarchy does not match what the eye reads as one
thing (`ai_cluster_items` + `ai_apply_clusters`). Naming that survives the trip
(`ai_auto_name_items`, `ai_propagate_names`). Reading frames and comparing them
(`ai_frame_tree`, `ai_diff_frames`, `ai_track_frames`). Layout and reframing.

**After Effects (`ae_*`, 55 tools).** Projects, comps, layers; effects and
expressions; keyframes, easing and interpolation. **`ae_animate`** writes
entrances and exits with anticipation, overshoot and settle — the parts that are
not in a storyboard and are what stop an interpolation looking dead.
**`ae_stagger`** orders layers by where they *actually* are in the comp, walking
the parent chain. Anchors and parenting, render queue, and headless rendering
with `ae_aerender` (`wait=False` returns a handle instead of holding the call
open; `ae_render_status` polls it).

**Between them (`ai_to_ae_*`, 2 tools).** `ai_to_ae_push` and `ai_to_ae_verify`.

![The same artwork in Illustrator and in After Effects, side by side, measured at 0.05 percent divergence](https://gitlab.com/vic-lab/mograph-mcp/-/raw/main/docs/header.png)

*The right-hand panel is what After Effects returned after the push; the 0.05%
is what `ai_to_ae_verify` measured between the two renders. The layer names
travelled because the source had named groups — that is the whole difference.*

The coordinate maths — the Y flip, artboard-to-comp scaling, bezier handles to
tangents, gradient endpoints — lives in `mapping.py` as pure functions with unit
tests, so it is verifiable without either application.

### Renders come back as images

`ai_see_document`, `ae_see_frame` and `ai_contact_sheet` return the PNG inline,
not just a path on disk. A path only works if the client happens to have
filesystem access and happens to think of reading it, and the protocol promises
neither — a poor foundation for the tools everything else is verified with.

Images are downscaled to `max_dim=1024` on the long side by default; the file
path is still in the reply, and `max_dim=0` returns the path alone.

### Field notes are served on demand

Many tools carry substantial notes — the traps, why each default is what it is,
what breaks. Loading all of that into every session would cost thousands of
tokens before the first question, so `tools/list` carries what a tool does and
when to use it, and the rest is fetched only if you want it:

- `docs://guia` — which tools have extended notes
- `docs://tools/<name>` — the full notes for one

### Three recipes to start from

The tool list says what each tool does. It cannot say which one comes next, and
the order is where the costly mistakes live — grouping before looking, pushing
every frame instead of the last, parenting before anchoring. Those sequences are
MCP Prompts:

- **Prepare a delivered Illustrator file** — inspect, clean and group before
  animating anything
- **Turn a storyboard into motion** — a run of frames to keyframes
- **Push artwork to After Effects and verify it** — the transfer, and the part
  people skip
- **Review an animation you just built** — look at it, measure what you see,
  and fix what a verify score cannot show

---

## Configuration

The full tool set is ~18,500 tokens of `tools/list`, paid at connect time. A
session that will only touch one application does not need the other half:

```bash
MOGRAPH_TOOLS=ai            # Illustrator only  -> 57 tools, ~9,000 tokens
MOGRAPH_TOOLS=ae            # After Effects only
MOGRAPH_TOOLS=ai,symbiosis  # Illustrator plus the transfer
MOGRAPH_TOOLS=all           # everything (default)
```

An invalid name is a startup error rather than an empty server: exposing zero
tools looks exactly like a broken installation.

Every tool ships `annotations` and a readable title, so a client can
auto-approve reads and ask only about mutations. Failures arrive as protocol
errors, not as successful calls with a failure buried in the body.

| Variable | Default | What it does |
|---|---|---|
| `MOGRAPH_WORKSPACE` | `~/mograph` | Where files land. A root declared by the client wins over it |
| `MOGRAPH_TOOLS` | `all` | Which tool families to expose |
| `MOGRAPH_WS_PORT` | `9123` | Bridge port; must match the panel |
| `MOGRAPH_ALLOW_RAW_SCRIPT` | `1` | `0` drops `ai_run_script` and `ae_run_script` |
| `MOGRAPH_PORT_TAKEOVER` | `0` | `1` kills whatever holds the bridge port |
| `MOGRAPH_BRIDGE_AUTH` | `1` | `0` accepts an unauthenticated panel — **unsafe** |
| `MOGRAPH_AI_APPNAME` | `Adobe Illustrator` | macOS only, if the app name differs |

## Security

**Local only, the bridge is authenticated, and two tools can run arbitrary
code.** The server mints a token per run, writes it where only a local process
can read it, and refuses both a second panel connection and any browser-origin
handshake. The full threat model is in [`SECURITY.md`](SECURITY.md).

---

## Known limitations

- **Gradients keep their geometry and lose their middle stops.** Measured: a
  two-stop gradient, linear or radial, arrives with a mean channel error of
  0.2/255 — angle, extent and centre exact. A three-stop one arrives at
  19.8/255, because only the first and last colours survive. After Effects does
  not expose a shape layer's multi-stop gradient to scripting at all, so this is
  a limit of the host. The push reports every gradient it flattened and names
  the colours it dropped. Patterns, brushes and mesh objects are skipped with a
  warning.
- **After Effects' first call of a session** takes 20–40s; the bridge waits 60s
  (`MOGRAPH_EVAL_TIMEOUT`).
- **One panel at a time**, by design — a second connection is refused rather
  than silently displacing the first.
- **No live feedback.** Nothing reacts to events in the applications; every
  exchange starts from a tool call.
- **macOS is untested.** See the table above.

## Troubleshooting

**The AE tools say no panel is connected.** Open After Effects and the `mograph
bridge` panel. Code `4401` means After Effects is still running the old
`main.js` from memory — restart it. `4409` means another server already holds a
panel. `mograph-mcp doctor` names which panels are installed, which port each
dials, and whether a session token is present.

**The bridge port is busy.** The error names the PID holding it. Stop that
process, or set `MOGRAPH_PORT_TAKEOVER=1`.

**Illustrator does not connect.** On Windows, COM launches it. On macOS, if
several versions are installed and it picks the wrong one, set
`MOGRAPH_AI_APPNAME="Adobe Illustrator 2026"`. Error `-1743` is the Automation
permission prompt: approve it in System Settings → Privacy & Security →
Automation.

**Shapes land in the wrong place after a push.** The mapping scales the artboard
onto the comp; if their aspect ratios differ, it distorts. Use a comp the same
size as the artboard.

**A gradient lost a colour.** See *Known limitations*. Check `degraded` in the
push reply, which names each flattened layer and the colours it dropped.

---

## Development

```bash
python -m pip install -e ".[dev]"
python -m pytest tests/ -q        # no Adobe required
python -m ruff check .
```

With both applications open and the panel connected:

```bash
python scripts/smoke_fidelity_ai.py   # Illustrator only, does not touch the bridge port
python scripts/smoke_fidelity_ae.py   # round trip, reads bezier + stroke back out of AE
python scripts/smoke_gradient.py      # gradient round trip, axis included
python scripts/smoke_stroke.py        # dashes, draw-on, and the shape of the ease
```

`dev_reload` swaps backend code in place without restarting the client, which
covers most of the debugging loop. It cannot add or rename a tool — the list is
handed to the client once, at connect time.

[`CONTRIBUTING.md`](CONTRIBUTING.md) has the ground rules,
[`AGENTS.md`](AGENTS.md) the accumulated field notes about how these two
applications actually behave, [`CHANGELOG.md`](CHANGELOG.md) what changed in
each version, and [`ROADMAP.md`](ROADMAP.md) what is known to be left.

## Licence

[Apache-2.0](LICENSE). "Adobe", "Illustrator" and "After Effects" are trademarks
of Adobe Inc.; this project is not affiliated with them and ships no Adobe code.
See [`NOTICE`](NOTICE).
