premiere-pro-mcp 1.11.2 → 1.11.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 +14 -0
- package/README.md +16 -11
- 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/security/capabilities.js +1 -0
- package/dist/tools/transcript-edits.d.ts +26 -0
- package/dist/tools/transcript-edits.js +82 -0
- package/dist/tools/uxp.d.ts +126 -0
- package/dist/tools/uxp.js +62 -1
- package/dist/workflows/catalog.d.ts +7 -2
- package/dist/workflows/catalog.js +6 -0
- package/docs/supported-actions.md +3 -2
- package/package.json +1 -1
- package/scripts/validate-distribution.mjs +2 -9
- package/uxp-plugin/DISTRIBUTION.md +3 -1
- package/uxp-plugin/manifest.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,20 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [1.11.3] - 2026-08-18
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- Added a revision-locked `plan_transcript_rough_cut_uxp` workflow that maps native transcript
|
|
14
|
+
deletion ranges to verified 1x sequence placements, orders cut instructions from the end of the
|
|
15
|
+
timeline, and requires duplicate-sequence and post-mutation verification safeguards.
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- Premiere Pro 26.3 can reject a manifest list of loopback WebSocket domains with `Manifest entry
|
|
20
|
+
not found`. The UXP package now uses Adobe's compatible network permission while the panel keeps
|
|
21
|
+
enforcing the exact loopback-only `/uxp` endpoint at runtime.
|
|
22
|
+
|
|
9
23
|
## [1.11.2] - 2026-08-18
|
|
10
24
|
|
|
11
25
|
### Added
|
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
**Give compatible AI assistants structured control over supported Adobe Premiere Pro workflows.**
|
|
8
8
|
|
|
9
|
-
285 core tools across 32 modules, 4 resources, and
|
|
9
|
+
285 core tools across 32 modules, 4 resources, and 6 guided workflows. A connected UXP host adds 49 capability-gated tools.
|
|
10
10
|
|
|
11
11
|
[](LICENSE)
|
|
12
12
|
[](https://nodejs.org)
|
|
@@ -29,9 +29,9 @@ An [MCP (Model Context Protocol)](https://modelcontextprotocol.io) server that l
|
|
|
29
29
|
"Add the B-roll clips to V2, apply a cross dissolve between each, color correct them to match the A-roll, and export a 1080p ProRes."
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
-
The AI handles the entire workflow through 285 core tools spanning the supported ExtendScript, QE DOM, local media analysis, revisioned project-context retrieval, safe edit-planning, and connection-verification surfaces. A compatible, authenticated UXP panel adds
|
|
32
|
+
The AI handles the entire workflow through 285 core tools spanning the supported ExtendScript, QE DOM, local media analysis, revisioned project-context retrieval, safe edit-planning, and connection-verification surfaces. A compatible, authenticated UXP panel adds 49 documented, capability-gated tools without replacing the production CEP bridge.
|
|
33
33
|
|
|
34
|
-
### Latest release: 1.11.
|
|
34
|
+
### Latest release: 1.11.3
|
|
35
35
|
|
|
36
36
|
- **Honest timeline mutations:** trim, split, track creation, and overwrite placement now verify
|
|
37
37
|
observable postconditions instead of trusting Premiere 26.x calls that can silently no-op.
|
|
@@ -42,7 +42,7 @@ The AI handles the entire workflow through 285 core tools spanning the supported
|
|
|
42
42
|
- **Truthful compatibility:** the fixes have automated CEP/QE contract coverage; confirmation in
|
|
43
43
|
a licensed Premiere Pro 26.x host remains a separate validation boundary.
|
|
44
44
|
|
|
45
|
-
See the [v1.11.
|
|
45
|
+
See the [v1.11.3 release notes](https://github.com/leancoderkavy/premiere-pro-mcp/releases/tag/v1.11.3)
|
|
46
46
|
for complete details. Live installation in Premiere Pro still requires host verification.
|
|
47
47
|
|
|
48
48
|
---
|
|
@@ -51,9 +51,9 @@ for complete details. Live installation in Premiere Pro still requires host veri
|
|
|
51
51
|
|
|
52
52
|
### Easiest supported path: Claude Desktop
|
|
53
53
|
|
|
54
|
-
1. Download the current [Claude Desktop bundle (`.mcpb`)](https://github.com/leancoderkavy/premiere-pro-mcp/releases/download/v1.11.
|
|
54
|
+
1. Download the current [Claude Desktop bundle (`.mcpb`)](https://github.com/leancoderkavy/premiere-pro-mcp/releases/download/v1.11.3/premiere-pro-mcp-1.11.3.mcpb).
|
|
55
55
|
2. In Claude Desktop, open **Settings > Extensions > Advanced settings > Install Extension**, select the downloaded bundle, and restart Claude Desktop.
|
|
56
|
-
3. Download the separate [signed Premiere connector (`.zxp`)](https://github.com/leancoderkavy/premiere-pro-mcp/releases/download/v1.11.
|
|
56
|
+
3. Download the separate [signed Premiere connector (`.zxp`)](https://github.com/leancoderkavy/premiere-pro-mcp/releases/download/v1.11.3/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.
|
|
57
57
|
4. Restart Premiere, open a project, then open **Window > Extensions > MCP Bridge**.
|
|
58
58
|
5. In Claude, enter: `Safely check my Premiere connection with verify_premiere_connection. Make no changes.`
|
|
59
59
|
|
|
@@ -277,11 +277,11 @@ From a clone of this repository:
|
|
|
277
277
|
```bash
|
|
278
278
|
codex plugin marketplace add .
|
|
279
279
|
codex plugin add premiere-pro@premiere-pro-mcp
|
|
280
|
-
npx -y premiere-pro-mcp@1.11.
|
|
280
|
+
npx -y premiere-pro-mcp@1.11.3 --install-cep
|
|
281
281
|
```
|
|
282
282
|
|
|
283
283
|
Restart Premiere Pro and start a new Codex session after installation. The plugin
|
|
284
|
-
launches `premiere-pro-mcp@1.11.
|
|
284
|
+
launches `premiere-pro-mcp@1.11.3` through `npx`; the separate CEP installation is
|
|
285
285
|
required because the MCP server communicates with the running Premiere host through
|
|
286
286
|
the local bridge.
|
|
287
287
|
|
|
@@ -301,7 +301,7 @@ For Claude Code, add this repository as a marketplace and install the plugin:
|
|
|
301
301
|
Then install the Premiere bridge and start a new Claude Code session:
|
|
302
302
|
|
|
303
303
|
```bash
|
|
304
|
-
npx -y premiere-pro-mcp@1.11.
|
|
304
|
+
npx -y premiere-pro-mcp@1.11.3 --install-cep
|
|
305
305
|
```
|
|
306
306
|
|
|
307
307
|
The Claude Code package lives in
|
|
@@ -375,6 +375,11 @@ capability negotiation.
|
|
|
375
375
|
- Frame.io needs a separately authenticated Frame.io API integration; an account
|
|
376
376
|
entitlement alone does not make it callable through Premiere's DOM.
|
|
377
377
|
- Transcript JSON import/export is documented in UXP. Starting Speech-to-Text is not.
|
|
378
|
+
- `preview_transcript_edit_uxp` and `plan_transcript_rough_cut_uxp` provide a
|
|
379
|
+
revision-locked transcript-edit workflow. The planner maps selected transcript
|
|
380
|
+
ranges to verified 1x placements in a duplicate sequence and emits descending
|
|
381
|
+
split/remove instructions; it does not claim that Adobe exposes native transcript
|
|
382
|
+
text deletion or perform an unverified destructive edit.
|
|
378
383
|
- The remaining AI operations are user-assisted or unsupported by documented
|
|
379
384
|
public APIs. The tool explains what can be inspected after a user completes
|
|
380
385
|
the operation and where artifact provenance cannot be established safely.
|
|
@@ -483,11 +488,11 @@ The file-based IPC bridge is simple, reliable, and works across macOS and Window
|
|
|
483
488
|
|
|
484
489
|
---
|
|
485
490
|
|
|
486
|
-
## Tools (285 core total; 283 under the default profile;
|
|
491
|
+
## Tools (285 core total; 283 under the default profile; 332 with a connected UXP bridge)
|
|
487
492
|
|
|
488
493
|
The [complete supported-actions catalog](docs/supported-actions.md) lists every
|
|
489
494
|
registered core tool, the two tools restricted behind explicit `unsafe-script`
|
|
490
|
-
authority, and all
|
|
495
|
+
authority, and all 49 authenticated UXP additions with their current action or mode
|
|
491
496
|
values. It is generated from the same MCP registration surface returned to clients;
|
|
492
497
|
the tables below are a shorter workflow-oriented overview.
|
|
493
498
|
|
|
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.11.
|
|
2
|
+
<ExtensionManifest Version="7.0" ExtensionBundleId="com.mcp.premiere.bridge" ExtensionBundleVersion="1.11.3" ExtensionBundleName="MCP Bridge">
|
|
3
3
|
<ExtensionList>
|
|
4
|
-
<Extension Id="com.mcp.premiere.bridge.panel" Version="1.11.
|
|
5
|
-
<Extension Id="com.mcp.premiere.bridge.headless" Version="1.11.
|
|
4
|
+
<Extension Id="com.mcp.premiere.bridge.panel" Version="1.11.3"/>
|
|
5
|
+
<Extension Id="com.mcp.premiere.bridge.headless" Version="1.11.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">Connector updates</span>
|
|
84
|
-
<strong id="updateTitle">Version 1.11.
|
|
84
|
+
<strong id="updateTitle">Version 1.11.3</strong>
|
|
85
85
|
<span id="updateDetail">Checking for updates…</span>
|
|
86
86
|
</div>
|
|
87
87
|
<button id="btnUpdate" class="button button-update" onclick="handleUpdateClick()" type="button" disabled>
|
package/cep-plugin/updater.cjs
CHANGED
|
@@ -43,6 +43,7 @@ const INSPECT_TOOL_NAMES = new Set([
|
|
|
43
43
|
"get_capabilities",
|
|
44
44
|
"preview_edit_plan",
|
|
45
45
|
"preview_transcript_edit_uxp",
|
|
46
|
+
"plan_transcript_rough_cut_uxp",
|
|
46
47
|
"create_context_edit_plan",
|
|
47
48
|
]);
|
|
48
49
|
// detect_silence reads a media file from disk and shells out to ffmpeg. It
|
|
@@ -9,7 +9,33 @@ export interface TranscriptEditPreview {
|
|
|
9
9
|
confirmationToken: string;
|
|
10
10
|
applied: false;
|
|
11
11
|
}
|
|
12
|
+
export interface TranscriptPlacement {
|
|
13
|
+
placement_id: string;
|
|
14
|
+
track_type: "video" | "audio";
|
|
15
|
+
track_index: number;
|
|
16
|
+
source_in_seconds: number;
|
|
17
|
+
source_out_seconds: number;
|
|
18
|
+
timeline_start_seconds: number;
|
|
19
|
+
timeline_end_seconds: number;
|
|
20
|
+
}
|
|
21
|
+
export interface TranscriptRoughCutStep {
|
|
22
|
+
placement_id: string;
|
|
23
|
+
track_type: "video" | "audio";
|
|
24
|
+
track_index: number;
|
|
25
|
+
source_range: TranscriptDeletionRange;
|
|
26
|
+
timeline_range: TranscriptDeletionRange;
|
|
27
|
+
instructions: readonly [string, string, string, string];
|
|
28
|
+
}
|
|
29
|
+
export interface TranscriptRoughCutPlan extends TranscriptEditPreview {
|
|
30
|
+
planVersion: 1;
|
|
31
|
+
requiresDuplicateSequence: true;
|
|
32
|
+
requiresPostMutationRequery: true;
|
|
33
|
+
ripple: boolean;
|
|
34
|
+
steps: TranscriptRoughCutStep[];
|
|
35
|
+
unmappedDeletionRanges: TranscriptDeletionRange[];
|
|
36
|
+
}
|
|
12
37
|
export declare function transcriptRevision(json: string): string;
|
|
13
38
|
export declare function normalizeTranscriptDeletionRanges(value: unknown, handleSeconds?: number): TranscriptDeletionRange[];
|
|
14
39
|
export declare function previewTranscriptEdit(json: string, requestedRevision: string, deletions: unknown, handleSeconds?: number): TranscriptEditPreview;
|
|
40
|
+
export declare function planTranscriptRoughCut(preview: TranscriptEditPreview, placementsValue: unknown, ripple?: boolean): TranscriptRoughCutPlan;
|
|
15
41
|
//# sourceMappingURL=transcript-edits.d.ts.map
|
|
@@ -61,4 +61,86 @@ export function previewTranscriptEdit(json, requestedRevision, deletions, handle
|
|
|
61
61
|
applied: false,
|
|
62
62
|
};
|
|
63
63
|
}
|
|
64
|
+
function finite(value, label) {
|
|
65
|
+
if (!Number.isFinite(value))
|
|
66
|
+
throw new Error(`${label} must be a finite number`);
|
|
67
|
+
return Number(value);
|
|
68
|
+
}
|
|
69
|
+
export function planTranscriptRoughCut(preview, placementsValue, ripple = true) {
|
|
70
|
+
if (!Array.isArray(placementsValue) || placementsValue.length === 0) {
|
|
71
|
+
throw new Error("placements must contain at least one verified 1x sequence placement");
|
|
72
|
+
}
|
|
73
|
+
if (placementsValue.length > 256)
|
|
74
|
+
throw new Error("transcript rough cuts are limited to 256 placements");
|
|
75
|
+
const placements = placementsValue.map((value, index) => {
|
|
76
|
+
if (!value || typeof value !== "object")
|
|
77
|
+
throw new Error(`placement ${index} must be an object`);
|
|
78
|
+
const item = value;
|
|
79
|
+
if (typeof item.placement_id !== "string" || !item.placement_id.trim() || item.placement_id.length > 512) {
|
|
80
|
+
throw new Error(`placement ${index} placement_id must be 1-512 characters`);
|
|
81
|
+
}
|
|
82
|
+
if (item.track_type !== "video" && item.track_type !== "audio") {
|
|
83
|
+
throw new Error(`placement ${index} track_type must be video or audio`);
|
|
84
|
+
}
|
|
85
|
+
if (!Number.isInteger(item.track_index) || Number(item.track_index) < 0) {
|
|
86
|
+
throw new Error(`placement ${index} track_index must be a non-negative integer`);
|
|
87
|
+
}
|
|
88
|
+
const sourceIn = finite(item.source_in_seconds, `placement ${index} source_in_seconds`);
|
|
89
|
+
const sourceOut = finite(item.source_out_seconds, `placement ${index} source_out_seconds`);
|
|
90
|
+
const timelineStart = finite(item.timeline_start_seconds, `placement ${index} timeline_start_seconds`);
|
|
91
|
+
const timelineEnd = finite(item.timeline_end_seconds, `placement ${index} timeline_end_seconds`);
|
|
92
|
+
if (sourceIn < 0 || timelineStart < 0 || sourceOut <= sourceIn || timelineEnd <= timelineStart) {
|
|
93
|
+
throw new Error(`placement ${index} must contain increasing non-negative source and timeline ranges`);
|
|
94
|
+
}
|
|
95
|
+
if (Math.abs((sourceOut - sourceIn) - (timelineEnd - timelineStart)) > 0.001) {
|
|
96
|
+
throw new Error(`placement ${index} is retimed or has an unverified source-to-timeline mapping`);
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
placement_id: item.placement_id,
|
|
100
|
+
track_type: item.track_type,
|
|
101
|
+
track_index: Number(item.track_index),
|
|
102
|
+
source_in_seconds: sourceIn,
|
|
103
|
+
source_out_seconds: sourceOut,
|
|
104
|
+
timeline_start_seconds: timelineStart,
|
|
105
|
+
timeline_end_seconds: timelineEnd,
|
|
106
|
+
};
|
|
107
|
+
});
|
|
108
|
+
const mapped = new Set();
|
|
109
|
+
const steps = [];
|
|
110
|
+
for (const placement of placements) {
|
|
111
|
+
for (let rangeIndex = 0; rangeIndex < preview.deletionRanges.length; rangeIndex++) {
|
|
112
|
+
const deletion = preview.deletionRanges[rangeIndex];
|
|
113
|
+
const start = Math.max(deletion.start_seconds, placement.source_in_seconds);
|
|
114
|
+
const end = Math.min(deletion.end_seconds, placement.source_out_seconds);
|
|
115
|
+
if (end <= start)
|
|
116
|
+
continue;
|
|
117
|
+
mapped.add(rangeIndex);
|
|
118
|
+
const timelineStart = roundSeconds(placement.timeline_start_seconds + start - placement.source_in_seconds);
|
|
119
|
+
const timelineEnd = roundSeconds(placement.timeline_start_seconds + end - placement.source_in_seconds);
|
|
120
|
+
steps.push({
|
|
121
|
+
placement_id: placement.placement_id,
|
|
122
|
+
track_type: placement.track_type,
|
|
123
|
+
track_index: placement.track_index,
|
|
124
|
+
source_range: { start_seconds: roundSeconds(start), end_seconds: roundSeconds(end) },
|
|
125
|
+
timeline_range: { start_seconds: timelineStart, end_seconds: timelineEnd },
|
|
126
|
+
instructions: [
|
|
127
|
+
`Split ${placement.track_type} track ${placement.track_index} at ${timelineEnd}s.`,
|
|
128
|
+
`Split ${placement.track_type} track ${placement.track_index} at ${timelineStart}s.`,
|
|
129
|
+
"Re-query the sequence and identify the segment enclosed by those verified boundaries.",
|
|
130
|
+
`Remove only that segment${ripple ? " with ripple enabled" : " without ripple"}, then re-query and verify the resulting structure.`,
|
|
131
|
+
],
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
steps.sort((left, right) => right.timeline_range.start_seconds - left.timeline_range.start_seconds);
|
|
136
|
+
return {
|
|
137
|
+
...preview,
|
|
138
|
+
planVersion: 1,
|
|
139
|
+
requiresDuplicateSequence: true,
|
|
140
|
+
requiresPostMutationRequery: true,
|
|
141
|
+
ripple,
|
|
142
|
+
steps,
|
|
143
|
+
unmappedDeletionRanges: preview.deletionRanges.filter((_, index) => !mapped.has(index)),
|
|
144
|
+
};
|
|
145
|
+
}
|
|
64
146
|
//# sourceMappingURL=transcript-edits.js.map
|
package/dist/tools/uxp.d.ts
CHANGED
|
@@ -314,6 +314,132 @@ export declare function getUxpTools(bridge: UxpWebSocketBridge): {
|
|
|
314
314
|
data?: undefined;
|
|
315
315
|
}>;
|
|
316
316
|
};
|
|
317
|
+
plan_transcript_rough_cut_uxp: {
|
|
318
|
+
description: string;
|
|
319
|
+
parameters: {
|
|
320
|
+
type: "object";
|
|
321
|
+
properties: {
|
|
322
|
+
project_item_id: {
|
|
323
|
+
type: string;
|
|
324
|
+
maxLength: number;
|
|
325
|
+
};
|
|
326
|
+
project_item_name: {
|
|
327
|
+
type: string;
|
|
328
|
+
maxLength: number;
|
|
329
|
+
};
|
|
330
|
+
transcript_revision: {
|
|
331
|
+
type: string;
|
|
332
|
+
pattern: string;
|
|
333
|
+
};
|
|
334
|
+
deletions: {
|
|
335
|
+
type: string;
|
|
336
|
+
minItems: number;
|
|
337
|
+
maxItems: number;
|
|
338
|
+
items: {
|
|
339
|
+
type: string;
|
|
340
|
+
additionalProperties: boolean;
|
|
341
|
+
properties: {
|
|
342
|
+
start_seconds: {
|
|
343
|
+
type: string;
|
|
344
|
+
minimum: number;
|
|
345
|
+
};
|
|
346
|
+
end_seconds: {
|
|
347
|
+
type: string;
|
|
348
|
+
exclusiveMinimum: number;
|
|
349
|
+
};
|
|
350
|
+
};
|
|
351
|
+
required: string[];
|
|
352
|
+
};
|
|
353
|
+
};
|
|
354
|
+
placements: {
|
|
355
|
+
type: string;
|
|
356
|
+
minItems: number;
|
|
357
|
+
maxItems: number;
|
|
358
|
+
description: string;
|
|
359
|
+
items: {
|
|
360
|
+
type: string;
|
|
361
|
+
additionalProperties: boolean;
|
|
362
|
+
properties: {
|
|
363
|
+
placement_id: {
|
|
364
|
+
type: string;
|
|
365
|
+
minLength: number;
|
|
366
|
+
maxLength: number;
|
|
367
|
+
};
|
|
368
|
+
track_type: {
|
|
369
|
+
type: string;
|
|
370
|
+
enum: string[];
|
|
371
|
+
};
|
|
372
|
+
track_index: {
|
|
373
|
+
type: string;
|
|
374
|
+
minimum: number;
|
|
375
|
+
};
|
|
376
|
+
source_in_seconds: {
|
|
377
|
+
type: string;
|
|
378
|
+
minimum: number;
|
|
379
|
+
};
|
|
380
|
+
source_out_seconds: {
|
|
381
|
+
type: string;
|
|
382
|
+
exclusiveMinimum: number;
|
|
383
|
+
};
|
|
384
|
+
timeline_start_seconds: {
|
|
385
|
+
type: string;
|
|
386
|
+
minimum: number;
|
|
387
|
+
};
|
|
388
|
+
timeline_end_seconds: {
|
|
389
|
+
type: string;
|
|
390
|
+
exclusiveMinimum: number;
|
|
391
|
+
};
|
|
392
|
+
};
|
|
393
|
+
required: string[];
|
|
394
|
+
};
|
|
395
|
+
};
|
|
396
|
+
handle_seconds: {
|
|
397
|
+
type: string;
|
|
398
|
+
minimum: number;
|
|
399
|
+
maximum: number;
|
|
400
|
+
};
|
|
401
|
+
ripple: {
|
|
402
|
+
type: string;
|
|
403
|
+
description: string;
|
|
404
|
+
};
|
|
405
|
+
};
|
|
406
|
+
required: string[];
|
|
407
|
+
};
|
|
408
|
+
handler: (args: {
|
|
409
|
+
project_item_id?: string;
|
|
410
|
+
project_item_name?: string;
|
|
411
|
+
transcript_revision: string;
|
|
412
|
+
deletions: unknown;
|
|
413
|
+
placements: unknown;
|
|
414
|
+
handle_seconds?: number;
|
|
415
|
+
ripple?: boolean;
|
|
416
|
+
}) => Promise<{
|
|
417
|
+
success: boolean;
|
|
418
|
+
data: {
|
|
419
|
+
backend: string;
|
|
420
|
+
result: {
|
|
421
|
+
planVersion: 1;
|
|
422
|
+
requiresDuplicateSequence: true;
|
|
423
|
+
requiresPostMutationRequery: true;
|
|
424
|
+
ripple: boolean;
|
|
425
|
+
steps: import("./transcript-edits.js").TranscriptRoughCutStep[];
|
|
426
|
+
unmappedDeletionRanges: import("./transcript-edits.js").TranscriptDeletionRange[];
|
|
427
|
+
transcriptRevision: string;
|
|
428
|
+
deletionRanges: import("./transcript-edits.js").TranscriptDeletionRange[];
|
|
429
|
+
deletedSeconds: number;
|
|
430
|
+
confirmationToken: string;
|
|
431
|
+
applied: false;
|
|
432
|
+
projectItemId: unknown;
|
|
433
|
+
projectItemName: unknown;
|
|
434
|
+
};
|
|
435
|
+
};
|
|
436
|
+
error?: undefined;
|
|
437
|
+
} | {
|
|
438
|
+
success: boolean;
|
|
439
|
+
error: string;
|
|
440
|
+
data?: undefined;
|
|
441
|
+
}>;
|
|
442
|
+
};
|
|
317
443
|
detect_object_masks_uxp: {
|
|
318
444
|
description: string;
|
|
319
445
|
parameters: {
|
package/dist/tools/uxp.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { previewTranscriptEdit, transcriptRevision } from "./transcript-edits.js";
|
|
1
|
+
import { planTranscriptRoughCut, previewTranscriptEdit, transcriptRevision } from "./transcript-edits.js";
|
|
2
2
|
import { getUxpAdvancedWorkflowTools } from "./uxp-advanced-workflows.js";
|
|
3
3
|
import { getUxpNextWorkflowTools } from "./uxp-next-workflows.js";
|
|
4
4
|
import { getUxpWorkflowTools } from "./uxp-workflows.js";
|
|
@@ -172,6 +172,67 @@ export function getUxpTools(bridge) {
|
|
|
172
172
|
}
|
|
173
173
|
},
|
|
174
174
|
},
|
|
175
|
+
plan_transcript_rough_cut_uxp: {
|
|
176
|
+
description: "Build a revision-locked, non-mutating rough-cut plan from Premiere's native transcript and verified 1x sequence placements. The plan orders cuts from the end of the timeline, requires a duplicate sequence, and requires re-query after every mutation.",
|
|
177
|
+
parameters: {
|
|
178
|
+
type: "object",
|
|
179
|
+
properties: {
|
|
180
|
+
project_item_id: { type: "string", maxLength: 512 },
|
|
181
|
+
project_item_name: { type: "string", maxLength: 255 },
|
|
182
|
+
transcript_revision: { type: "string", pattern: "^sha256:[a-f0-9]{64}$" },
|
|
183
|
+
deletions: {
|
|
184
|
+
type: "array", minItems: 1, maxItems: 100,
|
|
185
|
+
items: {
|
|
186
|
+
type: "object", additionalProperties: false,
|
|
187
|
+
properties: {
|
|
188
|
+
start_seconds: { type: "number", minimum: 0 },
|
|
189
|
+
end_seconds: { type: "number", exclusiveMinimum: 0 },
|
|
190
|
+
},
|
|
191
|
+
required: ["start_seconds", "end_seconds"],
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
placements: {
|
|
195
|
+
type: "array", minItems: 1, maxItems: 256,
|
|
196
|
+
description: "Verified 1x placements of this source in the target duplicate sequence.",
|
|
197
|
+
items: {
|
|
198
|
+
type: "object", additionalProperties: false,
|
|
199
|
+
properties: {
|
|
200
|
+
placement_id: { type: "string", minLength: 1, maxLength: 512 },
|
|
201
|
+
track_type: { type: "string", enum: ["video", "audio"] },
|
|
202
|
+
track_index: { type: "integer", minimum: 0 },
|
|
203
|
+
source_in_seconds: { type: "number", minimum: 0 },
|
|
204
|
+
source_out_seconds: { type: "number", exclusiveMinimum: 0 },
|
|
205
|
+
timeline_start_seconds: { type: "number", minimum: 0 },
|
|
206
|
+
timeline_end_seconds: { type: "number", exclusiveMinimum: 0 },
|
|
207
|
+
},
|
|
208
|
+
required: ["placement_id", "track_type", "track_index", "source_in_seconds", "source_out_seconds", "timeline_start_seconds", "timeline_end_seconds"],
|
|
209
|
+
},
|
|
210
|
+
},
|
|
211
|
+
handle_seconds: { type: "number", minimum: 0, maximum: 10 },
|
|
212
|
+
ripple: { type: "boolean", description: "Whether the resulting instructions should ripple removals; defaults to true." },
|
|
213
|
+
},
|
|
214
|
+
required: ["transcript_revision", "deletions", "placements"],
|
|
215
|
+
},
|
|
216
|
+
handler: async (args) => {
|
|
217
|
+
try {
|
|
218
|
+
const exported = await bridge.request("transcript.export", {
|
|
219
|
+
...(args.project_item_id ? { projectItemId: args.project_item_id } : {}),
|
|
220
|
+
...(args.project_item_name ? { projectItemName: args.project_item_name } : {}),
|
|
221
|
+
});
|
|
222
|
+
if (typeof exported?.json !== "string")
|
|
223
|
+
throw new Error("Premiere returned an empty transcript");
|
|
224
|
+
const preview = previewTranscriptEdit(exported.json, args.transcript_revision, args.deletions, args.handle_seconds);
|
|
225
|
+
return { success: true, data: { backend: "uxp", result: {
|
|
226
|
+
projectItemId: exported.projectItemId,
|
|
227
|
+
projectItemName: exported.projectItemName,
|
|
228
|
+
...planTranscriptRoughCut(preview, args.placements, args.ripple ?? true),
|
|
229
|
+
} } };
|
|
230
|
+
}
|
|
231
|
+
catch (error) {
|
|
232
|
+
return { success: false, error: error instanceof Error ? error.message : String(error) };
|
|
233
|
+
}
|
|
234
|
+
},
|
|
235
|
+
},
|
|
175
236
|
detect_object_masks_uxp: {
|
|
176
237
|
description: "Detect whether the active project or sequence contains an Object Mask using Premiere 26.3+.",
|
|
177
238
|
parameters: {
|
|
@@ -24,12 +24,17 @@ export declare const WORKFLOW_CATALOG: readonly [{
|
|
|
24
24
|
readonly title: "Build a context-aware rough cut";
|
|
25
25
|
readonly summary: "Capture reusable project context, retrieve only evidence relevant to the edit intent, create a revision-guarded plan, then preview before applying.";
|
|
26
26
|
readonly recommendedTools: readonly ["manage_project_context", "search_project_context", "create_context_edit_plan", "preview_edit_plan", "apply_edit_plan"];
|
|
27
|
+
}, {
|
|
28
|
+
readonly id: "transcript-rough-cut";
|
|
29
|
+
readonly title: "Plan a transcript-driven rough cut";
|
|
30
|
+
readonly summary: "Export Premiere's native transcript, select revision-locked source ranges, map them to verified 1x placements in a duplicate sequence, then execute the descending cut plan with re-query verification.";
|
|
31
|
+
readonly recommendedTools: readonly ["get_clip_transcript_uxp", "search_clip_transcript_uxp", "preview_transcript_edit_uxp", "plan_transcript_rough_cut_uxp", "manage_sequences_uxp", "split_clip", "get_sequence_structure"];
|
|
27
32
|
}];
|
|
28
33
|
export declare const WORKFLOW_RESOURCE: string;
|
|
29
34
|
export declare const WORKFLOW_PROMPTS: {
|
|
30
35
|
name: string;
|
|
31
|
-
title: "Assemble a rough cut" | "Clean up dialogue" | "Caption and style a sequence" | "Prepare a delivery export" | "Build a context-aware rough cut";
|
|
32
|
-
description: "Inspect the project, import media, create or select a sequence, assemble clips, then verify and save." | "Inspect audio tracks, normalize dialogue, apply conservative cleanup, and verify levels before saving." | "Inspect the active sequence, create captions, apply styling, verify timing, and save." | "Validate the sequence and destination, export with an explicit preset, then report the produced artifact." | "Capture reusable project context, retrieve only evidence relevant to the edit intent, create a revision-guarded plan, then preview before applying.";
|
|
36
|
+
title: "Assemble a rough cut" | "Clean up dialogue" | "Caption and style a sequence" | "Prepare a delivery export" | "Build a context-aware rough cut" | "Plan a transcript-driven rough cut";
|
|
37
|
+
description: "Inspect the project, import media, create or select a sequence, assemble clips, then verify and save." | "Inspect audio tracks, normalize dialogue, apply conservative cleanup, and verify levels before saving." | "Inspect the active sequence, create captions, apply styling, verify timing, and save." | "Validate the sequence and destination, export with an explicit preset, then report the produced artifact." | "Capture reusable project context, retrieve only evidence relevant to the edit intent, create a revision-guarded plan, then preview before applying." | "Export Premiere's native transcript, select revision-locked source ranges, map them to verified 1x placements in a duplicate sequence, then execute the descending cut plan with re-query verification.";
|
|
33
38
|
argsSchema: {
|
|
34
39
|
goal: z.ZodString;
|
|
35
40
|
constraints: z.ZodOptional<z.ZodString>;
|
|
@@ -30,6 +30,12 @@ export const WORKFLOW_CATALOG = [
|
|
|
30
30
|
summary: "Capture reusable project context, retrieve only evidence relevant to the edit intent, create a revision-guarded plan, then preview before applying.",
|
|
31
31
|
recommendedTools: ["manage_project_context", "search_project_context", "create_context_edit_plan", "preview_edit_plan", "apply_edit_plan"],
|
|
32
32
|
},
|
|
33
|
+
{
|
|
34
|
+
id: "transcript-rough-cut",
|
|
35
|
+
title: "Plan a transcript-driven rough cut",
|
|
36
|
+
summary: "Export Premiere's native transcript, select revision-locked source ranges, map them to verified 1x placements in a duplicate sequence, then execute the descending cut plan with re-query verification.",
|
|
37
|
+
recommendedTools: ["get_clip_transcript_uxp", "search_clip_transcript_uxp", "preview_transcript_edit_uxp", "plan_transcript_rough_cut_uxp", "manage_sequences_uxp", "split_clip", "get_sequence_structure"],
|
|
38
|
+
},
|
|
33
39
|
];
|
|
34
40
|
export const WORKFLOW_RESOURCE = JSON.stringify({
|
|
35
41
|
version: 1,
|
|
@@ -11,8 +11,8 @@ descriptions, action enums, authority visibility, and counts stay aligned with t
|
|
|
11
11
|
| Registered core actions | 285 | CEP/local server catalog; host and authority checks still apply |
|
|
12
12
|
| Default-profile core actions | 283 | Advertised with `inspect,edit,export,filesystem` |
|
|
13
13
|
| Restricted core actions | 2 | Require explicit `unsafe-script` authority |
|
|
14
|
-
| Authenticated UXP additions |
|
|
15
|
-
| Default profile with UXP |
|
|
14
|
+
| Authenticated UXP additions | 49 | Advertised only while a compatible authenticated UXP panel is connected |
|
|
15
|
+
| Default profile with UXP | 332 | 283 core plus 49 UXP tools |
|
|
16
16
|
|
|
17
17
|
## How to read support
|
|
18
18
|
|
|
@@ -366,6 +366,7 @@ authenticated and the connected host advertises the required command capabilitie
|
|
|
366
366
|
| `manage_track_state_uxp` | Connected UXP | `inspect`, `set_mute` | Inspect audio, video, and caption track mute state or set one media type serially with stale-state preflight and per-track readback. Adobe exposes this as direct promises, so no undo transaction is claimed. |
|
|
367
367
|
| `manage_workflow_checkpoints_uxp` | Connected UXP | `has`, `get`, `set`, `clear` | Read or transactionally write small, namespaced workflow checkpoints on the active project or a targeted sequence. Persistent values may sync with cloud projects; never store secrets, native paths, transcripts, or media names. |
|
|
368
368
|
| `organize_project_items_uxp` | Connected UXP | `inspect_bin`, `create_bin`, `create_smart_bin`, `rename`, `move`, `set_color`, `remove` | Inspect a bin or transactionally create, rename, move, color-label, and remove project items with stable-ID guards. |
|
|
369
|
+
| `plan_transcript_rough_cut_uxp` | Connected UXP | Single operation | Build a revision-locked, non-mutating rough-cut plan from Premiere's native transcript and verified 1x sequence placements. The plan orders cuts from the end of the timeline, requires a duplicate sequence, and requires re-query after every mutation. |
|
|
369
370
|
| `preflight_production_storage_uxp` | Connected UXP | `preflight`, `configure_project` | Inspect project/Production scratch disks and ingest state, or set supported project scratch categories to Premiere's symbolic destinations in one undoable transaction. |
|
|
370
371
|
| `preview_transcript_edit_uxp` | Connected UXP | Single operation | Validate and merge source-time ranges selected from Premiere's native transcript. Returns a confirmation token and never changes the timeline. Automatic timeline application remains withheld until the source-to-sequence mapping is live-host verified. |
|
|
371
372
|
| `relink_offline_media_uxp` | Connected UXP | Single operation | Relink one offline clip to a workspace-contained media path after stale-path and capability checks. This Premiere API is non-undoable and requires explicit confirmation. |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "premiere-pro-mcp",
|
|
3
|
-
"version": "1.11.
|
|
3
|
+
"version": "1.11.3",
|
|
4
4
|
"description": "Adobe Premiere Pro MCP server with 285 core AI video editing tools and a capability-aware UXP bridge for supported Premiere workflows.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -8,12 +8,6 @@ const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
|
8
8
|
|
|
9
9
|
const MCPB_SCHEMA =
|
|
10
10
|
"https://raw.githubusercontent.com/modelcontextprotocol/mcpb/main/schemas/mcpb-manifest-v0.4.schema.json";
|
|
11
|
-
const LOOPBACK_DOMAINS = new Set([
|
|
12
|
-
"http://127.0.0.1",
|
|
13
|
-
"http://localhost",
|
|
14
|
-
"ws://127.0.0.1",
|
|
15
|
-
"ws://localhost",
|
|
16
|
-
]);
|
|
17
11
|
const SEMVER = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
|
|
18
12
|
const ADOBE_VERSION = /^\d+\.\d+\.\d+$/;
|
|
19
13
|
|
|
@@ -129,10 +123,9 @@ export function validateUxpManifest(manifest, packageJson, { expectedId } = {})
|
|
|
129
123
|
"UXP package must use operator-requested local file access",
|
|
130
124
|
);
|
|
131
125
|
const domains = manifest.requiredPermissions?.network?.domains;
|
|
132
|
-
assert(Array.isArray(domains) && domains.length > 0, "UXP package must declare its loopback network access");
|
|
133
126
|
assert(
|
|
134
|
-
domains
|
|
135
|
-
"UXP package
|
|
127
|
+
domains === "all",
|
|
128
|
+
"UXP package must use Adobe's compatible network permission; runtime code remains the loopback-only authority",
|
|
136
129
|
);
|
|
137
130
|
}
|
|
138
131
|
|
|
@@ -25,7 +25,9 @@ The builder uses a fixed ZIP timestamp, lexical file order, and stored entries,
|
|
|
25
25
|
then reads the generated central directory and checks every entry and CRC. The
|
|
26
26
|
result is reproducible for identical source bytes. It also rejects symlinks,
|
|
27
27
|
requires the UXP v5 Premiere manifest, checks the version against
|
|
28
|
-
`package.json
|
|
28
|
+
`package.json`. Adobe's Premiere 26.3 runtime requires the compatible `domains: "all"`
|
|
29
|
+
manifest form for the WebSocket connection; `workspace.cjs` remains the enforced authority and
|
|
30
|
+
accepts only `ws://127.0.0.1:<port>/uxp` or `ws://localhost:<port>/uxp`.
|
|
29
31
|
|
|
30
32
|
For an Adobe Creative Cloud Marketplace submission, Adobe Developer
|
|
31
33
|
Distribution must first create the Marketplace plugin ID. Build a separate
|
package/uxp-plugin/manifest.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"manifestVersion": 5,
|
|
3
3
|
"id": "com.ppmcp.premiere.uxp",
|
|
4
4
|
"name": "Premiere Pro MCP Bridge",
|
|
5
|
-
"version": "1.11.
|
|
5
|
+
"version": "1.11.3",
|
|
6
6
|
"main": "index.html",
|
|
7
7
|
"host": { "app": "premierepro", "minVersion": "25.6.0" },
|
|
8
8
|
"entrypoints": [
|
|
@@ -17,6 +17,6 @@
|
|
|
17
17
|
],
|
|
18
18
|
"requiredPermissions": {
|
|
19
19
|
"localFileSystem": "request",
|
|
20
|
-
"network": { "domains":
|
|
20
|
+
"network": { "domains": "all" }
|
|
21
21
|
}
|
|
22
22
|
}
|