Metadata-Version: 2.4
Name: mograph-mcp
Version: 0.6.0
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

# mograph

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

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

The interesting part is not that it can draw a rectangle. It is
**`ai_to_ae_push`**: it takes what you have selected in Illustrator and rebuilds
it in an After Effects comp as editable shape layers — real bezier curves,
strokes, gradients, the group hierarchy recreated as parented nulls — and then
`ai_to_ae_verify` renders both sides and tells you how far apart they are, with
a number instead of an opinion.

It was built against a real 52-artboard storyboard, and most of what is in here
exists because that file broke something.

> **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, using Adobe's own scripting interfaces.

**Protocol:** implements 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.

## 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 a real client file | ⚠️ untested |
| Unit tests | ✅ | ✅ (no Adobe needed, run anywhere) |

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

---

## Install

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

Tested against **Illustrator 2026 (30.x)** and **After Effects 2026** on Windows.
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.

```bash
pip install mograph-mcp
```

Then register it with your client:

```bash
mograph-mcp register codex     # or: claude, zcode
```

`--print` shows the config instead of writing it, if you would rather paste it
yourself or your client is not one of the three:

```bash
mograph-mcp register codex --print
```

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.

`mograph-mcp doctor` reports what this machine can and cannot do, and changes
nothing.

Illustrator needs nothing else — it is driven over COM on Windows and
`osascript` on macOS. After Effects needs the panel below.

## After Effects: the panel

After Effects has no COM interface, so this talks to it through a small CEP
extension that runs inside the application and connects back to the server over
a local WebSocket. There are two ways to install it, and the difference matters
before you pick one.

### Signed — recommended

Download `mograph-bridge.zxp` from
[Releases](https://gitlab.com/vic-lab/mograph-mcp/-/releases). It loads with
`PlayerDebugMode` off, so nothing about your Adobe installation changes.

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

That hands the package to Adobe's own installer — `UnifiedPluginInstallerAgent`,
which comes with Creative Cloud Desktop, or `ExManCmd` if you have it. Add
`--print` to see the command without running it, `--installer <path>` if the
tool is somewhere unusual, and `--list` to ask Adobe what it thinks is
installed. `mograph-mcp doctor` says whether the tool was found at all.

**That command has never been run against a real Adobe installation** — the tool
locations come from Adobe's documentation, not from a machine. If it does not
find the installer, [ZXPInstaller](https://zxpinstaller.com/) installs the same
file by hand and needs none of it.

The certificate is self-signed, so the installer will report 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 instead
with `python scripts/sign_panel.py` if you would rather not trust this one.

### Folder copy — for development

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

Faster, and it is what you want while changing the panel itself. It copies the
panel in place, which Adobe treats as unsigned, **so it enables
`PlayerDebugMode`** — a setting that tells CEP to load unsigned extensions,
*all* of them and not just this one, and that stays on after the panel is
removed. It is a defence in your Adobe installation being lowered, 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.

If you want neither trade, skip the panel: 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 what the server returns from `tools/list`. A
hand-written inventory rots — this README once claimed 33 tools. 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 the 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_*`, 52 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 makes an interpolation stop looking dead.
**`ae_stagger`** orders layers by where they *actually* are in the comp, walking
the parent chain. Anchors and parenting, render queue, headless `aerender`.

**Between them (`ai_to_ae_*`, 2 tools).** `ai_to_ae_push` and `ai_to_ae_verify`,
described at the top. 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 — which is a poor foundation for the tool that everything else is
verified with.

They are downscaled to `max_dim=1024` on the long side by default; the file path
is still in the reply, and `max_dim=0` restores the old path-only behaviour.

### The long notes are a resource, not a tax

Several tools carry substantial field notes — the traps, why each default is
what it is, what broke last time. Those are the most valuable thing here and
they used to be paid for, in tokens, at the start of every session whether or not
you ever called the tool.

Now `tools/list` carries what a tool does and when to use it, and the rest is
served on demand:

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

Nothing was deleted; there is one copy of each docstring and a test fails if a
paragraph goes missing.

### Three recipes you can start from

The tools tell you what each one does. What they cannot tell you is the order,
and the order is where the costly mistakes live — grouping before looking,
pushing every frame instead of the last one, parenting before anchoring. Those
sequences are MCP **Prompts**, so a client can offer them as a starting point:

- **Prepare a delivered Illustrator file** — inspect, clean and group a client
  file 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

They carry the sequence only; each trap stays documented once, in the notes of
the tool it belongs to, and the recipe points there.

---

## Choosing what gets exposed

The full set is ~20,000 tokens of `tools/list`, paid at connect time before the
first question. 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
the reads and ask only about the mutations. Without that, all of them look
equally dangerous and people approve everything without reading.

Failures arrive as protocol errors (`isError`), not as successful calls with
`ok: false` buried in the body.

---

## Security

Short version: **local only, the bridge is authenticated, and two tools can run
arbitrary code.** The full threat model — including why a web page you visit was
the attacker that mattered — is in [`SECURITY.md`](SECURITY.md).

| Variable | Default | What it does |
|---|---|---|
| `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_WS_PORT` | `9123` | Bridge port; must match the panel |
| `MOGRAPH_AI_APPNAME` | `Adobe Illustrator` | macOS only, if the app name does not match |

---

## Development

```bash
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
```

`dev_reload` swaps the 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.

See [`CONTRIBUTING.md`](CONTRIBUTING.md), [`AGENTS.md`](AGENTS.md) for the
accumulated field notes, and [`ROADMAP.md`](ROADMAP.md) for known work.

---

## Troubleshooting

**The AE tools say no panel is connected.** Open After Effects and the `mograph
bridge` panel. If the panel says `code 4401`, After Effects is still running the
old `main.js` from memory — restart it. `4409` means another server already has a
panel. `mograph-mcp doctor` names which panels are installed, which port each one
dials, and whether a session token is present; [`docs/panel.md`](docs/panel.md)
covers the rest.

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

**Illustrator does not connect.** On Windows COM launches it. On macOS, if you
have several versions installed and it picks the wrong one, set
`MOGRAPH_AI_APPNAME="Adobe Illustrator 2026"`. A macOS 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.** Only the first and last stop survive: After
Effects will not let scripting touch a shape layer's multi-stop gradient. The
geometry is not the problem -- that transfers exactly. Check `degraded` in the
push reply, which names each flattened layer and the colours it dropped, and
rasterize in Illustrator if the middle colours carry the design.

---

## Known limitations

- **Gradients keep their geometry and lose their middle stops.** Measured
  against the applications: a two-stop gradient, linear or radial, arrives with
  a mean channel error of 0.2/255 -- the angle, extent and centre are 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 (`Colors` reports `NO_VALUE` and refuses both get and set),
  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 launch** 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 at the top.

---

## 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).
