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.
Files changed (59) hide show
  1. package/CHANGELOG.md +83 -0
  2. package/README.md +38 -20
  3. package/after-effects-cep-plugin/CSXS/manifest.xml +2 -2
  4. package/after-effects-cep-plugin/bridge-directory-security.cjs +18 -9
  5. package/artifacts/MCPBridgeCEP.zxp +0 -0
  6. package/cep-plugin/CSXS/manifest.xml +3 -3
  7. package/cep-plugin/bridge-directory-security.cjs +18 -9
  8. package/cep-plugin/index.html +1 -1
  9. package/cep-plugin/updater.cjs +1 -1
  10. package/dist/ai/mask-fit.d.ts +125 -0
  11. package/dist/ai/mask-fit.js +308 -0
  12. package/dist/ai/timeline-qa.js +1 -1
  13. package/dist/bridge/file-bridge.d.ts +7 -0
  14. package/dist/bridge/file-bridge.js +21 -8
  15. package/dist/bridge/script-builder.js +178 -8
  16. package/dist/http-server.js +2 -2
  17. package/dist/index.js +1 -1
  18. package/dist/resources/extendscript-reference.js +1 -1
  19. package/dist/security/capabilities.js +1 -0
  20. package/dist/server.js +4 -2
  21. package/dist/telemetry.d.ts +2 -0
  22. package/dist/telemetry.js +9 -0
  23. package/dist/tools/advanced.d.ts +8 -0
  24. package/dist/tools/advanced.js +32 -4
  25. package/dist/tools/clipboard.d.ts +58 -0
  26. package/dist/tools/clipboard.js +495 -0
  27. package/dist/tools/export.d.ts +5 -1
  28. package/dist/tools/export.js +47 -13
  29. package/dist/tools/inspection.js +21 -60
  30. package/dist/tools/mask-fit.d.ts +182 -0
  31. package/dist/tools/mask-fit.js +357 -0
  32. package/dist/tools/media.d.ts +5 -0
  33. package/dist/tools/media.js +166 -13
  34. package/dist/tools/metadata.js +5 -2
  35. package/dist/tools/mogrt-authoring.d.ts +26 -3
  36. package/dist/tools/mogrt-authoring.js +188 -42
  37. package/dist/tools/mogrt-text.d.ts +39 -0
  38. package/dist/tools/mogrt-text.js +107 -0
  39. package/dist/tools/project.js +24 -6
  40. package/dist/tools/text.d.ts +8 -0
  41. package/dist/tools/text.js +52 -3
  42. package/dist/tools/timeline-qa.js +1 -1
  43. package/dist/tools/timeline.d.ts +42 -0
  44. package/dist/tools/timeline.js +298 -56
  45. package/dist/tools/track-targeting.d.ts +5 -0
  46. package/dist/tools/track-targeting.js +125 -34
  47. package/dist/tools/uxp-timeline-source-label-workflows.d.ts +8 -1
  48. package/dist/tools/uxp-timeline-source-label-workflows.js +14 -5
  49. package/dist/tools/uxp.d.ts +7 -0
  50. package/dist/workflows/agent-instructions.js +3 -0
  51. package/dist/workflows/tool-metadata.js +1 -0
  52. package/docs/mogrt-authoring.md +26 -2
  53. package/docs/supported-actions.md +20 -17
  54. package/package.json +2 -2
  55. package/public-product-manifest.json +5 -5
  56. package/uxp-plugin/commands.cjs +22 -11
  57. package/uxp-plugin/manifest.json +1 -1
  58. package/uxp-plugin/timeline-source-label-workflows.cjs +46 -9
  59. 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: 381 core tools across 56 modules, 4 resources, and 19 guided workflows. A connected UXP host adds 95 capability-gated tools.
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 381 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.
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.16.4
111
+ ### Latest release: 1.18.0
112
112
 
113
- The published v1.16.3 npm artifact contains **381 core tools**, 379 in its default profile,
114
- and 474 with a compatible UXP connection. The development catalog above can include
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.16.4 release notes](https://github.com/leancoderkavy/premiere-pro-mcp/releases/tag/v1.16.4)
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.16.4
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.16.4` |
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.16.4/premiere-pro-mcp-1.16.4.mcpb).
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.16.4/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.
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.16.3 --install-cep
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.16.3` through `npx`; the separate CEP installation is
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.16.3 --install-cep
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 (381 core total; 379 under the default profile; 474 with a connected UXP bridge)
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 (10 + 27 advanced)
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 has no supported scripting API for changing a timeline clip's speed or direction |
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. `reverse_clip`,
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-render retimed media. `add_text_overlay` likewise stops
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 + 6)
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 381 tools, filtered by authority profile
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.16.4" ExtensionBundleName="MCP for Adobe After Effects">
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.16.4"/>
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[0].path +
192
- " (" + unsafeAncestors[0].sid + ")"
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.16.4" ExtensionBundleName="MCP for Adobe Premiere Pro">
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.16.4"/>
5
- <Extension Id="com.mcp.premiere.bridge.headless" Version="1.16.4"/>
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[0].path +
192
- " (" + unsafeAncestors[0].sid + ")"
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) {
@@ -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.16.4</strong>
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>
@@ -7,7 +7,7 @@
7
7
  })(this, function () {
8
8
  "use strict";
9
9
 
10
- var CURRENT_VERSION = "1.16.4";
10
+ var CURRENT_VERSION = "1.18.0";
11
11
  var PACKAGE_NAME = "premiere-pro-mcp";
12
12
  var LATEST_PACKAGE_API = "https://registry.npmjs.org/" + PACKAGE_NAME;
13
13
  var LATEST_RELEASE_API =
@@ -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