premiere-pro-mcp 1.16.4 → 1.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +83 -0
- package/README.md +38 -20
- package/after-effects-cep-plugin/CSXS/manifest.xml +2 -2
- package/after-effects-cep-plugin/bridge-directory-security.cjs +18 -9
- package/artifacts/MCPBridgeCEP.zxp +0 -0
- package/cep-plugin/CSXS/manifest.xml +3 -3
- package/cep-plugin/bridge-directory-security.cjs +18 -9
- package/cep-plugin/index.html +1 -1
- package/cep-plugin/updater.cjs +1 -1
- package/dist/ai/mask-fit.d.ts +125 -0
- package/dist/ai/mask-fit.js +308 -0
- package/dist/ai/timeline-qa.js +1 -1
- package/dist/bridge/file-bridge.d.ts +7 -0
- package/dist/bridge/file-bridge.js +21 -8
- package/dist/bridge/script-builder.js +178 -8
- package/dist/http-server.js +2 -2
- package/dist/index.js +1 -1
- package/dist/resources/extendscript-reference.js +1 -1
- package/dist/security/capabilities.js +1 -0
- package/dist/server.js +4 -2
- package/dist/telemetry.d.ts +2 -0
- package/dist/telemetry.js +9 -0
- package/dist/tools/advanced.d.ts +8 -0
- package/dist/tools/advanced.js +32 -4
- package/dist/tools/clipboard.d.ts +58 -0
- package/dist/tools/clipboard.js +495 -0
- package/dist/tools/export.d.ts +5 -1
- package/dist/tools/export.js +47 -13
- package/dist/tools/inspection.js +21 -60
- package/dist/tools/mask-fit.d.ts +182 -0
- package/dist/tools/mask-fit.js +357 -0
- package/dist/tools/media.d.ts +5 -0
- package/dist/tools/media.js +166 -13
- package/dist/tools/metadata.js +5 -2
- package/dist/tools/mogrt-authoring.d.ts +26 -3
- package/dist/tools/mogrt-authoring.js +188 -42
- package/dist/tools/mogrt-text.d.ts +39 -0
- package/dist/tools/mogrt-text.js +107 -0
- package/dist/tools/project.js +24 -6
- package/dist/tools/text.d.ts +8 -0
- package/dist/tools/text.js +52 -3
- package/dist/tools/timeline-qa.js +1 -1
- package/dist/tools/timeline.d.ts +42 -0
- package/dist/tools/timeline.js +298 -56
- package/dist/tools/track-targeting.d.ts +5 -0
- package/dist/tools/track-targeting.js +125 -34
- package/dist/tools/uxp-timeline-source-label-workflows.d.ts +8 -1
- package/dist/tools/uxp-timeline-source-label-workflows.js +14 -5
- package/dist/tools/uxp.d.ts +7 -0
- package/dist/workflows/agent-instructions.js +3 -0
- package/dist/workflows/tool-metadata.js +1 -0
- package/docs/mogrt-authoring.md +26 -2
- package/docs/supported-actions.md +20 -17
- package/package.json +2 -2
- package/public-product-manifest.json +5 -5
- package/uxp-plugin/commands.cjs +22 -11
- package/uxp-plugin/manifest.json +1 -1
- package/uxp-plugin/timeline-source-label-workflows.cjs +46 -9
- package/uxp-plugin/workflows.cjs +17 -7
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,89 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [1.18.0] - 2026-09-23
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- MOGRT text recipes default to `text_controls: "full"`: each text layer exposes
|
|
14
|
+
Font Size, Stroke Width, Fill Color, and Stroke Color controls plus named
|
|
15
|
+
Position, Scale, Rotation, Anchor Point, and Opacity Essential Graphics
|
|
16
|
+
controls. The create result reads back source-comp controller names.
|
|
17
|
+
`text_only` keeps the previous behavior. Font-family editing is not scriptable
|
|
18
|
+
and is reported as a known gap. (#618)
|
|
19
|
+
- `media_placeholder` MOGRT recipe imports a workspace-contained PNG, JPEG, MOV,
|
|
20
|
+
or MP4, requests a replaceable Essential Graphics media slot, and exposes its
|
|
21
|
+
transform controls. Not verified on a live After Effects or Premiere host.
|
|
22
|
+
(#619)
|
|
23
|
+
- `import_mogrt` accepts `text_values`, writes each named text control after
|
|
24
|
+
insertion (replacing only the text value so styling is kept), and reports
|
|
25
|
+
`verified`, `mismatch`, `missing_property`, or `committed_unverified` per
|
|
26
|
+
field. `get_mogrt_component` returns `textValue` for every parameter and an
|
|
27
|
+
optional `expected_values` audit that flags stale Headline text. (#617)
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
|
|
31
|
+
- `encode_file` and `encode_project_item` pass natively typed arguments (String
|
|
32
|
+
paths, Boolean removal flag, Time in/out), fixing "Illegal Parameter type";
|
|
33
|
+
`encode_file` fails early when the preset file is missing. (#615)
|
|
34
|
+
- `set_xmp_metadata` passes numeric `XMPConst` options to
|
|
35
|
+
`XMPUtils.appendProperties`, fixing "Bad argument list". (#611)
|
|
36
|
+
- `manage_proxies` auto-discovery skips "Same as Project" proxy presets whose
|
|
37
|
+
output never reached `output_path`, and asks for `preset_path` when no safe
|
|
38
|
+
preset exists. (#610)
|
|
39
|
+
- `manage_metadata_uxp` and `create_subclip_uxp` find items inside nested bins.
|
|
40
|
+
(#612, #613)
|
|
41
|
+
- `set_scale_to_frame_size` accepts timeline clip IDs and reports `verified` or
|
|
42
|
+
`committed_unverified`. (#614)
|
|
43
|
+
|
|
44
|
+
### Known limitations
|
|
45
|
+
|
|
46
|
+
- The Essential Graphics panel can display a stale Headline after a MOGRT text
|
|
47
|
+
write. The tools read stored values and cannot refresh the host panel (#616
|
|
48
|
+
remains open).
|
|
49
|
+
- These fixes are covered by mocked automated tests only; they are not verified
|
|
50
|
+
on a licensed Premiere or After Effects host.
|
|
51
|
+
|
|
52
|
+
## [1.17.0] - 2026-09-21
|
|
53
|
+
|
|
54
|
+
### Added
|
|
55
|
+
|
|
56
|
+
- `paste_clip_attributes` copies a source clip's effect stack, values, and
|
|
57
|
+
keyframes onto a target clip with per-property readback. Masks and a differing
|
|
58
|
+
Blend Mode are reported as not copied because no documented scripting surface
|
|
59
|
+
exposes them. (#595)
|
|
60
|
+
- `compute_mask_fit_motion` computes Motion Scale/Position that place a still's
|
|
61
|
+
subject inside an existing Rounded Crop, Crop, or similar mask. Inspect only.
|
|
62
|
+
(#594)
|
|
63
|
+
- `set_clip_duration` sets a placed timeline clip's duration or absolute end by
|
|
64
|
+
moving only `TrackItem.end`, so still images can be extended past their import
|
|
65
|
+
length. It refuses overlaps with the next clip, guards effect keyframes when
|
|
66
|
+
shortening, reads start/end back, and restores the original end when Premiere
|
|
67
|
+
clamps the write. (#592)
|
|
68
|
+
|
|
69
|
+
### Changed
|
|
70
|
+
|
|
71
|
+
- Clip speed messaging is consistent across `speed_change`, `set_clip_speed_qe`,
|
|
72
|
+
`set_clip_properties`, agent instructions, docs, and skills: documented
|
|
73
|
+
ExtendScript and UXP (through 26.3) expose only speed getters, the QE setter
|
|
74
|
+
stays unused, and `set_clip_duration` is the supported timing alternative. (#593)
|
|
75
|
+
|
|
76
|
+
### Fixed
|
|
77
|
+
|
|
78
|
+
- `set_target_track` targets exclusively by default (`exclusive: false` keeps
|
|
79
|
+
other tracks targeted) and reads every track back; `get_target_tracks` lists
|
|
80
|
+
every targeted track and unreadable tracks. (#587)
|
|
81
|
+
- `create_bars_and_tone` returns the created item's name, node ID, and tree path.
|
|
82
|
+
(#588)
|
|
83
|
+
- `get_bin_contents` resolves nested bins by node ID with guarded child access and
|
|
84
|
+
clean errors instead of a raw TypeError. (#589)
|
|
85
|
+
- `manage_timeline_source_label_uxp` accepts `sequence_id` and resolves it by GUID,
|
|
86
|
+
failing closed instead of targeting the active sequence. (#590)
|
|
87
|
+
- `create_bin` honors `parent_bin_id` and reads back the new bin's parent. (#591)
|
|
88
|
+
- Windows bridge-directory ACL checks ignore capability and app-container SIDs
|
|
89
|
+
(`S-1-15-*`), so the default location under `%LOCALAPPDATA%` no longer fails at
|
|
90
|
+
startup; the ancestry error names each offending path and SID. (#581)
|
|
91
|
+
|
|
9
92
|
## [1.16.4] - 2026-09-20
|
|
10
93
|
|
|
11
94
|
### Added
|
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ Free, MIT licensed, local-first, and published to npm as [`premiere-pro-mcp`](ht
|
|
|
12
12
|
|
|
13
13
|
[Website](https://premiere-pro-mcp.com/) · [Recorded demo](https://premiere-pro-mcp.com/demo/) · [Compare servers](https://premiere-pro-mcp.com/compare/) · [Setup guides](https://premiere-pro-mcp.com/blog/how-to-set-up-premiere-pro-mcp/) · [Search tools](https://premiere-pro-mcp.com/tools/) · [Troubleshooting](https://premiere-pro-mcp.com/docs/troubleshooting/) · [Release facts](https://premiere-pro-mcp.com/facts/)
|
|
14
14
|
|
|
15
|
-
Development source:
|
|
15
|
+
Development source: 384 core tools across 57 modules, 4 resources, and 19 guided workflows. A connected UXP host adds 95 capability-gated tools.
|
|
16
16
|
|
|
17
17
|
The [completed AE render handoff](docs/after-effects-render-handoff.md) previews and confirms importing one finished render into an existing Premiere bin, with host and file rechecks and an import receipt.
|
|
18
18
|
|
|
@@ -104,14 +104,14 @@ and repository before configuring a client. The new
|
|
|
104
104
|
VS Code, or Codex settings that point directly to this installation. It is a
|
|
105
105
|
feature included in v1.15.1 and later.
|
|
106
106
|
|
|
107
|
-
The current source exposes
|
|
107
|
+
The current source exposes 384 core tools for supported workflow steps spanning the supported ExtendScript, QE DOM, local media and interchange analysis, revisioned project-context retrieval, safe edit-planning, project-intake preview, review handoff, connection verification, and guarded After Effects MOGRT authoring, batch, library, render-queue, inspection, and Premiere-handoff workflows. A compatible, authenticated UXP panel adds 95 documented, capability-gated tools without replacing the production CEP bridge.
|
|
108
108
|
|
|
109
109
|
<a id="latest-release"></a>
|
|
110
110
|
|
|
111
|
-
### Latest release: 1.
|
|
111
|
+
### Latest release: 1.18.0
|
|
112
112
|
|
|
113
|
-
The published v1.
|
|
114
|
-
and
|
|
113
|
+
The published v1.17.0 npm artifact contains **384 core tools**, 382 in its default profile,
|
|
114
|
+
and 477 with a compatible UXP connection. The development catalog above can include
|
|
115
115
|
unreleased work. See the [versioned facts and package provenance](https://premiere-pro-mcp.com/facts/).
|
|
116
116
|
|
|
117
117
|
### Try a bounded workflow
|
|
@@ -160,7 +160,7 @@ if the connection is unavailable.
|
|
|
160
160
|
local Premiere processes. See the generated [supported action catalog](docs/supported-actions.md)
|
|
161
161
|
for individual capability and verification contracts.
|
|
162
162
|
|
|
163
|
-
See the [v1.
|
|
163
|
+
See the [v1.18.0 release notes](https://github.com/leancoderkavy/premiere-pro-mcp/releases/tag/v1.18.0)
|
|
164
164
|
for complete details. Live installation in Premiere Pro still requires host verification.
|
|
165
165
|
|
|
166
166
|
### Current MCP protocol support
|
|
@@ -208,7 +208,7 @@ their bins, media rules, and organization rules before a facility uses one.
|
|
|
208
208
|
> ### Install the published package (verify the name)
|
|
209
209
|
>
|
|
210
210
|
> ```bash
|
|
211
|
-
> npm i -g premiere-pro-mcp@1.
|
|
211
|
+
> npm i -g premiere-pro-mcp@1.18.0
|
|
212
212
|
> ```
|
|
213
213
|
>
|
|
214
214
|
> This repository publishes only **`premiere-pro-mcp`**. A differently named package (`adobe-premiere-pro-mcp`) may also declare a `premiere-pro-mcp` executable. Before configuring a client, confirm:
|
|
@@ -216,7 +216,7 @@ their bins, media rules, and organization rules before a facility uses one.
|
|
|
216
216
|
> | Check | Expected |
|
|
217
217
|
> | --- | --- |
|
|
218
218
|
> | Package name | `premiere-pro-mcp` (not `adobe-premiere-pro-mcp`) |
|
|
219
|
-
> | Version | `1.
|
|
219
|
+
> | Version | `1.18.0` |
|
|
220
220
|
> | Homepage / repo | https://premiere-pro-mcp.com/ · https://github.com/leancoderkavy/premiere-pro-mcp |
|
|
221
221
|
>
|
|
222
222
|
> ```bash
|
|
@@ -229,9 +229,9 @@ their bins, media rules, and organization rules before a facility uses one.
|
|
|
229
229
|
|
|
230
230
|
### Easiest supported path: Claude Desktop
|
|
231
231
|
|
|
232
|
-
1. Download the current [Claude Desktop bundle (`.mcpb`)](https://github.com/leancoderkavy/premiere-pro-mcp/releases/download/v1.
|
|
232
|
+
1. Download the current [Claude Desktop bundle (`.mcpb`)](https://github.com/leancoderkavy/premiere-pro-mcp/releases/download/v1.18.0/premiere-pro-mcp-1.18.0.mcpb).
|
|
233
233
|
2. In Claude Desktop, open **Settings > Extensions > Advanced settings > Install Extension**, select the downloaded bundle, and restart Claude Desktop.
|
|
234
|
-
3. Download the separate [signed Premiere connector (`.zxp`)](https://github.com/leancoderkavy/premiere-pro-mcp/releases/download/v1.
|
|
234
|
+
3. Download the separate [signed Premiere connector (`.zxp`)](https://github.com/leancoderkavy/premiere-pro-mcp/releases/download/v1.18.0/MCPBridgeCEP.zxp). Open it with your trusted ZXP installer. If your computer has no ZXP installer, use the npm connector installer in **Advanced setup** below.
|
|
235
235
|
4. Restart Premiere, open a project, then open **Window > Extensions > MCP for Adobe Premiere Pro**.
|
|
236
236
|
5. In Claude, enter: `Safely check my Premiere connection with verify_premiere_connection. Make no changes.`
|
|
237
237
|
|
|
@@ -531,11 +531,11 @@ From a clone of this repository:
|
|
|
531
531
|
```bash
|
|
532
532
|
codex plugin marketplace add .
|
|
533
533
|
codex plugin add premiere-pro@premiere-pro-mcp
|
|
534
|
-
npx -y premiere-pro-mcp@1.
|
|
534
|
+
npx -y premiere-pro-mcp@1.17.0 --install-cep
|
|
535
535
|
```
|
|
536
536
|
|
|
537
537
|
Restart Premiere Pro and start a new Codex session after installation. The plugin
|
|
538
|
-
launches `premiere-pro-mcp@1.
|
|
538
|
+
launches `premiere-pro-mcp@1.17.0` through `npx`; the separate CEP installation is
|
|
539
539
|
required because the MCP server communicates with the running Premiere host through
|
|
540
540
|
the local bridge.
|
|
541
541
|
|
|
@@ -566,7 +566,7 @@ For Claude Code, add this repository as a marketplace and install the plugin:
|
|
|
566
566
|
Then install the Premiere bridge and start a new Claude Code session:
|
|
567
567
|
|
|
568
568
|
```bash
|
|
569
|
-
npx -y premiere-pro-mcp@1.
|
|
569
|
+
npx -y premiere-pro-mcp@1.17.0 --install-cep
|
|
570
570
|
```
|
|
571
571
|
|
|
572
572
|
The Claude Code package lives in
|
|
@@ -882,7 +882,7 @@ reports revision-bound notes, VFX state, change impact and turnover exceptions.
|
|
|
882
882
|
It performs local inspection; host edits and exports use separate guarded tools.
|
|
883
883
|
See [usage, example and remaining execution adapters](docs/film-editorial-workflows.md).
|
|
884
884
|
|
|
885
|
-
## Tools (
|
|
885
|
+
## Tools (384 core total; 382 under the default profile; 477 with a connected UXP bridge)
|
|
886
886
|
|
|
887
887
|
The [complete supported-actions catalog](docs/supported-actions.md) lists every
|
|
888
888
|
registered core tool, the two tools restricted behind explicit `unsafe-script`
|
|
@@ -922,7 +922,7 @@ the tables below are a shorter workflow-oriented overview.
|
|
|
922
922
|
| `set_scratch_disk_path` | Configure scratch disks |
|
|
923
923
|
| `consolidate_and_transfer` | Project Manager consolidation |
|
|
924
924
|
|
|
925
|
-
### Timeline & Editing (
|
|
925
|
+
### Timeline & Editing (11 + 27 advanced)
|
|
926
926
|
|
|
927
927
|
| Tool | Description |
|
|
928
928
|
| :--- | :---------- |
|
|
@@ -930,8 +930,9 @@ the tables below are a shorter workflow-oriented overview.
|
|
|
930
930
|
| `ripple_delete` | Remove clip and close gap (QE) |
|
|
931
931
|
| `roll_edit` / `slide_edit` / `slip_edit` | Professional trim modes (QE) |
|
|
932
932
|
| `move_clip_to_track` | Move between tracks (QE) |
|
|
933
|
-
| `reverse_clip` / `speed_change` / `set_clip_speed_qe` | Unavailable: Premiere
|
|
933
|
+
| `reverse_clip` / `speed_change` / `set_clip_speed_qe` | Unavailable: Premiere's documented ExtendScript and UXP APIs have no setter for a timeline clip's speed or direction; use `set_clip_duration` for timeline length |
|
|
934
934
|
| `split_clip` / `trim_clip` / `move_clip` | Basic edits; trim verifies source points and visible timeline edges |
|
|
935
|
+
| `set_clip_duration` | Set a clip's timeline duration or absolute end (extends still images); refuses next-clip overlaps and restores the original end if Premiere clamps |
|
|
935
936
|
| `set_clip_properties` | Opacity, scale, rotation, position (speed requests fail before mutation) |
|
|
936
937
|
| `link_selection` / `unlink_selection` | Link/unlink A/V |
|
|
937
938
|
|
|
@@ -946,9 +947,10 @@ the tables below are a shorter workflow-oriented overview.
|
|
|
946
947
|
|
|
947
948
|
> **Speed, caption, and visual-keyframe boundaries:** Premiere Pro 26.3 may reflect legacy QE
|
|
948
949
|
> speed/direction methods, but exposes no supported scripting setter or Time Remapping component
|
|
949
|
-
> for timeline-clip speed or direction. `
|
|
950
|
+
> for timeline-clip speed or direction (documented UXP through 26.3 has only `getSpeed` /
|
|
951
|
+
> `isSpeedReversed`). `reverse_clip`,
|
|
950
952
|
> `speed_change`, `set_clip_speed_qe`, and `set_clip_properties` with `speed` now stop before host mutation;
|
|
951
|
-
> use the Speed/Duration UI or pre-
|
|
953
|
+
> use `set_clip_duration` to change timeline length, or the Speed/Duration UI or pre-rendered media to retime. `add_text_overlay` likewise stops
|
|
952
954
|
> before mutation because a raw-text-to-caption API is not exposed; import an `.srt`/`.vtt`
|
|
953
955
|
> and use `create_caption_track`, or use a MOGRT/PNG overlay. Keyframe and caption-track
|
|
954
956
|
> responses can prove parameter/structure readback only—not rendered pixels—so verify playback
|
|
@@ -973,6 +975,15 @@ cut boundaries. Its QE path cannot prove effect-keyframe redistribution, so a su
|
|
|
973
975
|
labels those semantics `unverified`. These are CEP contract checks, not validation in a licensed
|
|
974
976
|
Premiere Pro 26.x host.
|
|
975
977
|
|
|
978
|
+
`set_clip_duration` changes a placed clip's timeline length without touching source in/out
|
|
979
|
+
directly: pass exactly one of `duration_seconds` (from the current start) or `end_seconds`
|
|
980
|
+
(absolute timeline end). It writes the documented `TrackItem.end` as a tick-based `Time`, refuses
|
|
981
|
+
an end that would overlap the next clip on the same track, applies the same `keyframe_policy`
|
|
982
|
+
guard as `trim_clip` when shortening, and reads start/end back. If Premiere clamps the end (for
|
|
983
|
+
example, video media with no remaining handle, or a still whose project item has in/out points),
|
|
984
|
+
the original end is restored and the tool returns an error. Linked audio/video partners are not
|
|
985
|
+
adjusted. This is a CEP contract check, not validation in a licensed Premiere Pro host.
|
|
986
|
+
|
|
976
987
|
### Effects & Color (8)
|
|
977
988
|
|
|
978
989
|
| Tool | Description |
|
|
@@ -1036,12 +1047,13 @@ presenting UI-only operations as available tools.
|
|
|
1036
1047
|
| `play_timeline` / `stop_playback` | Playback control (QE) |
|
|
1037
1048
|
| `play_source_monitor` | Play in source monitor |
|
|
1038
1049
|
|
|
1039
|
-
### Selection & Clipboard (7 +
|
|
1050
|
+
### Selection & Clipboard (7 + 7)
|
|
1040
1051
|
|
|
1041
1052
|
| Tool | Description |
|
|
1042
1053
|
| :--- | :---------- |
|
|
1043
1054
|
| `select_clips_by_name` / `select_clips_in_range` | Smart selection |
|
|
1044
1055
|
| `copy_effects_between_clips` | Copy effects via QE |
|
|
1056
|
+
| `paste_clip_attributes` | Paste Attributes: effect stack, values, and keyframes with per-property readback; masks and differing Blend Mode are reported, not copied |
|
|
1045
1057
|
| `batch_apply_effect` | Apply effect to multiple clips |
|
|
1046
1058
|
| `set_blend_mode` | 27 blend modes |
|
|
1047
1059
|
|
|
@@ -1110,6 +1122,12 @@ evidence behind these tools and their verification boundaries.
|
|
|
1110
1122
|
| `plan_speaker_checkerboard` | Per-speaker segments, split points, and track assignments for checkerboarded dialogue |
|
|
1111
1123
|
| `plan_active_speaker_reframe` | Active-speaker vertical reframe keyframes, or static stacked / side-by-side two-speaker layouts |
|
|
1112
1124
|
|
|
1125
|
+
### Mask Fit (1)
|
|
1126
|
+
|
|
1127
|
+
| Tool | Description |
|
|
1128
|
+
| :--- | :---------- |
|
|
1129
|
+
| `compute_mask_fit_motion` | Inspect only: Motion Scale and Position that place a still's subject box (source-image fractions) inside an existing Rounded Crop, Crop, or similar mask, with the math inputs and warnings. Apply with `set_clip_scale` / `set_clip_position`, then check with `capture_frame`. No image analysis. |
|
|
1130
|
+
|
|
1113
1131
|
### Rhythm Plans (2)
|
|
1114
1132
|
|
|
1115
1133
|
| Tool | Description |
|
|
@@ -1350,7 +1368,7 @@ premiere-pro-mcp/
|
|
|
1350
1368
|
├── src/
|
|
1351
1369
|
│ ├── index.ts # Entry point — stdio transport setup
|
|
1352
1370
|
│ ├── http-server.ts # Entry point — HTTP/SSE transport (Fly.io / remote)
|
|
1353
|
-
│ ├── server.ts # MCP server — registers
|
|
1371
|
+
│ ├── server.ts # MCP server — registers 384 tools, filtered by authority profile
|
|
1354
1372
|
│ ├── bridge/
|
|
1355
1373
|
│ │ ├── file-bridge.ts # File-based IPC (write .jsx, poll .json)
|
|
1356
1374
|
│ │ └── script-builder.ts # ExtendScript generator with ES3 helpers
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<ExtensionManifest Version="7.0" ExtensionBundleId="com.mcp.aftereffects.bridge" ExtensionBundleVersion="1.
|
|
2
|
+
<ExtensionManifest Version="7.0" ExtensionBundleId="com.mcp.aftereffects.bridge" ExtensionBundleVersion="1.18.0" ExtensionBundleName="MCP for Adobe After Effects">
|
|
3
3
|
<ExtensionList>
|
|
4
|
-
<Extension Id="com.mcp.aftereffects.bridge.panel" Version="1.
|
|
4
|
+
<Extension Id="com.mcp.aftereffects.bridge.panel" Version="1.18.0"/>
|
|
5
5
|
</ExtensionList>
|
|
6
6
|
<ExecutionEnvironment>
|
|
7
7
|
<HostList>
|
|
@@ -23,12 +23,12 @@
|
|
|
23
23
|
' $ancestorOwner = $ancestorAcl.GetOwner([System.Security.Principal.SecurityIdentifier]).Value',
|
|
24
24
|
' if ($ancestorOwner -notin $trustedAncestors) { $unsafeAncestors += [pscustomobject]@{ sid = $ancestorOwner; path = $ancestor.FullName; reason = "owner" } }',
|
|
25
25
|
' $unsafeAncestors += @($ancestorAcl.GetAccessRules($true, $true, [System.Security.Principal.SecurityIdentifier]) | Where-Object {',
|
|
26
|
-
' $_.AccessControlType -eq [System.Security.AccessControl.AccessControlType]::Allow -and (($_.PropagationFlags -band [System.Security.AccessControl.PropagationFlags]::InheritOnly) -eq 0) -and (($_.FileSystemRights -band $replacement) -ne 0) -and $_.IdentityReference.Value -notin $trustedAncestors',
|
|
26
|
+
' $_.AccessControlType -eq [System.Security.AccessControl.AccessControlType]::Allow -and (($_.PropagationFlags -band [System.Security.AccessControl.PropagationFlags]::InheritOnly) -eq 0) -and (($_.FileSystemRights -band $replacement) -ne 0) -and $_.IdentityReference.Value -notin $trustedAncestors -and $_.IdentityReference.Value -notlike "S-1-15-*"',
|
|
27
27
|
' } | ForEach-Object { [pscustomobject]@{ sid = $_.IdentityReference.Value; path = $ancestor.FullName; reason = "replacement_rights" } })',
|
|
28
28
|
' $ancestor = $ancestor.Parent',
|
|
29
29
|
'}',
|
|
30
30
|
'if ($initialize) {',
|
|
31
|
-
' if ($unsafeAncestors.Count -ne 0) { throw "Bridge directory ancestry is unsafe" }',
|
|
31
|
+
' if ($unsafeAncestors.Count -ne 0) { throw ("Bridge directory ancestry is unsafe: " + (($unsafeAncestors | ForEach-Object { "{0} ({1}: {2})" -f $_.path, $_.reason, $_.sid }) -join "; ")) }',
|
|
32
32
|
' $acl.SetAccessRuleProtection($true, $false)',
|
|
33
33
|
' $inheritance = [System.Security.AccessControl.InheritanceFlags]::ContainerInherit -bor [System.Security.AccessControl.InheritanceFlags]::ObjectInherit',
|
|
34
34
|
' $propagation = [System.Security.AccessControl.PropagationFlags]::None',
|
|
@@ -46,11 +46,17 @@
|
|
|
46
46
|
'$unsafe = @($acl.GetAccessRules($true, $true, [System.Security.Principal.SecurityIdentifier]) | Where-Object {',
|
|
47
47
|
' $_.AccessControlType -eq [System.Security.AccessControl.AccessControlType]::Allow -and (($_.FileSystemRights -band $mutating) -ne 0)',
|
|
48
48
|
'} | ForEach-Object {',
|
|
49
|
-
' if ($_.IdentityReference.Value -notin $trusted) { [pscustomobject]@{ sid = $_.IdentityReference.Value; isInherited = [bool]$_.IsInherited } }',
|
|
49
|
+
' if ($_.IdentityReference.Value -notin $trusted -and $_.IdentityReference.Value -notlike "S-1-15-*") { [pscustomobject]@{ sid = $_.IdentityReference.Value; isInherited = [bool]$_.IsInherited } }',
|
|
50
50
|
'})',
|
|
51
51
|
'[pscustomobject]@{ ownerSid = $owner; currentUserSid = $current; unsafeWriteAces = $unsafe; unsafeAncestorEntries = $unsafeAncestors } | ConvertTo-Json -Compress',
|
|
52
52
|
].join("\n");
|
|
53
53
|
|
|
54
|
+
// Capability (S-1-15-3-*) and app-container package (S-1-15-2-*) SIDs are not
|
|
55
|
+
// logon principals; stock profiles inherit one with FullControl on AppData (#581).
|
|
56
|
+
function isWindowsCapabilitySid(sid) {
|
|
57
|
+
return typeof sid === "string" && sid.toUpperCase().indexOf("S-1-15-") === 0;
|
|
58
|
+
}
|
|
59
|
+
|
|
54
60
|
function createBridgeDirectorySecurity(runtime) {
|
|
55
61
|
if (!runtime || !runtime.fs || !runtime.path) {
|
|
56
62
|
throw new Error("Bridge directory security requires filesystem and path runtimes");
|
|
@@ -170,26 +176,29 @@
|
|
|
170
176
|
if (!acl || !acl.ownerSid || !acl.currentUserSid || acl.ownerSid !== acl.currentUserSid) {
|
|
171
177
|
throw new Error("Bridge directory is not owned by the current Windows user: " + resolved);
|
|
172
178
|
}
|
|
173
|
-
var unsafe = Array.isArray(acl.unsafeWriteAces)
|
|
179
|
+
var unsafe = (Array.isArray(acl.unsafeWriteAces)
|
|
174
180
|
? acl.unsafeWriteAces
|
|
175
181
|
: acl.unsafeWriteAces
|
|
176
182
|
? [acl.unsafeWriteAces]
|
|
177
|
-
: [];
|
|
183
|
+
: []).filter(function (ace) { return !isWindowsCapabilitySid(ace && ace.sid); });
|
|
178
184
|
if (unsafe.length > 0) {
|
|
179
185
|
var unsafeSids = unsafe.map(function (ace) { return ace && ace.sid ? ace.sid : "unknown"; });
|
|
180
186
|
throw new Error(
|
|
181
187
|
"Bridge directory grants write access to untrusted identities (" + unsafeSids.join(", ") + "): " + resolved
|
|
182
188
|
);
|
|
183
189
|
}
|
|
184
|
-
var unsafeAncestors = Array.isArray(acl.unsafeAncestorEntries)
|
|
190
|
+
var unsafeAncestors = (Array.isArray(acl.unsafeAncestorEntries)
|
|
185
191
|
? acl.unsafeAncestorEntries
|
|
186
192
|
: acl.unsafeAncestorEntries
|
|
187
193
|
? [acl.unsafeAncestorEntries]
|
|
188
|
-
: []
|
|
194
|
+
: []).filter(function (entry) {
|
|
195
|
+
return !entry || entry.reason !== "replacement_rights" || !isWindowsCapabilitySid(entry.sid);
|
|
196
|
+
});
|
|
189
197
|
if (unsafeAncestors.length > 0) {
|
|
190
198
|
throw new Error(
|
|
191
|
-
"Bridge path has a replaceable ancestor " + unsafeAncestors
|
|
192
|
-
|
|
199
|
+
"Bridge path has a replaceable ancestor " + unsafeAncestors.map(function (entry) {
|
|
200
|
+
return (entry && entry.path) + " (" + (entry && entry.reason) + ": " + (entry && entry.sid ? entry.sid : "none") + ")";
|
|
201
|
+
}).join("; ")
|
|
193
202
|
);
|
|
194
203
|
}
|
|
195
204
|
if (newlyCreated && fs.readdirSync(resolved).length > 0) {
|
|
Binary file
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<ExtensionManifest Version="7.0" ExtensionBundleId="com.mcp.premiere.bridge" ExtensionBundleVersion="1.
|
|
2
|
+
<ExtensionManifest Version="7.0" ExtensionBundleId="com.mcp.premiere.bridge" ExtensionBundleVersion="1.18.0" ExtensionBundleName="MCP for Adobe Premiere Pro">
|
|
3
3
|
<ExtensionList>
|
|
4
|
-
<Extension Id="com.mcp.premiere.bridge.panel" Version="1.
|
|
5
|
-
<Extension Id="com.mcp.premiere.bridge.headless" Version="1.
|
|
4
|
+
<Extension Id="com.mcp.premiere.bridge.panel" Version="1.18.0"/>
|
|
5
|
+
<Extension Id="com.mcp.premiere.bridge.headless" Version="1.18.0"/>
|
|
6
6
|
</ExtensionList>
|
|
7
7
|
<ExecutionEnvironment>
|
|
8
8
|
<HostList>
|
|
@@ -23,12 +23,12 @@
|
|
|
23
23
|
' $ancestorOwner = $ancestorAcl.GetOwner([System.Security.Principal.SecurityIdentifier]).Value',
|
|
24
24
|
' if ($ancestorOwner -notin $trustedAncestors) { $unsafeAncestors += [pscustomobject]@{ sid = $ancestorOwner; path = $ancestor.FullName; reason = "owner" } }',
|
|
25
25
|
' $unsafeAncestors += @($ancestorAcl.GetAccessRules($true, $true, [System.Security.Principal.SecurityIdentifier]) | Where-Object {',
|
|
26
|
-
' $_.AccessControlType -eq [System.Security.AccessControl.AccessControlType]::Allow -and (($_.PropagationFlags -band [System.Security.AccessControl.PropagationFlags]::InheritOnly) -eq 0) -and (($_.FileSystemRights -band $replacement) -ne 0) -and $_.IdentityReference.Value -notin $trustedAncestors',
|
|
26
|
+
' $_.AccessControlType -eq [System.Security.AccessControl.AccessControlType]::Allow -and (($_.PropagationFlags -band [System.Security.AccessControl.PropagationFlags]::InheritOnly) -eq 0) -and (($_.FileSystemRights -band $replacement) -ne 0) -and $_.IdentityReference.Value -notin $trustedAncestors -and $_.IdentityReference.Value -notlike "S-1-15-*"',
|
|
27
27
|
' } | ForEach-Object { [pscustomobject]@{ sid = $_.IdentityReference.Value; path = $ancestor.FullName; reason = "replacement_rights" } })',
|
|
28
28
|
' $ancestor = $ancestor.Parent',
|
|
29
29
|
'}',
|
|
30
30
|
'if ($initialize) {',
|
|
31
|
-
' if ($unsafeAncestors.Count -ne 0) { throw "Bridge directory ancestry is unsafe" }',
|
|
31
|
+
' if ($unsafeAncestors.Count -ne 0) { throw ("Bridge directory ancestry is unsafe: " + (($unsafeAncestors | ForEach-Object { "{0} ({1}: {2})" -f $_.path, $_.reason, $_.sid }) -join "; ")) }',
|
|
32
32
|
' $acl.SetAccessRuleProtection($true, $false)',
|
|
33
33
|
' $inheritance = [System.Security.AccessControl.InheritanceFlags]::ContainerInherit -bor [System.Security.AccessControl.InheritanceFlags]::ObjectInherit',
|
|
34
34
|
' $propagation = [System.Security.AccessControl.PropagationFlags]::None',
|
|
@@ -46,11 +46,17 @@
|
|
|
46
46
|
'$unsafe = @($acl.GetAccessRules($true, $true, [System.Security.Principal.SecurityIdentifier]) | Where-Object {',
|
|
47
47
|
' $_.AccessControlType -eq [System.Security.AccessControl.AccessControlType]::Allow -and (($_.FileSystemRights -band $mutating) -ne 0)',
|
|
48
48
|
'} | ForEach-Object {',
|
|
49
|
-
' if ($_.IdentityReference.Value -notin $trusted) { [pscustomobject]@{ sid = $_.IdentityReference.Value; isInherited = [bool]$_.IsInherited } }',
|
|
49
|
+
' if ($_.IdentityReference.Value -notin $trusted -and $_.IdentityReference.Value -notlike "S-1-15-*") { [pscustomobject]@{ sid = $_.IdentityReference.Value; isInherited = [bool]$_.IsInherited } }',
|
|
50
50
|
'})',
|
|
51
51
|
'[pscustomobject]@{ ownerSid = $owner; currentUserSid = $current; unsafeWriteAces = $unsafe; unsafeAncestorEntries = $unsafeAncestors } | ConvertTo-Json -Compress',
|
|
52
52
|
].join("\n");
|
|
53
53
|
|
|
54
|
+
// Capability (S-1-15-3-*) and app-container package (S-1-15-2-*) SIDs are not
|
|
55
|
+
// logon principals; stock profiles inherit one with FullControl on AppData (#581).
|
|
56
|
+
function isWindowsCapabilitySid(sid) {
|
|
57
|
+
return typeof sid === "string" && sid.toUpperCase().indexOf("S-1-15-") === 0;
|
|
58
|
+
}
|
|
59
|
+
|
|
54
60
|
function createBridgeDirectorySecurity(runtime) {
|
|
55
61
|
if (!runtime || !runtime.fs || !runtime.path) {
|
|
56
62
|
throw new Error("Bridge directory security requires filesystem and path runtimes");
|
|
@@ -170,26 +176,29 @@
|
|
|
170
176
|
if (!acl || !acl.ownerSid || !acl.currentUserSid || acl.ownerSid !== acl.currentUserSid) {
|
|
171
177
|
throw new Error("Bridge directory is not owned by the current Windows user: " + resolved);
|
|
172
178
|
}
|
|
173
|
-
var unsafe = Array.isArray(acl.unsafeWriteAces)
|
|
179
|
+
var unsafe = (Array.isArray(acl.unsafeWriteAces)
|
|
174
180
|
? acl.unsafeWriteAces
|
|
175
181
|
: acl.unsafeWriteAces
|
|
176
182
|
? [acl.unsafeWriteAces]
|
|
177
|
-
: [];
|
|
183
|
+
: []).filter(function (ace) { return !isWindowsCapabilitySid(ace && ace.sid); });
|
|
178
184
|
if (unsafe.length > 0) {
|
|
179
185
|
var unsafeSids = unsafe.map(function (ace) { return ace && ace.sid ? ace.sid : "unknown"; });
|
|
180
186
|
throw new Error(
|
|
181
187
|
"Bridge directory grants write access to untrusted identities (" + unsafeSids.join(", ") + "): " + resolved
|
|
182
188
|
);
|
|
183
189
|
}
|
|
184
|
-
var unsafeAncestors = Array.isArray(acl.unsafeAncestorEntries)
|
|
190
|
+
var unsafeAncestors = (Array.isArray(acl.unsafeAncestorEntries)
|
|
185
191
|
? acl.unsafeAncestorEntries
|
|
186
192
|
: acl.unsafeAncestorEntries
|
|
187
193
|
? [acl.unsafeAncestorEntries]
|
|
188
|
-
: []
|
|
194
|
+
: []).filter(function (entry) {
|
|
195
|
+
return !entry || entry.reason !== "replacement_rights" || !isWindowsCapabilitySid(entry.sid);
|
|
196
|
+
});
|
|
189
197
|
if (unsafeAncestors.length > 0) {
|
|
190
198
|
throw new Error(
|
|
191
|
-
"Bridge path has a replaceable ancestor " + unsafeAncestors
|
|
192
|
-
|
|
199
|
+
"Bridge path has a replaceable ancestor " + unsafeAncestors.map(function (entry) {
|
|
200
|
+
return (entry && entry.path) + " (" + (entry && entry.reason) + ": " + (entry && entry.sid ? entry.sid : "none") + ")";
|
|
201
|
+
}).join("; ")
|
|
193
202
|
);
|
|
194
203
|
}
|
|
195
204
|
if (newlyCreated && fs.readdirSync(resolved).length > 0) {
|
package/cep-plugin/index.html
CHANGED
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
<section class="update-section" aria-live="polite">
|
|
82
82
|
<div class="update-copy">
|
|
83
83
|
<span class="section-label">MCP updates</span>
|
|
84
|
-
<strong id="updateTitle">Version 1.
|
|
84
|
+
<strong id="updateTitle">Version 1.18.0</strong>
|
|
85
85
|
<span id="updateDetail">Checking the global MCP server and connector release…</span>
|
|
86
86
|
</div>
|
|
87
87
|
<button id="btnUpdate" class="button button-update" onclick="handleUpdateClick()" type="button" aria-describedby="updateDetail" disabled>
|
package/cep-plugin/updater.cjs
CHANGED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic geometry for fitting a still image's subject inside an
|
|
3
|
+
* existing crop/mask region by changing only Motion Scale and Position.
|
|
4
|
+
*
|
|
5
|
+
* No image analysis happens here. The caller supplies the subject box as
|
|
6
|
+
* fractions of the source frame, and the mask region comes either from the
|
|
7
|
+
* mask effect's own parameters or from an explicit override.
|
|
8
|
+
*
|
|
9
|
+
* Motion model (rotation 0, uniform scale), with the source measured in
|
|
10
|
+
* display pixels (width x pixel aspect ratio):
|
|
11
|
+
*
|
|
12
|
+
* sequence_x = position_x + (u - anchor_u) * displayWidth * scale * prescale
|
|
13
|
+
* sequence_y = position_y + (v - anchor_v) * displayHeight * scale * prescale
|
|
14
|
+
*
|
|
15
|
+
* where (u, v) and (anchor_u, anchor_v) are fractions of the source frame.
|
|
16
|
+
*/
|
|
17
|
+
export interface FrameSize {
|
|
18
|
+
width: number;
|
|
19
|
+
height: number;
|
|
20
|
+
}
|
|
21
|
+
/** Axis-aligned box as fractions (0..1) of a frame. */
|
|
22
|
+
export interface NormalizedBox {
|
|
23
|
+
left: number;
|
|
24
|
+
top: number;
|
|
25
|
+
right: number;
|
|
26
|
+
bottom: number;
|
|
27
|
+
}
|
|
28
|
+
export interface MaskPlacement {
|
|
29
|
+
/** Subject top edge as a fraction of the mask height (0 = mask top). */
|
|
30
|
+
top: number;
|
|
31
|
+
/** Subject bottom edge as a fraction of the mask height (1 = mask bottom). */
|
|
32
|
+
bottom: number;
|
|
33
|
+
/** Subject left edge as a fraction of the mask width (width fit only). */
|
|
34
|
+
left: number;
|
|
35
|
+
/** Subject right edge as a fraction of the mask width (width fit only). */
|
|
36
|
+
right: number;
|
|
37
|
+
/** Subject horizontal center as a fraction of the mask width (height fit only). */
|
|
38
|
+
center_x: number;
|
|
39
|
+
/** Subject vertical center as a fraction of the mask height (width fit only). */
|
|
40
|
+
center_y: number;
|
|
41
|
+
}
|
|
42
|
+
export type FitAxis = "height" | "width";
|
|
43
|
+
export interface MaskFitInput {
|
|
44
|
+
sequence: FrameSize;
|
|
45
|
+
source: FrameSize & {
|
|
46
|
+
pixelAspectRatio?: number;
|
|
47
|
+
};
|
|
48
|
+
/** Mask region as fractions of the sequence frame. */
|
|
49
|
+
mask: NormalizedBox;
|
|
50
|
+
/** Subject box as fractions of the source frame. */
|
|
51
|
+
subject: NormalizedBox;
|
|
52
|
+
placement?: Partial<MaskPlacement>;
|
|
53
|
+
fitAxis?: FitAxis;
|
|
54
|
+
/** Motion Anchor Point as fractions of the source frame; defaults to the center. */
|
|
55
|
+
anchor?: {
|
|
56
|
+
x: number;
|
|
57
|
+
y: number;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Extra scale Premiere applies before Motion (for example "Scale to Frame
|
|
61
|
+
* Size"). Defaults to 1. Motion Scale is reported net of this factor.
|
|
62
|
+
*/
|
|
63
|
+
sourcePrescale?: number;
|
|
64
|
+
}
|
|
65
|
+
export interface MaskFitResult {
|
|
66
|
+
scale_percent: number;
|
|
67
|
+
position_pixels: {
|
|
68
|
+
x: number;
|
|
69
|
+
y: number;
|
|
70
|
+
};
|
|
71
|
+
position_normalized: {
|
|
72
|
+
x: number;
|
|
73
|
+
y: number;
|
|
74
|
+
};
|
|
75
|
+
placement: MaskPlacement;
|
|
76
|
+
fit_axis: FitAxis;
|
|
77
|
+
mask_pixels: {
|
|
78
|
+
left: number;
|
|
79
|
+
top: number;
|
|
80
|
+
right: number;
|
|
81
|
+
bottom: number;
|
|
82
|
+
width: number;
|
|
83
|
+
height: number;
|
|
84
|
+
};
|
|
85
|
+
subject_pixels: {
|
|
86
|
+
left: number;
|
|
87
|
+
top: number;
|
|
88
|
+
right: number;
|
|
89
|
+
bottom: number;
|
|
90
|
+
width: number;
|
|
91
|
+
height: number;
|
|
92
|
+
};
|
|
93
|
+
image_pixels: {
|
|
94
|
+
left: number;
|
|
95
|
+
top: number;
|
|
96
|
+
right: number;
|
|
97
|
+
bottom: number;
|
|
98
|
+
};
|
|
99
|
+
warnings: string[];
|
|
100
|
+
}
|
|
101
|
+
export declare const DEFAULT_MASK_PLACEMENT: MaskPlacement;
|
|
102
|
+
export declare function validateNormalizedBox(box: NormalizedBox, label: string, allowOutside?: boolean): void;
|
|
103
|
+
export declare function resolvePlacement(placement: Partial<MaskPlacement> | undefined): MaskPlacement;
|
|
104
|
+
/** Compute the Motion Scale and Position that map the subject box onto the target region of the mask. */
|
|
105
|
+
export declare function computeMaskFitMotion(input: MaskFitInput): MaskFitResult;
|
|
106
|
+
/** One effect parameter as read from Premiere. */
|
|
107
|
+
export interface RawEffectProperty {
|
|
108
|
+
name: string;
|
|
109
|
+
value: unknown;
|
|
110
|
+
}
|
|
111
|
+
export interface MaskInterpretation {
|
|
112
|
+
box: NormalizedBox;
|
|
113
|
+
method: "edges" | "center_size";
|
|
114
|
+
used_properties: string[];
|
|
115
|
+
assumptions: string[];
|
|
116
|
+
}
|
|
117
|
+
export declare function looksNormalizedPoint(point: readonly number[]): boolean;
|
|
118
|
+
/**
|
|
119
|
+
* Turn a mask effect's parameters into a box in sequence-frame fractions.
|
|
120
|
+
* Supports edge insets (Crop-style Left/Top/Right/Bottom percentages) and
|
|
121
|
+
* center plus size (Center/Position with Width/Height, Size, or Radius).
|
|
122
|
+
* Returns undefined when neither shape is recognizable.
|
|
123
|
+
*/
|
|
124
|
+
export declare function interpretMaskProperties(properties: readonly RawEffectProperty[], sequence: FrameSize): MaskInterpretation | undefined;
|
|
125
|
+
//# sourceMappingURL=mask-fit.d.ts.map
|