premiere-pro-mcp 1.18.2 → 1.18.3
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 +16 -0
- package/README.md +11 -11
- package/after-effects-cep-plugin/CSXS/manifest.xml +2 -2
- package/artifacts/MCPBridgeCEP.zxp +0 -0
- package/cep-plugin/CSXS/manifest.xml +3 -3
- package/cep-plugin/index.html +1 -1
- package/cep-plugin/updater.cjs +1 -1
- package/dist/bridge/script-builder.js +8 -0
- package/dist/bridge/uxp-websocket-bridge.js +11 -0
- package/dist/security/path-guard.d.ts +10 -0
- package/dist/security/path-guard.js +106 -0
- package/dist/tools/export.js +6 -1
- package/dist/tools/playhead.js +19 -6
- package/package.json +1 -1
- package/public-product-manifest.json +1 -1
- package/uxp-plugin/manifest.json +1 -1
- package/uxp-plugin/next-workflows.cjs +16 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,22 @@ 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.3] - 2026-09-28
|
|
10
|
+
|
|
11
|
+
### Security
|
|
12
|
+
|
|
13
|
+
- UXP path arguments are now checked in the MCP server process before a command is sent. Any absolute path that goes through a symbolic link or directory junction is refused with `UXP_PATH_SYMLINK_REFUSED`. Premiere 26.5 UXP reports a link's own path and cannot `lstat`, so the panel's workspace check could be bypassed through a link inside the approved folder. (#640)
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- `get_work_area` now reads work-area points as seconds, as live Premiere 25.2 and 26.5.1 hosts return them. It had divided them by ticks-per-second and reported values near zero. `set_work_area` writes seconds and reads the result back; it fails honestly when a build ignores the write. (#642)
|
|
18
|
+
- `export_sequence` now fails when Premiere rejects the render or writes no file. (#647)
|
|
19
|
+
- UXP source-media timing reads Premiere 26.5's documented synchronous `Media.getStart()` / `getDuration()` before the deprecated Promise-returning `start` / `duration` properties, so `manage_source_media_timing_uxp` can set a start time on 26.5 hosts instead of reporting the command unavailable.
|
|
20
|
+
|
|
21
|
+
### Verification scope
|
|
22
|
+
|
|
23
|
+
- Automated checks validate package behavior. The UXP media timing change and the server-side symlink guard have not been verified on a licensed Premiere host.
|
|
24
|
+
|
|
9
25
|
## [1.18.2] - 2026-09-26
|
|
10
26
|
|
|
11
27
|
### Added
|
package/README.md
CHANGED
|
@@ -110,10 +110,10 @@ The current source exposes 384 core tools for supported workflow steps spanning
|
|
|
110
110
|
|
|
111
111
|
<a id="latest-release"></a>
|
|
112
112
|
|
|
113
|
-
### Latest release: 1.18.
|
|
113
|
+
### Latest release: 1.18.2
|
|
114
114
|
|
|
115
|
-
The published v1.18.
|
|
116
|
-
and
|
|
115
|
+
The published v1.18.2 npm artifact contains **384 core tools**, 382 in its default profile,
|
|
116
|
+
and 478 with a compatible UXP connection. The development catalog above can include
|
|
117
117
|
unreleased work. See the [versioned facts and package provenance](https://premiere-pro-mcp.com/facts/).
|
|
118
118
|
|
|
119
119
|
### Try a bounded workflow
|
|
@@ -162,7 +162,7 @@ if the connection is unavailable.
|
|
|
162
162
|
local Premiere processes. See the generated [supported action catalog](docs/supported-actions.md)
|
|
163
163
|
for individual capability and verification contracts.
|
|
164
164
|
|
|
165
|
-
See the [v1.18.
|
|
165
|
+
See the [v1.18.2 release notes](https://github.com/leancoderkavy/premiere-pro-mcp/releases/tag/v1.18.2)
|
|
166
166
|
for complete details. Live installation in Premiere Pro still requires host verification.
|
|
167
167
|
|
|
168
168
|
### Current MCP protocol support
|
|
@@ -210,7 +210,7 @@ their bins, media rules, and organization rules before a facility uses one.
|
|
|
210
210
|
> ### Install the published package (verify the name)
|
|
211
211
|
>
|
|
212
212
|
> ```bash
|
|
213
|
-
> npm i -g premiere-pro-mcp@1.18.
|
|
213
|
+
> npm i -g premiere-pro-mcp@1.18.2
|
|
214
214
|
> ```
|
|
215
215
|
>
|
|
216
216
|
> 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:
|
|
@@ -218,7 +218,7 @@ their bins, media rules, and organization rules before a facility uses one.
|
|
|
218
218
|
> | Check | Expected |
|
|
219
219
|
> | --- | --- |
|
|
220
220
|
> | Package name | `premiere-pro-mcp` (not `adobe-premiere-pro-mcp`) |
|
|
221
|
-
> | Version | `1.18.
|
|
221
|
+
> | Version | `1.18.2` |
|
|
222
222
|
> | Homepage / repo | https://premiere-pro-mcp.com/ · https://github.com/leancoderkavy/premiere-pro-mcp |
|
|
223
223
|
>
|
|
224
224
|
> ```bash
|
|
@@ -231,9 +231,9 @@ their bins, media rules, and organization rules before a facility uses one.
|
|
|
231
231
|
|
|
232
232
|
### Easiest supported path: Claude Desktop
|
|
233
233
|
|
|
234
|
-
1. Download the current [Claude Desktop bundle (`.mcpb`)](https://github.com/leancoderkavy/premiere-pro-mcp/releases/download/v1.18.
|
|
234
|
+
1. Download the current [Claude Desktop bundle (`.mcpb`)](https://github.com/leancoderkavy/premiere-pro-mcp/releases/download/v1.18.2/premiere-pro-mcp-1.18.2.mcpb).
|
|
235
235
|
2. In Claude Desktop, open **Settings > Extensions > Advanced settings > Install Extension**, select the downloaded bundle, and restart Claude Desktop.
|
|
236
|
-
3. Download the separate [signed Premiere connector (`.zxp`)](https://github.com/leancoderkavy/premiere-pro-mcp/releases/download/v1.18.
|
|
236
|
+
3. Download the separate [signed Premiere connector (`.zxp`)](https://github.com/leancoderkavy/premiere-pro-mcp/releases/download/v1.18.2/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.
|
|
237
237
|
4. Restart Premiere, open a project, then open **Window > Extensions > MCP for Adobe Premiere Pro**.
|
|
238
238
|
5. In Claude, enter: `Safely check my Premiere connection with verify_premiere_connection. Make no changes.`
|
|
239
239
|
|
|
@@ -533,11 +533,11 @@ From a clone of this repository:
|
|
|
533
533
|
```bash
|
|
534
534
|
codex plugin marketplace add .
|
|
535
535
|
codex plugin add premiere-pro@premiere-pro-mcp
|
|
536
|
-
npx -y premiere-pro-mcp@1.18.
|
|
536
|
+
npx -y premiere-pro-mcp@1.18.2 --install-cep
|
|
537
537
|
```
|
|
538
538
|
|
|
539
539
|
Restart Premiere Pro and start a new Codex session after installation. The plugin
|
|
540
|
-
launches `premiere-pro-mcp@1.18.
|
|
540
|
+
launches `premiere-pro-mcp@1.18.2` through `npx`; the separate CEP installation is
|
|
541
541
|
required because the MCP server communicates with the running Premiere host through
|
|
542
542
|
the local bridge.
|
|
543
543
|
|
|
@@ -575,7 +575,7 @@ For Claude Code, add this repository as a marketplace and install the plugin:
|
|
|
575
575
|
Then install the Premiere bridge and start a new Claude Code session:
|
|
576
576
|
|
|
577
577
|
```bash
|
|
578
|
-
npx -y premiere-pro-mcp@1.18.
|
|
578
|
+
npx -y premiere-pro-mcp@1.18.2 --install-cep
|
|
579
579
|
```
|
|
580
580
|
|
|
581
581
|
The Claude Code package lives in
|
|
@@ -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.18.
|
|
2
|
+
<ExtensionManifest Version="7.0" ExtensionBundleId="com.mcp.aftereffects.bridge" ExtensionBundleVersion="1.18.3" ExtensionBundleName="MCP for Adobe After Effects">
|
|
3
3
|
<ExtensionList>
|
|
4
|
-
<Extension Id="com.mcp.aftereffects.bridge.panel" Version="1.18.
|
|
4
|
+
<Extension Id="com.mcp.aftereffects.bridge.panel" Version="1.18.3"/>
|
|
5
5
|
</ExtensionList>
|
|
6
6
|
<ExecutionEnvironment>
|
|
7
7
|
<HostList>
|
|
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.18.
|
|
2
|
+
<ExtensionManifest Version="7.0" ExtensionBundleId="com.mcp.premiere.bridge" ExtensionBundleVersion="1.18.3" ExtensionBundleName="MCP for Adobe Premiere Pro">
|
|
3
3
|
<ExtensionList>
|
|
4
|
-
<Extension Id="com.mcp.premiere.bridge.panel" Version="1.18.
|
|
5
|
-
<Extension Id="com.mcp.premiere.bridge.headless" Version="1.18.
|
|
4
|
+
<Extension Id="com.mcp.premiere.bridge.panel" Version="1.18.3"/>
|
|
5
|
+
<Extension Id="com.mcp.premiere.bridge.headless" Version="1.18.3"/>
|
|
6
6
|
</ExtensionList>
|
|
7
7
|
<ExecutionEnvironment>
|
|
8
8
|
<HostList>
|
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.18.
|
|
84
|
+
<strong id="updateTitle">Version 1.18.3</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
|
@@ -43,6 +43,14 @@ function __ticksToSeconds(ticks) {
|
|
|
43
43
|
return parseFloat(ticks) / TICKS_PER_SECOND;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
// Sequence work-area getters return seconds (often as a string) on live 25.x
|
|
47
|
+
// and 26.x hosts. Values above 1e6 can only be ticks, so convert those.
|
|
48
|
+
function __workAreaSeconds(value) {
|
|
49
|
+
var number = parseFloat(value);
|
|
50
|
+
if (!isFinite(number) || number <= -399999) return null;
|
|
51
|
+
return number > 1000000 ? number / TICKS_PER_SECOND : number;
|
|
52
|
+
}
|
|
53
|
+
|
|
46
54
|
function __secondsToTicks(seconds) {
|
|
47
55
|
return Math.round(parseFloat(seconds) * TICKS_PER_SECOND);
|
|
48
56
|
}
|
|
@@ -2,6 +2,7 @@ import { randomUUID, timingSafeEqual } from "node:crypto";
|
|
|
2
2
|
import { EventEmitter } from "node:events";
|
|
3
3
|
import { createServer } from "node:http";
|
|
4
4
|
import { WebSocket, WebSocketServer } from "ws";
|
|
5
|
+
import { assertNoSymlinkedPaths, SymlinkPathError } from "../security/path-guard.js";
|
|
5
6
|
const LOOPBACK_HOST = "127.0.0.1";
|
|
6
7
|
const SUPPORTED_PROTOCOLS = new Set([1, 2]);
|
|
7
8
|
export class UxpBridgeError extends Error {
|
|
@@ -125,6 +126,16 @@ export class UxpWebSocketBridge extends EventEmitter {
|
|
|
125
126
|
if (hello.commands[command]?.supported !== true) {
|
|
126
127
|
throw new UxpBridgeError("UXP_COMMAND_UNSUPPORTED", `Connected Premiere host does not support UXP command '${command}'`);
|
|
127
128
|
}
|
|
129
|
+
// The panel cannot see through links on Premiere 26.5 UXP (#640), so refuse
|
|
130
|
+
// symlinked path segments here, before anything reaches the host.
|
|
131
|
+
try {
|
|
132
|
+
assertNoSymlinkedPaths(args);
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
if (error instanceof SymlinkPathError)
|
|
136
|
+
throw new UxpBridgeError(error.code, error.message);
|
|
137
|
+
throw error;
|
|
138
|
+
}
|
|
128
139
|
const minimumTimeoutMs = requestOptions.minimumTimeoutMs ?? 0;
|
|
129
140
|
if (!Number.isInteger(minimumTimeoutMs) || minimumTimeoutMs < 0) {
|
|
130
141
|
throw new Error("UXP minimum request timeout must be a non-negative integer");
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare class SymlinkPathError extends Error {
|
|
2
|
+
readonly argumentPath: string;
|
|
3
|
+
readonly code = "UXP_PATH_SYMLINK_REFUSED";
|
|
4
|
+
constructor(argumentPath: string);
|
|
5
|
+
}
|
|
6
|
+
/** Returns the first symlinked segment of an absolute path, or null. */
|
|
7
|
+
export declare function findSymlinkedSegment(value: string): string | null;
|
|
8
|
+
/** Throws SymlinkPathError when any absolute path argument crosses a link. */
|
|
9
|
+
export declare function assertNoSymlinkedPaths(args: unknown): void;
|
|
10
|
+
//# sourceMappingURL=path-guard.d.ts.map
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { lstatSync, readlinkSync } from "node:fs";
|
|
2
|
+
import { posix, win32 } from "node:path";
|
|
3
|
+
/**
|
|
4
|
+
* Server-side symlink confinement for UXP path arguments (issue #640).
|
|
5
|
+
*
|
|
6
|
+
* The UXP panel checks lexical containment inside the approved workspace, but
|
|
7
|
+
* Premiere 26.5 UXP cannot see through links: `Entry.nativePath` reports the
|
|
8
|
+
* link's own path and `lstat` is unimplemented. The MCP server runs on the same
|
|
9
|
+
* machine as Premiere, so it walks every absolute path argument with Node's
|
|
10
|
+
* real filesystem before a command is sent and refuses any symlinked or
|
|
11
|
+
* junctioned segment. Segments that do not exist yet (new output files) end
|
|
12
|
+
* the walk; they cannot redirect anything.
|
|
13
|
+
*/
|
|
14
|
+
const MAX_DEPTH = 8;
|
|
15
|
+
const MAX_STRINGS = 512;
|
|
16
|
+
/** macOS calibration links that always point into /private. */
|
|
17
|
+
const SYSTEM_LINK_TARGETS = {
|
|
18
|
+
"/tmp": ["private/tmp", "/private/tmp"],
|
|
19
|
+
"/var": ["private/var", "/private/var"],
|
|
20
|
+
"/etc": ["private/etc", "/private/etc"],
|
|
21
|
+
};
|
|
22
|
+
export class SymlinkPathError extends Error {
|
|
23
|
+
argumentPath;
|
|
24
|
+
code = "UXP_PATH_SYMLINK_REFUSED";
|
|
25
|
+
constructor(argumentPath) {
|
|
26
|
+
super(`${argumentPath} goes through a symbolic link or junction. Use the real folder inside the approved workspace. No command was sent to Premiere.`);
|
|
27
|
+
this.argumentPath = argumentPath;
|
|
28
|
+
this.name = "SymlinkPathError";
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function absoluteFlavor(value) {
|
|
32
|
+
if (/^[A-Za-z]:[\\/]/.test(value) || /^\\\\[^\\]/.test(value))
|
|
33
|
+
return win32;
|
|
34
|
+
if (value.startsWith("/") && !value.startsWith("//"))
|
|
35
|
+
return posix;
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
function isSystemLink(segment) {
|
|
39
|
+
const targets = SYSTEM_LINK_TARGETS[segment];
|
|
40
|
+
if (!targets || process.platform !== "darwin")
|
|
41
|
+
return false;
|
|
42
|
+
try {
|
|
43
|
+
return targets.includes(readlinkSync(segment));
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/** Returns the first symlinked segment of an absolute path, or null. */
|
|
50
|
+
export function findSymlinkedSegment(value) {
|
|
51
|
+
const flavor = absoluteFlavor(value);
|
|
52
|
+
if (!flavor || value.includes("\0"))
|
|
53
|
+
return null;
|
|
54
|
+
const normalized = flavor.normalize(value);
|
|
55
|
+
const root = flavor.parse(normalized).root;
|
|
56
|
+
const parts = normalized.slice(root.length).split(flavor.sep).filter(Boolean);
|
|
57
|
+
let current = root;
|
|
58
|
+
for (const part of parts) {
|
|
59
|
+
current = flavor.join(current, part);
|
|
60
|
+
let stats;
|
|
61
|
+
try {
|
|
62
|
+
stats = lstatSync(current);
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
if (stats.isSymbolicLink()) {
|
|
68
|
+
if (!isSystemLink(current))
|
|
69
|
+
return current;
|
|
70
|
+
// Keep walking below /tmp, /var and /etc: lstat of later segments
|
|
71
|
+
// resolves through the calibration link and still sees user links.
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
if (!stats.isDirectory())
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
function collectStrings(value, path, out, depth) {
|
|
80
|
+
if (out.length >= MAX_STRINGS || depth > MAX_DEPTH)
|
|
81
|
+
return;
|
|
82
|
+
if (typeof value === "string") {
|
|
83
|
+
if (absoluteFlavor(value))
|
|
84
|
+
out.push([path, value]);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (Array.isArray(value)) {
|
|
88
|
+
value.forEach((entry, index) => collectStrings(entry, `${path}[${index}]`, out, depth + 1));
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
if (value && typeof value === "object") {
|
|
92
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
93
|
+
collectStrings(entry, path ? `${path}.${key}` : key, out, depth + 1);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/** Throws SymlinkPathError when any absolute path argument crosses a link. */
|
|
98
|
+
export function assertNoSymlinkedPaths(args) {
|
|
99
|
+
const candidates = [];
|
|
100
|
+
collectStrings(args, "", candidates, 0);
|
|
101
|
+
for (const [argumentPath, value] of candidates) {
|
|
102
|
+
if (findSymlinkedSegment(value))
|
|
103
|
+
throw new SymlinkPathError(argumentPath || "path");
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=path-guard.js.map
|
package/dist/tools/export.js
CHANGED
|
@@ -647,8 +647,13 @@ export function getExportTools(bridgeOptions) {
|
|
|
647
647
|
presetPath,
|
|
648
648
|
${args.work_area_only ? "app.encoder.ENCODE_WORKAREA" : "app.encoder.ENCODE_ENTIRE"}
|
|
649
649
|
);
|
|
650
|
+
// Premiere documents a boolean; false means the render was rejected.
|
|
651
|
+
// Some hosts throw instead; buildToolScript already maps that to __error.
|
|
652
|
+
if (exportResult === false) return __error("Premiere rejected the sequence export.");
|
|
653
|
+
var outputFile = new File(outputPath);
|
|
654
|
+
if (!outputFile.exists) return __error("Premiere did not write the requested export file.");
|
|
650
655
|
|
|
651
|
-
return __result({ exported: true, outputPath: outputPath, presetUsed: presetPath });
|
|
656
|
+
return __result({ exported: true, verified: true, outputPath: outputPath, presetUsed: presetPath });
|
|
652
657
|
`);
|
|
653
658
|
return sendCommand(script, { ...bridgeOptions, timeoutMs: 120000 }); // 2 min timeout for exports
|
|
654
659
|
},
|
package/dist/tools/playhead.js
CHANGED
|
@@ -65,10 +65,21 @@ export function getPlayheadTools(bridgeOptions) {
|
|
|
65
65
|
var seq = app.project.activeSequence;
|
|
66
66
|
if (!seq) return __error("No active sequence");
|
|
67
67
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
68
|
+
// Live hosts (25.2, 26.5.1) read and write work-area points in seconds,
|
|
69
|
+
// not ticks. Write seconds, then read back: some builds ignore the write.
|
|
70
|
+
var requestedIn = ${Number(args.in_seconds)};
|
|
71
|
+
var requestedOut = ${Number(args.out_seconds)};
|
|
72
|
+
if (!(requestedOut > requestedIn)) return __error("out_seconds must be greater than in_seconds.");
|
|
73
|
+
seq.setWorkAreaInPoint(requestedIn);
|
|
74
|
+
seq.setWorkAreaOutPoint(requestedOut);
|
|
75
|
+
var observedIn = __workAreaSeconds(seq.getWorkAreaInPoint());
|
|
76
|
+
var observedOut = __workAreaSeconds(seq.getWorkAreaOutPoint());
|
|
77
|
+
var frameSeconds = seq.timebase ? __ticksToSeconds(seq.timebase) : 1 / 24;
|
|
78
|
+
if (observedIn === null || observedOut === null ||
|
|
79
|
+
Math.abs(observedIn - requestedIn) > frameSeconds || Math.abs(observedOut - requestedOut) > frameSeconds) {
|
|
80
|
+
return __error("Premiere did not apply the work area (read back " + observedIn + " to " + observedOut + " s). Use set_sequence_in_out_points to mark an export range instead.");
|
|
81
|
+
}
|
|
82
|
+
return __result({ workAreaIn: observedIn, workAreaOut: observedOut, verified: true });
|
|
72
83
|
`);
|
|
73
84
|
return sendCommand(script, bridgeOptions);
|
|
74
85
|
},
|
|
@@ -83,8 +94,10 @@ export function getPlayheadTools(bridgeOptions) {
|
|
|
83
94
|
var inPoint = seq.getWorkAreaInPoint();
|
|
84
95
|
var outPoint = seq.getWorkAreaOutPoint();
|
|
85
96
|
return __result({
|
|
86
|
-
inSeconds:
|
|
87
|
-
outSeconds:
|
|
97
|
+
inSeconds: __workAreaSeconds(inPoint),
|
|
98
|
+
outSeconds: __workAreaSeconds(outPoint),
|
|
99
|
+
rawIn: String(inPoint),
|
|
100
|
+
rawOut: String(outPoint)
|
|
88
101
|
});
|
|
89
102
|
`);
|
|
90
103
|
return sendCommand(script, bridgeOptions);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "premiere-pro-mcp",
|
|
3
3
|
"mcpName": "io.github.leancoderkavy/premiere-pro",
|
|
4
|
-
"version": "1.18.
|
|
4
|
+
"version": "1.18.3",
|
|
5
5
|
"description": "MCP server for Adobe Premiere Pro with 384 core AI video editing tools, a guarded After Effects MOGRT studio, and a capability-aware UXP bridge for supported Premiere workflows.",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"name": "MCP for Adobe Premiere Pro",
|
|
11
11
|
"mcpName": "io.github.leancoderkavy/premiere-pro",
|
|
12
12
|
"npmPackage": "premiere-pro-mcp",
|
|
13
|
-
"version": "1.18.
|
|
13
|
+
"version": "1.18.3",
|
|
14
14
|
"repository": "https://github.com/leancoderkavy/premiere-pro-mcp",
|
|
15
15
|
"homepage": "https://premiere-pro-mcp.com/",
|
|
16
16
|
"license": "MIT",
|
package/uxp-plugin/manifest.json
CHANGED
|
@@ -1196,9 +1196,17 @@
|
|
|
1196
1196
|
return { projectItemId, startSeconds: start, durationSeconds: duration };
|
|
1197
1197
|
}
|
|
1198
1198
|
|
|
1199
|
+
// Premiere 26.5 documents synchronous Media.getStart()/getDuration() and
|
|
1200
|
+
// deprecates the start/duration properties, which return Promise<TickTime>.
|
|
1201
|
+
function mediaTimingGetter(media, propertyName) {
|
|
1202
|
+
const getterName = propertyName === "start" ? "getStart" : "getDuration";
|
|
1203
|
+
return media && typeof media[getterName] === "function" ? getterName : null;
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1199
1206
|
function synchronousMediaTimingValue(media, propertyName) {
|
|
1200
1207
|
try {
|
|
1201
|
-
const
|
|
1208
|
+
const getterName = mediaTimingGetter(media, propertyName);
|
|
1209
|
+
const value = getterName ? media[getterName]() : media[propertyName];
|
|
1202
1210
|
if (value && typeof value.then === "function") return null;
|
|
1203
1211
|
return boundedMediaTimingSeconds(value);
|
|
1204
1212
|
} catch (_) { return null; }
|
|
@@ -1332,6 +1340,13 @@
|
|
|
1332
1340
|
}
|
|
1333
1341
|
|
|
1334
1342
|
async function mediaTimingValue(media, propertyName) {
|
|
1343
|
+
const getterName = mediaTimingGetter(media, propertyName);
|
|
1344
|
+
if (getterName) {
|
|
1345
|
+
try {
|
|
1346
|
+
const seconds = boundedMediaTimingSeconds(await media[getterName]());
|
|
1347
|
+
if (seconds != null) return { accessor: getterName + "()", seconds };
|
|
1348
|
+
} catch (_) { /* fall back to the deprecated property */ }
|
|
1349
|
+
}
|
|
1335
1350
|
try {
|
|
1336
1351
|
return { accessor: propertyName, seconds: boundedMediaTimingSeconds(await media[propertyName]) };
|
|
1337
1352
|
} catch (_) {
|