io.github.VicThor-wpp/mograph-mcp
Drive Adobe Illustrator and After Effects, and move artwork between them as editable shape layers.
Open source Open in the app JSON README (API)
About
Drive Adobe Illustrator and After Effects, and move artwork between them as editable shape layers.
Details
- Kind
- MCP servers
- Topic
- No topic detected
- Publisher
- victhor-wpp
- Origin
- official
- Category
- ferramentas
- Transport
- local
- Version
- 0.12.0
- Added
- 2026-08-29 03:02:18
- Updated
- 2026-09-04 16:00:36
- Origin id
io.github.VicThor-wpp/mograph-mcp
README
**English** · [Español](README.es.md)
# mograph
<!-- mcp-name: io.github.VicThor-wpp/mograph-mcp -->
[](https://pypi.org/project/mograph-mcp/)
[](https://pypi.org/project/mograph-mcp/)
[](LICENSE)
[](https://modelcontextprotocol.io)
**An MCP server that drives Adobe Illustrator and After Effects, and moves
artwork between them as editable shape layers.**

*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.
## Update
```bash
pip install -U mograph-mcp
```
Three things make an update look like it did not happen, and all three are
quiet:
1. **The running server still has the old code.** The process your client
started is alive with the previous version in memory, and `dev_reload` does
not help — the tool list is handed to the client once, at connect. Restart
the client, or kill `mograph-mcp` and let it relaunch. A new tool that does
not appear is almost always this.
2. **Update the environment the CLIENT launches, which may not be the one on
your PATH.** Read the `command` in the MCP entry: if it points at a venv,
`pip` has to run from that venv's Python. Upgrading the wrong one leaves
everything looking correct and changes nothing.
3. **`uvx` caches.** `uvx mograph-mcp` keeps serving the version it cached the
first time; `uvx mograph-mcp@latest` gets the new one.
`mograph-mcp doctor` prints the version it is actually running, which is the
fastest way to tell an update that landed from one that did not.
**If a release changes the CEP panel, reinstall it and restart After Effects.**
Reinstalling is not enough on its own: AE holds the old JavaScript in memory,
keeps connecting with it, and the server refuses the stale panel — which from
the outside looks exactly like the panel never being open. `CHANGELOG.md` says
when a release touches the panel.
## 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_*`, 66 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 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).